jarvisoj_level2_x64
文件是64位ELF文件
IDA查看函数vuln,明显栈溢出
查看字符串,发现存在'/bin/sh',地址为0x600A90
查看函数,发现存在system函数,地址为0x4004c0。注意不能用下面那个extern的外部system函数
现在只要让函数返回到system,并传入参数'/bin/sh'就行了
64位程序函数调用时的操作和32位有所不同。32位程序函数调用时,依次将子函数的参数从右到左入栈,然后再压栈eip和ebp。64位程序如果子函数的参数数量<=6个,则会将参数从左到右依次存入rdi,rsi,rdx,rcx,r8,r9这6个寄存器中,如果还有参数,则像32位一样压栈。所以64位函数调用后,子函数运行时会先将参数从寄存器里pop出来,也就是会执行pop rdi; ret指令
本题中给出了system()函数的地址,以及'/bin/sh'字符串的地址,那么如何覆盖呢?首先用128+8个字节覆盖掉buf和rbp,然后是pop rdi; ret指令的地址,再接着是'/bin/sh'字符串的地址,最后是system()函数的地址。流程为:子函数返回到pop rdi; ret处,该指令会将当前栈顶的元素('/bin/sh'字符串的地址)出栈并存入rdi中,并返回到下一条指令处。此时栈中就只有system()函数的地址了,所以下一条指令正是system(),而它需要的参数正好就在rdi寄存器中,这样就执行了system('/bin/sh')
pop rdi; ret指令的地址通过Linux下的ROPgadget工具查找
ROPgadget --binary ./Desktop/level2_x64 --only "pop|ret"
payload如下
from pwn import *
r = remote("node4.buuoj.cn",28104)
payload = b'a'*(128+8)+p64(0x4006b3)+p64(0x600A90)+p64(0x4004C0)
r.sendline(payload)
r.interactive()
标签:bin,system,函数调用,x64,地址,64,pop,BUU,rdi
From: https://www.cnblogs.com/nemuzuki/p/17218722.html