在上一篇文章《进程切换的本质是什么?》中举了一个示例,也就是这段代码:
#include #include
void funcc() { printf(jump to funcc !!!\\n) ; exit(-1) ;}
void funcb() { long *p = null ; p = (long*)&p ; *(p+2) = (long)funcc ;}
void funca() { funcb();}
int main() { funca() ; return 0 ;}有同学问不能在自己的机器上复现,并给出了编译后的机器指令:
00000000004005ee : 4005ee: 55 push %rbp 4005ef: 48 89 e5 mov %rsp,%rbp 4005f2: 48 83 ec 10 sub $0x10,%rsp 4005f6: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 4005fd: 00 00 4005ff: 48 89 45 f8 mov %rax,-0x8(%rbp) 400603: 31 c0 xor %eax,%eax 400605: 48 c7 45 f0 00 00 00 movq $0x0,-0x10(%rbp) 40060c: 00 40060d: 48 8d 45 f0 lea -0x10(%rbp),%rax 400611: 48 89 45 f0 mov %rax,-0x10(%rbp) 400615: 48 8b 45 f0 mov -0x10(%rbp),%rax 400619: 48 83 c0 10 add $0x10,%rax 40061d: ba d6 05 40 00 mov $0x4005d6,%edx 400622: 48 89 10 mov %rdx,(%rax) 400625: 90 nop 400626: 48 8b 45 f8 mov -0x8(%rbp),%rax 40062a: 64 48 33 04 25 28 00 xor %fs:0x28,%rax 400631: 00 00 400633: 74 05 je 40063a 400635: e8 66 fe ff ff callq 4004a0 40063a: c9 leaveq 40063b: c3 retq仔细看这段代码,有这样一段可疑的指令:
mov %fs:0x28,%raxmov %rax,-0x8(%rbp)这两行指令将fs:[0x28] (段寻址的方式)处的值push到了调用栈上(%rbp偏移8字节),并在函数即将返回的时候又检查了一遍该值有没有被修改:
mov -0x8(%rbp),%raxxor %fs:0x28,%rax接下来如果保存到栈上的值不等于fs:[0x28]处的值(xor指令进行比较)那么跳转到__stack_chk_fail函数,我们的疑问是为什么要有这么一遍检查呢?
本质上我们在开头给出的代码相对于缓冲区溢出攻击,做法是修改上一个栈帧的返回地址,将其修改为某个特定地址(黑客希望跳转到的地方);
在开头的这段代码中本来funca函数调用完funcb后需要返回funca,但在我们的“精心”设计下调用完funcb后却跳转到了funcc ,那么我们有没有办法防范这种攻击呢?
答案是肯定的,这种方法要追溯到很久很久以前。
在上世纪初,煤矿开采是一项很危险的工作,因为煤矿中的有毒气体通常极难被人类察觉,这给矿工的生命带来很大的威胁,而金丝雀对毒气非常敏感,这样矿工可以利用金丝雀来监控矿区,从而提早发现险情。
这里也是一样的道理,我们可以在栈区中放置一个“金丝雀”(fs:[0x28]处的值):
当函数返回时我们会再次拿fs:[0x28]处的值与栈上的“金丝雀”进行对比, 一旦发现这两个值不同我们就可以认为当前的栈已经被破坏了,由于栈上的数据已然不可信,因此我们必须及早撤离矿区 ,也就是调用__stack_chk_fail函数提前终止进程。
而金丝雀也就是fs:[0x28]是随机产生的(每次程序运行时都不一样),因此攻击者很难提前知道该值是多少。
当然我们也可以看到,添加堆栈保护功能需要增加额外的机器指令,这些也会稍稍对性能产生影响,代价就是需要额外多执行一部分机器指令。
这就是编译器的堆栈保护功能,当然这个功能也是可以去掉的,编译时添加-fno-stack-protector编译选项(在这里感谢小风哥微信技术群里同学的提示),这样即可关闭堆栈保护功能,生成的代码就可以复现上一篇文章《进程切换的本质是什么》中提到的效果了。
怎么样,想成为黑客还是没那么容易吧,就好比只有真正理解法律才能钻空子一样,只有真正理解计算机的工作原理才能hack它,当然,想成为顶尖黑客只有对计算机的理解还不够,你还需要有想象力。
北汽新能源股价暴跌 转型遭遇拦路虎
电路板中:铝基板与FR-4 PCB电路板有什么区别?
晶体振荡器三态输出技术到底是什么?
LED台灯可为行动设备充电
赛普拉斯推出加快物联网产品设计的统一软件套件
简述缓冲区溢出攻击与堆栈保护
基于电容式触摸屏技术的触摸按键设计与应用分析
运用工业机器人打造服务业自动化
信号的正交分解和差分传输的区别
医疗器械行业为什么选择超声波电机,它的优势是什么
霍金寻找外星人项目进展如何_传霍金已经被外星人控制
controller_4G08的方案设计 实现了FPGA对F
ROHM扩充“全SiC”功率模块产品阵容
影驰GTX1080Ti名人堂怎么样?一图看懂影驰GTX1080 Ti名人堂显卡
浅析基于stm32f103与涂鸦智能的智能蜜蜂养殖系统
震撼!机器人居然会剥小龙虾?
英特尔收购小型芯片厂商eASIC 进一步降低对CPU依赖
润开鸿承办OpenHarmony赛题结硕果并获特殊贡献奖
Zephyr无人机不断打破记录的民间授权飞行器
手机无线充电器怎么选择,快充无线充电器测评