c++ - 当 hModule 和 lpProcName 有效时 GetProcAddress 返回 NULL

标签 c++ windows debugging winapi

我最近开始了一个新项目,我的目标是将字节码注入(inject)另一个进程,然后启动一个远程线程执行我的字节码,但是我遇到了一个非常奇怪的问题。

它的作用是分配并写入任意进程的内存,它为远程进程写入一个包含指向 user32.dll 和 kernel32.dll 中函数的指针的结构体,它还为函数指针写入一个调用操作然后,它从该结构中创建一个带有“调用操作”的 lpStartAddress 的远程线程

您可以在这里找到源代码: http://pastie.org/9298306

在第 55 行调用 GetPrivileges(第 185 行的方法),它返回 true,这意味着 OpenProcessToken、LookupPrivilegeValue 和 AdjustTokenPrivileges 返回 true。

不久之后将调用以下内容:

param->pMessageBox = (DWORD)GetProcAddress(user32, "MessageBoxA");
param->pSleep = (DWORD)GetProcAddress(kernel32, "Sleep");

user32 和 kernel32 都是有效句柄,但 param->pMessageBox 将被设置为 NULL,而 param->pSleep 将获取 Sleep 的实际指针。

奇怪的是,当我用我在线复制的代码片段替换 GetPrivileges 时,它工作正常,并且 param->pMessageBox 将设置为正确的指针地址。

BOOL GetPrivileges()
{
  HANDLE tokenHandle;
  TOKEN_PRIVILEGES tokenPriv;

  if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &tokenHandle) != 0)
  {
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tokenPriv.Privileges[0].Luid);
    tokenPriv.PrivilegeCount = 1;
    tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(tokenHandle, 0, &tokenPriv, sizeof(tokenPriv), NULL, NULL);
  }
  else
  {
    TCHAR buffer[256];    
    wsprintf(buffer, TEXT("0x%x"), GetLastError());
    MessageBox(NULL, buffer, TEXT("OpenProcessTokenError"), MB_ICONERROR);

    return FALSE;
  }

  return true;
}

继续进行调试,请注意,由于 OpenProcessToken 按预期返回 true,因此不会调用复制的 GetPrivileges 中的 else 语句,并删除:

TCHAR buffer[256];    
wsprintf(buffer, TEXT("0x%x"), GetLastError());

param->pMessageBox 将设置为 NULL,怎么可能?

向沮丧的 ogelami 致敬。

最佳答案

模块句柄实际上无效。它们是远程进程的模块句柄。模块句柄实际上是作为基地址实现的,因此仅对执行进程的虚拟地址空间有意义。

碰巧,注入(inject)进程的kernel32模块的基地址与远程进程的kernel32模块的基地址相同。

实际上,如果您在注入(inject)过程中放入如此多的代码,您的目标将很难实现。如果将 DLL 注入(inject)到其他进程中,情况会更好。创建一个远程线程,其第一步是加载此 DLL。然后,您将在另一个进程的地址空间内运行代码,因此能够直接调用 GetModuleHandleGetProcAddress 等函数。

关于c++ - 当 hModule 和 lpProcName 有效时 GetProcAddress 返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24259796/

相关文章:

c# - 在类型初始值设定项中调试异常

android - 使用 SSL 和 SQL 支持为 Android 构建 Qt 5.12 LTS

windows - 批处理脚本循环变量

mysql - 在数据库上执行SQL触发器以限制删除/更改/创建语法错误,尽管按照以下教程进行操作,但ON在此位置无效吗?

windows - 在 windows 上与 node.js 或 karma 或其他任何东西一起使用时如何多次使用 cmd

c++ - GetWindowPlacement 给出了不正确的窗口位置

php - 如何在 Netbeans 中调试 PHP 测试文件

c++ - 解析 mmap()-ed 文件

c++ - 是否有可用于 C++ 的广泛使用的多处理抽象库?

c++ - Visual Studio 2008 编译器不会在 C++ 中使用 sqrt 自动转换为 double 吗?