网站菜单
日记 - 奇奇怪怪的C
* 日记 | winterkuifa | 奇奇怪怪的C
Avatar 作者: winterkuifa ( 2026/07/22 17:02)
阅读量: 22
我只是在做C Primer Plus第三章的第二道练习题。
题目要求,输入一个数字给出对应ascii字符。

#include <stdio.h>
int main (void)
{
char cAa = 0;
printf("GIVE ME AN Ascii number, MY MASTER!");
scanf("%d", &cAa); //问题在这,%d是四字节int,gcc给出了警告
printf("A IKUikuiku!!!!! %cn", cAa);
return 0;
}
然后我发现,不管输入什么,程序都会在最后的printf结束后:
*** stack smashing detected ***: terminated 中止 (核心已傾印)

奇怪。
然后注意到:

通过gdb,我可以观察到canary值被修改、导致程序在返回时触发栈粉碎。

原因:scanf("%d", &cAa),cAa是一字节char变量,%d会写入四字节int。
而char变量只有一字节,剩余三字节理论上会溢出覆盖canary值,整个程序只有这一个变量。

分析:
1.
方便观察,我向一个char变量输入了2147483648(0x80000000),
平台为aarch64,小端序,所以会由低到高写入。程序会依次写入 00 00 00 80,其中 后三个应该会溢出,把高位内存覆盖三字节为800000。
在ARM64下,使用x/gx $sp + 8来查看运行时金丝雀值(的末尾)
0x17e7147510a42300(前)
0x17e7147510800000(后)
可以注意到后三个字节,a42300确实被替换成了800000。
因为前后不符,运行至return 0;后,程序金丝雀值比对不通过,触发栈粉碎*** stack smashing detected ***: terminated。
2.
更换数字,如果我输入1(0x00 00 00 01)
按照由低到高写入,程序会依次写入 10 00 00 00,其中 后三个应该会溢出,把高位内存覆盖三字节为000000。
0x09dee24c8c700100(前)
0x09dee24c8c000000(后)
后三个字节同样被替换成了000000,符合分析。运行结果同样触发栈粉碎。
3.
对照测试。
同一个程序,提前获取canary值,并且写入对应值,理应能正常退出。
x/gx $sp + 7能看到canary值末尾和char变量
0x0a0775aabf7d00(00),括号内为char变量cAa的值,我们初始化为0。
注意最后四个字节,scanf将会写入这四个字节,即bf7d0000。按照猜测,把这个值写入进去,金丝雀值将不会有变化,程序会正常退出。
我们把bf7d0000转换为十进制得到3212640256,作为scanf的输入值。
写入后,继续访问同一个地址
0x0a0775aa [bf 7d 00(00)]
没有变化。
gdb可以看到,__libc_start_call_main将x/gx $sp + 0x08地址的金丝雀值与$tpidr + 0x28地址存储的金丝雀值进行比对。因为前后没有变化,所以没有触发栈粉碎。
[Inferior 1 (process 46207) exited normally],程序正常退出,符合预测。

smile
« 上一页 (第20页 共6191页) 下一页 »
* (0) *
评论: (7)
* 日记 | winterkuifa | 奇奇怪怪的C
官方QQ群-310379632
© DCMS-Social