2010-01-12 98 views
3

我從C++ exe導出函數[使用_declspec(dllexport)]。該函數在由exe本身調用時工作正常。我正從另一個exe文件(測試項目的exe文件 - 我將調用這個exe2文件)加載這個exe文件(讓我們調用這個exe1文件),使用靜態鏈接,例如我使用exe1的.lib文件,同時編譯exe2和exe2,在啓動時將它加載到內存中,就像任何DLL。這會導致函數執行失敗。從exe加載exe

確切的問題是在反彙編函數中的switch case語句中顯示的。

彙編代碼時EXE1調用函數

switch (dwType) 
0040FF84 mov   eax,dword ptr [dwType] 
0040FF87 mov   dword ptr [ebp-4],eax 
0040FF8A cmp   dword ptr [ebp-4],0Bh 
0040FF8E ja   $LN2+7 (40FFD2h) 
0040FF90 mov   ecx,dword ptr [ebp-4] 
0040FF93 jmp   dword ptr (40FFE0h)[ecx*4] 

考慮的最後兩個指令。 mov將傳入的參數移動到ecx中。在40EFF0h處,我們提供了相應案例陳述的各種說明。因此,當EXE2調用函數

switch (dwType) 
0037FF84 mov   eax,dword ptr [dwType] 
0037FF87 mov   dword ptr [ebp-4],eax 
0037FF8A cmp   dword ptr [ebp-4],0Bh 
0037FF8E ja   $LN2+7 (37FFD2h) 
0037FF90 mov   ecx,dword ptr [ebp-4] 
0037FF93 jmp   dword ptr [ecx*4+40FFE0h] 

點什麼出錯的JMP將帶我們到相關情況的說明,

彙編代碼? 該指令地址爲。該代碼現在已被加載到內存中的不同位置。當編譯exe1時,編譯器認爲我們將始終啓動它,因此它總是會在0x0040000加載[與所有windows exes一樣]。因此它將40FFE0h這樣的一些值硬編碼到指令中。只有在第二種情況下,40FFE0和垃圾內存一樣好,因爲我們正在尋找的指令地址表不在那裏。

我該如何解決這個問題,而無需將exe1轉換爲dll?

回答

1

只是不這樣做。它不值得費心。

我已經嘗試了你剛剛嘗試的內容。您可以通過更改「Linker-> Advenced-> Fixed base address」下的屬性窗口中的選項來解決不可重定位的exe問題,但是您會遇到其他問題。
最終讓我意識到浪費時間的事情是意識到EXE沒有DllMain()函數。這意味着CRT庫沒有被初始化,並且各種各樣的東西不能按照您期望的方式工作。

Here's the question I posted about this a while back

+0

試圖做同樣的事情,並得出同樣的結論。 – Chad 2013-08-17 12:30:32

1

你有沒有考慮這樣做的另一種方式?如將第二個.exe文件製作成.dll文件,並將其作爲可執行文件使用時使用rundll32進行調用?

否則: 生成的程序集很好。問題是Win32可移植可執行文件有一個基地址(在這種情況下是0x0040000)和一個包含地址詳細信息位置的部分,以便在需要時可以對其進行重定位。

因此,有兩件事發生: - 編譯器在構建.exe時不包括IMAGE_BASE_RELOCATION記錄。 - 或運行時間不進行基址重定位時dynamiclaly加載.EXE - (可能兩者)

如果.exe文件確實包含搬遷記錄,你可以閱讀和執行基地搬遷自己。你必須像確保你有寫訪問內存(VirtualAlloc等)一樣跳過,但它在概念上很簡單。

如果.exe不包含您被塞滿的重定位記錄 - 或者找到一個編譯器選項來強制它們包含,或者找到另一種方法來做你正在做的事情。

編輯:shoosh指出,你可能會遇到其他問題,一旦你解決這個問題。