逆向分析细节总结

来源:互联网 发布:mac怎么安装程序 编辑:程序博客网 时间:2024/05/23 20:04
1、函数识别及参数传递

 Call指令 == 跳转指令+返回地址
 Call指令跳转的地址即被调用函数的起始地址

 函数参数传递方式:
  1)堆栈传递参数
  2)寄存器传递参数(__fastcall、thiscall(寄存器传递this指针))

 参数入栈顺序,平衡堆栈:
  1)C/C++和MFC程序默认使用__cdecl调用约定,参数从右到左入栈,由调用者平衡堆栈;
  2) Win32 API函数使用stdcall调用约定,参数从右到左入栈,由被调用者平衡堆栈(参数个数固定,函数知道传入的参数个数,因此被调用函数可在返回前用一条“retn”指令直接清理传递参数的堆栈);VC++默认使用。

  2、函数返回值
  
   返回方式:return返回、引用返回、全局变量返回。
   函数返回值一般放在EAX中返回,若超出容量,高32位放入EDX中;

    在调试程序时,不要见Call就跟进,在Call之前所做的所有PUSH动作以及对寄存器的操作都可能是在给函数传递参数,而函数的返回值一般都放在EAX里面,当然这个值可能是一个指针,指向一个数据结构。从汇编角度来看,主要有如下形式:

1)通过寄存器返回函数值;
2)通过参数按引用方式返回函数值;
3)通过全局变量返回函数值;
4)通过处理器标志返回函数值;
   一般情况下,由retrun操作符返回的值放在EAX寄存器之中,如果结果超过这个寄存器的位容量,那么该结果的高32位会加载到EDX寄存器中。 如果返回一个含有几百个字节的结构或者一个近似大小的对象,编译器会在不告诉程序的情况下,给函数传递一个隐式参数,这个指针指向保存的返回结果。

3、数据结构

    局部变量:sub esp,8 ;分配空间
                       push reg;分配4个字节空间
                      [ebp-xxx];寻址调用变量
                      [ebp+xxx];寻址调用参数,优化模式时,通过esp寄存器对局部变量与参数寻址;
    全局变量:通常位于数据区固定地址上,访问时通过固定地址直接对内存寻址;
    初始化:mov指令,push指令直接将值压入堆栈;
    寄存器存放:编译器尽量使用寄存器存放局部变量,不够则使用堆栈;
    注:局部变量生命周期短,必须及时确定当前寄存器存放的是哪个变量;

     程序运行(调试)过程中,我们可以得到指定代码段的虚拟地址(VA),减去其加载基址,即为其相对虚拟地址(RVA),此时可得到该代码段在PE文件的哪个区段,转换公式为:
       文件偏移 =  RVA - 节偏移 (由存储单位差异引起的节基址差称为节偏移)

4、启动函数
     首先我们明确,Windows程序的执行并不是从WinMain函数开始,首先被执行的是启动函数相关代码,这段代码是编译器生成的。这段启动代码作用是初始化进程,然后调用WinMain( )函数。即Start( ) ->WinMain( )
     在WinMain( )函数原型中,参数hInstance(实例句柄)一般通过GetModuleHandleA函数进行获取,这对识别WinMain函数会有些帮助。
     对WinMain的调用通常放在启动函数代码结尾部分,后面通常跟着诸如exit或XcptFilter之内的两、三个函数。
     另一标志:___security_cookie
0 0
原创粉丝点击