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

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

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

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

我做了一个实验:1.复制ntdll.dll – > a.dll

  1. 复制kernel32.dll – > b.dll
  2. 修改PE映像文件b.dll,使其不依赖于ntdll.dll而是a.dll
  3. 编写一个简单的程序a.exe,并修改PE映像文件a.exe,使其不依赖于kernel32.dll而是b.dll
  4. 运行一个.exe,程序崩溃

是否有可能使a.exe正常运行?

这是我第一个关于堆栈溢出的问题,对不起我的英文不好。 谢谢。

Solutions Collecting From Web of "如何在不连接kernel32.dll和ntdll.dll的情况下运行PE映像"

我不认为你可以做到这一点。 kernel32.dll和ntdll.dll,AFAIK不可重定位。 也就是说,MS从他们那里删除了重定位信息,因为由于它们已经在每个进程中被加载,所以它们的分配地址总是可用的。

所以,如果你试图把它们加载到不同的地址,那么它们会崩溃。 你理论上可以尝试重建他们的重新安置信息…但我不会赌它。

我的问题依次是:为什么你不能使用预加载的kernel32 / ntdll? 你为什么觉得你需要私人副本? 正如我所看到的,你应该把它们看作是系统API,所以不要管它们。

在Visual Studio中,将项目属性linker->input->Ignore All default libraries放入yes。 然后在c++->Code Generation->Basic Runtime Check默认(避免链接在__RTC_* 。然后在链接器 – linker->Advanced->Entry Point你指定一个函数在你想要被调用的程序启动时。

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

如果你想在你的代码中使用你自己的ntdll.dll(a.dll)版本,那么你可以使用Readfile()来读取DLL并解析你的代码中使用的PE结构。 例如:您可以解析导出名称表,导出序号表和导出地址表来查找指向导出函数的指针,并在您的可执行文件中使用相同的指针。