重学C---------第二节:求两个整数之和
求两个整数之和,也是一个很小的程序,但是其中的道理,还是很多的,我们要好好体会。
相加的两个数从哪来,到哪去?
1 #include <stdio.h> 2 3 void main() 4 { 5 int a,b,sum; 6 a=123; 7 b=456; 8 sum=a+b; 9 printf("sum is %d \n",sum); 10 }
工程下载地址:https://files.cnblogs.com/tk091/rl002.zip
同样的,我们我OD来查看对应的汇编代码:
00401010 > 55 push ebp 00401011 8BEC mov ebp,esp 00401013 83EC 4C sub esp,0x4C 00401016 53 push ebx 00401017 56 push esi 00401018 57 push edi 00401019 8D7D B4 lea edi,dword ptr ss:[ebp-0x4C] 0040101C B9 13000000 mov ecx,0x13 00401021 B8 CCCCCCCC mov eax,0xCCCCCCCC 00401026 F3:AB rep stos dword ptr es:[edi] 00401028 C745 FC 7B00000>mov dword ptr ss:[ebp-0x4],0x7B 0040102F C745 F8 C801000>mov dword ptr ss:[ebp-0x8],0x1C8 00401036 8B45 FC mov eax,dword ptr ss:[ebp-0x4] 00401039 0345 F8 add eax,dword ptr ss:[ebp-0x8] 0040103C 8945 F4 mov dword ptr ss:[ebp-0xC],eax 0040103F 8B4D F4 mov ecx,dword ptr ss:[ebp-0xC] 00401042 51 push ecx ; <%d> 00401043 68 1C204200 push rl002.0042201C ; format = "sum is %d " 00401048 E8 33000000 call rl002.printf ; printf 0040104D 83C4 08 add esp,0x8 00401050 5F pop edi 00401051 5E pop esi 00401052 5B pop ebx 00401053 83C4 4C add esp,0x4C 00401056 3BEC cmp ebp,esp 00401058 E8 A3000000 call rl002._chkesp 0040105D 8BE5 mov esp,ebp 0040105F 5D pop ebp 00401060 C3 retn
对应的,我们用IDA来看看对应的代码是什么:
1 int __cdecl main() 2 { 3 char v1; // [sp+Ch] [bp-4Ch]@1 4 unsigned int v2; // [sp+4Ch] [bp-Ch]@1 5 int v3; // [sp+50h] [bp-8h]@1 6 int v4; // [sp+54h] [bp-4h]@1 7 8 memset(&v1, -858993460, 0x4Cu); 9 v4 = 123; //int a=123; 10 v3 = 456; //int b=456; 11 v2 = 579; 12 printf("sum is %d \n", 579); 13 return _chkesp(); 14 }
上面我们看的都是Debug版的程序,我们来瞅瞅Release版的。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
首先是OD查看:
1 00401000 /$ 68 43020000 push 0x243 2 00401005 |. 68 30704000 push rl002.00407030 ; ASCII "sum is %d 3 " 4 0040100A |. E8 11000000 call rl002.00401020 5 0040100F |. 83C4 08 add esp,0x8 6 00401012 \. C3 retn
然后是IDA查看:
1 int __cdecl main(int argc, const char **argv, const char **envp) 2 { 3 return sub_401020("sum is %d \n", 579); 4 }
我们突然发现,原来main函数是有三个参数的,而不是两个。
我把它修改成这个样子:
1 ; int __cdecl main(int argc, const char **argv, const char **envp) 2 _main proc near 3 push 579 4 push offset Format ; "sum is %d \n" 5 call _printf 6 add esp, 8 7 retn 8 _main endp
很多东西,在编译的过程中已经丢失了。
当你苦苦追寻,在学习中经过多次努力,忽然获得我们所求的东西,那种感受,就是 一种幸福。
通过对sig文件的研究,终于对这个程序的逆向变成了:
主函数:
1 ; int __cdecl main(int argc, const char **argv, const char **envp) 2 _main proc near 3 push 243h 4 push offset Format ; "sum = %d \n" 5 call _printf 6 add esp, 8 7 retn 8 _main endp
而进入call则是:
1 int __cdecl main(int argc, const char **argv, const char **envp) 2 { 3 return printf("sum = %d \n", 579); 4 }
在这里感谢所有的前辈给出的经验。