如何将x86 DLL从WOW64进程注入到x64进程

有没有办法将x86 DLL从WOW64进程注入到x64进程? 我知道,根据MSDN,它通常不可能:

在64位Windows上,64位进程无法加载32位动态链接库(DLL)。 此外,32位进程无法加载64位DLL

但是我在Metasploit的仓库中找到了下面的代码,并想知道如何在我的项目中使用它:

/*
 * Attempt to gain code execution in a native x64 process from a wow64 process by transitioning out of the wow64 (x86)
 * enviroment into a native x64 enviroment and accessing the native win64 API's.
 * Note: On Windows 2003 the injection will work but in the target x64 process issues occur with new 
 *       threads (kernel32!CreateThread will return ERROR_NOT_ENOUGH_MEMORY). Because of this we filter out
 *       Windows 2003 from this method of injection, however the APC injection method will work on 2003.
 */
DWORD inject_via_remotethread_wow64( HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE * pThread )
{
    DWORD dwResult           = ERROR_SUCCESS;
    EXECUTEX64 pExecuteX64   = NULL;
    X64FUNCTION pX64function = NULL;
    WOW64CONTEXT * ctx       = NULL;
    OSVERSIONINFO os         = {0};

    do
    {
        os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

        if( !GetVersionEx( &os ) )
            BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: GetVersionEx failed" )

        // filter out Windows 2003
        if ( os.dwMajorVersion == 5 && os.dwMinorVersion == 2 )
        {
            SetLastError( ERROR_ACCESS_DENIED );
            BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: Windows 2003 not supported." )
        }

        // alloc a RWX buffer in this process for the EXECUTEX64 function
        pExecuteX64 = (EXECUTEX64)VirtualAlloc( NULL, sizeof(migrate_executex64), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
        if( !pExecuteX64 )
            BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: VirtualAlloc pExecuteX64 failed" )

        // alloc a RWX buffer in this process for the X64FUNCTION function (and its context)
        pX64function = (X64FUNCTION)VirtualAlloc( NULL, sizeof(migrate_wownativex)+sizeof(WOW64CONTEXT), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
        if( !pX64function )
            BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: VirtualAlloc pX64function failed" )

        // copy over the wow64->x64 stub
        memcpy( pExecuteX64, &migrate_executex64, sizeof(migrate_executex64) );

        // copy over the native x64 function
        memcpy( pX64function, &migrate_wownativex, sizeof(migrate_wownativex) );

        // set the context
        ctx = (WOW64CONTEXT *)( (BYTE *)pX64function + sizeof(migrate_wownativex) );

        ctx->h.hProcess       = hProcess;
        ctx->s.lpStartAddress = lpStartAddress;
        ctx->p.lpParameter    = lpParameter;
        ctx->t.hThread        = NULL;

        dprintf( "[INJECT] inject_via_remotethread_wow64: pExecuteX64=0x%08X, pX64function=0x%08X, ctx=0x%08X", pExecuteX64, pX64function, ctx );

        // Transition this wow64 process into native x64 and call pX64function( ctx )
        // The native function will use the native Win64 API's to create a remote thread in the target process.
        if( !pExecuteX64( pX64function, (DWORD)ctx ) )
        {
            SetLastError( ERROR_ACCESS_DENIED );
            BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: pExecuteX64( pX64function, ctx ) failed" )
        }

        if( !ctx->t.hThread )
        {
            SetLastError( ERROR_INVALID_HANDLE );
            BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: ctx->t.hThread is NULL" )
        }

        // Success! grab the new thread handle from of the context
        *pThread = ctx->t.hThread;

        dprintf( "[INJECT] inject_via_remotethread_wow64: Success, hThread=0x%08X", ctx->t.hThread );

    } while( 0 );

    if( pExecuteX64 )
        VirtualFree( pExecuteX64, 0, MEM_DECOMMIT );

    if( pX64function )
        VirtualFree( pX64function, 0, MEM_DECOMMIT );

    return dwResult;
}

我试图使用下面的代码:

#include <boost/scope_exit.hpp>

#include <Windows.h>

#include <cstdlib>
#include <iostream>

typedef struct _WOW64CONTEXT
{
  union
  {
    HANDLE hProcess;
    BYTE bPadding2[8];
  } h;
  union
  {
    LPVOID lpStartAddress;
    BYTE bPadding1[8];
  } s;
  union
  {
    LPVOID lpParameter;
    BYTE bPadding2[8];
  } p;
  union
  {
    HANDLE hThread;
    BYTE bPadding2[8];
  } t;
} WOW64CONTEXT, *LPWOW64CONTEXT;

typedef BOOL(WINAPI * X64FUNCTION)(DWORD dwParameter);
typedef DWORD(WINAPI * EXECUTEX64)(X64FUNCTION pFunction, DWORD dwParameter);

BYTE migrate_executex64[] = "x55x89xE5x56x57x8Bx75x08x8Bx4Dx0CxE8x00x00x00x00"
                            "x58x83xC0x25x83xECx08x89xE2xC7x42x04x33x00x00x00"
                            "x89x02xE8x09x00x00x00x83xC4x14x5Fx5Ex5DxC2x08x00"
                            "x8Bx3Cx24xFFx2Ax48x31xC0x57xFFxD6x5Fx50xC7x44x24"
                            "x04x23x00x00x00x89x3Cx24xFFx2Cx24";

BYTE migrate_wownativex[] = "xFCx48x89xCEx48x89xE7x48x83xE4xF0xE8xC8x00x00x00"
                            "x41x51x41x50x52x51x56x48x31xD2x65x48x8Bx52x60x48"
                            "x8Bx52x18x48x8Bx52x20x48x8Bx72x50x48x0FxB7x4Ax4A"
                            "x4Dx31xC9x48x31xC0xACx3Cx61x7Cx02x2Cx20x41xC1xC9"
                            "x0Dx41x01xC1xE2xEDx52x41x51x48x8Bx52x20x8Bx42x3C"
                            "x48x01xD0x66x81x78x18x0Bx02x75x72x8Bx80x88x00x00"
                            "x00x48x85xC0x74x67x48x01xD0x50x8Bx48x18x44x8Bx40"
                            "x20x49x01xD0xE3x56x48xFFxC9x41x8Bx34x88x48x01xD6"
                            "x4Dx31xC9x48x31xC0xACx41xC1xC9x0Dx41x01xC1x38xE0"
                            "x75xF1x4Cx03x4Cx24x08x45x39xD1x75xD8x58x44x8Bx40"
                            "x24x49x01xD0x66x41x8Bx0Cx48x44x8Bx40x1Cx49x01xD0"
                            "x41x8Bx04x88x48x01xD0x41x58x41x58x5Ex59x5Ax41x58"
                            "x41x59x41x5Ax48x83xECx20x41x52xFFxE0x58x41x59x5A"
                            "x48x8Bx12xE9x4FxFFxFFxFFx5Dx4Dx31xC9x41x51x48x8D"
                            "x46x18x50xFFx76x10xFFx76x08x41x51x41x51x49xB8x01"
                            "x00x00x00x00x00x00x00x48x31xD2x48x8Bx0Ex41xBAxC8"
                            "x38xA4x40xFFxD5x48x85xC0x74x0Cx48xB8x00x00x00x00"
                            "x00x00x00x00xEBx0Ax48xB8x01x00x00x00x00x00x00x00"
                            "x48x83xC4x50x48x89xFCxC3";

int main(int argc, char* argv[])
{
  if (argc != 2)
  {
    std::cout << "Usage: " << argv[0] << " [pid]" << std::endl;
    return EXIT_SUCCESS;
  }

  int pid = std::atoi(argv[1]);
  if (pid == 0)
  {
    std::cerr << "Invalid pid" << std::endl;
    return EXIT_FAILURE;
  }

  HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
  if (process_handle == NULL)
  {
    std::cerr << "An error occurred while using function OpenProcess. Error code: " << GetLastError() << std::endl;
    return EXIT_FAILURE;
  }
  BOOST_SCOPE_EXIT_ALL(process_handle)
  {
    CloseHandle(process_handle);
  };

  LPVOID load_library_addr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
  if (load_library_addr == NULL)
  {
    std::cerr << "An error occurred while using function GetProcAddress. Error code: " << GetLastError() << std::endl;
    return EXIT_FAILURE;
  }

  const char* dll_path = "D:helper.dll";

  LPVOID dll_path_memory = VirtualAllocEx(process_handle, NULL, strlen(dll_path) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  if (dll_path_memory == NULL)
  {
    std::cerr << "An error occurred while using function VirtualAllocEx. Error code: " << GetLastError() << std::endl;
    return EXIT_FAILURE;
  }

  BOOL res = WriteProcessMemory(process_handle, dll_path_memory, dll_path, strlen(dll_path) + 1, NULL);
  if (res == 0)
  {
    std::cerr << "An error occurred while using function WriteProcessMemory. Error code: " << GetLastError() << std::endl;
    return EXIT_FAILURE;
  }

  HANDLE thread_handle = CreateRemoteThread(process_handle, NULL, 0, (LPTHREAD_START_ROUTINE)load_library_addr, dll_path_memory, 0, NULL);
  if (thread_handle == NULL)
  {
    std::cerr << "An error occurred while using function CreateRemoteThread. Error code: " << GetLastError() << std::endl;

    EXECUTEX64 pExecuteX64 = (EXECUTEX64)VirtualAlloc(NULL, sizeof(migrate_executex64), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (pExecuteX64 == NULL)
    {
      std::cerr << "An error occurred while using function VirtualAlloc. Error code: " << GetLastError() << std::endl;
      return EXIT_FAILURE;
    }

    X64FUNCTION pX64function = (X64FUNCTION)VirtualAlloc(NULL, sizeof(migrate_wownativex) + sizeof(WOW64CONTEXT), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (pX64function == NULL)
    {
      std::cerr << "An error occurred while using function VirtualAlloc. Error code: " << GetLastError() << std::endl;
      return EXIT_FAILURE;
    }

    std::memcpy(pExecuteX64, &migrate_executex64, sizeof(migrate_executex64));
    std::memcpy(pX64function, &migrate_wownativex, sizeof(migrate_wownativex));

    WOW64CONTEXT* ctx = (WOW64CONTEXT *)((BYTE *)pX64function + sizeof(migrate_wownativex));
    ctx->h.hProcess = process_handle;
    ctx->s.lpStartAddress = load_library_addr;
    ctx->p.lpParameter = dll_path_memory;
    ctx->t.hThread = NULL;

    if (!pExecuteX64(pX64function, (DWORD)ctx))
    {
      std::cerr << "Error" << std::endl;
      return EXIT_FAILURE;
    }

    if (!ctx->t.hThread)
    {
      std::cerr << "ctx->t.hThread is NULL" << std::endl;
      return EXIT_FAILURE;
    }

    HANDLE hThread = ctx->t.hThread;

    if (ResumeThread(hThread) == (DWORD)-1)
    {
      std::cerr << "An error occurred while using function ResumeThread. Error code: " << GetLastError() << std::endl;
      return EXIT_FAILURE;
    }
  }

  WaitForSingleObject(thread_handle, INFINITE);

  std::cout << "Done" << std::endl;
}

在将x86 DLL注入到x86进程的情况下,但在将x64 DLL注入到x64进程(注入的进程刚刚崩溃)的情况下,它完美地工作。

我究竟做错了什么? 我该如何解决它?

提前致谢。


不是真的

一个64位Windows操作系统可以本机运行64位代码,也可以使用WOW64运行32位代码。 但是,每个过程可能只是一个或另一个。

进入内部时,可以看到每个进程标记为32位或64位。 当操作系统指示CPU运行与该进程相关的线程时,它将以32位或64位代码的形式跳转。

因此,如果你以某种方式加载32位字节码(无论它从哪里编码,无论是DLL还是别的什么地方)到64位进程中,当OS运行它时,进程将会崩溃,因为进程将在64位模式,并将操作码解释为64位操作码。

在32位代码上运行64位代码也是如此。

编辑

实际上,一个x32 WOW64进程可以执行x64代码。根据这篇文章。 但是,我找不到有关运行x86代码的x64进程的资源。

链接地址: http://www.djcxy.com/p/60319.html

上一篇: How to inject x86 DLL from the WOW64 process to the x64 process

下一篇: Unloading an Injected DLL