Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源
定义导出函数方法:
///
1. 在.def中声明
导出为C格式函数,函数名未修饰,使用时直接 加 extern "C" 声明函数就可以使用
2. 使用dllexport导出函数
导出为C++格式函数,函数名称被修饰为类似 ?max@....,仅供C++使用,C++使用时加 dllimport 声明可以使用
3. 使用 extern "C" dllexport导出函数
导出为C格式函数,函数名未修饰,使用时直接 加 extern "C" 声明函数就可以使用
4. 修改为C导出格式: 样可以使用extern "C" {},把头文件内容全部括进来,从而使导出的内容全为C格式函数
通常使用宏来选择使用dllexport/dllimport,下面例子只有导出部分
例子1: 使用dllexport导出类/函数
class dllexport MyClass{};
例子2: 使用dllexport导出函数
bool dllexport IsEqual(xxx, xxx);
例子3: 只导出类中的某部分函数,则类不能声明为导出,对函数进行导出
class MyClass{
dllexport MyClass();
dllexport ~MyClass();
bool dllexport CompareWith(xxx);
...
}
基于def文件生成lib文件的方法:
参考地址:http://wenku.baidu.com/view/73f084e6524de518964b7d2a.html
基于def文件生成lib文件的方法:
lib /DEF:swscale-2.def /MACHINE:IX86-2
(使用VC++的LIB工具,带"/DEF:xxx.def /MACHINE:IX86" (80X86机器),就输出符合VC++格式的的LIB文件)
swscale-2文件内容如下:(因为是C格式库,导出C格式函数-基于.def文件导出的函数,不涉及C++名称修饰重载,.def文件格式比较简单,函数名称按顺序布置即可)
基于def文件生成lib文件-C++类型函数:
参考:http://www.360doc.com/content/14/0518/15/7378868_378761402.shtml
参考:http://bbs.csdn.net/topics/240054505
参考:http://blog.chinaunix.net/uid-799319-id-2035224.html C++编译器的函数名修饰规则
像MFCM90U.dll的def文件定义的时候时,因为部分函数使用dllexport不带extern "C"方式导出,函数使用了C++修饰
// 注意:?必须包括 C++函数修饰都是以一个“?”开始,后面紧跟函数的名字,再后面是参数表的开始标识和按照参数类型代号拼出的参数表
EXPORTS
InitMfcmDll
AfxmReleaseManagedReferences
AfxmEnsureManagedInitialization
?SetPropertyV@CWinFormsControlSite@MFC@VisualC@Microsoft@@UEAAXJGPEAD@
?PreTranslateMessage@CWinFormsView@MFC@VisualC@Microsoft@@MEAAHPEAUtagMSG@@@
...
定义之后,可以基于这个 生成MFC90U.lib: lib /DEF:MFC90U.def /MACHINE:IX86-2
例如:下面这个.def声明两个命名空间中的函数
void MYSPACE::Del(void*)
void* MYSPACE::Get()
; Define文件内容
@@YAXPAX@Z 代表 参数为:"void __cdecl operator delete(void *)"
YA __cdecl
X void
PAX void *
@Z -- 名字结束
查看lib/dll文件的函数方法:
参考地址: http://www.oschina.net/question/565065_85858
1. Window下命令dumpbin -exports 你的 lib/dll名称
( dumpbin 例如 在:\Microsoft Visual Studio 9.0\VC\bin\amd64\dumpbin.exe 位置)
2. 如果你用gcc,可用objdump查看
3. linux的nm命令可以一个文件中的符号列表,列出以上代码Gcc -c编译出的a.o(a.a a.so)可以通过nm命令来查看其中的符号信息
以下为转载内容:lib文件介绍
lib /list xx .lib 列出lib里所有obj文件名,我这里如下
。。。。。很多省略
lib/err/err.obj
lib/dict/dictll.obj
lib/coreDump/coreDumpWin32.obj
lib/config/preference.obj
lib/config/configUL.obj
找到你关注的obj,这里选择configUL.obj,然后 lib /EXTRACT:lib/config/configUL.obj xx .lib
解出configUL.obj, 然后把obj拖入IDA,我这里是ida5.5,在函数列表里找你要调用的函数,然后逆之
_Config_GetString .text 00000068 00000039 R . . . B . .
_Config_GetBool .text 000000B8 00000039 R . . . B . .
_Config_GetLong .text 00000108 00000039 R . . . B . .
_Config_GetInt64 .text 00000158 0000003D R . . . B . .
_Config_GetTriState .text 00000198 00000039 R . . . B . .
_Config_GetDouble .text 000001E8 00000041 R . . . B T .
_Config_GetPathName .text 00000288 00000039 R . . . B . .
_Config_NotSet .text 000002C4 00000035 R . . . B . .
_Config_GetLongPlain .text 000003B0 00000015 . . . . . . .
_Panic UNDEF 000003D0 00000004 R . . . . . .
_Preference_GetString UNDEF 000003D4 00000004 R . . . . . .
_Str_Vsnprintf UNDEF 000003D8 00000004 R . . . . . .
_Preference_GetBool UNDEF 000003DC 00000004 R . . . . . .
_Preference_GetLong UNDEF 000003E0 00000004 R . . . . . .
_Preference_GetInt64 UNDEF 000003E4 00000004 R . . . . . .
_Preference_GetTriState UNDEF 000003E8 00000004 R . . . . . .
_Preference_GetDouble UNDEF 000003EC 00000004 R . . . . . .
_Preference_GetPathName UNDEF 000003F4 00000004 R . . . . . .
_Preference_NotSet UNDEF 000003F8 00000004 R . . . . . .
我这里随便选择一个函数 _Config_GetString,很小的函数,呵呵,方便说明
.text:00000068 _Config_GetString proc near
.text:00000068
.text:00000068 var_400 = byte ptr -400h
.text:00000068 arg_0 = dword ptr 8
.text:00000068 arg_4 = dword ptr 0Ch
.text:00000068 arg_8 = byte ptr 10h
.text:00000068
.text:00000068 push ebp
.text:00000069 mov ebp, esp
.text:0000006B mov ecx, [ebp+arg_4]
.text:0000006E sub esp, 400h
.text:00000074 lea eax, [ebp+arg_8]
.text:00000077 push eax
.text:00000078 push ecx
.text:00000079 lea edx, [ebp+var_400]
.text:0000007F push 400h
.text:00000084 push edx
.text:00000085 call _Str_Vsnprintf
.text:0000008A mov ecx, [ebp+arg_0]
.text:0000008D lea eax, [ebp+var_400]
.text:00000093 push eax
.text:00000094 push ecx
.text:00000095 call _Preference_GetString
.text:0000009A add esp, 18h
.text:0000009D mov esp, ebp
.text:0000009F pop ebp
.text:000000A0 retn
.text:000000A0 _Config_GetString endp
这个函数很简单,一看就知道功能了,格式化一个buffer,构建一个字符串返回,
下面是是直接f5后修改的结果
int __cdecl Config_GetString(int a1, int a2, char *buf)
{
char buffer[0x400];
Str_Vsnprintf(buffer, sizeof(buffer), a2, buf);
return Preference_GetString(a1, &v4);
}
这种手法,搞个10个,8个的函数还行,多了会死人的,最好看了关键思路自己写个来的更快