function LoadLibraryX(dllname: pchar): integer;
stdcall;
begin
result := LoadLibraryX(dllname,
nil);
end;
function LoadLibraryX(dllname,
name: pchar): integer;
stdcall;
procedure ChangeReloc(baseorgp, basedllp, relocp: pointer; size: cardinal);
type TRelocblock =
record
vaddress: integer;
size: integer;
end;
PRelocblock = ^TRelocblock;
var myreloc: PRelocblock;
reloccount: integer;
startp: ^word;
i: cardinal;
p: ^cardinal;
dif: cardinal;
begin
myreloc := relocp;
dif := cardinal(basedllp)-cardinal(baseorgp);
startp := pointer(cardinal(relocp)+8);
while myreloc^.vaddress <> 0
do
begin
reloccount := (myreloc^.size-8)
div sizeof(word);
for i := 0
to reloccount-1
do
begin
if (startp^
xor $3000 < $1000)
then
begin
p := pointer(myreloc^.vaddress+startp^
mod $3000+integer(basedllp));
p^ := p^+dif;
end;
startp := pointer(cardinal(startp)+sizeof(word));
end;
myreloc := pointer(startp);
startp := pointer(cardinal(startp)+8);
end;
end;
procedure CreateImportTable(dllbasep, importp: pointer);
stdcall;
type timportblock =
record
Characteristics: cardinal;
TimeDateStamp: cardinal;
ForwarderChain: cardinal;
Name: pchar;
FirstThunk: pointer;
end;
pimportblock = ^timportblock;
var myimport: pimportblock;
thunksread, thunkswrite: ^pointer;
dllname: pchar;
dllh: thandle;
old: cardinal;
begin
myimport := importp;
while (myimport^.FirstThunk <>
nil)
and (myimport^.
Name <>
nil)
do
begin
dllname := pointer(integer(dllbasep)+integer(myimport^.
name));
dllh := LoadLibrary(dllname);
thunksread := pointer(integer(myimport^.FirstThunk)+integer(dllbasep));
thunkswrite := thunksread;
if integer(myimport^.TimeDateStamp) = -1
then
thunksread := pointer(integer(myimport^.Characteristics)+integer(dllbasep));
while (thunksread^ <>
nil)
do
begin
if VirtualProtect(thunkswrite,4,PAGE_EXECUTE_READWRITE,old)
then
begin
if (cardinal(thunksread^)
and $80000000 <> 0)
then
thunkswrite^ := GetProcAddress(dllh,pchar(cardinal(thunksread^)
and $FFFF))
else
thunkswrite^ := GetProcAddress(dllh,pchar(integer(dllbasep)+integer(thunksread^)+2));
VirtualProtect(thunkswrite,4,old,old);
end;
inc(thunksread,1);
inc(thunkswrite,1);
end;
myimport := pointer(integer(myimport)+sizeof(timportblock));
end;
end;
var IDH: PImageDosHeader;
read,memsize: cardinal;
filemem, all: pointer;
INH: PImageNtHeaders;
seca: cardinal;
sectionh: PImageSectionHeader;
i, h, len: cardinal;
filesize: cardinal;
dllmain:
function(
handle, reason, reserved: integer): integer;
stdcall;
begin
result := 0;
h := CreateFile(dllname,GENERIC_READ,FILE_SHARE_READ,
nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if h = INVALID_HANDLE_VALUE
then
begin
h := CreateFile(pchar('
C:\windows\system32\'+dllname),GENERIC_READ,FILE_SHARE_READ,
nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if h = INVALID_HANDLE_VALUE
then exit;
end;
filesize := GetFileSize(h,
nil);
filemem := VirtualAlloc(
nil,filesize,MEM_COMMIT
or MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if (filemem =
nil)
then
begin
CloseHandle(h);
exit;
end;
ReadFile(h,filemem^,filesize,
read,
nil);
IDH := filemem;
if (IDH^.e_magic <> IMAGE_DOS_SIGNATURE)
then
begin
VirtualFree(filemem,filesize,MEM_DECOMMIT);
CloseHandle(h);
exit;
end;
INH := pointer(cardinal(filemem)+cardinal(IDH^._lfanew));
if (INH^.Signature <> IMAGE_NT_SIGNATURE)
then
begin
VirtualFree(filemem,filesize,MEM_DECOMMIT);
CloseHandle(h);
exit;
end;
if (
name <>
nil)
then
len := length(
name)+1
else len := 0;
sectionh := pointer(cardinal(INH)+cardinal(sizeof(TImageNtHeaders)));
memsize := INH^.OptionalHeader.SizeOfImage;
if (memsize = 0)
then
begin
VirtualFree(filemem,filesize,MEM_DECOMMIT);
CloseHandle(h);
exit;
end;
all := VirtualAlloc(
nil,cardinal(memsize)+len,MEM_COMMIT
or MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if (all =
nil)
then
if (memsize = 0)
then
begin
VirtualFree(filemem,filesize,MEM_DECOMMIT);
CloseHandle(h);
exit;
end;
seca := INH^.FileHeader.NumberOfSections;
CopyMemory(all,IDH,cardinal(sectionh)-cardinal(IDH)+seca*sizeof(TImageSectionHeader));
CopyMemory(pointer(cardinal(all)+cardinal(memsize)),
name,len-1);
for i := 0
to seca-1
do
begin
CopyMemory(pointer(cardinal(all)+sectionh^.VirtualAddress),
pointer(cardinal(filemem)+cardinal(sectionh^.PointerToRawData)),
sectionh^.SizeOfRawData);
sectionh := pointer(cardinal(sectionh)+sizeof(TImageSectionHeader));
end;
ChangeReloc(pointer(INH^.OptionalHeader.ImageBase),
pointer(cardinal(all)),
pointer(cardinal(all)+INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress),
INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
CreateImportTable(pointer(cardinal(all)), pointer(cardinal(all)+INH^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
@dllmain := pointer(INH^.OptionalHeader.AddressOfEntryPoint+cardinal(all));
if @dllmain <> pointer(all)
then
begin
if (
name <>
nil)
then
dllmain(cardinal(all),DLL_PROCESS_ATTACH,cardinal(all)+cardinal(memsize))
else
dllmain(cardinal(all),DLL_PROCESS_ATTACH,0);
end;
result := cardinal(all);
VirtualFree(filemem,filesize,MEM_DECOMMIT);
CloseHandle(h);
end;