Advertisement
Guest User

Darawk's Manual Mapping code

a guest
Apr 3rd, 2011
10,227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.78 KB | None | 0 0
  1. //         ManualMap - by Darawk
  2. //        Featured @ www.RealmGX.com & www.Darawk.com
  3. //
  4. //   The purpose of ManualMap is to "manually map" a dll
  5. //   module into a remote process's address space.  This
  6. //   means that instead of just manipulating the remote
  7. //   process into calling the LoadLibrary function, we
  8. //   have our own emulation of what LoadLibrary does
  9. //   without all those annoying detectability issues ^^.
  10. //   The advantage of this method over using something
  11. //   like my CloakDll function, is that this method never
  12. //   has to call a function like LoadLibrary inside the
  13. //   remote process.  Since LoadLibrary can be hooked,
  14. //   the dll   could still be caught at the injection stage.
  15. //   Or possibly also through the weakness I discussed in
  16. //   the comment header of that file, which is not present
  17. //   when using this technique.
  18. #include
  19. #include
  20. #include
  21.  
  22. #pragma comment(lib, "shlwapi.lib")
  23.  
  24. #define IMAGE_DIRECTORY_ENTRY_IMPORT 1
  25. #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
  26.  
  27. //   Pietrek's macro
  28. //
  29. //   MakePtr is a macro that allows you to easily add to values (including
  30. //   pointers) together without dealing with C's pointer arithmetic.  It
  31. //   essentially treats the last two parameters as DWORDs.  The first
  32. //   parameter is used to typecast the result to the appropriate pointer type.
  33. #define MakePtr( cast, ptr, addValue ) (cast)( (DWORD_PTR)(ptr) + (DWORD_PTR)(addValue))
  34.  
  35. //   This one is mine, but obviously..."adapted" from matt's original idea =p
  36. #define MakeDelta(cast, x, y) (cast) ( (DWORD_PTR)(x) - (DWORD_PTR)(y))
  37.  
  38. bool MapRemoteModule(unsigned long, char *);
  39.  
  40. unsigned long GetProcessIdByName(char *);
  41. HMODULE GetRemoteModuleHandle(unsigned long, char *);
  42. FARPROC GetRemoteProcAddress(unsigned long, char *, char *);
  43.  
  44. bool FixImports(unsigned long, void *, IMAGE_NT_HEADERS *, IMAGE_IMPORT_DESCRIPTOR *);
  45. bool FixRelocs(void *, void *, IMAGE_NT_HEADERS *, IMAGE_BASE_RELOCATION *, unsigned int);
  46. bool MapSections(HANDLE, void *, void *, IMAGE_NT_HEADERS *);
  47.  
  48. PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD, PIMAGE_NT_HEADERS);
  49. LPVOID GetPtrFromRVA(DWORD, PIMAGE_NT_HEADERS, PBYTE);
  50.  
  51. //   Stub that calls the Dll from within the remote process.
  52. //   This is necessary because a DllMain function takes 3
  53. //   arguments, and CreateRemoteThread can pass only 1.
  54. __declspec(naked) void DllCall_stub(HMODULE hMod)
  55. {
  56.    _asm
  57.    {
  58.       push 0
  59.       push 1
  60.       push [esp+0Ch]      //   Pointer to the hMod argument
  61.         mov eax, 0xDEADBEEF   //   Patch this in with the real value at run-time
  62.  
  63.       call eax         //   MSVC++ doesn't like direct absolute calls, so we have to be
  64.                      //   clever about it.
  65.  
  66.       ret               //   Don't have to clean up the stack because the calling function
  67.                      //   is just going to call ExitThread() immediately after this
  68.                      //   function returns.
  69.    }
  70. }
  71.  
  72. //   Marker for the end of the DllCall_stub function
  73. __declspec(naked) void DC_stubend(void) { }
  74.  
  75. int main(int argc, char **argv)
  76. {
  77.    //   Just my test values...Cmdline.dll is a plugin that comes with
  78.    //   Olly Debug 1.10
  79.    MapRemoteModule(GetProcessIdByName("notepad.exe"), "Cmdline.dll");
  80.    return 0;
  81. }
  82.  
  83. bool MapRemoteModule(unsigned long pId, char *module)
  84. {
  85.    IMAGE_DOS_HEADER *dosHd;
  86.    IMAGE_NT_HEADERS *ntHd;
  87.  
  88.    HANDLE hFile = CreateFile(module,
  89.       GENERIC_READ,
  90.       FILE_SHARE_READ | FILE_SHARE_WRITE,
  91.       NULL,
  92.       OPEN_EXISTING,
  93.       FILE_ATTRIBUTE_NORMAL,
  94.       NULL);
  95.  
  96.    if(hFile == INVALID_HANDLE_VALUE)
  97.       return false;
  98.  
  99.    unsigned int fSize;
  100.  
  101.    if(GetFileAttributes(module) & FILE_ATTRIBUTE_COMPRESSED)
  102.       fSize = GetCompressedFileSize(module, NULL);
  103.    else
  104.       fSize = GetFileSize(hFile, NULL);
  105.  
  106.    unsigned char *dllBin = new unsigned char[fSize];
  107.    unsigned int nBytes;
  108.  
  109.    ReadFile(hFile, dllBin, fSize, (LPDWORD)&nBytes, FALSE);
  110.    CloseHandle(hFile);
  111.  
  112.    //   Every PE file contains a little DOS stub for backwards compatibility
  113.    //   it's only real relevance is that it contains a pointer to the actual
  114.    //   PE header.
  115.    dosHd = MakePtr(IMAGE_DOS_HEADER *, dllBin, 0);
  116.  
  117.    //   Make sure we got a valid DOS header
  118.    if(dosHd->e_magic != IMAGE_DOS_SIGNATURE)
  119.    {
  120.       delete dllBin;
  121.       return false;
  122.    }
  123.  
  124.    //   Get the real PE header from the DOS stub header
  125.    ntHd = MakePtr(IMAGE_NT_HEADERS *, dllBin, dosHd->e_lfanew);
  126.  
  127.    //   Verify the PE header
  128.    if(ntHd->Signature != IMAGE_NT_SIGNATURE)
  129.    {
  130.       delete dllBin;
  131.       return false;
  132.    }
  133.  
  134.    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
  135.  
  136.    if(!hProcess)
  137.       return false;
  138.  
  139.    //   Allocate space for the module in the remote process
  140.    void *moduleBase = VirtualAllocEx(hProcess,
  141.       NULL,
  142.       ntHd->OptionalHeader.SizeOfImage,
  143.       MEM_COMMIT | MEM_RESERVE,
  144.       PAGE_EXECUTE_READWRITE);
  145.  
  146.    //   Make sure we got the memory space we wanted
  147.    if(!moduleBase)
  148.       return false;
  149.  
  150.    //   Allocate space for our stub
  151.    void *stubBase = VirtualAllocEx(hProcess,
  152.       NULL,
  153.       MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
  154.       MEM_COMMIT | MEM_RESERVE,
  155.       PAGE_EXECUTE_READWRITE);
  156.  
  157.    //   Make sure we got the memory space we wanted
  158.    if(!stubBase)
  159.       return false;
  160.  
  161.    //   Fix up the import table of the new module
  162.    IMAGE_IMPORT_DESCRIPTOR *impDesc = (IMAGE_IMPORT_DESCRIPTOR *)GetPtrFromRVA(
  163.       (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress),
  164.       ntHd,
  165.       (PBYTE)dllBin);
  166.  
  167.    if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
  168.       FixImports(pId,
  169.          (unsigned char *)dllBin,
  170.          ntHd,
  171.          impDesc);
  172.  
  173.    //   Fix "base relocations" of the new module.  Base relocations are places
  174.    //   in the module that use absolute addresses to reference data.  Since
  175.    //   the base address of the module can be different at different times,
  176.    //   the base relocation data is necessary to make the module loadable
  177.    //   at any address.
  178.    IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION *)GetPtrFromRVA(
  179.       (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress),
  180.       ntHd,
  181.       (PBYTE)dllBin);
  182.  
  183.    if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
  184.       FixRelocs(dllBin,
  185.          moduleBase,
  186.          ntHd,
  187.          reloc,
  188.          ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
  189.  
  190.    //   Write the PE header into the remote process's memory space
  191.    WriteProcessMemory(hProcess,
  192.       moduleBase,
  193.       dllBin,
  194.       ntHd->FileHeader.SizeOfOptionalHeader + sizeof(ntHd->FileHeader) + sizeof(ntHd->Signature),
  195.       (SIZE_T *)&nBytes);
  196.  
  197.    //   Map the sections into the remote process(they need to be aligned
  198.    //   along their virtual addresses)
  199.    MapSections(hProcess, moduleBase, dllBin, ntHd);
  200.  
  201.    //   Change the page protection on the DllCall_stub function from PAGE_EXECUTE_READ
  202.    //   to PAGE_EXECUTE_READWRITE, so we can patch it.
  203.    VirtualProtect((LPVOID)DllCall_stub,
  204.       MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
  205.       PAGE_EXECUTE_READWRITE,
  206.       (DWORD *)&nBytes);
  207.  
  208.    //   Patch the stub so it calls the correct address
  209.    *MakePtr(unsigned long *, DllCall_stub, 9) =
  210.       MakePtr(unsigned long, moduleBase, ntHd->OptionalHeader.AddressOfEntryPoint);
  211.  
  212.  
  213.    //   Write the stub into the remote process
  214.    WriteProcessMemory(hProcess,
  215.       stubBase,
  216.       (LPVOID)DllCall_stub,
  217.       MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
  218.       (SIZE_T *)&nBytes);
  219.  
  220.    //   Execute our stub in the remote process
  221.    CreateRemoteThread(hProcess,
  222.       NULL,
  223.       0,
  224.       (LPTHREAD_START_ROUTINE)stubBase,
  225.       moduleBase,      //   Pass the base address of the module as the argument to the stub.
  226.                   //   All a module handle is, is the base address of the module(except
  227.                   //   in windows CE), so we're really passing a handle to the module
  228.                   //   so that it can refer to itself, create dialogs, etc..
  229.       0,
  230.       NULL);
  231.  
  232.    delete dllBin;
  233.    return true;
  234. }
  235.  
  236. bool MapSections(HANDLE hProcess, void *moduleBase, void *dllBin, IMAGE_NT_HEADERS *ntHd)
  237. {
  238.    IMAGE_SECTION_HEADER *header = IMAGE_FIRST_SECTION(ntHd);
  239.    unsigned int nBytes = 0;
  240.    unsigned int virtualSize = 0;
  241.    unsigned int n = 0;
  242.  
  243.    //   Loop through the list of sections
  244.    for(unsigned int i = 0; ntHd->FileHeader.NumberOfSections; i++)
  245.    {
  246.       //   Once we've reached the SizeOfImage, the rest of the sections
  247.       //   don't need to be mapped, if there are any.
  248.       if(nBytes >= ntHd->OptionalHeader.SizeOfImage)
  249.          break;
  250.      
  251.       WriteProcessMemory(hProcess,
  252.          MakePtr(LPVOID, moduleBase, header->VirtualAddress),
  253.          MakePtr(LPCVOID, dllBin, header->PointerToRawData),
  254.          header->SizeOfRawData,
  255.          (LPDWORD)&n);
  256.  
  257.       virtualSize = header->VirtualAddress;
  258.       header++;
  259.       virtualSize = header->VirtualAddress - virtualSize;
  260.       nBytes += virtualSize;
  261.  
  262.       //   Set the proper page protections for this section.
  263.       //   This really could be skipped, but it's not that
  264.       //   hard to implement and it makes it more like a
  265.       //   real loader.
  266.       VirtualProtectEx(hProcess,
  267.          MakePtr(LPVOID, moduleBase, header->VirtualAddress),
  268.          virtualSize,
  269.          header->Characteristics & 0x00FFFFFF,
  270.          NULL);
  271.    }
  272.  
  273.    return true;
  274. }
  275.  
  276. bool FixImports(unsigned long pId, void *base, IMAGE_NT_HEADERS *ntHd, IMAGE_IMPORT_DESCRIPTOR *impDesc)
  277. {
  278.    char *module;
  279.  
  280.    //   Loop through all the required modules
  281.    while((module = (char *)GetPtrFromRVA((DWORD)(impDesc->Name), ntHd, (PBYTE)base)))
  282.    {
  283.       //   If the library is already loaded(like kernel32.dll or ntdll.dll) LoadLibrary will
  284.       //   just return the handle to that module.
  285.         HMODULE localMod = LoadLibrary(module);
  286.  
  287.       //   If the module isn't loaded in the remote process, we recursively call the
  288.       //   module mapping code.  This has the added benefit of ensuring that any of
  289.       //   the current modules dependencies will be just as invisble as this one.
  290.       if(!GetRemoteModuleHandle(pId, module))
  291.          MapRemoteModule(pId, module);
  292.      
  293.       //   Lookup the first import thunk for this module
  294.       //   NOTE: It is possible this module could forward functions...which is something
  295.       //   that I really should handle.  Maybe i'll add support for forwared functions
  296.       //   a little bit later.
  297.       IMAGE_THUNK_DATA *itd =
  298.          (IMAGE_THUNK_DATA *)GetPtrFromRVA((DWORD)(impDesc->FirstThunk), ntHd, (PBYTE)base);
  299.  
  300.       while(itd->u1.AddressOfData)
  301.       {
  302.          IMAGE_IMPORT_BY_NAME *iibn;
  303.          iibn = (IMAGE_IMPORT_BY_NAME *)GetPtrFromRVA((DWORD)(itd->u1.AddressOfData), ntHd, (PBYTE)base);
  304.  
  305.              itd->u1.Function = MakePtr(DWORD, GetRemoteProcAddress(pId,
  306.             module,
  307.             (char *)iibn->Name), 0);
  308.  
  309.          itd++;
  310.       }    
  311.       impDesc++;
  312.    }
  313.  
  314.    return true;
  315. }
  316.  
  317. bool FixRelocs(void *base, void *rBase, IMAGE_NT_HEADERS *ntHd, IMAGE_BASE_RELOCATION *reloc, unsigned int size)
  318. {
  319.    unsigned long ImageBase = ntHd->OptionalHeader.ImageBase;
  320.    unsigned int nBytes = 0;
  321.  
  322.    unsigned long delta = MakeDelta(unsigned long, rBase, ImageBase);
  323.  
  324.    while(1)
  325.    {
  326.       unsigned long *locBase =
  327.          (unsigned long *)GetPtrFromRVA((DWORD)(reloc->VirtualAddress), ntHd, (PBYTE)base);
  328.       unsigned int numRelocs = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
  329.  
  330.       if(nBytes >= size) break;
  331.  
  332.       unsigned short *locData = MakePtr(unsigned short *, reloc, sizeof(IMAGE_BASE_RELOCATION));
  333.       for(unsigned int i = 0; i < numRelocs; i++)
  334.       {    
  335.          if(((*locData >> 12) & IMAGE_REL_BASED_HIGHLOW))
  336.              *MakePtr(unsigned long *, locBase, (*locData & 0x0FFF)) += delta;
  337.  
  338.          locData++;
  339.       }
  340.  
  341.       nBytes += reloc->SizeOfBlock;
  342.       reloc = (IMAGE_BASE_RELOCATION *)locData;
  343.    }
  344.  
  345.    return true;
  346. }
  347.  
  348.  
  349. FARPROC GetRemoteProcAddress(unsigned long pId, char *module, char *func)
  350. {
  351.    HMODULE remoteMod = GetRemoteModuleHandle(pId, module);
  352.    HMODULE localMod = GetModuleHandle(module);
  353.  
  354.    //   Account for potential differences in base address
  355.    //   of modules in different processes.
  356.    unsigned long delta = MakeDelta(unsigned long, remoteMod, localMod);
  357.    return MakePtr(FARPROC, GetProcAddress(localMod, func), delta);
  358. }
  359.  
  360. unsigned long GetProcessIdByName(char *process)
  361. {
  362.    PROCESSENTRY32 pe;
  363.    HANDLE thSnapshot;
  364.    BOOL retval, ProcFound = false;
  365.  
  366.    thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  367.  
  368.    if(thSnapshot == INVALID_HANDLE_VALUE)
  369.    {
  370.       MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);
  371.       return false;
  372.    }
  373.  
  374.    pe.dwSize = sizeof(PROCESSENTRY32);
  375.  
  376.     retval = Process32First(thSnapshot, &pe);
  377.  
  378.    while(retval)
  379.    {
  380.       if(StrStrI(pe.szExeFile, process) )
  381.       {
  382.          ProcFound = true;
  383.          break;
  384.       }
  385.  
  386.       retval    = Process32Next(thSnapshot,&pe);
  387.       pe.dwSize = sizeof(PROCESSENTRY32);
  388.    }
  389.  
  390.    return pe.th32ProcessID;
  391. }
  392.  
  393. HMODULE GetRemoteModuleHandle(unsigned long pId, char *module)
  394. {
  395.    MODULEENTRY32 modEntry;
  396.    HANDLE tlh = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pId);
  397.  
  398.    modEntry.dwSize = sizeof(MODULEENTRY32);
  399.     Module32First(tlh, &modEntry);
  400.  
  401.    do
  402.    {
  403.       if(!stricmp(modEntry.szModule, module))
  404.          return modEntry.hModule;
  405.       modEntry.dwSize = sizeof(MODULEENTRY32);
  406.    }
  407.    while(Module32Next(tlh, &modEntry));
  408.  
  409.    return NULL;
  410. }
  411.  
  412. //   Matt Pietrek's function
  413. PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_NT_HEADERS pNTHeader)
  414. {
  415.     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
  416.     unsigned int i;
  417.  
  418.     for ( i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
  419.     {
  420.       // This 3 line idiocy is because Watcom's linker actually sets the
  421.       // Misc.VirtualSize field to 0.  (!!! - Retards....!!!)
  422.       DWORD size = section->Misc.VirtualSize;
  423.       if ( 0 == size )
  424.          size = section->SizeOfRawData;
  425.        
  426.         // Is the RVA within this section?
  427.         if ( (rva >= section->VirtualAddress) &&
  428.              (rva < (section->VirtualAddress + size)))
  429.             return section;
  430.     }
  431.  
  432.     return 0;
  433. }
  434.  
  435. //   This function is also Pietrek's
  436. LPVOID GetPtrFromRVA( DWORD rva, IMAGE_NT_HEADERS *pNTHeader, PBYTE imageBase )
  437. {
  438.    PIMAGE_SECTION_HEADER pSectionHdr;
  439.    INT delta;
  440.      
  441.    pSectionHdr = GetEnclosingSectionHeader( rva, pNTHeader );
  442.    if ( !pSectionHdr )
  443.       return 0;
  444.  
  445.    delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
  446.    return (PVOID) ( imageBase + rva - delta );
  447. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement