从exe加载exe

时间:2010-01-12 10:49:08

标签: visual-c++ winapi

我从C ++ exe导出函数[使用_declspec(dllexport)]。当exe本身调用时,该函数工作正常。我正在使用静态链接从另一个exe [测试项目的exe - 我将调用此exe2]加载此exe(让我们调用此exe1),即我在编译exe2时使用exe1的.lib文件,exe2在启动时将其加载到内存中任何dll。这会导致函数执行失败。

在函数中的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,我们有相应案例陈述的各种指令的地址。因此,jmp会将我们带到相关的案例指令

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]

现货出了什么问题? 指令地址。代码现在已加载到内存中的不同位置。编译exe1时,编译器假定我们将始终启动它,因此它将始终加载到0x0040000 [与所有Windows exes的情况一样]。因此它将40FFE0h等一些值硬编码到指令中。只有在第二种情况下,40FFE0和垃圾内存一样好,因为我们要查找的指令地址表不在那里。

如何在不将exe1转换为dll的情况下解决这个问题?

2 个答案:

答案 0 :(得分:1)

就是不要这样做。这不值得打扰。

我尝试过你刚才做的事情。您可以通过更改“Linker-> Advenced->固定基址”下的属性窗口中的选项来解决不可重定位的exe问题,但是您会遇到其他问题。
最终让我意识到浪费时间的事情就是意识到EXE没有DllMain()功能。这意味着CRT库没有被初始化,并且各种各样的东西都没有按照你期望的方式工作。

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

答案 1 :(得分:1)

您是否考虑过另一种方法?例如,当你想将第二个.exe用作可执行文件时,将第二个.exe转换为.dll并使用rundll32调用它?

否则: 生成的组件很好。问题是Win32可移植可执行文件有一个基地址(在这种情况下为0x0040000)和一个包含详细地址位置的部分,以便在需要时可以重新定位。

所以有两件事情发生了:    - 编译器在构建.exe时不包括IMAGE_BASE_RELOCATION记录。    - 或者,当动态加载.exe时,运行时没有执行基本重定位    - (可能两者)

如果.exe确实包含重定位记录,您可以自己读取它们并执行基本重定位。你必须跳过箍,比如确保你有对内存的写入权限(VirtualAlloc等),但它在概念上非常简单。

如果.exe不包含您填充的重定位记录 - 要么找到编译器选项以强制包含它们,要么找到另一种方法来执行您正在执行的操作。

编辑:正如shoosh指出的那样,一旦解决了这个问题,你可能会遇到其他问题。