【问题标题】:CreateRemoteThread succeeded, but LoadLibrary failed for some target appCreateRemoteThread 成功,但某些目标应用的 LoadLibrary 失败
【发布时间】:2019-06-07 07:50:18
【问题描述】:

我正在使用 CreateRemoteThread() + LoadLibrary() 方法注入代码。 当我在我的 Windows7 64 位操作系统笔记本电脑上运行我的注入器时一切正常,并且对于某些目标应用程序,它仍然可以在 Windows Server 2012 R2 64 位中工作。

但是,在这个 Windows Server 2012 环境中,对于一些目标应用程序,它是旧的 MFC 应用程序,CreateRemoteThread 成功但 DllMain 没有被调用,我发现 LoadLibrary() 似乎失败了,通过使用 GetExitCodeThread()创建远程线程。

为了写入目标进程的内存,我计算了终止的0字节。

另外,我已经知道 kernel32.dll 地址对于 Windows 7 和 Windows Server 2012 是相同的,使用下面 URL 回答部分介绍的方法。

CreateRemoteThread fails,maybe the lpBaseAddress in the target process is invalid,but it is allocated by the system?

下面的 GetExitCodeThread() 的退出代码为零。

    HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)addr, arg, NULL, NULL);
    if(hThread == NULL) {
        OutputDebugString(_T("Error: the remote thread could not be created.\n"));
        writeLog("Error: the remote thread could not be created.");
    }
    else {
        DWORD dResult = WAIT_OBJECT_0;
        dResult = WaitForSingleObject(hThread, 1000*3);// the thread may already exited, so do not wait INFINITE
        DWORD dwExitCode = 0;
        GetExitCodeThread(hThread, &dwExitCode);
        if(dwExitCode == 0)
        {
            writeLog("Error: LoadLibraryA failed.");
        }
        else
        {
            OutputDebugString(_T("Success: the remote thread was successfully created.\n"));
            writeLog("Success: the remote thread was successfully created.");
        }
    }

你知道我接下来应该怀疑什么吗?

总而言之,在下图中,您可以看到唯一的失败是我在 Windows Server 2012 上运行注入器以注入一些旧的 MFC 应用程序。

在下图中,有关于 MFC 应用程序有多旧的信息:

我正在努力提供足够的信息,如果您需要更多信息,请告诉我。

下面是注入我的 dll 的完整代码:

void inject(int procID, char* pszHookDll)
{
    g_nTargetProcId = procID;
    HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
    g_hTargetProc = process;

    BOOL bInit = SymInitialize(g_hTargetProc, g_sPdbFolder, TRUE);// for analysing the information spy.dll send out

    if(process == NULL) {
        writeLog("Error: the specified process couldn't be found.");
    }
    /*
    * Get address of the LoadLibrary function.
    */
    LPVOID addr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
    if(addr == NULL) {
        writeLog("Error: the LoadLibraryA function was not found inside kernel32.dll library.");
    }
    //addr = getProcAddrInTargetProcess(procID, process);

    /*
    * Allocate new memory region inside the process's address space.
    */
    int nBufSize = strlen(pszHookDll)+1;
    LPVOID arg = (LPVOID)VirtualAllocEx(process, NULL, nBufSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if(arg == NULL) {
        writeLog("Error: the memory could not be allocated inside the chosen process.");
    }

    /*
    * Write the argument to LoadLibraryA to the process's newly allocated memory region.
    */
    int n = WriteProcessMemory(process, arg, pszHookDll, nBufSize, NULL);
    if(n == 0) {
        writeLog("Error: there was no bytes written to the process's address space.");
    }

    /*
    * Inject our DLL into the process's address space.
    */
    HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)addr, arg, NULL, NULL);
    if(hThread == NULL) {
        writeLog("Error: the remote thread could not be created.");
    }
    else {
        DWORD dResult = WAIT_OBJECT_0;
        dResult = WaitForSingleObject(hThread, 1000*3);
        DWORD dwExitCode = 0;
        GetExitCodeThread(hThread, &dwExitCode);
        if(dwExitCode == 0)
        {
            writeLog("Error: LoadLibraryA failed.");
        }
        else
        {
            OutputDebugString(_T("Success: the remote thread was successfully created.\n"));
            writeLog("Success: the remote thread was successfully created.");
        }
    }

    /*
    * Close the handle to the process, becuase we've already injected the DLL.
    */
    //CloseHandle(process);close after symcleanup
}

【问题讨论】:

  • 我假设您正在使用 WriteProcessMemory 和 VirtualAllocEx 将 LoadLibrary 参数写入目标内存。如果是这种情况,您能否发布其余的代码?另外,两个系统上的测试应用程序是否相同?您确定 LoadLibrary 签名是相同的(它没有被钩住或类似的东西)吗?您确定您没有尝试将 64 位编译的 DLL 加载到 32 位进程中吗?如果其他一切都失败了,我建议附加 x64dbg 并在 LoadLibrary(A,无论你调用哪个) 上放置一个断点,看看那里有什么。
  • 那里超出了字符限制,所以是新评论。您的 DLL 是否具有目标系统上可能不存在的任何依赖项?尤其是可再发行包以及您正在使用的其他任何东西都非常重要。在某些情况下,缺少这些可能会导致完全静默且无错误的注入失败。
  • 一个可能的罪魁祸首是将错误的文件路径传递给LoadLibrary()。请显示您传递给它的实际值。更糟糕的情况是,您可以在调用LoadLibrary()GetLastError() 的远程进程中分配整个函数,并将错误代码存储在您可以使用ReadProcessMemory() 读取的位置。此外,在调用WaitForSingleObject() 时,您应该使用无限超时。线程句柄在远程线程结束时发出信号。您需要等待结束才能致电GetExitCodeThread()。如果线程在你进入等待之前结束就可以了
  • 我发布了我的完整源代码。我只是无法理解:我可以将我的 dll 注入到我的 windows 7 操作系统上的旧式 MFC 应用程序和新式 MFC 应用程序中,但对于 windows Server 2012 上的旧式 mFC 应用程序却失败了..
  • 老实说,我发现依赖关系在这里是一个非常可能的问题,尤其是因为它是一个旧版本。您确定您已经设置了正确的目标平台,所有可再发行包/外部依赖项都存在或静态链接吗?您可以使用 /MT 来避免依赖外部可再发行包。除了@RemyLebeau 提到的,代码看起来还不错

标签: c++ dll loadlibrary createremotethread dllmain


【解决方案1】:

我明白了:这是一个依赖问题。

这里是spy.dll的依赖:

spy.dll 依赖于msvcr100d.dll,在我的 windows Server 2012 环境中默认不可用。

我提到的新 MFC 应用与msvcr100d.dll 一起部署在 Windows Server 2012 上,所以没有问题。

谢谢巴菲和雷米!!

【讨论】:

  • 很高兴看到你解决了它!请记住,msvcr100d.dll 用于调试版本,您可能希望部署为发布版本。
猜你喜欢
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多