静态链接库其实属于一种压缩文件。可以通过一些压缩软件直接进行解压缩获取其中的内容(例如7z),如果其内容是.obj文件表明该文件为静态库。如果里面是.dll文件则说明是导入库,导入库中不含代码,代码包含在对应的dll文件中。

提取.obj文件

7zip

直接提取即可,解压后还有可能得到一个txt文件,里面是所有obj文件的列表,以及obj文件提供的函数的原型。

lib.exe(随vs默认安装)

查看lib文件中的obj信息

  1. lib /list xxx.lib > liblist.txt
  2. lib /list:liblist.txt xxx.lib

提取obj文件

  1. lib xxx.lib /extract:\Release\xxx.obj #\Release\xxx.obj是从liblist.txt中读出的

如果我们对obj中的二进制进行了修改,可以再导入进原来的lib或者生成一个新的lib:

  1. lib xxx.lib xxx.obj #导入原lib
  2. lib /OUT:xxx.lib xxx_new.lib xxx.obj #生成新lib

.obj文件逆向

dumpbin.exe

该工具同样随vs默认安装。
查看obj文件的基础信息

  1. dumpbin /all xxx.obj > xxxobj_info.txt

也可以反汇编obj文件

  1. 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++

考虑到函数重载,函数名修饰需要包含调用约定,返回值类型,参数个数及类型。具体格式为:

  1. ?+[构造/析构]+函数名+@@+调用约定+返回值类型+各个参数类型+结束标志

构造/析构

可选项,只有构造函数和析构函数有。

  1. 0:构造器
  2. 1:析构器

函数名

函数名包括类名和命名空间名,格式为:

  1. 函数名@类名@命名空间

调用约定
  1. __stdcall:@@YG
  2. __cdecl:@@YA
  3. __fastcall:@@YI

如果函数是类的成员函数,调用约定为__thiscall,根据保护方式的不同,又分为:
  1. public __thiscall:@@QAE
  2. protect __thiscall:@@IAE
  3. private __thiscall:@@AAE
  4. public __thiscall const:@@QBE
  5. protect __thiscall const:@@IBE
  6. private __thiscall const:@@ABE

返回值、参数的类型标识
  1. Bconst
  2. Dchar
  3. Eunsigned char
  4. Fshort
  5. Gunsigned short
  6. Hint
  7. Iunsigned int
  8. Jlong
  9. Kunsigned long
  10. Mfloat
  11. Ndouble
  12. _Nbool
  13. PA:指针(*,后面的代号表明指针类型,如果相同类型的指针连续出现,以0代替,一个0代表一次重复)
  14. PBconst指针
  15. AA:引用(&)
  16. ABconst引用
  17. U:类或结构体,通常后跟结构体的类型名,用“@@”表示结构类型名的结束。
  18. V:类,通常后跟结构体的类型名,用“@@”表示结构类型名的结束
  19. W4enum
  20. Xvoid
  21. Z: 结尾标记
  22. 0:相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复。
  23. @: 空,无得意思,构造或析构使用
  24. AAV1:参数类型是类实例的引用,通常后跟结构体的类型名,用“@@”表示结构类型名的结束。
  25. ABV1:参数类型是const类实例的引用,通常后跟结构体的类型名,用“@@”表示结构类型名的结束。
  26. ?AV:函数返回值为某个类,通常后跟结构体的类型名,用“@@”表示结构类型名的结束
  27. ?BV:函数返回值为某个类的const,通常后跟结构体的类型名,用“@@”表示结构类型名的结束
  28. PAV:返回值为某个类的指针,通常后跟结构体的类型名,用“@@”表示结构类型名的结束
  29. AAV:返回值为某个类的引用,通常后跟结构体的类型名,用“@@”表示结构类型名的结束
  30. PBV:返回值为某个类带有const性质的指针,通常后跟结构体的类型名,用“@@”表示结构类型名的结束
  31. ABV:返回值为某个类带有const性质的引用,通常后跟结构体的类型名,用“@@”表示结构类型名的结束
  32. V1@:函数参数为某个类的时候,并且该参数所使用的类曾经出现过

结束标志

参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。