如何使用 GetExitCodeThread 或其他 Windows Api 获取 64 位 exitCode

问题描述 投票:0回答:1

我试图在将dll注入到远程进程后卸载它,我使用CreateRemoteThread在该远程进程中调用“LoadLibraryA”,这意味着线程函数是“LoadLibraryA”。现在,我使用“GetExitCodeThread”来获取线程的退出代码。

代码片段:

    // create remote thread to invoke LoadLibraryA
    HANDLE tThread = CreateRemoteThread(remoteProcess, NULL, 0, LoadLibraryAAddr, remoteAddress, 0, NULL);
    if (!tThread) {
        cout << "failed to create remote thread" << endl;
        return 1;
    }

    // wait for remote thread stop
    HMODULE exitCode;
    WaitForSingleObject(tThread, INFINITE);
    cout << "successfully load library" << endl;
    
    GetExitCodeThread(tThread, (LPDWORD)&exitCode);

    // clean up, call FreeLibrary to unload dll
    LPTHREAD_START_ROUTINE freeLibraryAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
    if (NULL == freeLibraryAddr) {
        cout << "failed to get freeLibrary address" << endl;
        return 1;
    }

“GetExitCodeThread”声明:

BOOL GetExitCodeThread(
  [in]  HANDLE  hThread,
  [out] LPDWORD lpExitCode
);

document for GetExitCodeThread from ms

根据文档的描述,lpExitCode应该取“LoadLibraryA”的返回值,即“LoadLibraryA”加载的dll的基地址。然后我创建另一个远程进程来调用“FreeLibrary”来卸载这个dll,但失败了。

经过调试,我发现了问题:lpExitCode只保存了“LoadLibraryA”返回的低32位值。

runtime value of exitCode

高32位是0xcccccccc,因为变量“exitCode”在栈中,是用0xcc初始化的。这个结果很容易解释:“lpExitCode”的类型是LPDWORD,它是一个指向32位值的指针,因此它只能影响“exitCode”的低32位

一开始的代码在x86环境下运行得很好,因为x86环境下的地址是32位长,可以正确传递。但是,我在 x64 环境中运行它,“exitCode”仅获取 dll 基地址的低 32 位,然后传递给 FreeLibrary 并导致调用失败。结果,dll仍然位于该远程进程的内存中,这与我的预期不符。

那么有没有办法使用GetExitCodeThread或其他一些windows api来获取64位retuen值,希望有人能回复。

dll-injection
1个回答
0
投票
HMODULE getTargetModuleBase(HANDLE processHandle, string targetModuleName) {
    // get all moduels in the process
    HMODULE moduleHandleList[1024];
    DWORD cbNeeded;
    BOOL ret = EnumProcessModules(processHandle, moduleHandleList, sizeof(moduleHandleList), &cbNeeded);
    if (!ret) {
        cout << "failed to enum process modules" << endl;
        return NULL;
    }
    if (cbNeeded > sizeof(moduleHandleList)) {
        cout << "to many modules" << endl;
        return NULL;
    }
    DWORD processCount = cbNeeded / sizeof(HMODULE);
    // traverse to find target module
    char moduleName[1024];
    for (DWORD i = 0; i < processCount; i++) {
        GetModuleBaseNameA(processHandle, moduleHandleList[i], moduleName, 1024);
        if (!strncmp(targetModuleName.c_str(), moduleName, targetModuleName.size())) {
            return moduleHandleList[i];
        }
    }
    return NULL;
}

使用EnumProcessModules和GetModuleBaseNameA遍历并比较已加载模块的名称,可以找到目标模块并返回其baseAddress,然后将baseAddress传递给freeLibrary以卸载模块。

上面的代码只是一个简单的例子,如果没有一些错误句柄,moduleHandleList和moduleHandleList在保存结果时可能会超出范围,请注意。您可以检查 EnumProcessModules 和 GetModuleBaseNameA 的返回值来决定是否使用更大的数组再次调用这些 api。

© www.soinside.com 2019 - 2024. All rights reserved.