您的位置:首页 > 其它

逆向分析细节总结

2016-02-23 00:45 225 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: