如何确定程序栈保护机制所使用的Canary类型?
GCC栈保护Canary类型判定指南
启动时Canary动态变化的含义
首先可以直接排除终止符型Canary:这类Canary是固定硬编码值(通常为0x000aff0d,包含NULL、换行、回车、EOF四类字符串终止符),不会随进程启动发生变化。
但仅靠「每次启动Canary变化」不能判定为纯随机型Canary:随机型、随机异或型Canary的种子都来自内核熵池,每次进程启动都会重新生成,二者都会表现为启动时Canary值变化。
绝对判定Canary类型的方法
1. 依据GCC官方规则判定
你使用的32位Debian + GCC 10.3.0环境,配合-fstack-protector参数,默认使用的就是随机异或型Canary:
- GCC从4.8版本开始,x86、x86_64、ARM等主流架构的栈保护默认实现就已经从纯随机型切换为随机异或型,实现逻辑是将内核生成的全局随机值,和当前栈帧的返回地址做异或运算后再存入栈帧,相比纯随机型安全性更高:即使Canary被泄露,攻击者也无法构造通用的伪造值绕过保护,每个栈帧的Canary都和当前帧的返回地址绑定。
- 纯随机型Canary仅在非常老的GCC版本(4.7及更早)、或者小众嵌入式架构编译时才会默认使用。
2. 用GDB调试手动验证
你可以通过以下步骤直接验证当前程序的Canary类型:
- 编译程序时添加
-g参数保留调试符号,使用gdb ./目标程序名启动调试 - 在main函数入口打断点:
b main,运行程序:r - 读取当前进程的全局随机种子:32位x86环境下种子存在TLS段的固定偏移,执行命令
x/wx $gs:0x14,记录输出值记为A - 查找当前栈帧存储的Canary值:32位程序Canary默认存放在
ebp-0x8的位置,执行命令x/wx $ebp-0x8,记录输出值记为B - 读取当前栈帧的返回地址:执行命令
x/wx $ebp+0x4,记录输出值记为C - 做异或校验:
- 如果
A ^ C == B,则为随机异或型Canary - 如果
A == B,则为纯随机型Canary
- 如果
内容的提问来源于stack exchange,提问作者adrewSchucany
相关产品推荐
相关产品推荐

