CreateRemoteThread
的想法)。我按照所述的步骤进行操作,最终使其正常工作。我发现有趣的事情虽然花了一些时间才弄清楚如下:当创建我的远程线程并发送函数时,我希望以第一个/开始的方式运行,但是遇到了障碍,但运行失败为了调用适当的功能,当我在OllyDBG中查看它们时,它们似乎变成了垃圾,从而导致程序崩溃了。我当时使用的代码大致如下:static DWORD __stdcall inject(LPVOID threadParam)
{
MessageBoxA(NULL, "test", "test", NULL);
LoadLibrary("my.dll");
return 0;
}
以及其他地方:
CreateRemoteThreadEx(hProcess, NULL, 0, LPTHREAD_START_ROUTINE(fnPageBase), dbPageBase, 0, NULL, &threadId);
fnPageBase
是我在要为函数注入的过程中分配的内存,而dbPageBase是我分配给作为LPVOID threadParam
传递的结构的内存的dbPageBase。类似的问题是MessageBoxA
和LoadLibrary
都没有得到正确的地址,当我在OllyDBG中检查它们时,它们总是指向不存在的东西。我在Google上搜索了一下,发现我应该使用GetProcAddr
来获得一个地址,即:LoadLibrary
,以后可以通过在LPVOID threadParam
调用中通过inject()
发送一些数据来使用它。所以我的问题是:为什么当我使用GetProcAddr
而不是当我只是尝试“正常”使用它时,它为什么起作用?使用该地址时,我是否会获得始终映射到内存中同一区域中每个人的某些特定地址? 另外,我在
inject()
函数中的字符串会怎样?它们在编译过程中是否移到其他地方,从而使它们无法用于我正在注入的程序,因为它位于内存的完全不同的位置(即,它没有映射到那里)?我通过将它与LPVOID threadParam
一起发送到一个结构中来解决该问题,该结构已经复制到我要注入的.exe
可用的内存中。 如果您需要有关我如何处理其他部分的更多信息,请告诉我,我会进行更新。
#1 楼
您需要记住的一件事是,流程中的代码和目标流程中的代码位于不同的地址空间中。因此,程序中的任何地址在目标进程中都是不必要的,反之亦然。这意味着您注入的代码无法对函数或变量的地址进行任何假设。即使你
inject
函数的地址,只在你的进程有效;要使其在目标过程中可用,您必须:1)在此处复制代码;和2)确保所引用的任何函数或内存地址在新地址空间中均有效。这就是为什么与CreateRemoteThreadEx
一起使用的常规方法是将DLL名称复制到目标进程并创建线程使用LoadLibrary
函数的地址:// 1. Allocate memory in the remote process for szLibPath
pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath),
MEM_COMMIT, PAGE_READWRITE );
// 2. Write szLibPath to the allocated memory
::WriteProcessMemory( hProcess, pLibRemote, (void*)szLibPath,
sizeof(szLibPath), NULL );
// Load "LibSpy.dll" into the remote process
// (via CreateRemoteThread & LoadLibrary)
hThread = ::CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE) ::GetProcAddress( hKernel32,
"LoadLibraryA" ),
pLibRemote, 0, NULL );
(来自Code Project的片段)
您可以看到
pLibRemote
(地址为目标进程中的DLL名称)作为参数传递给线程例程。因此,此结果等效于:LoadLibraryA(pLibRemote);
在目标进程中执行。
严格来说,这不能保证能正常工作,因为您进程中的
LoadLibraryA
的地址不一定与其他进程中的LoadLibraryA
相同。但是,实际上它确实起作用,因为诸如kernel32(LoadLibraryA
所在的系统)之类的系统DLL在所有进程中都映射到相同的地址,因此LoadLibraryA
在两个进程中也具有相同的地址。
评论
因此,从理论上讲,即使使用GetProcAddr,我们也可能出错并没有获得正确的地址?另外,如果&LoadLibraryA都映射到相同的区域,为什么也不能给出一个好的地址?应该将其作为单独的问题发布在其他地方还是可以在这里提问?
–lfxgroove
2013年9月15日在8:46
&LoadLibraryA可能会返回指向您进程中的导入存根的指针,而不是返回kernel32.dll中的最终地址的指针。
–伊戈尔·斯科钦斯基♦
2013年9月15日12:30在
我认为,如今随着进程空间随机化,您甚至不能指望kernel32被映射到相同的地址...它在win7 / 8中是否仍然有效?
–洛伦佐·德马特(LorenzoDematté)
2013年9月16日13:18在
@LorenzoDematté:kernel32的AFAIK加载地址在每次引导时都是随机的,但之后保持不变。
–伊戈尔·斯科钦斯基♦
2013年9月16日13:38在
@ 0xC0000022L:我没有开始编写涵盖每个角落情况的DLL注入的详细指南,我只是想回答所述问题(并添加了一些背景知识)。如果我有任何具体错误,请指出。
–伊戈尔·斯科钦斯基♦
2013年9月17日20:22在