讓EXE導出函數
標?題
:?
【原創】讓EXE導出函數
作?者
:?
ylp1332
時?間
:?
2007
-
12
-
20
,
21
:
33
鏈?接
:?
http
:
//bbs.pediy.com/showthread.php?t=56840
初步搞定。
問題來源:
偶然發現OllyDBG
.
exe導出了一堆函數,這些函數都是供其插件調用的。對這種體系結構很感
興趣,想弄清楚它的實現原理。后來又看到梁肇新的書《編程高手箴言》第
278
頁提到的調用
門,覺得都應該差不多。
三種不同的解決辦法(原理可能是一樣的,
:)
):
1
)在導出函數聲明之前加上__declspec
(
dllexport
)
。例:
__declspec
(
dllexport
)?
int?
Add
(
int?
a
,?
int?
b
);
__declspec
(
dllexport
)?
int?
Sub
(
int?
a
,?
int?
b
);
__declspec
(
dllexport
)?
int?
Mul
(
int?
a
,?
int?
b
);
__declspec
(
dllexport
)?
int?
Div
(
int?
a
,?
int?
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?
a
,?
int?
b
)
{
????
return?
(
a?
+?
b
);
}
int?
Sub
(
int?
a
,?
int?
b
)
{
????
return?
(
a?
-?
b
);
}
int?
Mul
(
int?
a
,?
int?
b
)
{
????
return?
(
a?
*?
b
);
}
int?
Div
(
int?
a
,?
int?
b
)
{
????
if?
(
b?
==?
0
)
??????
return?
0
;
????
else
??????return?
(
a?
/?
b
);
}
}
編譯時會自動生成相應的導出庫(lib)文件,供調用者使用。
調用方法和普通的動態鏈接庫調用一樣。
調用者必須能夠找到被調用者的位置,否則報錯,被調用者是否運行不影響。
調用代碼舉例:
extern?
"C"
{
int?
Add
(
int?
a
,?
int?
b
);
int?
Sub
(
int?
a
,?
int?
b
);
int?
Mul
(
int?
a
,?
int?
b
);
int?
Div
(
int?
a
,?
int?
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_iNum1
,?
m_iNum2
);
??????
break
;
????}
case?
SUB
:
????{
??????
m_iResult?
=?
Sub
(
m_iNum1
,?
m_iNum2
);
??????
break
;
????}
...
...
我在OD中跟了一下,發現這跟調用動態鏈接庫也差不多。
不過那幾個函數被映射到下面的地址處:
003810F0?
>?
8B4424?08?????????????????
mov?????eax
,?
dword?ptr?
[
esp
+
8
]
003810F4????8B4C24?04?????????????????
mov?????ecx
,?
dword?ptr?
[
esp
+
4
]
003810F8????03C1??????????????????????
add?????eax
,?
ecx
003810FA????
C3????????????????????????retn
003810FB????
CC????????????????????????int3
003810FC????
CC????????????????????????int3
003810FD????
CC????????????????????????int3
003810FE????
CC????????????????????????int3
003810FF????
CC????????????????????????int3
00381100?
>?
8B4424?04?????????????????
mov?????eax
,?
dword?ptr?
[
esp
+
4
]
00381104????2B4424?08?????????????????
sub?????eax
,?
dword?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?????eax
,?
dword?ptr?
[
esp
+
4
]
00381114????0FAF4424?08???????????????
imul????eax
,?
dword?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?????ecx
,?
dword?ptr?
[
esp
+
8
]
00381124????85C9??????????????????????
test????ecx
,?
ecx
00381126????75?03?????????????????????
jnz?????
short?
0038112B
00381128????33C0??????????????????????
xor?????
eax
,?
eax
0038112A????
C3????????????????????????retn
跟常規的動態鏈接庫被映射到高地址處略有不同。
還不知道是什么原因。
結論:
EXE完全可以和DLL一樣導出函數,一樣被調用。
進一步的工作:
我發現這個例子跟OllyDbg
.
exe還是有些不同,跟“調用門”的說法也有不同。這里實際上還是
跟DLL差不多的原理。下一步爭取實現一個跟OllyDbg
.
exe差不多的例子。
致謝:
感謝海風月影、北極星
2003
、默數悲傷所提供的思路。
源代碼和例子見附件。
http
:
//bbs.pediy.com/attachment.php?attachmentid=10475&d=1198157615