|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
分析编译器对变长数组的实现
#include <stdio.h>
int main(void)
{
int n;
scanf("%d", &n); // 实验而已,输入n时,请输入大于3的数字
int ar[n];
ar[2] = 0xff00;
printf("%d\n", ar[2]);
printf("%p", ar);
return 0;
}
以上代码经codeblocks13.12编译后(release版),使用od载入后(请结合栈的变化图来分析)
CPU Disasm
Address Hex dump Command Comments
00401C2C /$ 8D4C24 04 lea ecx, [esp+4] ; ecx = argc变量的地址,c中的main(argc, argv, env),argc为第一个参数
00401C30 |. 83E4 F0 and esp, FFFFFFF0 ; dqword (16.-byte) stack alignment
00401C33 |. FF71 FC push dword ptr ds:[ecx-4] ; 返回地址再次压栈(如何获取函数返回后的地址?这就是方法)
00401C36 |. 55 push ebp
00401C37 |. 89E5 mov ebp, esp
00401C39 |. 53 push ebx
00401C3A |. 51 push ecx ; argc的地址压栈
00401C3B |. 83EC 20 sub esp, 20
00401C3E |. E8 ADFCFFFF call 004018F0 ; [cConsole.004018F0, 未分析出函数的目的
00401C43 |. 8D45 F4 lea eax, [ebp-0C]
00401C46 |. 894424 04 mov dword ptr ss:[esp+4], eax ; /<%d> => offset LOCAL.4
00401C4A |. C70424 243040 mov dword ptr ss:[esp], offset 00403024 ; |format => "%d"
00401C51 |. E8 36FFFFFF call <jmp.&msvcrt.scanf> ; \MSVCRT.scanf
00401C56 |. 8B45 F4 mov eax, dword ptr ss:[ebp-0C]
00401C59 |. 8D0485 120000 lea eax, [eax*4+12] ; 准备为变长数组分配空间,有多0x12,但为啥是0x12?
00401C60 |. 83E0 F0 and eax, FFFFFFF0 ; 清空了低4位,即又保证了栈为16字节对齐
00401C63 |. E8 C8FEFFFF call 00401B30 ; 检测变长数组的长度是否可能导致栈溢出, probes EAX bytes on stack
00401C68 |. 29C4 sub esp, eax ; 为变长数组分配空间,在栈中分配的哦
00401C6A |. 8D5C24 08 lea ebx, [esp+8] ; 现开始,esp指向的就是变长数组的首元素的首地址,即esp指向了变长数组的第一个元素
00401C6E |. C74424 10 00F mov dword ptr ss:[esp+10], 0FF00 ; 给ar[2]赋值0xff00
00401C76 |. C74424 04 00F mov dword ptr ss:[esp+4], 0FF00 ; /<%d> => 65280. 即0xff00 == 65280
00401C7E |. C70424 273040 mov dword ptr ss:[esp], offset 00403027 ; |format => "%d\n"
00401C85 |. E8 0AFFFFFF call <jmp.&msvcrt.printf> ; \MSVCRT.printf
00401C8A |. 895C24 04 mov dword ptr ss:[esp+4], ebx ; /<%p>
00401C8E |. C70424 2B3040 mov dword ptr ss:[esp], offset 0040302B ; |format => "%p"
00401C95 |. E8 FAFEFFFF call <jmp.&msvcrt.printf> ; \MSVCRT.printf
00401C9A |. 31C0 xor eax, eax
00401C9C |. 8D65 F8 lea esp, [ebp-8] ; 令esp指向argc
00401C9F |. 59 pop ecx ; argc的地址出栈
00401CA0 |. 5B pop ebx
00401CA1 |. 5D pop ebp
00401CA2 |. 8D61 FC lea esp, [ecx-4] ; 令esp指向返回地址
00401CA5 \. C3 retn
CPU Disasm
Address Hex dump Command Comments
004018A0 /> /53 push ebx
004018A1 |. |83EC 18 sub esp, 18
004018A4 |. |8B1D C41C4000 mov ebx, dword ptr ds:[401CC4]
004018AA |. |83FB FF cmp ebx, -1
004018AD |. |74 24 je short 004018D3
004018AF |> |85DB test ebx, ebx
004018B1 |. |74 0F jz short 004018C2
004018B3 |> |FF149D C41C40 /call near dword ptr ds:[ebx*4+401CC4]
004018BA |. |83EB 01 |sub ebx, 1
004018BD |. |8D76 00 |lea esi, [esi]
004018C0 |.^|75 F1 \jnz short 004018B3
004018C2 |> |C70424 701840 mov dword ptr ss:[esp], 00401870 ; Entry point
004018C9 |. |E8 F2F9FFFF call 004012C0
004018CE |. |83C4 18 add esp, 18
004018D1 |. |5B pop ebx
004018D2 |. |C3 retn
004018D3 |> |31DB xor ebx, ebx
004018D5 |. |EB 02 jmp short 004018D9
004018D7 |> |89C3 /mov ebx, eax
004018D9 |> |8D43 01 |lea eax, [ebx+1]
004018DC |. |8B1485 C41C40 |mov edx, dword ptr ds:[eax*4+401CC4]
004018E3 |. |85D2 |test edx, edx
004018E5 |.^|75 F0 \jnz short 004018D7
004018E7 |.^|EB C6 jmp short 004018AF
004018E9 | |8DB426 000000 lea esi, [esi]
004018F0 |$ |8B0D 24504000 mov ecx, dword ptr ds:[405024] ; cConsole.004018F0(guessed void)
004018F6 |. |85C9 test ecx, ecx
004018F8 |. |74 06 jz short 00401900
004018FA |. |F3:C3 rep retn
004018FC | |8D7426 00 lea esi, [esi]
00401900 |> |C705 24504000 mov dword ptr ds:[405024], 1
0040190A \.^\EB 94 jmp short 004018A0
CPU Disasm
Address Hex dump Command Comments
00401B30 /$ 51 push ecx
00401B31 |. 50 push eax
00401B32 |. 3D 00100000 cmp eax, 1000 ; 0x1000==4096==4k,变长数组长度不可超过4k字节?非也!参考下面
00401B37 |. 8D4C24 0C lea ecx, [esp+0C] ; 可是此子程序并没有实现什么功能啊
00401B3B |. 72 15 jb short 00401B52
00401B3D |> 81E9 00100000 /sub ecx, 1000
00401B43 |. 8309 00 |or dword ptr ds:[ecx], 00000000 ; 看似没有实现什么功能,实际上ecx不断减去4k,如果eax太大,则会使得ds:[ecx]进入操作系统数据区域,再进行写入数据时造成访问违例的异常!非常巧妙的技巧!
00401B46 |. 2D 00100000 |sub eax, 1000
00401B4B |. 3D 00100000 |cmp eax, 1000
00401B50 |.^ 77 EB \ja short 00401B3D
00401B52 |> 29C1 sub ecx, eax
00401B54 |. 8309 00 or dword ptr ds:[ecx], 00000000
00401B57 |. 58 pop eax
00401B58 |. 59 pop ecx
00401B59 \. C3 retn |
|