【问题标题】:C++ WriteProcessMemory error INVALID_HANDLE_VALUEC++ WriteProcessMemory 错误 INVALID_HANDLE_VALUE
【发布时间】:2014-10-10 09:27:00
【问题描述】:

我正在使用“CreateRemoteThread & WriteProcessMemory”技术将我的 dll 注入另一个进程。我的代码在 Windows 7,8 上运行良好,但 WriteProcessMemory 函数在 Windows XP(VirtualBox 机器)上运行时总是返回 FALSE(GetLastError = 6 - INVALID_HANDLE_VALUE)。你不能帮帮我吗? 以下是主要代码:

BOOL CHookDLL::DoHook(const DWORD dwProcessId, const CHAR* szDLLHookName)
{
    CHAR    szDllHookPath[1024] = "";
    HANDLE  hRemoteThread = NULL;
    HMODULE hLib = 0;
    LPVOID  RemoteString = NULL;
    LPVOID  LoadLibAddy = NULL;

    if (dwProcessId == NULL){
        __OutputDebug("CHookDLL::DoHook\tpProcessId NULL");
        return FALSE;
    }

    ::GetFullPathNameA(szDLLHookName, MAX_PATH, szDllHookPath, NULL);
    if (::PathFileExists((CString)szDllHookPath) == FALSE){
        __OutputDebug("CHookDLL::DoHook\tPathFileExists FALSE");
        return FALSE;
    }

    // enable SeDebugPrivilege
    if (!SetPrivilege(m_hTokenSetPrivilege, SE_DEBUG_NAME, TRUE))
    {
        __OutputDebug("CHookDLL::DoHook\tSetPrivilege FAILED");
        // close token handle
        CloseHandle(m_hTokenSetPrivilege);
        return FALSE;
    }
    m_hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if (m_hProcess == NULL){
        __OutputDebug("CHookDLL::DoHook\tOpenProcess FALSE: %d", GetLastError());
        return FALSE;
    }

    LoadLibAddy = (LPVOID)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "LoadLibraryA");

    if (LoadLibAddy == NULL){
        __OutputDebug("CHookDLL::DoHook\tGetProcAddress NULL");
        return FALSE;
    }
    // Allocate space in the process for our DLL 
    RemoteString = (LPVOID)VirtualAllocEx(m_hProcess, NULL, strlen(szDllHookPath) + 1,
        MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    if (RemoteString == NULL){
        __OutputDebug("CHookDLL::DoHook\tVirtualAllocEx NULL");
        return FALSE;
    }

        // this line is return FALSE
    if (WriteProcessMemory(m_hProcess, RemoteString, szDllHookPath, strlen(szDllHookPath) + 1, NULL) == FALSE)
    {
        __OutputDebug("CHookDLL::DoHook\tWriteProcessMemory FALSE: %d", GetLastError());
        return FALSE;
    }

    hRemoteThread = ::CreateRemoteThread(m_hProcess, NULL, NULL,
        (LPTHREAD_START_ROUTINE)LoadLibAddy,
        (LPVOID)RemoteString, NULL, NULL);

    ::WaitForSingleObject(hRemoteThread, INFINITE);

    // Get handle of the loaded module
    ::GetExitCodeThread(hRemoteThread, &m_hLibModule);
    if (m_hLibModule == NULL){
        __OutputDebug("CHookDLL::DoHook\tCreateRemoteThread NULL");
        return FALSE;
    }
    // Clean up
    ::CloseHandle(hRemoteThread);
    ::VirtualFreeEx(m_hProcess, RemoteString,
        strlen(szDllHookPath) + 1, MEM_RELEASE);

    __OutputDebug("Hook OK");
    return TRUE;
}

// Common function Output Debug String
static INT __OutputDebug(const CHAR* format, ...)
{
#ifndef DEBUG
    return -1;
#endif // DEBUG

    if (format[0] == 0) return -1;

    CHAR szDebug[1024] = "";

    va_list arglist;
    va_start(arglist, format);
    vsprintf_s(szDebug,format, arglist);
    va_end(arglist);
    strcat_s(szDebug, "\n");

    OutputDebugStringA(szDebug);
    return 1;
}

【问题讨论】:

  • 您已经验证句柄有效。所以你可能已经破坏了错误报告,摸索 GetLastError() 是一个非常常见的问题。我们看不到 __OutputDebug,请确保它不是宏。
  • 谢谢你的评论。 __OutputDebug 只是调用 API OutputDebugString 的常用函数。我只想解决为什么 WriteProcessMemory 返回 FALSE。你觉得呢?请给我你的想法。谢谢你。
  • 我在问题页脚中有 __OutputDebug 的邮政编码。
  • 好吧,不是这样。在“m_hProcess”上设置一个数据断点,这样你就可以看到它被覆盖了,这就是我能想到的。

标签: c++ winapi


【解决方案1】:

问题在于您的OpenProcess 电话。从这里:http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx,在PROCESS_ALL_ACCESS 下列出访问权限:

Windows Server 2003 和 Windows XP:在 Windows Server 2008 和 Windows Vista 上增加了 PROCESS_ALL_ACCESS 标志的大小。如果为 Windows Server 2008 和 Windows Vista 编译的应用程序在 Windows Server 2003 或 Windows XP 上运行,则 PROCESS_ALL_ACCESS 标志太大并且指定此标志的函数将失败并显示 ERROR_ACCESS_DENIED。要避免此问题,请指定操作所需的最小访问权限集。如果必须使用 PROCESS_ALL_ACCESS,请将 _WIN32_WINNT 设置为应用程序所针对的最低操作系统(例如,#define _WIN32_WINNT _WIN32_WINNT_WINXP)。有关详细信息,请参阅使用 Windows 标头。

因此,PROCESS_VM_READPROCESS_VM_OPERATION 可能没有设置,因此稍后会出现无效句柄错误。我知道如果 OpenProcess 失败了,它确实应该返回一个错误代码 - 但事实并非如此 - 但如果这个标志真的溢出,我可以看到一个静默失败是如何发生的。

【讨论】:

    猜你喜欢
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    相关资源
    最近更新 更多