Closed GoogleCodeExporter closed 9 years ago
Hi,
Here is a quick example:
//------------------------------------
program HookThread;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.Classes,
CPUID in 'E:\Delphi\DDL\trunk\v2\src\CPUID.pas',
DDetours in 'E:\Delphi\DDL\trunk\v2\src\DDetours.pas',
InstDecode in 'E:\Delphi\DDL\trunk\v2\src\InstDecode.pas';
type
TMyThread = class(TThread)
protected
procedure Execute; override;
end;
var
TrampoBeginThread: function(SecurityAttributes: Pointer; StackSize: LongWord; ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
var ThreadId: TThreadID): THandle;
TrampoTerminate: procedure(Self: Pointer);
m: TMyThread;
procedure TerminateHooked(Self: Pointer);
begin
Writeln(Format('%s Terminated!', [TThread(Self).ClassName]));
TrampoTerminate(Self);
end;
function BeginThreadHooked(SecurityAttributes: Pointer; StackSize: LongWord;
ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
var ThreadId: TThreadID): THandle;
begin
Writeln(Format('%s Created!', [TThread(Parameter).ClassName]));
Result := TrampoBeginThread(SecurityAttributes, StackSize, ThreadFunc, Parameter, CreationFlags, ThreadId);
end;
{ TMyThread }
procedure TMyThread.Execute;
begin
inherited;
end;
begin
{ initialization }
@TrampoBeginThread := InterceptCreate(@BeginThread, @BeginThreadHooked);
@TrampoTerminate := InterceptCreate(@TThread.Terminate, @TerminateHooked);
m := TMyThread.Create(False);
sleep(1000);
m.Terminate;
m.Free;
{ finalization }
InterceptRemove(@TrampoBeginThread);
InterceptRemove(@TrampoTerminate);
Readln;
end.
//----------------------------
I am not sure that i will integrate this example in the DDL demo .
The purpose of demo is only to show how the library works ! and there is
already many integrated simple demo.
Regards,
Mahdi
Original comment by ismspi...@gmail.com
on 9 Jan 2015 at 4:29
Hello!
This is a better way to do it however I am not sure if this will work on
XP/XP64..
- LdrShutdownThread ( Shutdown )
- BaseThreadInitThunk ( Initialize )
- RtlUserThreadStart ( Start )
Original comment by david.lo...@gmail.com
on 9 Jan 2015 at 4:36
Attachments:
Its seems this library doesn't allow hooking in this way :/
Original comment by david.lo...@gmail.com
on 9 Jan 2015 at 4:52
Same example could be used with DDL:
//------------------------------------
program HookThread;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, WinApi.Windows, System.Classes,
CPUID in 'E:\Delphi\DDL\trunk\v2\src\CPUID.pas',
DDetours in 'E:\Delphi\DDL\trunk\v2\src\DDetours.pas',
InstDecode in 'E:\Delphi\DDL\trunk\v2\src\InstDecode.pas';
type
LPTHREAD_START_ROUTINE = function(lpThreadParameter: LPVOID): DWORD; stdcall;
TLdrShutdownThread = procedure; stdcall;
TRtlUserThreadStart = procedure(pfnStartAddr: LPTHREAD_START_ROUTINE; pvParam: PVOID); stdcall;
var
LdrShutdownThreadNext: TLdrShutdownThread;
RtlUserThreadStartNext: TRtlUserThreadStart;
RunningThreads: Integer = 0;
procedure LdrShutdownThreadCallback;
begin
Writeln('Shutdown Thread !');
LdrShutdownThreadNext;
end;
procedure RtlUserThreadStartCallback(pfnStartAddr: LPTHREAD_START_ROUTINE;
pvParam: PVOID);
begin
Writeln('Thread Started !');
RtlUserThreadStartNext(pfnStartAddr, pvParam);
end;
type
TMyThread = class(TThread)
protected
procedure Execute; override;
end;
{ TMyThread }
procedure TMyThread.Execute;
begin
inherited;
end;
var
m: TMyThread;
begin
@LdrShutdownThreadNext := InterceptCreate('ntdll.dll', 'LdrShutdownThread', @LdrShutdownThreadCallback);
@RtlUserThreadStartNext := InterceptCreate('ntdll.dll', 'RtlUserThreadStart', @RtlUserThreadStartCallback);
m := TMyThread.Create(False);
Sleep(1000);
m.Terminate;
m.Free;
InterceptRemove(@LdrShutdownThreadNext);
InterceptRemove(@RtlUserThreadStartNext);
ReadLn;
end.
//------------------------------
Original comment by ismspi...@gmail.com
on 9 Jan 2015 at 4:58
Seems LdrShutdownThread is not getting hooked on XE7 :/
But the other hook work!
Original comment by david.lo...@gmail.com
on 9 Jan 2015 at 5:04
I tested on win7 with XE7 and it's work!
Original comment by ismspi...@gmail.com
on 9 Jan 2015 at 5:17
Yes it seems I removed the hook too fast :D
Original comment by david.lo...@gmail.com
on 9 Jan 2015 at 5:20
Btw this fails on x64!
@CreateThread := InterceptCreate('kernel32.dll', 'CreateThread', @CreateThreadCallback);
Original comment by david.lo...@gmail.com
on 9 Jan 2015 at 9:41
Please report the new one in a new issue (including a steps to produce the
issue).
Original comment by ismspi...@gmail.com
on 9 Jan 2015 at 10:50
Original comment by ismspi...@gmail.com
on 9 Jan 2015 at 11:24
There seems to be another bug with BaseThreadInitThunk. Hook fails with 32 bit!
But work with x64 :/
program HookThread;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
WinApi.Windows,
System.Classes,
CPUID,
DDetours,
InstDecode;
type
LPTHREAD_START_ROUTINE = function(lpThreadParameter: LPVOID): DWORD; stdcall;
TLdrShutdownThread = procedure; stdcall;
TRtlUserThreadStart = procedure(lpStartAddress: LPTHREAD_START_ROUTINE; lpParameter: PVOID); stdcall;
TBaseThreadInitThunk = procedure(LdrReserved: DWORD; lpStartAddress: LPTHREAD_START_ROUTINE; lpParameter: LPVOID); register;
TCreateThread = function(lpThreadAttributes: Pointer; dwStackSize: SIZE_T; lpStartAddress: TFNThreadStartRoutine; lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;
var
LdrShutdownThread: TLdrShutdownThread;
RtlUserThreadStart: TRtlUserThreadStart;
BaseThreadInitThunk: TBaseThreadInitThunk;
CreateThread: TCreateThread;
procedure LdrShutdownThreadCallback; stdcall;
begin
Writeln('Thread Destroyed: ' + GetCurrentThreadId.ToString);
LdrShutdownThread;
end;
procedure RtlUserThreadStartCallback(lpStartAddress: LPTHREAD_START_ROUTINE;
lpParameter: PVOID); stdcall;
begin
Writeln('Thread Started: ' + GetCurrentThreadId.ToString);
RtlUserThreadStart(lpStartAddress, lpParameter);
end;
procedure BaseThreadInitThunkCallback(LdrReserved: DWORD; lpStartAddress:
LPTHREAD_START_ROUTINE; lpParameter: LPVOID); register;
begin
Writeln('Thread Started: ' + GetCurrentThreadId.ToString);
BaseThreadInitThunk(LdrReserved, lpStartAddress, lpParameter);
end;
function CreateThreadCallback(lpThreadAttributes: Pointer; dwStackSize: SIZE_T;
lpStartAddress: TFNThreadStartRoutine; lpParameter: Pointer; dwCreationFlags:
DWORD; var lpThreadId: DWORD): THandle; stdcall;
begin
Result := CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
Writeln('Thread Created: ' + lpThreadId.ToString + ' with Handle: ' + Result.ToString);
end;
begin
@BaseThreadInitThunk := InterceptCreate('kernel32.dll', 'BaseThreadInitThunk', @BaseThreadInitThunkCallback);
@LdrShutdownThread := InterceptCreate('ntdll.dll', 'LdrShutdownThread', @LdrShutdownThreadCallback);
@RtlUserThreadStart := InterceptCreate('ntdll.dll', 'RtlUserThreadStart', @RtlUserThreadStartCallback);
@CreateThread := InterceptCreate('kernel32.dll', 'CreateThread', @CreateThreadCallback);
TThread.CreateAnonymousThread(
procedure
begin
Sleep(1000);
end).Start;
ReadLn;
InterceptRemove(@LdrShutdownThread);
InterceptRemove(@BaseThreadInitThunk);
InterceptRemove(@RtlUserThreadStart);
InterceptRemove(@CreateThread);
end.
Original comment by david.lo...@gmail.com
on 10 Jan 2015 at 10:26
Hi,
This is not a bug related to DDL!
First you are hooking undocumented functions.
Second TRtlUserThreadStart seems to be register and TBaseThreadInitThunk seems
to be stdcall.
DDL will fails when passing wrong params or wrong calling convention (since
it's undocumented functions , it's hardly to guess the correct args
type/calling convention.
Last thing, when you report a bug make sure that you are given a correct
functions parameters and calling convention so i can work on your
issue.Undocumented functions are hardly to debug and hardly for invoke (I don't
guarantee anything!).
//---------------------------------------------
program Project1;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
WinApi.Windows,
System.Classes,
CPUID in 'E:\Delphi\DDL\trunk\v2\src\CPUID.pas',
DDetours in 'E:\Delphi\DDL\trunk\v2\src\DDetours.pas',
InstDecode in 'E:\Delphi\DDL\trunk\v2\src\InstDecode.pas';
type
LPTHREAD_START_ROUTINE = function(lpThreadParameter: LPVOID): DWORD; stdcall;
TLdrShutdownThread = procedure; stdcall;
TRtlUserThreadStart = procedure(lpStartAddress: LPTHREAD_START_ROUTINE; lpParameter: PVOID); register;
TBaseThreadInitThunk = procedure(LdrReserved: DWORD; lpStartAddress: LPTHREAD_START_ROUTINE; lpParameter: LPVOID); stdcall;
TCreateThread = function(lpThreadAttributes: Pointer; dwStackSize: SIZE_T; lpStartAddress: TFNThreadStartRoutine; lpParameter: Pointer;
dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;
var
LdrShutdownThread: TLdrShutdownThread;
RtlUserThreadStart: TRtlUserThreadStart;
BaseThreadInitThunk: TBaseThreadInitThunk;
CreateThread: TCreateThread;
procedure LdrShutdownThreadCallback; stdcall;
begin
Writeln('Thread Destroyed: ' + GetCurrentThreadId.ToString);
LdrShutdownThread;
end;
procedure RtlUserThreadStartCallback(lpStartAddress: LPTHREAD_START_ROUTINE;
lpParameter: PVOID); register;
begin
Writeln('Thread Started: ' + GetCurrentThreadId.ToString);
RtlUserThreadStart(lpStartAddress, lpParameter);
end;
procedure BaseThreadInitThunkCallback(LdrReserved: DWORD; lpStartAddress:
LPTHREAD_START_ROUTINE; lpParameter: LPVOID); stdcall;
begin
// Writeln('Thread Started: ' + GetCurrentThreadId.ToString);
BaseThreadInitThunk(LdrReserved, lpStartAddress, lpParameter);
end;
function CreateThreadCallback(lpThreadAttributes: Pointer; dwStackSize: SIZE_T;
lpStartAddress: TFNThreadStartRoutine; lpParameter: Pointer;
dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;
begin
Result := CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
Writeln('Thread Created: ' + lpThreadId.ToString + ' with Handle: ' + Result.ToString);
end;
begin
@BaseThreadInitThunk := InterceptCreate('kernel32.dll', 'BaseThreadInitThunk', @BaseThreadInitThunkCallback);
@LdrShutdownThread := InterceptCreate('ntdll.dll', 'LdrShutdownThread', @LdrShutdownThreadCallback);
@RtlUserThreadStart := InterceptCreate('ntdll.dll', 'RtlUserThreadStart', @RtlUserThreadStartCallback);
@CreateThread := InterceptCreate('kernel32.dll', 'CreateThread', @CreateThreadCallback);
TThread.CreateAnonymousThread(
procedure
begin
Sleep(1000);
end).Start;
ReadLn;
InterceptRemove(@LdrShutdownThread);
InterceptRemove(@BaseThreadInitThunk);
InterceptRemove(@RtlUserThreadStart);
InterceptRemove(@CreateThread);
end.
Original comment by ismspi...@gmail.com
on 11 Jan 2015 at 11:14
Yes I use these hooked functions for thread diagnostics! To find bugs in my
program :)
Original comment by david.lo...@gmail.com
on 11 Jan 2015 at 11:25
Original issue reported on code.google.com by
david.lo...@gmail.com
on 9 Jan 2015 at 11:01