当hModule和lpProcName有效时,GetProcAddress返回NULL

时间:2014-06-17 09:09:35

标签: c++ windows debugging winapi

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

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

的lpStartAddress创建一个remotethread

您可以在此处找到源代码: 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。

1 个答案:

答案 0 :(得分:1)

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

看起来,一个偶然的机会,注入过程的kernel32模块的基地址与远程进程中kernel32模块的基地址相同。

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