標(biāo) 題:
【原創(chuàng)】讓EXE導(dǎo)出函數(shù)
作 者:
ylp1332
時(shí) 間: 2007-12-20,21:33 鏈 接: http://bbs.pediy.com/showthread.php?t=56840
初步搞定。
問(wèn)題來(lái)源: 偶然發(fā)現(xiàn)OllyDBG.exe導(dǎo)出了一堆函數(shù),這些函數(shù)都是供其插件調(diào)用的。對(duì)這種體系結(jié)構(gòu)很感 興趣,想弄清楚它的實(shí)現(xiàn)原理。后來(lái)又看到梁肇新的書(shū)《編程高手箴言》第278頁(yè)提到的調(diào)用 門(mén),覺(jué)得都應(yīng)該差不多。
三種不同的解決辦法(原理可能是一樣的,:)):
1)在導(dǎo)出函數(shù)聲明之前加上__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)在鏈接器參數(shù)中設(shè)置。例: #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)添加一個(gè)def文件,例: EXPORTS ?? Add??????? @1?? NONAME ?? Sub??????? @2?? NONAME ?? Mul??????? @3?? NONAME ?? Div??????? @4?? NONAME 另需要在鏈接器命令行參數(shù)中指定def文件名: /DEF:Callee.def 注意:在def文件中不要有 LIBRARY [library][BASE=address] 這樣的語(yǔ)句。
相比較而言,后兩種方法可以設(shè)置更多的參數(shù)。
函數(shù)舉例:
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); ?? }
}
編譯時(shí)會(huì)自動(dòng)生成相應(yīng)的導(dǎo)出庫(kù)(lib)文件,供調(diào)用者使用。
調(diào)用方法和普通的動(dòng)態(tài)鏈接庫(kù)調(diào)用一樣。 調(diào)用者必須能夠找到被調(diào)用者的位置,否則報(bào)錯(cuò),被調(diào)用者是否運(yùn)行不影響。
調(diào)用代碼舉例:
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中跟了一下,發(fā)現(xiàn)這跟調(diào)用動(dòng)態(tài)鏈接庫(kù)也差不多。 不過(guò)那幾個(gè)函數(shù)被映射到下面的地址處:
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
跟常規(guī)的動(dòng)態(tài)鏈接庫(kù)被映射到高地址處略有不同。 還不知道是什么原因。
結(jié)論: EXE完全可以和DLL一樣導(dǎo)出函數(shù),一樣被調(diào)用。
進(jìn)一步的工作: 我發(fā)現(xiàn)這個(gè)例子跟OllyDbg.exe還是有些不同,跟“調(diào)用門(mén)”的說(shuō)法也有不同。這里實(shí)際上還是 跟DLL差不多的原理。下一步爭(zhēng)取實(shí)現(xiàn)一個(gè)跟OllyDbg.exe差不多的例子。
致謝: 感謝海風(fēng)月影、北極星2003、默數(shù)悲傷所提供的思路。
|