Viusal C++, Borland Delphi程序的分析

Viusal C++, Borland Delphi程序的分析
======================================
[1] Viusal C++程序的分析
先将编译器设定为Visual C++,载入签名如vc32rtf,vc32mfc等.待IDA扫描分析完毕就可以开始工作了.

逆向前,先要说下函数有4种调用约定,即stdcall,cdecl,fastcall,pascal.它们之间的区别体现在参数入栈顺序和清理入栈参数的方式上.

stdcall的参数入栈顺序是从右到左,且在函数返回前清理入栈参数,在反汇编代码上体现为retn xx,比如压入2个寄存器作为参数,函数返回时就是retn 8.采用stdcall约定的有WINAPI,以及CALLBACK回调函数等.

cdecl的参数入栈顺序也是从右到左,但是在函数返回后清理入栈参数,在反汇编代码上体现为add esp, xx,比如压入3个寄存器作为参数,返回时就是add esp, 0Ch.采用cdecl约定的有c标准函数库等.

可能有人要问stdcall和cdecl貌似没什么区别嘛,这样做不是多此一举吗?呵呵,想想最常用的printf函数族,发现什么了?它的入栈参数个数是不固定的,也就是说在编译期才能确定入栈参数,所以用stdcall是无法实现这类不固定参数的函数,只能用cdecl.

pascal的参数入栈顺序与上面二者相反,是从左到右.在函数返回前清理入栈参数,这与stdcall一致.
fastcall的特点就是采用寄存器来传递部分函数参数,但具体细节依赖于编译器.如Visual C++编译器的fastcall约定是前两个参数依次用ecx,edx,第3个开始push入栈.

归纳如下:
调用约定 入栈参数清理 参数入栈顺序
-----------        --------------         ----------------
cdecl      调用者处理       右->左
stdcall  函数自己处理      右->左
pascal  函数自己处理      左->右
fastcall 函数自己处理  依赖于编译器

直接调用Windows SDK写的C代码编译后是比较好分析的,只要熟悉Windows API基本就能找到和分析自己感兴趣的部分.比较棘手的是MFC一类C++代码的逆向问题.因为出现call dword ptr [esi+XXh]一类的虚函数调用,不能一路很顺利的跟下去.当然,你可以从调用点回溯到类实例创建的地方,从而知道调用的是什么函数.不过这样比较麻烦,投机取巧的办法,是用od到虚函数调用的地方前下断,然后由this指针得到虚函数表地址(this指针指向的类实例存储结构的第一项就是虚函数表地址),偏移XXh得到虚函数地址.

[2] Borland Delphi程序的分析
先把编译器设定为Delphi,载入签名d5vcl等.待IDA扫描分析完毕.

Delphi的函数调用是fastcall.Borland Delphi的fastcall约定是前3个参数依次用eax,edx,ecx传递,第4个开始push入栈.如果是虚函数,第一个参数eax就是this指针. 形象点就是function(eax, edx, ecx, push...).

举个例子:
code:004531CC lea eax, [ebp+var_30]
code:004531CF & nbsp; push eax & nbsp; ; 第4个参数
code:004531D0 lea ecx, [ebp+var_38] & nbsp;; 第3个参数
code:004531D3 mov edx, esi & nbsp; ; 第2个参数
code< style="color: #000000;">:004531D5 mov eax, ebx & nbsp; ; 第1个参数,this指针
code:004531D7 mov edi, [eax] ; edi <- vmt ptr
code:004531D9 call dword ptr [edi+0Ch] ; 虚函数调用

先前说过库函数是我们分析一个用户函数的重要线索,因为Delphi对Windows API做了封装,所以在Delphi程序里鲜有直接调用Windows API,基本是对库的调用,所以在分析的时候需要常翻Delphi Help.

另外,Delphi的字符串处理方式和C库有很大不同,没有熟知的str*函数族.推荐阅读看雪上firstrose整理的"Delphi的内部字符串处理函数/过程不完全列表"一文.
 

你可能感兴趣的:(C++,windows,Delphi,pascal,编译器,Borland)