逆向实战
应各位的建议,加了注释,喜欢的看官点个赞支持一下,哈哈!
逆向CallingConvention.exe,还原为C代码,记录过程。
程序入口
如何查找程序入口?
main 函数被调用前要先调用的函数如下:
GetVersion()
_heap_init()
GetCommandLineA()
_crtGetEnvironmentStringsA()
_setargv()
_setenvp()
_cinit()
这些函数调用结束后就会调用main 函数,根据main 函数调用的特征,将3 个参数压入栈内作为函数的参数。
回到反汇编图,我们可以看到OD给我们注释出来的GetCommandLineA()函数下面紧接着push了三个寄存器,这就是我们判断程序入口最简单的方法了!
main函数
简要分析:
这里通过push压入了三个参数,通过mov 寄存器,立即数传入了两个参数,符合__fastcall
调用约定的传参"手法";因为__fastcall
的传参顺序是从右往左,因此函数1的调用如右:func1(1,3,4,6,7)
通过Main函数识别出来程序大致框架如下:
- 函数3为编译器自动添加的堆栈平衡检查函数,故在此不用考虑。
void __fastcall func1(int a,int b,int c,int d,int e){
}
//函数2我们暂时不知道是什么,先写到这
void __cdecl func2(int x,int y){
}
void main(int argc,char *argv[])
{
func1(1,3,4,6,7);
func2(m,n);
}
func1函数
简要分析:
mov [local.2],edx实现将mov dword ptr ds:[ebp-8],edx,即给局部变量赋值,不熟悉这部分的朋友可以函数调用与堆栈图分析相关知识点。
这里push了三个参数,并且是在函数内部平衡的堆栈,可以基本判断调用方式为stdcall(这种调用约定在函数内部使用ret n的方式平衡堆栈,待分析func3的时候再论)。
你问我堆栈平衡怎么看,继续往下看吧,紧接着func3向下面分析:
mov [local.3],eax:这句的作用是将调用func3的返回结果eax放到[ebp-0c]中;紧接着又push了两个寄存器,调用func4,并且我们可以看到在call func4之后有条add esp,0x8
,这就是堆栈平衡,目的是让堆栈恢复到调用前的状态,由于是在func4外部平衡的堆栈,我们也叫做外平栈,调用约定为C和CPP默认的__cdecl
!
从以上汇编代码识别出func1的框架如下:
void __fastcall func1(int a,int b,int c,int d,int e){
int x=1;
int y=3;
func3(x,y,c);
func4();
func4();
}
func3函数
简要分析:
[arg.1]即我们之在main函数看到的传入的第一个参数(最左边的),其它的不再赘述,经过一番加法运算后将返回值放到eax中,看伪代码吧。
func3函数大致框架如下:
int __cdecl func3(int x,int y,it z)
{
return x+y+z;
}
func1函数补充如下:
void __fastcall func1(int a,int b,int c,int d,int e){
int x=1;
int y=3;
int z=func3(x,y,c);
func4(x,y);
func4();
}
这里再提一下,x即[ebp-4],y即[ebp-8],z即[ebp-0c],对应func1函数
部分的[local.1],[local.2],[local.3].
func4函数
简要分析
同上,不再赘述,直接看伪代码吧!
func4的函数框架如下:
int cdecl func4(int x.int y)
{
return x+y;
}
func1函数补充如下:
void __fastcall func1(int a,int b,int c,int d,int e){
int x=1;
int y=3;
int z=func3(x,y,c);
int p=func4(x,y);
func4(p,z); //运算后eax=0C
}
同理,p代表func1函数
部分的[local.4].
到此,func1基本逆向完成,回到main函数,继续func2的逆向,如下:
func2函数
进到func2函数内部,发现其应该是printf函数,那么回到main函数,继续完善,如下:
Main函数
int cdecl func4(int x,int y)
{
return x+y;
}
void __fastcall func1(int a,int b,int c,int d,int e){
int x=1;
int y=3;
int z=func3(x,y,c);
int p=func4(x,y);
func4(p,z); //运算后eax=0C
}
void main(int argc,char *argv[])
{
printf("%d",func1(1,3,4,6,7));
}