We don't display ads so we rely on your Bitcoin donations to 1KWEk9QaiJb2NwP5YFmR24LyUBa4JyuKqZ
Post date: Aug 25, 2010 1:48:21 PM
{
[===========================================]
[?]uDllFromMem - Loading a DLL from Memory[?]
[v] Version 1.0 [v]
[c] Hamtaro aka CorVu5 [c]
[@] hamtaro.6x.to OR corvu5.6x.to [@]
[================Description================]
[With this Code, you can load a DLL in your ]
[application directly from Memory, the file ]
[doesnt have to be present on your Harddrive]
[===================Note====================]
[ This example doesnt work with Bound ]
[ Import Tables at this time ]
[==================thx to===================]
[ CDW, Cryptocrack ]
[ & Joachim Bauch for his ]
[ GetSectionProtection function ]
[===========================================]
[ there must be 50 ways to learn to hover ]
[===========================================]
}
unit uDllfromMem;
interface
uses windows;
type
PImageBaseRelocation = ^TImageBaseRelocation;
_IMAGE_BASE_RELOCATION = packed record
VirtualAddress: DWORD;
SizeOfBlock: DWORD;
end;
{$EXTERNALSYM _IMAGE_BASE_RELOCATION}
TImageBaseRelocation = _IMAGE_BASE_RELOCATION;
IMAGE_BASE_RELOCATION = _IMAGE_BASE_RELOCATION;
{$EXTERNALSYM IMAGE_BASE_RELOCATION}
type
PImageImportDescriptor = ^TImageImportDescriptor;
TImageImportDescriptor = packed record
OriginalFirstThunk: dword;
TimeDateStamp: dword;
ForwarderChain: dword;
Name: dword;
FirstThunk: dword;
end;
type
PImageImportByName = ^TImageImportByName;
TImageImportByName = packed record
Hint : WORD;
Name : array[0..255] of Char;
end;
type
PImageThunkData = ^TImageThunkData;
TImageThunkData = packed record
case integer of
0 : (ForwarderString: PBYTE);
1 : (FunctionPtr : PDWORD);
2 : (Ordinal : DWORD);
3 : (AddressOfData : PImageImportByName);
end;
type
TDllEntryProc = function(hinstdll: THandle; fdwReason: DWORD; lpReserved: Pointer): BOOL; stdcall;
function memLoadLibrary(FileBase : Pointer) : Pointer;
function memGetProcAddress(Physbase : Pointer; NameOfFunction : String) : Pointer;
function memFreeLibrary(physbase : Pointer) : Boolean;
const
IMAGE_REL_BASED_HIGHLOW = 3;
IMAGE_ORDINAL_FLAG32 = DWORD($80000000);
var DllentryProc : TDLLEntryProc;
implementation
//strComp Function from SysUtils
function StrComp(const Str1, Str2: PChar): Integer; assembler;
asm
PUSH EDI
PUSH ESI
MOV EDI,EDX
MOV ESI,EAX
MOV ECX,0FFFFFFFFH
XOR EAX,EAX
REPNE SCASB
NOT ECX
MOV EDI,EDX
XOR EDX,EDX
REPE CMPSB
MOV AL,[ESI-1]
MOV DL,[EDI-1]
SUB EAX,EDX
POP ESI
POP EDI
end;
function GetSectionProtection(ImageScn: cardinal): cardinal;
begin
Result := 0;
if (ImageScn and IMAGE_SCN_MEM_NOT_CACHED) <> 0 then
begin
Result := Result or PAGE_NOCACHE;
end;
if (ImageScn and IMAGE_SCN_MEM_EXECUTE) <> 0 then
begin
if (ImageScn and IMAGE_SCN_MEM_READ)<> 0 then
begin
if (ImageScn and IMAGE_SCN_MEM_WRITE)<> 0 then
begin
Result := Result or PAGE_EXECUTE_READWRITE
end
else
begin
Result := Result or PAGE_EXECUTE_READ
end;
end
else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
begin
Result := Result or PAGE_EXECUTE_WRITECOPY
end
else
begin
Result := Result or PAGE_EXECUTE
end;
end
else if (ImageScn and IMAGE_SCN_MEM_READ)<> 0 then
begin
if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
begin
Result := Result or PAGE_READWRITE
end
else
begin
Result := Result or PAGE_READONLY
end
end
else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
begin
Result := Result or PAGE_WRITECOPY
end
else
begin
Result := Result or PAGE_NOACCESS;
end;
end;
function memLoadLibrary(FileBase : Pointer) : Pointer;
var
pfilentheader : PIMAGENTHEADERS;
pfiledosheader: PIMAGEDOSHEADER;
pphysntheader : PIMAGENTHEADERS;
pphysdosheader: PIMAGEDOSHEADER;
physbase : Pointer;
pphyssectionheader : PIMAGESECTIONHEADER;
i : Integer;
importsDir : PImageDataDirectory;
importsBase: Pointer;
importDesc : PImageImportDescriptor;
importThunk: PImageThunkData;
dll_handle : Cardinal;
importbyname : pimageimportbyname;
relocbase : Pointer;
relocdata : PIMAGeBaseRElocation;
relocitem : PWORD;
reloccount : Integer;
dllproc : TDLLEntryProc;
begin
result := 0;
pfiledosheader := filebase;
pfilentheader := Pointer(Cardinal(filebase) + pfiledosheader^._lfanew);
////////////////////////
/////////////allozieren/
physbase := VirtualAlloc(Pointer(pfilentheader^.OptionalHeader.ImageBase),pfilentheader^.OptionalHeader.SizeOfImage,MEM_RESERVE,PAGE_READWRITE);
if Cardinal(physbase) = 0 Then begin
physbase := VirtualAlloc(0,pfilentheader^.OptionalHeader.SizeOfImage,MEM_RESERVE Or Mem_COMMIT,PAGE_READWRITE);
end;
/////////////////////////////
/////////////header kopieren/
CopyMemory(physbase,filebase,pfilentheader^.OptionalHeader.SizeOfHeaders);
//header im memory finden & anpassen
pphysdosheader := physbase;
pphysntheader := Pointer(Cardinal(physbase) + pphysdosheader^._lfanew);
pphysntheader^.OptionalHeader.ImageBase := Cardinal(physbase);
///////////////////////////////
/////////////sections kopieren/
pphyssectionheader := Pointer(Cardinal(pphysntheader) + SizeOf(TIMAGENTHEADERS));
for i := 0 To (pphysntheader^.FileHeader.NumberOfSections - 1) do begin
if pphyssectionheader^.SizeOfRawData = 0 Then begin
//keine raw data
ZeroMemory(Pointer(Cardinal(physbase) + pphyssectionheader^.VirtualAddress),pphyssectionheader^.Misc.VirtualSize);
end else begin
//raw data vorhanden
CopyMemory(Pointer(Cardinal(physbase) + pphyssectionheader^.VirtualAddress),Pointer(Cardinal(filebase) + pphyssectionheader^.PointerToRawData),pphyssectionheader^.SizeOfRawData);
end;
pphyssectionheader^.Misc.PhysicalAddress := Cardinal(physbase) + pphyssectionheader^.VirtualAddress;
//next one please
pphyssectionheader := Pointer(Cardinal(pphyssectionheader) + SizeOf(TIMAGESECTIONHEADER));
end;
//////////////////////
/////////////imports/
importsBase := Pointer(Cardinal(physbase) + pphysntheader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
importDesc := importsBase;
while (importDesc.Name) <> 0 Do begin
dll_handle := LoadLibrary(pchar(Cardinal(physbase) + importdesc.Name));
importDesc.ForwarderChain := dll_handle;
importThunk := Pointer(Cardinal(physbase) + importDesc.FirstThunk);
while importThunk.Ordinal <> 0 Do begin
importbyname := Pointer(Cardinal(physbase) + importThunk.Ordinal);
//Später noch überprüfen ob OriginalFirstThunk = 0
if (importThunk.Ordinal and IMAGE_ORDINAL_FLAG32) <> 0 Then
begin //ordinal
importThunk.FunctionPtr := GetProcaddress(dll_handle,pchar(importThunk.Ordinal and $ffff))
end else begin //normal
importThunk.FunctionPtr := GetProcAddress(dll_handle,importByname.name);
end;
//next one, please
importThunk := Pointer(Cardinal(importThunk) + SizeOf(TIMAGETHUNKDATA));
end;
//next one, please
importDesc := Pointer(Cardinal(importDesc) + sizeOf(TIMAGEIMPORTDESCRIPTOR));
end;
/////////////////////
/////////////relocs/
relocbase := Pointer(Cardinal(physbase) + pphysntheader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
relocData := RElocbase;
while (Cardinal(relocdata) - Cardinal(relocbase)) < pphysntheader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size do begin
reloccount := trunc((relocdata.SizeOfBlock - 8) / 2);
relocitem := Pointer(Cardinal(relocdata) + 8);
For i := 0 To (reloccount - 1) do begin
if (relocitem^ shr 12) = IMAGE_REL_BASED_HIGHLOW Then begin
Inc(PDWord(Cardinal(physbase) + relocdata.VirtualAddress + (relocitem^ and $FFF))^,(Cardinal(physbase) - pfilentheader.OptionalHeader.ImageBase));
end;
relocitem := Pointer(Cardinal(relocitem) + SizeOf(WORD));
end;
//next one please
relocdata := Pointer(Cardinal(relocdata) + relocdata.SizeOfBlock);
end;
/////////////////////////////////
////////Section protection & so/
pphyssectionheader := Pointer(Cardinal(pphysntheader) + SizeOf(TIMAGENTHEADERS));
For i := 0 To (pphysntheader^.FileHeader.NumberOfSections - 1) do begin
VirtualProtect(Pointer(Cardinal(physbase) + pphyssectionheader^.VirtualAddress),pphyssectionheader^.Misc.VirtualSize,GetSectionProtection(pphyssectionheader.Characteristics),nil);
pphyssectionheader := Pointer(Cardinal(pphyssectionheader) + SizeOf(TIMAGESECTIONHEADER));
end;
////////////////////////////////
////////////////Dll entry proc/
dllEntryproc := Pointer(Cardinal(physbase) + pphysntheader.OptionalHeader.AddressOfEntryPoint);
dllEntryproc(cardinal(physbase),DLL_PROCESS_ATTACH,nil);
result := physbase;
end;
function memGetProcAddress(Physbase : Pointer; NameOfFunction : String) : Pointer;
var
pdosheader: PIMAGEDOSHEADER;
pntheader : PIMAGENTHEADERS;
pexportdir: PImageExportDirectory;
i : Integer;
pexportname : PDWORD;
pexportordinal : PWORD;
pexportFunction : PDWORD;
begin
result := 0;
pdosheader := physbase;
pntheader := Pointer(Cardinal(physbase) + pdosheader._lfanew);
pexportdir := Pointer(Cardinal(physbase) + pntheader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
if pexportdir.NumberOfFunctions Or pexportdir.NumberOfNames = 0 Then exit;
pexportName := Pointer(Cardinal(physbase) + Cardinal(pexportDir.AddressOfNames));
pexportordinal := Pointer(Cardinal(physbase) + Cardinal(pexportDir.AddressOfNameOrdinals));
pexportFunction:= Pointer(Cardinal(physbase) + Cardinal(pexportDir.AddressOfFunctions));
For i := 0 To (pexportdir.NumberOfNames - 1) Do begin
if StrComp(pchar(Pointer(Cardinal(physbase) + pexportName^)),pchar(NameOfFunction)) = 0 Then begin
result := pchar(Pointer(Cardinal(physbase) + pexportFunction^));
break;
end;
//next one, please
Inc(pexportFunction);
Inc(pexportName);
Inc(pexportOrdinal);
end;
end;
function memFreeLibrary(physbase : Pointer) : Boolean;
begin
try begin
//Keine Ahnung ob die DLL ihre Imports wieder "Free't" wenn man DLL_PROCESS_DETACH aufruft
result := true;
dllEntryProc(Cardinal(physbase),DLL_PROCESS_DETACH,0);
VirtualFree(physbase,0,MEM_RELEASE);
end except
result := false;
end;
end;
end.