因此,我只是读了一些有关如何将dll注入到Wikipedia上正在运行的程序中的知识(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。类似的问题是MessageBoxALoadLibrary都没有得到正确的地址,当我在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在