前言
这里会让逆一个完整的 C 语言程序,大家这个好好做,这可是你的第一个逆向工程哈哈哈哈
课堂
C 语言程序真正的入口
我们知道 C 语言中程序总是从 main 函数开始执行,那 main 函数是谁调用了它呢?通过看 main 函数的反汇编,我们可以发现是下面这个函数调用了 main 函数—mainCRTStartup()函数
所以一个程序的真正的入口函数其实是mainCRTStartup(),这个入口不要轻易的修改,因为这个函数做了很多初始化工作,如果修改了这个入口后面的程序会出现很多问题
mainCRTStartup 做了哪些初始化工作
//调用了下面特定功能的函数
GetVersion() //获得当前操作系统的版本
_heap_init() //初始化堆的空间大小
GetCommandLineA() //获取命令行的参数
_crtGetEnvironmentStringsA() //获取环境变量
_setargv() //等等
_setenvp()
_cinit()
怎么去找程序的入口
- 我们使用堆栈调用窗口双击 mainCRTStartup()函数,进去看一下它调用的 main 函数是怎么定义的
-
可以发现 main 函数有三个参数,所以如果我们想找程序入口,先找到 GetVersion() 、_heap_init() 、
-
GetCommandLineA() ,crtGetEnvironmentStringsA() ,setargv(),setenvp() ,cinit()中的任意一个函数,那么再在它们的后面找,找有三个参数的方法,如果找到了,就是 main 入口
-
现在用 OD 打开一个程序,OD 会自动识别二进制,形成注释,所以可以在反汇编窗口中右侧看到注释,会显示那一行指令表示哪一个函数,只要看到了上述函数,再往后找,找有传入了三个参数的方法,虽然用 push 和 add esp,x 的方法判断参数个数不一定正确,但是多半都满足这个规则,所以如果找到了一个 call 指令前有三个入栈,且后面跟了一个 add esp,0xC 来平衡堆栈那么多半调用的就是 main 函数,按回车跟踪地址就可以看到 main 函数中的内容
然后就找到了,进去进一步分析就行
作业
这里给大家这个程序的 exe,这个大家把后缀改成 zip 然后解压就行
// diyigefanhuibianchengxu.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int __cdecl plus2(int a,int b)
{
return a+b;
}
int __stdcall plus1(int a,int b,int c)
{
return a+b+c;
}
int __fastcall plus(int x,int y,int z,int m,int n)
{
int a = plus1(x,y,z);
int b = plus2(x,y);
return plus2(a,b);
}
int main(int argc, char* argv[])
{
//printf("Hello World!\n");
char c = '啊';
int a = plus(1,3,4,6,7);
printf("%d",a);
return 0;
}