如何在不链接kernel32.dll和ntdll.dll的情况下运行PE映像

时间:2011-09-20 07:30:10

标签: c++ c windows system

我试着写一个peloader。 我首先将可执行映像及其所有依赖的dll(包括kernel32.dll和ntdll.dll)加载到内存中,处理所有导入地址表,重写所有需要重定位的数据。

然后我按顺序调用所有图像的EntryPoint。 我从ntdll.dll的EntryPoint获得返回码0,但kernel32.dll返回0xC0000000。 当我试图调用可执行映像的EntryPoint时,程序崩溃了。

我知道Windows系统在创建进程时已经将ntdll.dll和kernel32.dll加载到进程内存中。 我的问题是如何将ntdll.dll和kernel32.dll的另一个副本加载到内存中,并将我的模块链接到副本。

我做了一个实验: 1.复制ntdll.dll - > A.DLL

  1. copy kernel32.dll - > B.DLL
  2. 修改PE图像文件b.dll使其不依赖于ntdll.dll而是依赖于a.dll
  3. 编写一个简单的程序a.exe,并修改PE映像文件a.exe,使其不依赖于kernel32.dll而是b.dll
  4. 运行a.exe,程序崩溃
  5. 是否可以正确运行a.exe?

    这是我关于堆栈溢出的第一个问题,抱歉我的英语不好。 感谢。

3 个答案:

答案 0 :(得分:3)

我认为你不能这样做。 kernel32.dll和ntdll.dll,AFAIK不可重定位。也就是说,MS从它们中删除了重定位信息,因为它们已经在每个进程中加载​​,因此它们的分配地址始终可用。

因此,如果您尝试将它们加载到不同的地址,那么它们会崩溃。理论上你可以尝试为他们重建重定位信息......但我不会赌它。

我的问题反过来是:为什么你不能使用预加载的kernel32 / ntdll?为什么你觉得你需要私人副本?我认为,您应该将它们视为系统API,因此不要管它们。

答案 1 :(得分:0)

在visual studio中将项目属性linker->input->Ignore All default libraries置于是。然后在c++->Code Generation->Basic Runtime Check中默认(以避免在__RTC_*中链接。然后在linker->Advanced->Entry Point中指定项目中要在程序启动时调用的函数。

构建所有内容,你应该有一个没有链接到任何库的程序,包括c-runtime。

答案 2 :(得分:0)

如果您希望在代码中使用自己的ntdll.dll(a.dll)版本,则可以使用Readfile()读取dll并解析要在代码中使用的PE结构。 例如:您可以解析导出名称表,导出序号表和导出地址表,以查找导出函数的指针,并在可执行文件中使用它。