提取.obj文件7ziplib.exe(随vs默认安装).obj文件逆向dumpbin.exe源程序调用法逆向lib函数名修饰C函数名修饰C++构造/析构函数名调用约定如果函数是类的成员函数,调用约定为__thiscall,根据保护方式的不同,又分为:返回值、参数的类型标识结束标志静态链接库其实属于一种压缩文件。可以通过一些压缩软件直接进行解压缩获取其中的内容(例如7z),如果其内容是.obj文件表明该文件为静态库。如果里面是.dll文件则说明是导入库,导入库中不含代码,代码包含在对应的dll文件中。
提取.obj文件
7zip直接提取即可,解压后还有可能得到一个txt文件,里面是所有obj文件的列表,以及obj文件提供的函数的原型。
lib.exe(随vs默认安装)查看lib文件中的obj信息
lib /list xxx.lib > liblist.txtlib /list:liblist.txt xxx.lib
提取obj文件
lib xxx.lib /extract:\Release\xxx.obj #\Release\xxx.obj是从liblist.txt中读出的
如果我们对obj中的二进制进行了修改,可以再导入进原来的lib或者生成一个新的lib:
lib xxx.lib xxx.obj #导入原liblib /OUT:xxx.lib xxx_new.lib xxx.obj #生成新lib
.obj文件逆向
dumpbin.exe该工具同样随vs默认安装。查看obj文件的基础信息
dumpbin /all xxx.obj > xxxobj_info.txt
也可以反汇编obj文件
dumpbin.exe /disasm xxx.obj > xxxobj_asm.txt
但dumpbin不一定能得到想要的结果,运行dumpbin后就,可能会提示未知的对象类型(File Type: ANONYMOUS OBJECT),这是由于程序在编译时使用了/GL优化选项,该优化会使dumpbin功能失效。
源程序调用法逆向lib和逆向动态链接库时可以编写一个小demo加载dll一样,可以通过编写一个小demo调用obj里的函数,首先要编写一个头文件,文件名要和lib文件里的obj文件的名称相同。然后确定函数原型,使用文本编辑器打开提取出的obj文件之后可以在里面找到编译后的修饰名,根据修饰名可还原函数原型并在头文件中声明该函数。编写demo,include头文件,引入lib库,调用要分析的函数。
函数名修饰函数的名字修饰(Decorated Name)就是编译器在编译期间创建的一个字符串,用来指明函数的定义或原型。目的是方便编译过程中,链接器等中间过程识别不同的函数,尤其是在引入重载后,识别函数不能只看函数名,要结合参数、返回值类型来识别。
C函数名修饰C不存在函数重载,主要需要在函数修饰中体现出函数的调用约定:stdcall:函数名前加上一个下划线前缀,函数名后面加上一个“@”符号和其参数的字节数,例如 _functionname@number。cdecl:仅在输出函数名前加上一个下划线前缀,例如_functionname。__fastcall:在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数,例如@functionname@number
C++考虑到函数重载,函数名修饰需要包含调用约定,返回值类型,参数个数及类型。具体格式为:
?+[构造/析构]+函数名+@@+调用约定+返回值类型+各个参数类型+结束标志
构造/析构可选项,只有构造函数和析构函数有。
0:构造器1:析构器
函数名函数名包括类名和命名空间名,格式为:
函数名@类名@命名空间
调用约定__stdcall:@@YG__cdecl:@@YA__fastcall:@@YI
如果函数是类的成员函数,调用约定为__thiscall,根据保护方式的不同,又分为:public __thiscall:@@QAEprotect __thiscall:@@IAEprivate __thiscall:@@AAEpublic __thiscall const:@@QBEprotect __thiscall const:@@IBEprivate __thiscall const:@@ABE
返回值、参数的类型标识 B:const D:char E:unsigned char F:short G:unsigned short H:int I:unsigned int J:long K:unsigned long M:float N:double _N:bool PA:指针(*,后面的代号表明指针类型,如果相同类型的指针连续出现,以0代替,一个0代表一次重复) PB:const指针 AA:引用(&) AB:const引用 U:类或结构体,通常后跟结构体的类型名,用“@@”表示结构类型名的结束。 V:类,通常后跟结构体的类型名,用“@@”表示结构类型名的结束 W4:enum X:void Z: 结尾标记 0:相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复。 @: 空,无得意思,构造或析构使用 AAV1:参数类型是类实例的引用,通常后跟结构体的类型名,用“@@”表示结构类型名的结束。 ABV1:参数类型是const类实例的引用,通常后跟结构体的类型名,用“@@”表示结构类型名的结束。 ?AV:函数返回值为某个类,通常后跟结构体的类型名,用“@@”表示结构类型名的结束 ?BV:函数返回值为某个类的const,通常后跟结构体的类型名,用“@@”表示结构类型名的结束 PAV:返回值为某个类的指针,通常后跟结构体的类型名,用“@@”表示结构类型名的结束 AAV:返回值为某个类的引用,通常后跟结构体的类型名,用“@@”表示结构类型名的结束 PBV:返回值为某个类带有const性质的指针,通常后跟结构体的类型名,用“@@”表示结构类型名的结束 ABV:返回值为某个类带有const性质的引用,通常后跟结构体的类型名,用“@@”表示结构类型名的结束 V1@:函数参数为某个类的时候,并且该参数所使用的类曾经出现过
结束标志参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。