没办法给你写一个例子吧.具体Thunk技术的讲解可以去我的博客看
http://blog.csdn.net/wr960204/archive/2008/01/29/2071480.aspx
unit Unit2;
interface
uses
Windows, Messages;
Type
TObj = class
private
FThunk : Pointer;
FHWnd : HWND;
protected
Function WndProc(hWnd: HWND;
Msg: UINT;
wParam: WPARAM;
lParam: LPARAM): Integer;
stdcall;
procedure WMTimer(var Message: TWMTimer);
message WM_TIMER;
public
constructor Create;
destructor Destroy;
override;
property HWnd : HWND read FHWnd;
end;
implementation
//构造出一段Thunk代码
Function CreateThunk(Obj : TObject;
CallBackProc: Pointer)
ointer;
const
PageSize = 4096;
SizeOfJmpCode = 5;
type
TCode = packed record
Int3: Byte;
//想调试的的时候填Int 3($CC),不想调试的时候填nop($90)
PopEAX : Byte;
//把返回地址从栈中弹出
Push: Byte;
//压栈指令
AddrOfSelf: TObject;
//压入Self地址,把Self作为第一个参数
PushEAX : Byte;
//重新压入返回地址
Jmp: Byte;
//相对跳转指令
AddrOfJmp: Cardinal;
//要跳转到的地址,
end;
var
LCode : ^TCode;
begin
//分配一段可以执行,可读写的内存
Result := VirtualAlloc(nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
LCode := Result;
LCode^.Int3 := $90;
//nop
//LCode^.Int3 := $CC;
//Int 3
LCode^.PopEAX := $58;
LCode^.Push := $68;
LCode^.AddrOfSelf := Obj;
LCode^.PushEAX := $50;
LCode^.Jmp := $E9;
LCode^.AddrOfJmp := DWORD(CallBackProc) - (DWORD(@LCode^.Jmp) + SizeOfJmpCode);//计算相对地址
end;
//销毁thunk代码
procedure ReleaseThunk(Thunk: Pointer);
begin
VirtualFree(Thunk, 0, MEM_RELEASE);
end;
var
ObjWindowClass: TWndClass = (
style: 0;
lpfnWndProc: @DefWindowProc;
cbClsExtra: 0;
cbWndExtra: 0;
hInstance: 0;
hIcon: 0;
hCursor: 0;
hbrBackground: 0;
lpszMenuName: nil;
lpszClassName: 'TObjWindow');
constructor TObj.Create;
var
TempClass: TWndClass;
ClassRegistered: Boolean;
begin
FThunk := CreateThunk(Self, @TObj.WndProc);
ObjWindowClass.hInstance := HInstance;
ClassRegistered := GetClassInfo(HInstance, ObjWindowClass.lpszClassName,
TempClass);
if not ClassRegistered or (TempClass.lpfnWndProc <> @DefWindowProc) then
begin
if ClassRegistered then
Windows.UnregisterClass(ObjWindowClass.lpszClassName, HInstance);
Windows.RegisterClass(ObjWindowClass);
end;
FHWnd := CreateWindowEx(WS_EX_TOOLWINDOW, ObjWindowClass.lpszClassName,
'', WS_POPUP {+ 0}, 0, 0, 0, 0, 0, 0, HInstance, nil);
SetWindowLong(FHWnd, GWL_WNDPROC, Longint(FThunk));
end;
destructor TObj.Destroy;
begin
DestroyWindow(FHWnd);
FHWnd := 0;
ReleaseThunk(FThunk);
inherited Destroy;
end;
procedure TObj.WMTimer(var Message: TWMTimer);
begin
Windows.MessageBox(FHWnd,'a','b',2);
end;
Function TObj.WndProc(hWnd: HWND;
Msg: UINT;
wParam: WPARAM;
lParam: LPARAM): Integer;
stdcall;
var
_Msg : TMessage;
begin
_Msg.Msg := Msg;
_Msg.LParam := lParam;
_Msg.WParam := WParam;
_Msg.Result := 0;
Dispatch(_Msg);//分派消息
Result := _Msg.Result;
end;
end.