gmh5225 发表于 2014-12-25 13:55

汇编逆向(二)

本帖最后由 gmh5225 于 2014-12-25 14:47 编辑

写这个纯属就是自己记录下自己的学习经历,没有其他的意思。





C函数的传递方式有三种: (1) __cdecl(2) __stacall(3) __fastcall   当然还有其他的 pascal register 什么的,不过这都不是C调用的,不管
先随便写下三种方式的函数
int __cdecl add1(int a,int b)
{
      return a+b;
}
int __stdcall add2(int a,int b)
{
      return a+b;
}
int __fastcall add3(int a,int b)
{
      return a+b;
}
int main()
{
      int a=3,b=4,c=0;
      c=add1(a,b);
      c=add2(a,b);
      c=add3(a,b);
      printf("%d",c);
      system("pause");
      return 0;
}
载入OD003C1040 >55            push    ebp                              ;保存原来ebp指针
003C1041    8BEC            mov   ebp, esp                         ;ebp指向esp,即堆栈
003C1043    83EC 0C         sub   esp, 0xC                         ; 开辟12个字节空间供3个变量
003C1046    C745 FC 0300000>mov   dword ptr , 0x3         ; int a
003C104D    C745 F8 0400000>mov   dword ptr , 0x4         ; int b
003C1054    C745 F4 0000000>mov   dword ptr , 0x0         ; int c
003C105B    8B45 F8         mov   eax, dword ptr
003C105E    50            push    eax                              ; 压 b
003C105F    8B4D FC         mov   ecx, dword ptr
003C1062    51            push    ecx                              ; 压 b
003C1063    E8 98FFFFFF   call    testtest.add1                  ; _cdecl调用
003C1068    83C4 08         add   esp, 0x8                         ; 在函数外部平衡堆栈
003C106B    8945 F4         mov   dword ptr , eax
003C106E    8B55 F8         mov   edx, dword ptr
003C1071    52            push    edx                              ; 压 b
003C1072    8B45 FC         mov   eax, dword ptr
003C1075    50            push    eax                              ; 压 a
003C1076    E8 95FFFFFF   call    testtest.add2                  ; _stdcall 在函数内部平衡堆栈
003C107B    8945 F4         mov   dword ptr , eax
003C107E    8B55 F8         mov   edx, dword ptr          ; _fastcall特色不压参数
003C1081    8B4D FC         mov   ecx, dword ptr          ; 分别传递b,a
003C1084    E8 97FFFFFF   call    testtest.add3
003C1089    8945 F4         mov   dword ptr , eax
003C108C    8B4D F4         mov   ecx, dword ptr
003C108F    51            push    ecx
003C1090    68 F4203C00   push    testtest.003C20F4                ; ASCII "%d"
003C1095    FF15 9C203C00   call    dword ptr [<&MSVCR100.printf>]   ; msvcr100.printf
003C109B    83C4 08         add   esp, 0x8
003C109E    68 F8203C00   push    testtest.003C20F8                ; ASCII "pause"
003C10A3    FF15 A4203C00   call    dword ptr [<&MSVCR100.system>]   ; msvcr100.system
003C10A9    83C4 04         add   esp, 0x4
003C10AC    33C0            xor   eax, eax                                     ;清空eax
003C10AE    8BE5            mov   esp, ebp                                 ;esp指向当前ebp,同步跟进
003C10B0    5D            pop   ebp                                             ;还原原来ebp指针
003C10B1    C3            retn

__cdecl函数内部
003C1000 >55            push    ebp
003C1001    8BEC            mov   ebp, esp
003C1003    8B45 08         mov   eax, dword ptr     //这里是第一个参数,也就是a
003C1006    0345 0C         add   eax, dword ptr    // b
003C1009    5D            pop   ebp
003C100A    C3            retn
__stdcall函数内部
003C1010 >55            push    ebp
003C1011    8BEC            mov   ebp, esp
003C1013    8B45 08         mov   eax, dword ptr    //一样,第一个参数 ,a
003C1016    0345 0C         add   eax, dword ptr    // b
003C1019    5D            pop   ebp
003C101A    C2 0800         retn    0x8             //这里就是上述所说的在函数内部的堆栈平衡
__fastcall函数内部
003C1020 >55            push    ebp
003C1021    8BEC            mov   ebp, esp
003C1023    83EC 08         sub   esp, 0x8   //开辟8个字节,也就是2个int的空间
003C1026    8955 F8         mov   dword ptr , edx   //此edx就是函数外部的ebx ,也就是b
003C1029    894D FC         mov   dword ptr , ecx   //这是a
003C102C    8B45 FC         mov   eax, dword ptr //a赋值给eax
003C102F    0345 F8         add   eax, dword ptr //eax=eax+b
003C1032    8BE5            mov   esp, ebp
003C1034    5D            pop   ebp
003C1035    C3            retn      <font color="#0000ff">//因为之前没有压栈,这里不需要平衡
总结一下:_cdecl 和_stdcall 传递参数需要压栈,_cdecl和_fastcall在函数内部返回时不需要平衡堆栈,并且_cdecl在函数外部平衡堆栈,_fastcall因为根本就没有压栈,所以不需要平衡堆栈,最后是_stdcall是在函数内部返时平衡的堆栈 , 前2种满足堆栈的压栈方式,先进后出,也就是第一个压入的变量其实是最后一个。

这里要纠正一个错误:__fastcall 前2个int 都是由ecx和edx传递的,多余的函数还是需要和上面2个调用函数一样,需要压栈
补例:0020107E    8B4D F4         mov   ecx, dword ptr          ;         这里函数原型是int add(int a,int b,int c) 超过了2个int,所以需要压栈
00201081    51            push    ecx                              ;               //压入c
00201082    8B55 F8         mov   edx, dword ptr     //传递b
00201085    8B4D FC         mov   ecx, dword ptr    //传递 a
00201088    E8 93FFFFFF   call    testtest.add3


汇编命令自行百度谷歌。。。别来问我了
















Shark恒 发表于 2014-12-25 13:59

感谢分享学习笔记~ 赞一个~

520Kelly 发表于 2014-12-25 14:40

膜拜Android逆向帝,C编程帝,C逆向帝,汇编帝,反汇编帝

五帝合一,天下无敌,膜拜大神!占位支持

逍遥枷锁 发表于 2014-12-25 15:03




经典教学,谢谢。

果断 发表于 2014-12-25 16:03

Scar-疤痕 发表于 2014-12-25 16:05

向大神看齐!谢谢分享!

阿菜 发表于 2014-12-25 16:14

{:5_191:}膜拜楼主大牛···不明觉厉!···占位支持...

sndncel 发表于 2014-12-25 20:47

{:5_117:}谢谢分享,进来学习了呀。哈哈。

am873 发表于 2014-12-26 00:29

不错,学习了,谢谢!

kingone 发表于 2015-1-28 09:33

大神求加好友 ..
页: [1] 2 3
查看完整版本: 汇编逆向(二)