bool MapRemoteModule(unsigned long pId, char *module)
{
   IMAGE_DOS_HEADER *dosHd;
   IMAGE_NT_HEADERS *ntHd;

   HANDLE hFile = CreateFile(module,
      GENERIC_READ,
      FILE_SHARE_READ | FILE_SHARE_WRITE,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      NULL);

   if(hFile == INVALID_HANDLE_VALUE)
      return false;

   unsigned int fSize;

   if(GetFileAttributes(module) & FILE_ATTRIBUTE_COMPRESSED)
      fSize = GetCompressedFileSize(module, NULL);
   else
      fSize = GetFileSize(hFile, NULL);

   unsigned char *dllBin = new unsigned char[fSize];
   unsigned int nBytes;

   ReadFile(hFile, dllBin, fSize, (LPDWORD)&nBytes, FALSE);
   CloseHandle(hFile);

   //   Every PE file contains a little DOS stub for backwards compatibility
   //   it's only real relevance is that it contains a pointer to the actual
   //   PE header.
   dosHd = MakePtr(IMAGE_DOS_HEADER *, dllBin, 0);

   //   Make sure we got a valid DOS header
   if(dosHd->e_magic != IMAGE_DOS_SIGNATURE)
   {
      delete dllBin;
	  printf("invalid dos header\n");
      return false;
   }

   //   Get the real PE header from the DOS stub header
   ntHd = MakePtr(IMAGE_NT_HEADERS *, dllBin, dosHd->e_lfanew);

   //   Verify the PE header
   if(ntHd->Signature != IMAGE_NT_SIGNATURE)
   {
      delete dllBin;
	  printf("invalid nt header\n");
      return false;
   }

   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);

   if(!hProcess)
   {
	   printf("open process failed\n");
      return false;
   }

   //   Allocate space for the module in the remote process
   void *moduleBase = VirtualAllocEx(hProcess,
      NULL,
      ntHd->OptionalHeader.SizeOfImage,
      MEM_COMMIT | MEM_RESERVE,
      PAGE_EXECUTE_READWRITE);

   //   Make sure we got the memory space we wanted
   if(!moduleBase)
   {
	   printf("virtual alloc failed (moduleBase)\n");
      return false;
   }

   //   Allocate space for our stub
   void *stubBase = VirtualAllocEx(hProcess,
      NULL,
      MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
      MEM_COMMIT | MEM_RESERVE,
      PAGE_EXECUTE_READWRITE);

   //   Make sure we got the memory space we wanted
   if(!stubBase)
   {
	   printf("virtual alloc failed(stubBase)\n");
      return false;
   }

   //   Fix up the import table of the new module
   IMAGE_IMPORT_DESCRIPTOR *impDesc = (IMAGE_IMPORT_DESCRIPTOR *)GetPtrFromRVA(
      (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress),
      ntHd,
      (PBYTE)dllBin);

   if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
      FixImports(pId,
         (unsigned char *)dllBin,
         ntHd,
         impDesc);
 
   //   Fix "base relocations" of the new module.  Base relocations are places
   //   in the module that use absolute addresses to reference data.  Since
   //   the base address of the module can be different at different times,
   //   the base relocation data is necessary to make the module loadable
   //   at any address.
   IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION *)GetPtrFromRVA(
      (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress),
      ntHd,
      (PBYTE)dllBin);

   if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
      FixRelocs(dllBin,
         moduleBase,
         ntHd,
         reloc,
         ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);

   //   Write the PE header into the remote process's memory space
   WriteProcessMemory(hProcess,
      moduleBase,
      dllBin,
      ntHd->FileHeader.SizeOfOptionalHeader + sizeof(ntHd->FileHeader) + sizeof(ntHd->Signature),
      (SIZE_T *)&nBytes);

   //   Map the sections into the remote process(they need to be aligned
   //   along their virtual addresses)
   MapSections(hProcess, moduleBase, dllBin, ntHd);
 
   //   Change the page protection on the DllCall_stub function from PAGE_EXECUTE_READ
   //   to PAGE_EXECUTE_READWRITE, so we can patch it.
   VirtualProtect((LPVOID)DllCall_stub,
      MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
      PAGE_EXECUTE_READWRITE,
      (DWORD *)&nBytes);

   //   Patch the stub so it calls the correct address
   *MakePtr(unsigned long *, DllCall_stub, 9) =
      MakePtr(unsigned long, moduleBase, ntHd->OptionalHeader.AddressOfEntryPoint);


   //   Write the stub into the remote process
   WriteProcessMemory(hProcess,
      stubBase,
      (LPVOID)DllCall_stub,
      MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
      (SIZE_T *)&nBytes);

   //   Execute our stub in the remote process
   CreateRemoteThread(hProcess,
      NULL,
      0,
      (LPTHREAD_START_ROUTINE)stubBase,
      moduleBase,      //   Pass the base address of the module as the argument to the stub.
                  //   All a module handle is, is the base address of the module(except
                  //   in windows CE), so we're really passing a handle to the module
                  //   so that it can refer to itself, create dialogs, etc..
      0,
      NULL);

   delete dllBin;
   return true;
}
////////////////////////////////////////////////////////////////////////////////////////////
// MapRemoteModuleW
////////////////////////////////////////////////////////////////////////////////////////////
BOOL
MapRemoteModuleW(
        DWORD dwProcessId,
        LPCWSTR lpModulePath
        )
{
        BOOL bRet = FALSE;
        HANDLE hFile = 0;
        DWORD fileSize = 0;
        BYTE *dllBin = 0;
        PIMAGE_NT_HEADERS nt_header = 0;
        PIMAGE_DOS_HEADER dos_header = 0;
        HANDLE hProcess = 0;
        LPVOID lpModuleBase = 0;
 
        PIMAGE_IMPORT_DESCRIPTOR pImgImpDesc = 0;
        PIMAGE_BASE_RELOCATION pImgBaseReloc = 0;
        PIMAGE_TLS_DIRECTORY pImgTlsDir = 0;
 
        __try
        {
                // Get a handle for the target process.
                hProcess = OpenProcess(
                        PROCESS_QUERY_INFORMATION       |       // Required by Alpha
                        PROCESS_CREATE_THREAD           |       // For CreateRemoteThread
                        PROCESS_VM_OPERATION            |       // For VirtualAllocEx/VirtualFreeEx
                        PROCESS_VM_WRITE                |       // For WriteProcessMemory
                        PROCESS_VM_READ,
                        FALSE,
                        dwProcessId);
                if(!hProcess)
                {
                        PRINT_ERROR_MSGA("Could not get handle to process (PID: 0x%X).", dwProcessId);
                        __leave;
                }
 
                hFile = CreateFileW(
                        lpModulePath,
                        GENERIC_READ,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);
                if(hFile == INVALID_HANDLE_VALUE)
                {
                        PRINT_ERROR_MSGA("CreateFileW failed.");
                        __leave;
                }
 
                if(GetFileAttributesW(lpModulePath) & FILE_ATTRIBUTE_COMPRESSED)
                {
                        fileSize = GetCompressedFileSizeW(lpModulePath, NULL);
                }
                else
                {
                        fileSize = GetFileSize(hFile, NULL);
                }
 
                if(fileSize == INVALID_FILE_SIZE)
                {
                        PRINT_ERROR_MSGA("Could not get size of file.");
                        __leave;
                }
 
                dllBin = (BYTE*)malloc(fileSize);
 
                {
                        DWORD NumBytesRead = 0;
                        if(!ReadFile(hFile, dllBin, fileSize, &NumBytesRead, FALSE))
                        {
                                PRINT_ERROR_MSGA("ReadFile failed.");
                        }
                }
       
                dos_header = (PIMAGE_DOS_HEADER)dllBin;
               
                // Make sure we got a valid DOS header
                if(dos_header->e_magic != IMAGE_DOS_SIGNATURE)
                {
                        PRINT_ERROR_MSGA("Invalid DOS header.");
                        __leave;
                }
               
                // Get the real PE header from the DOS stub header
                nt_header = (PIMAGE_NT_HEADERS)( (DWORD_PTR)dllBin +
                        dos_header->e_lfanew);
 
                // Verify the PE header
                if(nt_header->Signature != IMAGE_NT_SIGNATURE)
                {
                        PRINT_ERROR_MSGA("Invalid PE header.");
                        __leave;
                }
 
                // Allocate space for the module in the remote process
                lpModuleBase = VirtualAllocEx(
                        hProcess,
                        NULL,
                        nt_header->OptionalHeader.SizeOfImage,
                        MEM_COMMIT | MEM_RESERVE,
                        PAGE_EXECUTE_READWRITE);
                if(!lpModuleBase)
                {
                        PRINT_ERROR_MSGA("Could not allocate memory in remote process.");
                        __leave;
                }
               
                // fix imports
                pImgImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)GetPtrFromRVA(
                        nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
                        nt_header,
                        (PBYTE)dllBin);
                if(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
                {
                        if(!FixIAT(dwProcessId, hProcess, (PBYTE)dllBin, nt_header, pImgImpDesc))
                        {
                                PRINT_ERROR_MSGA("@Fixing imports.");
                                __leave;
                        }
                }
               
                // fix relocs
                pImgBaseReloc = (PIMAGE_BASE_RELOCATION)GetPtrFromRVA(
                        (DWORD)(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress),
                        nt_header,
                        (PBYTE)dllBin);
                if(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
                {
                        if(!FixRelocations(dllBin, lpModuleBase, nt_header, pImgBaseReloc))
                        {
                                PRINT_ERROR_MSGA("@Fixing relocations.");
                                __leave;
                        }
                }
 
                // Write the PE header into the remote process's memory space
                {
                        SIZE_T NumBytesWritten = 0;
                        SIZE_T nSize = nt_header->FileHeader.SizeOfOptionalHeader +
                                sizeof(nt_header->FileHeader) +
                                sizeof(nt_header->Signature);
                       
                        if(!WriteProcessMemory(hProcess, lpModuleBase, dllBin, nSize, &NumBytesWritten) ||
                                NumBytesWritten != nSize)
                        {
                                PRINT_ERROR_MSGA("Could not write to memory in remote process.");
                                __leave;
                        }
                }
 
                // Map the sections into the remote process(they need to be aligned
                // along their virtual addresses)
                if(!MapSections(hProcess, lpModuleBase, dllBin, nt_header))
                {
                        PRINT_ERROR_MSGA("@Map sections.");
                        __leave;
                }
 
                // call all tls callbacks
                //
                pImgTlsDir = (PIMAGE_TLS_DIRECTORY)GetPtrFromRVA(
                        nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress,
                        nt_header,
                        (PBYTE)dllBin);
                if(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
                {
                        if(!CallTlsInitializers(dllBin, nt_header, hProcess, (HMODULE)lpModuleBase, DLL_PROCESS_ATTACH, pImgTlsDir))
                        {
                                PRINT_ERROR_MSGA("@Call TLS initializers.");
                                __leave;
                        }
                }
 
                // call entry point
                if(!RemoteDllMainCall(
                        hProcess,
                        (LPVOID)( (DWORD_PTR)lpModuleBase + nt_header->OptionalHeader.AddressOfEntryPoint),
                        (HMODULE)lpModuleBase, 1, 0))
                {
                        PRINT_ERROR_MSGA("@Call DllMain.");
                        __leave;
                }
 
                bRet = TRUE;
 
                wprintf(L"Successfully injected (%s | PID: %x):\n\n"
                        L"  AllocationBase:\t0x%p\n"
                        L"  EntryPoint:\t\t0x%p\n"
                        L"  SizeOfImage:\t\t0x%p\n"
                        L"  CheckSum:\t\t0x%p\n",
                        lpModulePath,
                        dwProcessId,
                        lpModuleBase,
                        (DWORD_PTR)lpModuleBase + nt_header->OptionalHeader.AddressOfEntryPoint,
                        nt_header->OptionalHeader.SizeOfImage,
                        nt_header->OptionalHeader.CheckSum);
        }
        __finally
        {
                if(hFile)
                {
                        CloseHandle(hFile);
                }
 
                if(dllBin)
                {
                        free(dllBin);
                }
 
                if(hProcess)
                {
                        CloseHandle(hProcess);
                }
        }
       
        return bRet;
}
Exemple #3
0
bool MapRemoteModule(unsigned long pId, const char *module)
{
   IMAGE_DOS_HEADER *dosHd;
   IMAGE_NT_HEADERS *ntHd;
   IMAGE_NT_HEADERS64 *ntHd64 = NULL;

   HANDLE hFile = CreateFileA(module,
      GENERIC_READ,
      FILE_SHARE_READ | FILE_SHARE_WRITE,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      NULL);

   if(hFile == INVALID_HANDLE_VALUE)
      return false;

   unsigned int fSize;

   if(GetFileAttributesA(module) & FILE_ATTRIBUTE_COMPRESSED)
      fSize = GetCompressedFileSizeA(module, NULL);
   else
      fSize = GetFileSize(hFile, NULL);

   unsigned char *dllBin = new unsigned char[fSize];
   unsigned int nBytes;

   // copy into our dllBin buffer the entire DLL
   ReadFile(hFile, dllBin, fSize, (LPDWORD)&nBytes, FALSE);
   CloseHandle(hFile);

   //   Every PE file contains a little DOS stub for backwards compatibility
   //   its only real relevance is that it contains a pointer to the actual
   //   PE header.
   dosHd = MakePtr(IMAGE_DOS_HEADER *, dllBin, 0);

   //   Make sure we got a valid DOS header
   if(dosHd->e_magic != IMAGE_DOS_SIGNATURE)
   {
       wxMessageBox( _("The DOS header was invalid"), 
           _("Error:  Invalid DOS header"),
           wxICON_ERROR );
       delete [] dllBin;
       return false;
   }

   //   Get the real PE header from the DOS stub header
   //   This header contains pointers to the Optional Header and the 
   //   COFF File Header.
   ntHd = MakePtr(IMAGE_NT_HEADERS *, dllBin, dosHd->e_lfanew);

   //   Verify that the PE header is PE00
   if(ntHd->Signature != IMAGE_NT_SIGNATURE)
   {
       wxMessageBox( _("The PE Header was not found."), 
           _("Error:  PE Header not found"),
           wxICON_ERROR );
       delete [] dllBin;
       return false;
   }

   //   Verify that the image file is a DLL
   if( (ntHd->FileHeader.Characteristics & IMAGE_FILE_DLL) == false )
   {
       wxMessageBox( _("You may only inject DLL image files."), 
           _("Error:  Injected image file was not a DLL"),
           wxICON_ERROR );
       delete [] dllBin;
       return false;
   }

   // Open the target process
   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);

   // We failed to open the process, so return false
   if(!hProcess)
   {
       wxMessageBox( _("Failed to open target process."), 
           _("Error:  Failed to open process"),
           wxICON_ERROR );
       delete [] dllBin;
       return false;
   }

   //   Determine whether the image is a PE32 or PE32+ executable
   if( ntHd->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC )
   {
        if( ntHd->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC )
        {
            ntHd64 = (IMAGE_NT_HEADERS64 *)ntHd;
            wxMessageBox( _("Image is a PE32+ executable.\nInjector Gadget doesn't support PE32+ executables yet."),
                _("Error:  Image is not a PE32 executable"),
                wxICON_ERROR );
        }
        else if( ntHd->OptionalHeader.Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC )
        {
            wxMessageBox( _("Image is a ROM image.\nInjector Gadget doesn't support ROM images."),
                _("Error:  Image is not a PE32 executable"),
                wxICON_ERROR );
        }
        delete [] dllBin;
        return false;
   }

   //   Allocate space for the module in the remote process
   void *imageBase = VirtualAllocEx(hProcess,
      NULL,
      ntHd->OptionalHeader.SizeOfImage,
      MEM_COMMIT | MEM_RESERVE,
      PAGE_EXECUTE_READWRITE);

   //   Make sure we got the memory space we wanted
   if(!imageBase)
   {
       delete [] dllBin;
       return false;
   }
   //   Allocate space for our stub
   void *stubBase = VirtualAllocEx(hProcess,
      NULL,
      MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
      MEM_COMMIT | MEM_RESERVE,
      PAGE_EXECUTE_READWRITE);

   //   Make sure we got the memory space we wanted
   if(!stubBase)
   {
       delete [] dllBin;
       return false;
   }

   //   We now need to fix up the tables.
   //   The tables are as follows (in order):
   //   Export Table, Import Table, Resource Table, Exception Table,
   //   Certificate Table, Base Relocation Table, Debug, Architecture,
   //   Global Ptr, TLS Table, Load Config Table, Bound Import, IAT,
   //   Delay Import Descriptor, CLR Runtime Header, Reserved

   //   First important section is the Export Table.  We're going to skip this
   //   since the whole point of cloaking a DLL is to hide its presence.

   //   Second important section is the Import Table.  We really need this.
   if( ntHd->OptionalHeader.NumberOfRvaAndSizes > 1 )
   {
       IMAGE_IMPORT_DESCRIPTOR *impDesc = (IMAGE_IMPORT_DESCRIPTOR *)GetPtrFromRVA(
           (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress),
           ntHd,
           (PBYTE)dllBin);
       if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
           FixImports(pId,
           (unsigned char *)dllBin,
           ntHd,
           impDesc);
       else // size was 0 for the import directory entry
       {
           wxMessageBox(
               _("Size of import directory entry was 0"),
               _("Error:  Import Directory size is 0"),
               wxICON_ERROR);
           delete [] dllBin;
           return false;
       }
   }
   else // IMAGE_DIRECTORY_ENTRY_IMPORT didn't exist in the data directories
   {
       wxMessageBox( _("The import table referenced an invalid index in the data directory."),
           _("Error:  Import table could not be located"),
           wxICON_ERROR );
       delete [] dllBin;
       return false;
   }

   //   Fix "base relocations" of the new module.  Base relocations are places
   //   in the module that use absolute addresses to reference data.  Since
   //   the base address of the module can be different at different times,
   //   the base relocation data is necessary to make the module loadable
   //   at any address.
   IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION *)GetPtrFromRVA(
      (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress),
      ntHd,
      (PBYTE)dllBin);

   if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
      FixRelocs(dllBin,
         imageBase,
         ntHd,
         reloc,
         ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);

   //   Write the PE header into the remote process's memory space
   WriteProcessMemory(hProcess,
      imageBase,
      dllBin,
      ntHd->FileHeader.SizeOfOptionalHeader + sizeof(ntHd->FileHeader) + sizeof(ntHd->Signature),
      (SIZE_T *)&nBytes);

   //   Map the sections into the remote process(they need to be aligned
   //   along their virtual addresses)
   MapSections(hProcess, imageBase, dllBin, ntHd);

   //   Change the page protection on the DllCall_stub function from PAGE_EXECUTE_READ
   //   to PAGE_EXECUTE_READWRITE, so we can patch it.
   VirtualProtect((LPVOID)DllCall_stub,
      MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
      PAGE_EXECUTE_READWRITE,
      (DWORD *)&nBytes);

   //   Patch the stub so it calls the correct address
   *MakePtr(unsigned long *, DllCall_stub, 9) =
      MakePtr(unsigned long, imageBase, ntHd->OptionalHeader.AddressOfEntryPoint);

   //   Write the stub into the remote process
   WriteProcessMemory(hProcess,
      stubBase,
      (LPVOID)DllCall_stub,
      MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
      (SIZE_T *)&nBytes);

#ifdef __USING_DEBUGGER
   wxMessageBox(_("Calling CreateRemoteThread"));
   wxMessageBox( _("hProcess: ") + wxString::Format("%08X",hProcess) );
   wxMessageBox( _("stubBase: ") + wxString::Format("%08X",stubBase) );
   wxMessageBox( _("moduleBas: ") + wxString::Format("%08X",imageBase) );
#endif
   //   Execute our stub in the remote process
   CreateRemoteThread(hProcess,
      NULL,
      ntHd->OptionalHeader.SizeOfStackCommit,
      (LPTHREAD_START_ROUTINE)stubBase,
      imageBase,      //   Pass the base address of the module as the argument to the stub.
                       //   All a module handle is, is the base address of the module(except
                       //   in windows CE), so we're really passing a handle to the module
                       //   so that it can refer to itself, create dialogs, etc..
      0,
      NULL);

   delete dllBin;
   return true;
}