Hi,
Some may find this usefull, others may not. We are assuming you are loaded inside the process.
Code:
type
PImageDOSHeader = ^TImageDOSHeader;
TImageDOSHeader = packed record
e_magic: Word;
e_cblp: Word;
e_cp: Word;
e_crlc: Word;
e_cparhdr: Word;
e_minalloc: Word;
e_maxalloc: Word;
e_ss: Word;
e_sp: Word;
e_csum: Word;
e_ip: Word;
e_cs: Word;
e_lfarlc: Word;
e_onvo: Word;
e_res: array [0..3] of Word;
e_oemid: Word;
e_oeminfo: Word;
e_res2: array [0..9] of Word;
e_lfanew: DWord;
end;
type
PImageNtHeaders = ^TImageNtHeaders;
TImageNtHeaders = packed record
signature: dword;
FileHeader: TImageFileHeader;
OptionalHeader: TImageOptionalHeader;
end;
type
PImageFileHeader = ^TImageFileHeader;
TImageFileHeader = packed record
Machine: Word;
NumberOfSections: Word;
TimeDateStamp: dword;
PointerToSymbolTable: dword;
NumberOfSymbols: dword;
SizeOfOptionalHeader: Word;
Characteristics: Word;
end;
type
PImageOptionalHeader = ^TImageOptionalHeader;
TImageOptionalHeader = packed record
Magic: Word;
MajorLinkerVersion: byte;
MinorLinkerVersion: byte;
SizeOfCode : dword;
SizeOfInitializedData: dword;
SizeOfUninitializedData: dword;
AddressOfEntryPoint: dword;
BaseOfCode: dword;
BaseOfData: dword;
ImageBase: dword;
SectionAlignment: dword;
FileAlignment: dword;
MajorOperatingSystemVersion: Word;
MinorOperatingSystemVersion: Word;
MajorImageVersion: Word;
MinorImageVersion: Word;
MajorSubsystemVersion: Word;
MinorSubsystemVersion: Word;
Win32VersionVaule: dword;
SizeOfImage: dword;
SizeOfHeaders: dword;
CheckSum: dword;
Subsystem : Word;
DllCharacteristics: Word;
SizeOfStackReserve: dword;
SizeOfStackCommit: dword;
SizeOfHeapReserve: dword;
SizeOfHeapCommit: dword;
LoaderFlags: dword;
NumberOfRvaAndSizes: dword;
DataDirectory: array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory
end;
type
PImageDataDirectory = ^TImageDataDirectory;
TImageDataDirectory = packed record
VirtualAddress: dword;
size: dword;
end;
type
PImageImportDirectory = ^TImageImportDirectory;
TImageImportDirectory = packed record
rvaImportLookupTable: dword;
TimeDateStamp: dword;
ForwarderChain: dword;
rvaModuleName: dword;
rvaImportAddressTable: dword;
end;
function PatchIAT(Module: string; Import: string; NewFunctor: Pointer): boolean;
var
Base: Pointer;
ImportDW, CurrentImport: DWORD;
CurrentName: string;
Function RVA(P: Cardinal): Pointer;
begin
result:=PChar(Base) + P;
end;
var
PDOS: PImageDosHeader;
PNew: PImageNtHeaders;
PIID: PImageImportDirectory;
PRVA: PDWORD;
OldProtect, MyProtect: Cardinal;
begin
result:=false;
Module:=LowerCase(Module);
Base:=Pointer(GetModuleHandle(nil));
ImportDW:=DWORD(GetProcAddress(GetModuleHandle(PChar(Module)), PChar(Import)));
if ImportDW = 0 then
exit;
PDOS:=PImageDosHeader(Base);
PNew:=PIMageNtHeaders(RVA(PDOS^.e_lfanew));
PIID:=RVA(PNew^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while PIID^.rvaModuleName <> 0 do
begin
CurrentName:=LowerCase(PChar(RVA(PIID^.rvaModuleName)));
if (CurrentName = Module) then
begin
PRVA:=PDWORD(RVA(PIID^.rvaImportAddressTable));
while PRVA^ <> 0 do
begin
CurrentImport:=PRVA^;
if CurrentImport = ImportDW then
begin
//VirtualProtect(PRVA, 4, PAGE_EXECUTE_READWRITE, OldProtect);
PRVA^:=DWORD(NewFunctor);
//VirtualProtect(PRVA, 4, OldProtect, MyProtect);
result:=true;
MessageBox(0,PChar(IntToStr(GetCurrentProcessID)),PChar(IntToStr(GetCurrentProcessID)),0);
end;
inc(PRVA);
end;
end;
inc(PIID);
end;
end;
procedure Patch(dst, src, count: DWORD);
var
oldprot, tmp: DWORD;
begin
VirtualProtect(Pointer(dst), count, PAGE_EXECUTE_READWRITE, oldprot);
if not IsBadWritePtr(Pointer(dst), count) then
CopyMemory(Pointer(dst), Pointer(src), count)
else MessageBox(0, 'Patch failed', nil, 0);
VirtualProtect(Pointer(dst), count, oldprot, tmp);
end;
procedure PatchInJumpTo(Where: DWORD; JmpTo: DWORD; nops: Integer = 0);
var
PB: array[0..4+10] of byte;
offset: DWORD;
i: Integer;
begin
for i:=0 to PRED(sizeof(PB)) do
PB[i]:=$90;
offset:=JmpTo - Where - 5;
PB[0]:=$E9; // jump
PDWORD(PB[1])^:=offset;
Patch(Where, DWORD(PB), 5 + nops);
end;
procedure PatchInCallTo(Where: DWORD; JmpTo: DWORD; nops: Integer = 0);
var
PB: array[0..4+10] of byte;
offset: DWORD;
i: Integer;
begin
for i:=0 to PRED(sizeof(PB)) do
PB[i]:=$90;
offset:=JmpTo - Where - 5;
PB[0]:=$E8; // call
PDWORD(PB[1])^:=offset;
Patch(Where, DWORD(PB), 5 + nops);
end;
function NewCreateProcess(r1,r2: Pointer; lpApplicationName: PChar; lpCommandLine: PChar; lpProcessAttributes: PSecurityAttributes; lpThreadAttributes: PSecurityAttributes; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo; var lpProcessInformation: TProcessInformation): BOOL; cdecl;
begin
MessageBox(0,'Hooked','Hooked to my function',0);
end;
procedure NewCreateProcessStub; assembler;
asm
jmp NewCreateProcess
pop eax
push ebp
mov ebp, esp
jmp eax
end;
Useage Example: PatchIAT('kernel32.dll', 'CreateProcessA', NewCreateProcess)
Useage Example: PatchInJumpTo(dwCreateProcess, DWORD(NewCreatProcessStub));
Useage Example: PatchInCallTo(dwCreateProcess, DWORD(NewCreateProcessStub));
Hopefully some of you can put this to good use!
If you need examples of how to use, i have plenty of examples.
(NOTE: The site did not like me using the "at" symbol so i have to edit this post once its approved)