【问题标题】:CreateRemoteThread returning ERROR_ACCESS_DENIED - Windows 7 DLL InjectionCreateRemoteThread 返回 ERROR_ACCESS_DENIED - Windows 7 DLL 注入
【发布时间】:2012-03-16 09:46:11
【问题描述】:

我正在尝试编写一个使用 CreateRemoteThread 注入 dll 的程序。

问题是 CreateRemoteThread 拒绝工作。 GetLastError() 返回 5,即 ERROR_ACCESS_DENIED。我不知道为什么!

我正在观看此视频http://www.youtube.com/watch?v=H3O3hmXkt1I

#include <iostream>
#include <direct.h>
#include <Windows.h>
#include <TlHelp32.h>

using namespace std;


char* GetCurrentDir()
{
    char*   szRet = (char*)malloc(MAX_PATH);
    _getcwd(szRet, MAX_PATH);
    return szRet;
}

LPCTSTR SzToLPCTSTR(char* szString)
{
    LPTSTR  lpszRet;
    size_t  size = strlen(szString)+1;

    lpszRet = (LPTSTR)malloc(MAX_PATH);
    mbstowcs_s(NULL, lpszRet, size, szString, _TRUNCATE);

    return lpszRet;
}

void WaitForProcessToAppear(LPCTSTR lpcszProc, DWORD dwDelay)
{
    HANDLE          hSnap;
    PROCESSENTRY32  peProc;
    BOOL            bAppeared = FALSE;

    while(!bAppeared)
    {
        if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE)
        {
            peProc.dwSize = sizeof(PROCESSENTRY32);
            if(Process32First(hSnap, &peProc))
                while(Process32Next(hSnap, &peProc) && !bAppeared)
                    if(!lstrcmp(lpcszProc, peProc.szExeFile))
                        bAppeared = TRUE;
        }
        CloseHandle(hSnap);
        Sleep(dwDelay);
    }
}

DWORD GetProcessIdByName(LPCTSTR lpcszProc)
{
    HANDLE          hSnap;
    PROCESSENTRY32  peProc;
    DWORD           dwRet = -1;

    if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE)
    {
        peProc.dwSize = sizeof(PROCESSENTRY32);
        if(Process32First(hSnap, &peProc))
            while(Process32Next(hSnap, &peProc))
                if(!lstrcmp(lpcszProc, peProc.szExeFile))
                    dwRet = peProc.th32ProcessID;
    }
    CloseHandle(hSnap);

    return dwRet;
}

BOOL InjectDll(DWORD dwPid, char* szDllPath)
{
    DWORD   dwMemSize;
    HANDLE  hProc;
    LPVOID  lpRemoteMem, lpLoadLibrary;
    BOOL    bRet = FALSE;

    if((hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid)) != NULL)
    {
        dwMemSize = strlen(szDllPath);
        if((lpRemoteMem = VirtualAllocEx(hProc, NULL, dwMemSize, MEM_COMMIT, PAGE_READWRITE)) != NULL)
            if(WriteProcessMemory(hProc, lpRemoteMem, szDllPath, dwMemSize, NULL))
            {
                lpLoadLibrary = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
                if(CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadLibrary, lpRemoteMem, 0, NULL) != NULL)
                {
                    bRet = TRUE;
                }
                cout << GetLastError();
            }
    }
    CloseHandle(hProc);

    return bRet;
}

int main()
{
    char    szProc[MAX_PATH], szDll[MAX_PATH];
    char*   szDllPath = (char*)malloc(MAX_PATH);
    LPTSTR  lpszProc = NULL;

    for(;;)
    {
        cout << "Process: ";
        cin >> szProc;
        cout << "DLL: ";
        cin >> szDll;

        szDllPath = GetCurrentDir();
        strcat_s(szDllPath, MAX_PATH, "\\");
        strcat_s(szDllPath, MAX_PATH, szDll);

        cout << "Waiting for process.. ." << szDllPath << " " << szDll << endl;
        WaitForProcessToAppear(SzToLPCTSTR(szProc), 100);
        if(InjectDll(GetProcessIdByName(SzToLPCTSTR(szProc)), szDllPath))
            cout << "Injection Succeeded!" << endl;
        else
            cout << "Injection Failed!" << endl;
        cout << "\n";

    }

    return 0;

经过大量谷歌搜索后,我找不到这不起作用的原因。

CreateRemoteThread 在 Windows 7 下不能工作吗? 如果是这样,我是否犯了任何明显的错误?

【问题讨论】:

  • 这段代码有很多bug。最相关的是调用 GetLastError,即使您没有从 api 函数获得 FALSE 返回。
  • 我认为您还应该确保以管理员身份运行您的东西,而不是作为普通用户,因为 UAC 可能会干扰注入过程。
  • 一个与访问相关的问题是您不应该用PROCESS_ALL_ACCESS 调用OpenProcess。使用所需的最低访问权限集调用它。这背后的原因记录在这里:msdn.microsoft.com/en-us/library/windows/desktop/…

标签: winapi dll windows-7 code-injection createremotethread


【解决方案1】:

失败的原因是你的代码是 32 位的,而你的目标进程是 64 位的。

您拥有多少特权并不重要。 Windows 不会让这种情况发生。

我遇到了同样的问题。要么你生成一个系统 32 位 exe 并注入它,要么将你的代码移植到 64 位(这意味着它不能在 32 位系统上运行)。

编辑

很久以前,我发现了一种将代码注入任何处理器模式目标的好方法。它涉及将处理器模式动态切换到(任何)目标的模式。被称为“天堂之门”。为此,您必须使用内联汇编。所以基本上你可以在 32 位 exe 中同时拥有 64 位和 32 位代码,检测机器是否为 64 位,然后跳转到 64 位模式并运行 64 位代码。然后,您将遍历导入以找到 ntdll 并加载 64 位 kernel.dll 和其他库。以下是任何感兴趣的人的示例链接:http://bit.ly/19P0Lh3

【讨论】:

  • 为什么要使用内联汇编??你可以用Wow64DisableWow64FsRedirection
  • Wow64DisableWow64FsRedirection 会产生更多问题,尤其是在生成进程时。毕竟,它只能从 XP Pro 获得。 64 位。低于该值的任何东西都行不通。这种方法已经存在了一段时间。 Wow64DisableWow64FsRedirection 无论如何都不会让您在 32 位中执行 64 位代码。这只是一个文件系统重定向。在此处阅读 cmets:msdn.microsoft.com/en-us/library/windows/desktop/…
【解决方案2】:

我看到的直接问题是您没有获得应该这样做的访问令牌:

HANDLE hToken; 
TOKEN_PRIVILEGES tp; 
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() ); 

tp.PrivilegeCount = 1; 
LookupPrivilegeValue( NULL, _T("SeDebugPrivilege"), &tp.Privileges[0].Luid ); 
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken ); 

AdjustTokenPrivileges( hToken, FALSE, &tp, NULL, NULL, NULL ); 
CloseHandle( hToken );

我现在没有时间查看您的所有代码,但这是我从以前的一个项目中摘录的内容:

// returns open process handle
HANDLE InjectDLL( DWORD dwPID, LPCWSTR szDLLPath, HMODULE* lphInjected ) {
  int     cszDLL;
  LPVOID  lpAddress;
  HMODULE hMod;
  HANDLE  hThread;
  HANDLE  hProcess = OpenProcess( PROCESS_CREATE_THREAD | 
      PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION |
      PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwPID );

  if( hProcess == NULL ) {
    return NULL;
  }

  cszDLL = ( wcslen( szDLLPath ) + 1 ) * sizeof( WCHAR );

  // Injection
  lpAddress = VirtualAllocEx( hProcess, NULL, cszDLL, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
  if( lpAddress == NULL ) {
    return NULL;
  }

  WriteProcessMemory( hProcess, lpAddress, szDLLPath, cszDLL, NULL );

  hMod = GetModuleHandle( L"kernel32.dll" );
  if( hMod == NULL ) {
    return NULL;
  }

  hThread = CreateRemoteThread( hProcess, NULL, 0,
        (LPTHREAD_START_ROUTINE)( GetProcAddress( hMod,
        "LoadLibraryW" ) ), lpAddress, 0, NULL );

  // Locate address our payload was loaded
  if( hThread != 0 ) {
    WaitForSingleObject( hThread, INFINITE );
    GetExitCodeThread( hThread, ( LPDWORD )lphInjected );
    VirtualFreeEx( hProcess, lpAddress, 0, MEM_RELEASE );
    CloseHandle( hThread );
  }

  return hThread != 0 ? hProcess : NULL;
}

看看有没有帮助。以后再看。

【讨论】:

    【解决方案3】:

    好的,由于“受保护的进程”,您的代码可能会在 Windows 7 和 Vista 中失败,即只能由其他受保护进程(如 explorer.exe 等)操作的进程...在 Windows 7 x32有一种方法:因为您可以加载未签名的驱动程序,...好吧,您完成了(在 Google 中搜索 Alex Ionescu)。但是,在 Windows 7 x64 中,您不能(呃!)

    "CreateRemoteThread() 的第四个参数是一个地址。在你的例子中是 LoadLibraryA 地址。但是,在 windows 7 中,Kernel32.dll/LoadLibraryA 基地址在不同的进程中会有所不同;"

    好吧,这远非如此,因为尽管有 ASLR,但 DLL 在每个进程中都在相同的地址上共享。不过,DLL 可以重新定位,但您可以在调用 CreateRemoteThread 之前调用 GetProcAddress,因此 DLL 不太可能同时重新定位。

    【讨论】:

      【解决方案4】:

      我认为 CreateRemoteThread() dll 注入方法不能在 windows 7 中工作。

      CreateRemoteThread() 的第四个参数是一个地址。在您的情况下,它是 LoadLibraryA 地址。但是,在windows 7中,Kernel32.dll/LoadLibrary的基地址在不同的进程中会有所不同;因此, CreateRemoteThread() 将不起作用,因为地址不是您所期望的。这是我个人的看法,希望对你有所帮助。 :)

      【讨论】:

        【解决方案5】:

        CreateRemoteThread 函数在 Win Vista/7 中不起作用。为此,您必须使用未记录的 NTCreateThread 函数。

        【讨论】:

        • This 似乎表明它适用于所有 WinXP 及更高版本。我个人也看到它在 Win7 上也能正常工作。
        • CreateRemoteThread 可能适用于 Win VIsta/7,但我真正的意思是 UIPI,它在 Vista 和更高版本的操作系统中实现,阻止低完整性级别的进程写入高完整性级别的进程,尽管它可以提升 IL 。
        【解决方案6】:

        TLDR:你的代码没问题,将 Visual Studio 调试/编译目标更改为 x64。

        我之前也遇到过同样的问题,你的代码很好,问题是,Visual Studio(或任何理智的人)默认以 x86 模式(32 位)执行它的程序,因为编译你的代码会很好以在 x86 或 x64 架构中运行但不在进程注入场景中运行的方式编程!因为它的系统调用。

        在代码注入的情况下,您应该在项目资源管理器的项目属性中更改 VS 的构建和调试设置以编译/调试 x64 处理器, 或者如果你交叉编译你的程序,你应该使用 x64 编译器。

        如果你在寻找全局进程注入方法,有一个方法叫Heaven's GateThe 0x33 Segment Selector,在Vawtrak中使用过> 银行恶意软件。

        你可以看到this关于天堂之门方法的链接,上面写着:

        换句话说,它使人们能够创建“裸”64 位 可以隐蔽运行的代码,包括发行系统 呼叫,而大多数产品都无法拦截和/或 反省其执行

        【讨论】:

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