【问题标题】:CreateRemoteThread returns NULL while trying to use it to inject dllCreateRemoteThread 在尝试使用它注入 dll 时返回 NULL
【发布时间】:2020-03-14 21:26:29
【问题描述】:

这是一些代码,它应该注入我的 DLL 并在 notepad.exe 中运行它,但正如标题所述,CreateRemoteThread 调用返回 null MyGetProcessId 工作得很好我做了它并检查了它的结果,看看 pid 是否正确。

#define DLL_PATH "C:\\Users\\tkina\\Desktop\\3\\Dll1\\Debug\\Dll1.dll"
#include <Windows.h>
#include <iostream>
#include <tlhelp32.h>

DWORD MyGetProcessId(LPCTSTR ProcessName);

int main()
{
    TCHAR Buffer[MAX_PATH];
    DWORD err;

    // Get full path of DLL to inject
    DWORD pathLen = GetFullPathName(TEXT("mydll.dll"), MAX_PATH, Buffer, NULL);
    PVOID addrLoadLibrary = (PVOID)GetProcAddress(GetModuleHandle(Buffer), "LoadLibraryA");
    DWORD pID = MyGetProcessId(TEXT("Notepad.exe"));
    // Open remote process
    HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
    if (!proc)
    {
        std::cout << "Could not open the process!\n";
        system("pause");
    }
    // Get a pointer to memory location in remote process,
    // big enough to store DLL path
    PVOID memAddr = (PVOID)VirtualAllocEx(proc, 0, strlen(DLL_PATH)+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (NULL == memAddr) {
        err = GetLastError();
        return 0;
    }
    // Write DLL name to remote process memory
    BOOL check = WriteProcessMemory(proc, memAddr, (LPVOID)DLL_PATH, strlen(DLL_PATH) + 1, NULL);
    if (0 == check) {
        err = GetLastError();
        return 0;
    }
    // Open remote thread, while executing LoadLibrary
    // with parameter DLL name, will trigger DLLMain
    HANDLE hRemote = CreateRemoteThread(proc, 0, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("Kernel32.dll"),
        "LoadLibraryA"), (LPVOID)memAddr, 0,0);
    if (NULL == hRemote) {
        err = GetLastError();
        return 0;
    }
    WaitForSingleObject(hRemote, INFINITE);
    check = CloseHandle(hRemote);
    VirtualFreeEx(proc, memAddr, strlen(DLL_PATH) + 1, MEM_RELEASE);
    system("pause");
    return 0;
}

GetLastError 的调用返回 5。

【问题讨论】:

  • GetLastError返回的错误是什么?
  • Error 5 被拒绝访问。您是否拥有所有正确的权限?
  • 已编译 DLL 的路径表明您正在构建 32 位版本。如果您使用的是 64 位 Windows,则 notepad.exe 也是 64 位的。你不能混合 32/64 位。
  • @rustyx 我不知道你的意思是我在 VS 上构建了一个基本的 dll 我不知道它在 64 位 Windows 10 上是 64 位还是 32 位

标签: c++ windows


【解决方案1】:

函数CreateRemoteProcesslpStartAddress参数需要目标进程(notepad.exe)的virtual address space中的函数地址。但是,您在注入程序的地址空间中传递了此函数的地址。

如果函数的地址在两个进程的虚拟地址空间中相同,这将不是问题。在当前版本的 Windows 中,kernel32.dll 被加载到所有 32 位进程的相同地址,并且它也被加载到所有 64 位进程的相同地址。但是,它加载到的地址对于 32 位和 64 位进程是不同的。因此,如果一个进程是32位,另一个是64位,那么kernel32.dll中函数LoadLibraryA的地址也会不同。

通过将LoadLibraryA 在其自己的地址空间中的地址传递给对CreateRemoteThread 的调用,您的注入程序假定kernel32.dll 在其地址空间和目标程序(notepad.exe)。然而,如上所述,这个假设只有在两个进程都是 32 位或都是 64 位时才成立。

根据您在 cmets 部分中的 cmets 判断,您的注入程序似乎是 32 位的,而目标进程 (notepad.exe) 是 64 位的。因此,要解决此问题,您应该将 Visual Studio 中的构建目标从“x86”(32 位)更改为“x64”(64 位)。

另一个问题是您要注入的 DLL 也必须是 64 位的。如this StackOverflow question 所述,无法将 32 位 DLL 作为可执行代码加载到 64 位进程中。

【讨论】:

    猜你喜欢
    • 2012-03-16
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    相关资源
    最近更新 更多