2015-01-01 315 views
-1

所以我正在注入一个DLL到程序中。我可以通过Process Explorer的帮助来验证DLL是否被注入。注入后,我正在循环进程中的所有模块,比较名称并将注入的dll作为HMODULE返回。注入DLL不正确HMODULE

然后我GetProcAddress()这个HMODULE在里面找到一个extern函数,但是由于某些原因这个工作不正常。

HMODULE dllAddress = getModuleAddressFromProc(pid, "NewDll.dll"); 
externCreateThread createThread = (externCreateThread)GetProcAddress(dllAddress, "createThread"); 

当我断点和检查dllAddress它说:

enter image description here

当我使用LoadLibrary来加载DLL在我现有的程序和使用,作为一个HMODULE,它的工作。

HMODULE dllAddress = LoadLibrary(L"C:\\NewDll.dll"); 
externCreateThread createThread = (externCreateThread)GetProcAddress(dllAddress, "createThread"); 

设置断点检查dllAddress:

enter image description here

从HMODULES列表返回HMODULE是不一样的,从调用LoadLibrary的HMODULE。尽管指针地址是相同的。

列出过程中的所有模块是使用Microsoft提供的代码完成的。我修改了一下它来处理字符串比较,但这不影响HMODULE类型。

HMODULE getModuleAddressFromProc(DWORD pid, string moduleName) { 
    HMODULE hMods[1024]; 
    DWORD cbNeeded; 
    HMODULE output; 
    unsigned int i; 
    HANDLE newHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); 
    if (EnumProcessModules(newHandle, hMods, sizeof(hMods), &cbNeeded)) { 
     for (i = 0; i < (cbNeeded/sizeof(HMODULE)); i++) { 
      TCHAR szModName[MAX_PATH]; 
      if (GetModuleFileNameEx(newHandle, hMods[i], szModName, sizeof(szModName)/sizeof(TCHAR))) { 
       string s2 = charToString(szModName); 
       if (s2.find(moduleName) != string::npos) { 
        output = hMods[i]; 
        break; 
       } 
      } 
     } 
    } 
    return output; 
} 

回答

0

你可以得到另一个进程中加载​​的DLL的HMODULE,但你不能用它从你的过程中得到的是HMODULE的过程的地址。

这是由于Windows中的每个进程都有自己的内存空间。因此,在不同进程中加载​​的同一个DLL的HMODULE值每次都几乎肯定不同。因此,一旦您在另一个进程中获得DLL的HMODULE并调用GetProcAddress(..),Windows就会在您的应用程序的内存中查找,而不在其他进程的内存中。由于HMODULE在您的应用程序中无效GetProcAddress(..)将失败。

如果你想在另一个进程的上下文中调用函数,你必须使用某种interprocess communication。要做到这一点,你必须在另一个进程中运行一个线程来处理这些IPC(我猜createThread应该这样做)。

要做到这一点,你可以用你的注入DLL的DllMain(..)函数来执行一些代码(如通话功能createThread(..)):

BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module 
        DWORD fdwReason,  // reason for calling function 
        LPVOID lpReserved) // reserved 
{ 

    switch(fdwReason) 
    { 
     case DLL_PROCESS_ATTACH: 
     createThread(..); 
     break; 

     case DLL_THREAD_ATTACH: 
     // Do thread-specific initialization. 
     break; 

     case DLL_THREAD_DETACH: 
     // Do thread-specific cleanup. 
     break; 

     case DLL_PROCESS_DETACH: 
     // Perform any necessary cleanup. 
     break; 
    } 

    return (TRUE); 
} 
+0

是的,我最初尝试过,但似乎你不能从DllMain创建一个线程,因为它打破了程序。所以我去寻找一种方法。 – user616396

+0

您可以按照MSDN的规定(由我多次完成)在'DllMain'内创建线程。唯一的区别是线程不会立即启动,而是在完成dll的加载之后。您是否尝试过一个非常简单的线程进行测试(例如每秒钟用MessageBox/MessageBeep进行一次(1))? –

+0

我试过从DllMain的一个不结束的while循环,注入DLL的程序冻结直到while循环被转义。我尝试了CreatThread()并杀死了程序。 编辑:DllMain在装载机锁持有时运行。 – user616396