葛洲坝领导名单:让EXE导出函数

来源:百度文库 编辑:九乡新闻网 时间:2024/04/27 23:11:25
让EXE导出函数(ZT)
让EXE导出函数

标 题
【原创】让EXE导出函数
作 者
ylp1332
时 间
2007-12-20,21:33
链 接http://bbs.pediy.com/showthread.php?t=56840

初步搞定。

问题来源:
偶然发现OllyDBG
.exe导出了一堆函数,这些函数都是供其插件调用的。对这种体系结构很感
兴趣,想弄清楚它的实现原理。后来又看到梁肇新的书《编程高手箴言》第
278页提到的调用
门,觉得都应该差不多。


三种不同的解决办法(原理可能是一样的,
:)):

1)在导出函数声明之前加上__declspec(dllexport)。例:
__declspec
(dllexportint Add(int aint b);
__declspec(dllexportint Sub(int aint b);
__declspec(dllexportint Mul(int aint b);
__declspec(dllexportint Div(int aint b);

2)在链接器参数中设置。例:
#pragma comment(linker"/EXPORT:_Add,@1,NONAME")
#pragma comment(linker"/EXPORT:_Sub,@2,NONAME")
#pragma comment(linker"/EXPORT:_Mul,@3,NONAME")
#pragma comment(linker"/EXPORT:_Div,@4,NONAME")

3)添加一个def文件,例:
EXPORTS
Add       @1 NONAME
Sub       @2 NONAME
Mul       @3 NONAME
Div       @4 NONAME
另需要在链接器命令行参数中指定def文件名:
/DEF:Callee.def
注意:在def文件中不要有
LIBRARY 
[library][BASE=address]
这样的语句。

相比较而言,后两种方法可以设置更多的参数。


函数举例:

extern "C"
{

int Add(int aint b)
{
    
return (b);
}

int Sub(int aint b)
{
    
return (b);
}

int Mul(int aint b)
{
    
return (b);
}

int Div(int aint b)
{
    
if (== 0)
      
return 0;
    
else
      return 
(b);
}

}

编译时会自动生成相应的导出库(lib)文件,供调用者使用。


调用方法和普通的动态链接库调用一样。
调用者必须能够找到被调用者的位置,否则报错,被调用者是否运行不影响。

调用代码举例:

extern "C"
{
int Add(int aint b);
int Sub(int aint b);
int Mul(int aint b);
int Div(int aint b);
}

#pragma comment (lib"Callee.lib")

void CCallerDlg::OnBnClickedCalculate()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);

switch (((CComboBox *)GetDlgItem(IDC_COMBO_OPERATOR))->GetCurSel())
{
case ADD:
    {
      
m_iResult Add(m_iNum1m_iNum2);
      
break;
    }
case SUB:
    {
      
m_iResult Sub(m_iNum1m_iNum2);
      
break;
    }
...
...


我在OD中跟了一下,发现这跟调用动态链接库也差不多。
不过那几个函数被映射到下面的地址处:

003810F0 8B4424 08                 mov     eaxdword ptr [esp+8]
003810F4    8B4C24 04                 mov     ecxdword ptr [esp+4]
003810F8    03C1                      add     eaxecx
003810FA    C3                        retn
003810FB    CC                        int3
003810FC    CC                        int3
003810FD    CC                        int3
003810FE    CC                        int3
003810FF    CC                        int3
00381100 8B4424 04                 mov     eaxdword ptr [esp+4]
00381104    2B4424 08                 sub     eaxdword ptr [esp+8]
00381108    C3                        retn
00381109    CC                        int3
0038110A    CC                        int3
0038110B    CC                        int3
0038110C    CC                        int3
0038110D    CC                        int3
0038110E    CC                        int3
0038110F    CC                        int3
00381110 8B4424 04                 mov     eaxdword ptr [esp+4]
00381114    0FAF4424 08               imul    eaxdword ptr [esp+8]
00381119    C3                        retn
0038111A    CC                        int3
0038111B    CC                        int3
0038111C    CC                        int3
0038111D    CC                        int3
0038111E    CC                        int3
0038111F    CC                        int3
00381120 8B4C24 08                 mov     ecxdword ptr [esp+8]
00381124    85C9                      test    ecxecx
00381126    75 03                     jnz     short 0038112B
00381128    33C0                      
xor     eaxeax
0038112A    C3                        retn

跟常规的动态链接库被映射到高地址处略有不同。
还不知道是什么原因。

结论:
EXE完全可以和DLL一样导出函数,一样被调用。

进一步的工作:
我发现这个例子跟OllyDbg
.exe还是有些不同,跟“调用门”的说法也有不同。这里实际上还是
跟DLL差不多的原理。下一步争取实现一个跟OllyDbg
.exe差不多的例子。

致谢:
感谢海风月影、北极星
2003、默数悲伤所提供的思路。


源代码和例子见附件。
http
://bbs.pediy.com/attachment.php?attachmentid=10475&d=1198157615