Linux 二进制程序保护机制详解

本文深入讲解了ASLR、NX、PIE、Canary和RELRO等程序保护机制,包括它们的作用、表现形式及如何通过gcc编译选项进行配置。了解这些机制能帮助开发者提升程序的安全性。

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

0x00 检测

可以使用 pwntools 中的 checksec 工具进行检测,红色表示未开启该保护。
checksec 检测效果

0x01 保护

一、ASLR

1.介绍:

ASLR 的是操作系统的功能选项,作用于 executable(ELF)装入内存运行时,因而只能随机化 stack、heap、libraries 的基址。

2.表现形式

开启后每次加载程序的 stack、libarys、heap 等地址都会随机化,可用 cat /proc/`pidof xxx`/maps 查看。

3.作用

未开启:无作用
半开启:随机化 stack 和 libarys
全开启:随机化 stack、libarys 和 heap

4.保护开启和关闭方式
  ## 未开启:地址随机化关闭
  echo 0 > /proc/sys/kernel/randomize_va_space
  ## 半开启:随机化 stack 、librarys
  echo 1 > /proc/sys/kernel/randomize_va_space
  ## 全开启:随机化 stack 、librarys 、heap(默认选项)
  echo 2 > /proc/sys/kernel/randomize_va_space

二、NX

1.介绍

No-Execute(不可执行),Nx 的原理是将数据所在内存页标识为不可执行,当程序执行流被劫持到栈上时,程序会尝试在数据页面上执行指令,因为数据页被标记为不可知性,此时CPU就会抛出异常,而不是去执行栈上数据。

2.表现形式

在程序的某个位置有控制程序是否可以执行的标志位(若为 6 不可执行 、7 不可执行),也可以用 execstack 工具查询和设置该标志位,该标志位在 51e5 7464 后边。详细见下图

xxd 1 :无保护
xxd 1输出
xxd 2 :有保护
xxd 2 输出

3.作用

NX disabled: 栈可以执行,栈上的数据也可以被当作代码执行。
NX enabled: 栈不可执行,栈上的数据程序只认为是数据,如果去执行的话会发生错误。即栈上的数据不可以被当作代码执行。

4.gcc 编译选项(为程序添加保护的方式)
  ## 栈可执行:NX disabled
  gcc -z execstack
  ## 栈不可执行:NX enabled(默认选项)
  gcc -z noexecstack 

三、PIE

1.介绍

PIE(Position Independent Executables)是编译器(gcc,…)功能选项(-fPIE / -fpie),作用于编译过程,可将其理解为特殊的 PIC(so专用,Position Independent Code),加了 PIE 选项编译出来的 ELF 用 file 命令查看会显示其为 so,其随机化了 ELF 装载内存的基址(代码段、plt、got、data 等共同的基址)。其效果为用 objdump、IDA 反汇编之后的地址是用偏移表示的而不是绝对地址。

2.表现形式

PIE 表现形式

3.作用

No PIE: 无作用
PIE enabled: 代码段、plt、got、data 等共同的基址会随机化。在编译后的程序中,只保留指令、数据等的偏移,而不是绝对地址的形式。

4.gcc 编译选项(为程序添加保护的方式)
  ## 关闭:No PIE(默认选项)
  -no-pie
  ## 开启:PIE enabled
  -fpie -pie / -fPIE -pie  
  ## 笔者并不知道这两个选项有什么区别,在用不同选项编译一个程序时他们两个的 hash 居然都一样,所以在此求教各位。

四、Canary

1.介绍

金丝雀保护,是一种用来防护栈溢出的保护机制。其原理是在函数入口处,先从 fs/gs 寄存器中取出一个 4(eax)/8(rax) 字节的 cookie 信息存到栈上,当函数结束返回的时候会验证 cookie 信息是否合法(与开始存的是否一致),如果不合法就停止程序运行。真正的 cookie 信息也会保存在程序的某个位置。插入栈中的 cookie 一般在 ebp / rbp 之上的一个内存单元保存。

2.表现形式

Canary 表现形式

3.作用

无 Canary 保护: 无任何作用
部分函数 Canary 保护: 在一些容易受到攻击的函数返回地址之前添加 cookie 。在函数返回时,检查该 cookie 与原本程序插入该位置的 cookie 是否一致,若一致则程序认为没有受到栈溢出攻击。
全部函数 Canary 保护: 所有的自定义函数在返回地址之前都会添加 cookie 。在函数返回时,检查该 cookie 与原本程序插入该位置的 cookie 是否一致,若一致则程序认为没有受到栈溢出攻击。

4.gcc 编译选项(为程序添加保护的方式)
  ## 无 canary 保护:No canary found
  -fno-stack-protector() / -fstack-protector() 
  ## 部分 canary 保护:Canary found(默认选项)
  -fstack-protector-strong
  ## 全部 canary 保护:Canary found
  -fstack-protector-all 

五、RELRO

1.介绍

设置符号重定位表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对 GOT 攻击。

2.作用

No RELRO: 在这种模式下关于重定位并不进行任何保护。
Partial RELRO: 在这种模式下,一些段 (包括.dynamic) 在初始化后将会被标识为只读。
Full RELRO: 在这种模式下,除了会开启部分保护外。惰性解析会被禁用(所有的导入符号将在开始时被解析,.got.plt 段会被完全初始化为目标函数的终地址,并被标记为只读)。此外,既然惰性解析被禁用,GOT[1] 与 GOT[2] 条目将不会被初始化为提到的值。

3.gcc 编译选项(为程序添加保护的方式)
  ## 关闭: No RELRO
  -z norelro
  ## 开启: Partial RELRO(默认选项)
  -z lazy
  ## 完全开启: Full RELRO
  -z now
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值