我试着写一个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
是否可以正确运行a.exe?
这是我关于堆栈溢出的第一个问题,抱歉我的英语不好。 感谢。
答案 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结构。 例如:您可以解析导出名称表,导出序号表和导出地址表,以查找导出函数的指针,并在可执行文件中使用它。