静态链接库其实属于一种压缩文件。可以通过一些压缩软件直接进行解压缩获取其中的内容(例如7z),如果其内容是.obj文件表明该文件为静态库。如果里面是.dll文件则说明是导入库,导入库中不含代码,代码包含在对应的dll文件中。
提取.obj文件
7zip
直接提取即可,解压后还有可能得到一个txt文件,里面是所有obj文件的列表,以及obj文件提供的函数的原型。
lib.exe(随vs默认安装)
查看lib文件中的obj信息
lib /list xxx.lib > liblist.txt
lib /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 #导入原lib
lib /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:@@QAE
protect __thiscall:@@IAE
private __thiscall:@@AAE
public __thiscall const:@@QBE
protect __thiscall const:@@IBE
private __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@:函数参数为某个类的时候,并且该参数所使用的类曾经出现过