Pe Memory Loader by ErazerZ

Post date: Jul 17, 2010 5:40:26 PM

This code adds a new section to the pe file, so when its run the file its decrypted and loaded in memory

program PeLoader;

{

Example of a Pe Loader by ErazerZ

3rd May 2006

}

uses

Windows,

Dialogs,

untPeFile; { PE File Unit by ErazerZ }

var

Pe: TPeFile;

Open: TOpenDialog;

procedure AddExeLoader;

procedure _load_iat; stdcall; forward;

procedure _load_code(lpLoadLibrary, lpGetProcAddress: Pointer; lpSectionBegin: DWORD); stdcall; forward;

procedure _loader; stdcall;

asm

call _load_iat

call _load_code

end;

procedure _load_iat;

asm

pop eax

mov edx, eax

mov edx, eax

and eax, $fffff000

push eax

add eax, $55

lea eax, [eax]

push [eax]

lea eax, [eax+4]

push [eax]

push edx

end;

procedure _load_code(

lpLoadLibrary,

lpGetProcAddress: Pointer;

lpSectionBegin: DWORD); stdcall;

var

xLoadLibraryA: function(lpLibFileName: PChar): HMODULE; stdcall;

xGetProcAddress: function(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;

ImageBase, OldEntryPoint, OldIAT, EncryptStart, EncryptEnd, EncryptCounter: DWORD;

ImportDesc: PImageImportDescriptor;

lpDllName: PChar;

hDll: THandle;

ImageThunk: ^PImageThunkData;

ImageThunkWrite: ^Pointer;

begin

@xLoadLibraryA := lpLoadLibrary;

@xGetProcAddress := lpGetProcAddress;

ImageBase := DWORD(Pointer(DWORD(lpSectionBegin + $61))^);

OldEntryPoint := DWORD(Pointer(DWORD(lpSectionBegin + $65))^) + ImageBase;

OldIAT := DWORD(Pointer(DWORD(lpSectionBegin + $69))^) + ImageBase;

EncryptStart := DWORD(Pointer(DWORD(lpSectionBegin + $6D))^) + ImageBase;

EncryptEnd := DWORD(Pointer(DWORD(lpSectionBegin + $71))^) + ImageBase;

for EncryptCounter := EncryptStart to EncryptEnd do

begin

PByte(EncryptCounter)^ := PByte(EncryptCounter)^ xor $FF;

end;

ImportDesc := PImageImportDescriptor(OldIAT);

while (ImportDesc^.Name <> 0) do

begin

lpDllName := PChar(ImportDesc^.Name + ImageBase);

hDll := xLoadLibraryA(lpDllName);

if (ImportDesc^.OriginalFirstThunk <> 0) then

ImageThunk := Pointer(ImportDesc^.OriginalFirstThunk + ImageBase)

else

ImageThunk := Pointer(ImportDesc^.FirstThunk + ImageBase);

ImageThunkWrite := Pointer(ImportDesc^.FirstThunk + ImageBase);

while (ImageThunk^ <> nil) do

begin

if ((Cardinal(ImageThunk^) and $80000000) <> 0) then

ImageThunkWrite^ := xGetProcAddress(hDll, PChar(Cardinal(ImageThunk^) and $FFFF))

else

ImageThunkWrite^ := xGetProcAddress(hDll, PChar(ImageBase + Cardinal(ImageThunk^) + SizeOf(Word)));

Inc(ImageThunk);

Inc(ImageThunkWrite);

end;

Inc(ImportDesc);

end;

asm

jmp OldEntryPoint

end;

end;

procedure _loader_end; begin end;

var

dwOldIATVA, lsPointerToRawData, lpTemp, EncryptCounter, EncryptStart, EncryptEnd: Cardinal;

ImportDescriptor: TImageImportDescriptor;

ImageThunk: array[0..1] of TImageThunkData;

x: Word;

const

szIAT_DLL_KERNEL: string = 'kernel32.dll'#0;

szIAT_FUNC_GETPROCADDR: string = #0#0'GetProcAddress'#0;

szIAT_FUNC_LOADLIBRARY: string = #0#0'LoadLibraryA'#0;

begin

dwOldIATVA := Pe.ImageNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

if Pe.AddSection('.edi', $200) then

begin

FillChar(ImportDescriptor, SizeOf(TImageImportDescriptor), #0);

FillChar(ImageThunk, SizeOf(TImageThunkData), #0);

lsPointerToRawData := Pe.ImageSections[High(Pe.ImageSections)].PointerToRawData;

lpTemp := 0;

Pe.CopyMemoryBuffer(lsPointerToRawData + lpTemp, Pointer(szIAT_DLL_KERNEL), Length(szIAT_DLL_KERNEL));

ImportDescriptor.Name := Pe.FileOffsetToRva(lsPointerToRawData);

Inc(lpTemp, Length(szIAT_DLL_KERNEL));

Pe.CopyMemoryBuffer(lsPointerToRawData + lpTemp, Pointer(szIAT_FUNC_GETPROCADDR), Length(szIAT_FUNC_GETPROCADDR));

ImageThunk[0].Name := Pe.FileOffsetToRva(lsPointerToRawData + lpTemp);

Inc(lpTemp, Length(szIAT_FUNC_GETPROCADDR));

Pe.CopyMemoryBuffer(lsPointerToRawData + lpTemp, Pointer(szIAT_FUNC_LOADLIBRARY), Length(szIAT_FUNC_LOADLIBRARY));

ImageThunk[1].Name := Pe.FileOffsetToRva(lsPointerToRawData + lpTemp);

Inc(lpTemp, Length(szIAT_FUNC_LOADLIBRARY));

ImportDescriptor.FirstThunk := Pe.FileOffsetToRva(lsPointerToRawData + lpTemp + (SizeOf(TImageImportDescriptor) * 2));

Pe.CopyMemoryBuffer(lsPointerToRawData + lpTemp, @ImportDescriptor, SizeOf(TImageImportDescriptor));

Pe.ImageNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress := Pe.FileOffsetToRva(lsPointerToRawData + lpTemp);

Inc(lpTemp, SizeOf(TImageImportDescriptor) * 2);

Pe.CopyMemoryBuffer((lsPointerToRawData + lpTemp), @ImageThunk, SizeOf(ImageThunk));

Inc(lpTemp, SizeOf(ImageThunk) + SizeOf(TImageThunkData));

Pe.ImageNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size := lpTemp;

Pe.CopyMemoryBuffer((lsPointerToRawData + lpTemp), PDWORD(@Pe.ImageNtHeaders^.OptionalHeader.ImageBase), SizeOf(DWORD));

Inc(lpTemp, SizeOf(DWORD));

Pe.CopyMemoryBuffer((lsPointerToRawData + lpTemp), PDWORD(@Pe.ImageNtHeaders^.OptionalHeader.AddressOfEntryPoint), SizeOf(DWORD));

Inc(lpTemp, SizeOf(DWORD));

Pe.CopyMemoryBuffer((lsPointerToRawData + lpTemp), PDWORD(@dwOldIATVA), SizeOf(DWORD));

Inc(lpTemp, SizeOf(DWORD));

EncryptStart := Pe.ImageSections[Pe.GetCodeSection].VirtualAddress;

Pe.CopyMemoryBuffer((lsPointerToRawData + lpTemp), PDWORD(@EncryptStart), SizeOf(DWORD));

Inc(lpTemp, SizeOf(DWORD));

EncryptEnd := EncryptStart + Pe.ImageSections[Pe.GetCodeSection].Misc.VirtualSize;

Pe.CopyMemoryBuffer(lsPointerToRawData + lpTemp, PDWORD(@EncryptEnd), SizeOf(DWORD));

Inc(lpTemp, SizeOf(DWORD));

EncryptStart := Pe.RvaToVa(EncryptStart);

EncryptEnd := Pe.RvaToVa(EncryptEnd);

for EncryptCounter := EncryptStart to EncryptEnd do

begin

PByte(EncryptCounter)^ := PByte(EncryptCounter)^ xor $FF;

end;

Pe.ImageNtHeaders^.OptionalHeader.AddressOfEntryPoint := Pe.FileOffsetToRva(lsPointerToRawData + lpTemp);

Pe.CopyMemoryBuffer(lsPointerToRawData + lpTemp, @_loader, DWORD(@_loader_end) - DWORD(@_loader));

for x := Low(Pe.ImageSections) to High(Pe.ImageSections) do

Pe.ImageSections[x].Characteristics := Pe.ImageSections[x].Characteristics or IMAGE_SCN_MEM_WRITE;

Pe.ImageNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress := 0;

Pe.ImageNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size := 0;

Pe.ImageNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress := 0;

Pe.ImageNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size := 0;

Pe.ImageNtHeaders^.OptionalHeader.BaseOfCode := lsPointerToRawData;

Pe.ImageNtHeaders^.OptionalHeader.BaseOfData := lsPointerToRawData;

end;

end;

begin

Pe := TPeFile.Create;

Open := TOpenDialog.Create(Self);

if OpenDialog.Execute then

begin

Pe.LoadFromFile(Open.FileName);

AddExeLoader;

Pe.SaveToFile(Open.FileName);

end;

Open.Free;

Pe.Free;

end.