《软件调试分析技术》学习笔记(十二)

参数和返回值是函数的两个重要组成部分,可以通过参数向函数传入信息,通过返回值使函数传出信息。看一段C语言代码: 

#include  
int function(int a, int b) 
{ 
  if (a > b) 
  { 
    return a; 
  } 
  else 
  { 
    return b; 
  } 
} 
int main() 
{ 
  function(1, 2); 
  return 0; 
} 

这里定义了一个函数function(),参数是两个整型变量,返回值也是整型变量,当a的值大于b时返回a,否则返回b,很明显这个函数返回的是两个数中的较大数,然后在主函数中调用了这个函数,参数分别为1、2。编译后使用IDA进行分析,主函数的反汇编代码如下:

.text:00401020    push    ebp 
.text:00401021    mov     ebp, esp 
.text:00401023    push    2               ; b 
.text:00401025    push    1               ; a 
.text:00401027    call    ?function@@YAHHH@Z ; function(int,int) 


 
  
这里向栈中压入数据2和1,然后调用函数function(int,int)。可以猜想这样向堆栈里压入2和1就是在给被调用的过程传递参数了。这里要注意,传递参数的时候是反着来的,C语言里调用的时候是function(1, 2),等到反汇编的时候就变成先压入2,再压入1这样的了。 

.

text:0040102C    add     esp, 8 
  

  这一句代码用来抬高栈顶,抬高栈顶是为了平衡栈桢,前面为了给被调用过程传递参数向栈中压入了两个四字节的int型变量,这里把栈顶抬高八个字节就是为了销毁传递参数的痕迹。

.text:0040102F    xor     eax, eax 
.text:00401031    pop     ebp 
.text:00401032    retn 
下面是function()函数在IDA中的分析结果:

.text:00401000 ; Attributes: bp-based frame 
.text:00401000 
.text:00401000 ; int __cdecl function(int a, int b) 
.text:00401000 ?function@@YAHHH@Z proc near            ; CODE XREF: _main+7 p 
.text:00401000 
.text:00401000 a               = dword ptr  8 
.text:00401000 b               = dword ptr  0Ch 
.text:00401000

这里是对function()函数的参数、返回值、调用方式等信息的分析。这里说明了function()函数的调用方式为__cdecl,返回值是int型,两个参数a、b与ebp对应的偏移分别为0x08和0x0C。


.text:00401000    push    ebp 
.text:00401001    mov     ebp, esp 
.text:00401003    mov     eax, [ebp+a] 
.text:00401006    cmp     eax, [ebp+b] 
.text:00401009    jle     short loc_401012 
.text:0040100B    mov     eax, [ebp+a] 
.text:0040100E    jmp     short loc_401015 
.text:00401010    jmp     short loc_401015 
.text:00401012    mov     eax, [ebp+b] 
.text:00401015    pop     ebp 
.text:00401016    retn 
.text:00401016 ?function@@YAHHH@Z endp 

一般来说过程返回的结果都是储存在eax里的。这个函数比较两个参数a、b,如果参数a大于参数b则把参数a放到eax,跳到最后返回,如果参数a不大于参数b则把参数b放到eax中返回。 
  

你可能感兴趣的:(逆向工程,汇编,技术文章)