关于进程内的API钩子 我的应用程序或VCL本身调用了API函数,但是我想在不改变VCL源码或本身应用程序的情况下,写一个钩子,这个钩子只对我这个应用程序有效。如我想我的程序在调用:CreateBitmap API函数时先调用我的函数。谢谢各位高手。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 http://www.xfocus.net/articles/200205/392.html 按照楼上提供的地址,改了,但是没有Hook成功。代码如下:unit uHook;interfaceuses Windows, Messages, SysUtils, Classes;type TlmportCode = packed record Jumplnstruction: Word; //是$25FF,JUMP指令 AddressOfPointerToFunction: PPointer;//真正开始的地址 end; PlmportCode = ^TlmportCode;var FuncMessageboxA, FuncMessageboxW: PlmportCode;//静态挂接procedure API_Hookup;procedure Un_API_Hook;implementationtype TmessageA = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall; TmessageW = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall;var OldMessageBoxA: TmessageA; OldMessageBoxW: TmessageW;function TrueFunctionAddress(func: Pointer): Pointer;var Code: PlmportCode;Begin //返回指定函数的真正地址 Result:= func; if func = nil then exit; try Code := func; if (Code.jumplnstruction = $25FF) then Result := Code.AddressOfPointerToFunction^; except Result :=nil; end;end;Procedure PermuteFunction(OldFunc: pointer; NewFunc: pointer);var Written: DWORD; begin //写地址函数 WriteProcessMemory(GetCurrentProcess, @OldFunc, @NewFunc, 4, Written) // raise Exception.Create('Hook OK');end;function MyBoxA(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall;begin //新函数 result :=OldMessageBoxA(hWnd, 'Succes Hook MessageBoxA!', lpCaption, uType);end;function MyBoxW(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall;begin //新函数 result :=OldMessageBoxW(hWnd, 'Succes Hook MessageBoxW!', lpCaption, uType);end;procedure API_Hookup;begin //在旧函数的地址写上自己的函数 PermuteFunction(@FuncMessageboxA, @MyBoxA); PermuteFunction(@FuncMessageboxW, @MyBoxW);end;procedure Un_API_Hook;begin //在旧的函数地址写旧的函数 PermuteFunction(@FuncMessageboxA, @OldMessageboxA); PermuteFunction(@FuncMessageboxW, @OldMessageboxW);end;initialization //记住旧函数的跳转的指令位置. FuncMessageboxA:= @MessageBoxA; FuncMessageboxW:= @MessageBoxW; //从旧函数指针返回旧函数的真实地址,便于将来写回. @OldMessageBoxA:= TrueFunctionAddress(@MessageBoxA); @OldMessageBoxW:= TrueFunctionAddress(@MessageBoxW);end.Formuses uhook;procedure TForm1.btn2Click(Sender: TObject);begin API_Hookup;end;procedure TForm1.btn4Click(Sender: TObject);begin MessageBoxA(Form1.Handle,'NO HOOK UP A','MessageBoxA',MB_OK); MessageBoxW(Form1.Handle,'NO HOOK UP W','MessageBoxW',MB_OK); MessageBox (Form1.Handle,'NO HOOK UP BOX','MessageBox',MB_OK);end;procedure TForm1.btn3Click(Sender: TObject);begin Un_API_Hook;end; 呵呵,就是API Hook了例子很多的:)http://lysoft.7u7.net xthmpro_cn(安徽农民*在外打工) 的可以 sephil老大 那个 统计个数 问题还没帮我呢! 这样即可,请大家解释一下RepointAddrInModule递归函数的意思,我具体还不是很明白。以下主要代码来自CSDN:unit uhook;interfaceuses Windows, Messages, Classes;type TmessageA = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall; TmessageW = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall; //入口结构 Image_Import_Entry = record Characteristics: DWORD; TimeDateStamp: DWORD; MajorVersion: Word; MinorVersion: Word; Name: DWORD; LookupTable: DWORD; end; PImage_Import_Entry = ^Image_Import_Entry; //函数跳转的结构 TImportCode = packed record JumpInstruction: Word; //定义跳转指令jmp,是$25FF,JUMP指令 AddressOfPointerToFunction: ^Pointer; //定义要跳转到的函数,//真正开始的地址 end; PImportCode = ^TImportCode;procedure API_Hookup;procedure Un_API_Hook;implementationvar OldMessageBoxA: TmessageA; OldMessageBoxW: TmessageW;function GetFunctionAddress(PFunction: PImportCode): Pointer;begin Result:= PFunction; if PFunction = nil then exit; if (PFunction.JumpInstruction = $25FF) then Result:= PFunction.AddressOfPointerToFunction^;end;function RepointFunction(OldFunc, NewFunc: Pointer): Integer;var ProcessList: TList; function RepointAddrInModule(hModule: THandle; OldFunc, NewFunc: Pointer): Integer; var f: Pointer; RVA: DWORD; InportDLL: string; written: DWORD; Func: ^Pointer; NT: PImageNTHeaders; Dos: PImageDosHeader; ImportDesc: PImage_Import_Entry; begin //HOOK的数量 Result:= 0; //判断当前Module是否已经处理过 Dos:= Pointer(hModule); if ProcessList.IndexOf(Dos) >= 0 then exit; ProcessList.Add(Dos); if IsBadReadPtr(Dos, SizeOf(TImageDosHeader)) then exit; if Dos.e_magic <> IMAGE_DOS_SIGNATURE then exit; NT:= Pointer(Integer(Dos) + dos._lfanew); RVA:= NT^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; if RVA = 0 then exit; ImportDesc:= Pointer(Integer(Dos) + Integer(RVA)); //取旧的函数地址 OldFunc:= GetFunctionAddress(OldFunc); while (ImportDesc^.Name <> 0) do begin //递归处理函数包含的所有InprotDll InportDLL:= PChar(Integer(Dos) + Integer(ImportDesc^.Name)); RepointAddrInModule(GetModuleHandle(PChar(InportDLL)), OldFunc, NewFunc); //处理当前Dll导入的函数 Func:= Pointer(Integer(DOS) + Integer(ImportDesc.LookupTable)); while Func^ <> nil do begin f:= GetFunctionAddress(Func^); if f = OldFunc then begin WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written); if Written > 0 then Inc(Result); end; Inc(Func); end; Inc(ImportDesc); end; end;begin ProcessList:= TList.Create; try Result:= RepointAddrInModule(GetModuleHandle(nil), OldFunc, NewFunc); //这可以HOOK到“我的程序的代码” finally ProcessList.Free; end;end;function MyBoxA(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;begin //新函数 result:=OldMessageBoxA(hWnd, 'Succes Hook MessageBoxA!', lpCaption, uType);end;function MyBoxW(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;begin //新函数 // result:=OldMessageBoxW(hWnd, '成功HOOK!', lpCaption, uType); result:=OldMessageBoxA(hWnd, 'Succes Hook MessageBoxW!', lpCaption, uType);end;procedure API_Hookup;begin if @OldMessageBoxA = nil then @OldMessageBoxA:= GetFunctionAddress(@MessageBoxA); RepointFunction(@OldMessageBoxA, @MyBoxA); if @OldMessageBoxW = nil then @OldMessageBoxW:= GetFunctionAddress(@MessageBoxW); RepointFunction(@OldMessageBoxW, @MyBoxW);end;procedure Un_API_Hook;begin if @OldMessageBoxA <> nil then RepointFunction(@MyBoxA, @OldMessageBoxA); if @OldMessageBoxW <> nil then RepointFunction(@MyBoxW, @OldMessageBoxW);end;end. 另外这个代码编译的Exe文件不能用Aspack压缩,压缩后就钩不住了。还请大家帮忙! 原贴内容:关于API的钩子,我已经可以在进程内钩住了,但是如果将Exe文件用Aspack压缩后就又钩不住了,不知有没有高招?谢谢!Re:可以通过动态挂接技术,不使用Import Table的,直接就LoadLibrary后,修改由GetProcAddress获得的地址的前5Bytes为JMP XXX流程为:复制前+5Bytes(可能是6Bytes等,需要代码对齐)到某区域(可执行可写的区域)修改为JMP到地址新建立的区域中Call你的Hook过程,然后JMP到API入口+5后的地址http://lysoft.7u7.net 谢谢:ly_liuyang(Liu Yang) 目前我不使用Import Table,直接修改内存@MessageBoxA内存可以HOOK了,不受ASPACK等加壳软件的影响,但是,我HOOK不住控件对该API函数的调用,请指点一下,如果有源代码更好! 基本思路是按照这个文章,但是这个文章是错误的,文章是不完整的。http://www.xfocus.net/articles/200205/392.html 任务完成!导入表HOOK内存修改HOOK 空间无效内存修改HOOK 控件有效 串口发送短信的pdu设置问题 請教關於tstringlist 帮忙 求简单SQL语句 關于恢復數據庫的問題 高手請進 我的Delphi程序的Exe文件,再没有装Delphi的机子上不能运行, DBGrid 的onDrawDataCell事件什麽時候觸發 怎样制作磁盘扫描程序,代码举例。100 热心人来帮忙看一下为何这么奇怪? paradox 数据提交问题 再delphi中如何从进程中监视操作系统? 求 COM+ 组件的安装程序写法
代码如下:
unit uHook;interface
uses
Windows, Messages, SysUtils, Classes;
type
TlmportCode =
packed record
Jumplnstruction: Word; //是$25FF,JUMP指令
AddressOfPointerToFunction: PPointer;//真正开始的地址
end;
PlmportCode = ^TlmportCode;var
FuncMessageboxA, FuncMessageboxW: PlmportCode;
//静态挂接
procedure API_Hookup;
procedure Un_API_Hook;implementation
type
TmessageA = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall;
TmessageW = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall;var
OldMessageBoxA: TmessageA;
OldMessageBoxW: TmessageW;function TrueFunctionAddress(func: Pointer): Pointer;
var
Code: PlmportCode;
Begin
//返回指定函数的真正地址
Result:= func;
if func = nil then exit; try
Code := func;
if (Code.jumplnstruction = $25FF) then
Result := Code.AddressOfPointerToFunction^;
except
Result :=nil;
end;
end;Procedure PermuteFunction(OldFunc: pointer; NewFunc: pointer);
var
Written: DWORD;
begin
//写地址函数
WriteProcessMemory(GetCurrentProcess, @OldFunc, @NewFunc, 4, Written)
// raise Exception.Create('Hook OK');
end;function MyBoxA(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall;
begin
//新函数
result :=OldMessageBoxA(hWnd, 'Succes Hook MessageBoxA!', lpCaption, uType);
end;function MyBoxW(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall;
begin
//新函数
result :=OldMessageBoxW(hWnd, 'Succes Hook MessageBoxW!', lpCaption, uType);
end;procedure API_Hookup;
begin
//在旧函数的地址写上自己的函数
PermuteFunction(@FuncMessageboxA, @MyBoxA);
PermuteFunction(@FuncMessageboxW, @MyBoxW);
end;procedure Un_API_Hook;
begin
//在旧的函数地址写旧的函数
PermuteFunction(@FuncMessageboxA, @OldMessageboxA);
PermuteFunction(@FuncMessageboxW, @OldMessageboxW);
end;initialization
//记住旧函数的跳转的指令位置.
FuncMessageboxA:= @MessageBoxA;
FuncMessageboxW:= @MessageBoxW;
//从旧函数指针返回旧函数的真实地址,便于将来写回.
@OldMessageBoxA:= TrueFunctionAddress(@MessageBoxA);
@OldMessageBoxW:= TrueFunctionAddress(@MessageBoxW);
end.Form
uses uhook;
procedure TForm1.btn2Click(Sender: TObject);
begin
API_Hookup;
end;procedure TForm1.btn4Click(Sender: TObject);
begin
MessageBoxA(Form1.Handle,'NO HOOK UP A','MessageBoxA',MB_OK);
MessageBoxW(Form1.Handle,'NO HOOK UP W','MessageBoxW',MB_OK);
MessageBox (Form1.Handle,'NO HOOK UP BOX','MessageBox',MB_OK);
end;procedure TForm1.btn3Click(Sender: TObject);
begin
Un_API_Hook;
end;
例子很多的:)http://lysoft.7u7.net
以下主要代码来自CSDN:
unit uhook;interfaceuses
Windows, Messages, Classes;type
TmessageA = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall;
TmessageW = function(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): integer; stdcall; //入口结构
Image_Import_Entry = record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
Name: DWORD;
LookupTable: DWORD;
end;
PImage_Import_Entry = ^Image_Import_Entry;
//函数跳转的结构
TImportCode = packed record
JumpInstruction: Word; //定义跳转指令jmp,是$25FF,JUMP指令
AddressOfPointerToFunction: ^Pointer; //定义要跳转到的函数,//真正开始的地址
end;
PImportCode = ^TImportCode;procedure API_Hookup;
procedure Un_API_Hook;implementationvar
OldMessageBoxA: TmessageA;
OldMessageBoxW: TmessageW;function GetFunctionAddress(PFunction: PImportCode): Pointer;
begin
Result:= PFunction;
if PFunction = nil then exit;
if (PFunction.JumpInstruction = $25FF) then
Result:= PFunction.AddressOfPointerToFunction^;
end;function RepointFunction(OldFunc, NewFunc: Pointer): Integer;
var
ProcessList: TList;
function RepointAddrInModule(hModule: THandle; OldFunc, NewFunc: Pointer): Integer;
var
f: Pointer;
RVA: DWORD;
InportDLL: string;
written: DWORD;
Func: ^Pointer;
NT: PImageNTHeaders;
Dos: PImageDosHeader;
ImportDesc: PImage_Import_Entry;
begin
//HOOK的数量
Result:= 0; //判断当前Module是否已经处理过
Dos:= Pointer(hModule);
if ProcessList.IndexOf(Dos) >= 0 then exit;
ProcessList.Add(Dos); if IsBadReadPtr(Dos, SizeOf(TImageDosHeader)) then exit;
if Dos.e_magic <> IMAGE_DOS_SIGNATURE then exit;
NT:= Pointer(Integer(Dos) + dos._lfanew);
RVA:= NT^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if RVA = 0 then exit;
ImportDesc:= Pointer(Integer(Dos) + Integer(RVA)); //取旧的函数地址
OldFunc:= GetFunctionAddress(OldFunc);
while (ImportDesc^.Name <> 0) do
begin
//递归处理函数包含的所有InprotDll
InportDLL:= PChar(Integer(Dos) + Integer(ImportDesc^.Name));
RepointAddrInModule(GetModuleHandle(PChar(InportDLL)), OldFunc, NewFunc);
//处理当前Dll导入的函数
Func:= Pointer(Integer(DOS) + Integer(ImportDesc.LookupTable));
while Func^ <> nil do
begin
f:= GetFunctionAddress(Func^);
if f = OldFunc then
begin
WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written);
if Written > 0 then Inc(Result);
end;
Inc(Func);
end;
Inc(ImportDesc);
end;
end;begin
ProcessList:= TList.Create;
try
Result:= RepointAddrInModule(GetModuleHandle(nil), OldFunc, NewFunc); //这可以HOOK到“我的程序的代码”
finally
ProcessList.Free;
end;
end;function MyBoxA(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;
begin
//新函数
result:=OldMessageBoxA(hWnd, 'Succes Hook MessageBoxA!', lpCaption, uType);
end;function MyBoxW(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;
begin
//新函数
// result:=OldMessageBoxW(hWnd, '成功HOOK!', lpCaption, uType);
result:=OldMessageBoxA(hWnd, 'Succes Hook MessageBoxW!', lpCaption, uType);
end;procedure API_Hookup;
begin
if @OldMessageBoxA = nil then
@OldMessageBoxA:= GetFunctionAddress(@MessageBoxA);
RepointFunction(@OldMessageBoxA, @MyBoxA); if @OldMessageBoxW = nil then
@OldMessageBoxW:= GetFunctionAddress(@MessageBoxW);
RepointFunction(@OldMessageBoxW, @MyBoxW);
end;procedure Un_API_Hook;
begin
if @OldMessageBoxA <> nil then
RepointFunction(@MyBoxA, @OldMessageBoxA); if @OldMessageBoxW <> nil then
RepointFunction(@MyBoxW, @OldMessageBoxW);
end;
end.
关于API的钩子,我已经可以在进程内钩住了,但是如果将Exe文件用Aspack压缩后就又钩不住了,不知有没有高招?谢谢!Re:可以通过动态挂接技术,不使用Import Table的,直接就LoadLibrary后,修改由GetProcAddress获得的地址的前5Bytes为JMP XXX流程为:
复制前+5Bytes(可能是6Bytes等,需要代码对齐)到某区域(可执行可写的区域)
修改为JMP到地址
新建立的区域中Call你的Hook过程,然后JMP到API入口+5后的地址http://lysoft.7u7.net
目前我不使用Import Table,直接修改内存@MessageBoxA内存可以HOOK了,不受ASPACK等加壳软件的影响,但是,我HOOK不住控件对该API函数的调用,请指点一下,如果有源代码更好!
http://www.xfocus.net/articles/200205/392.html
导入表HOOK
内存修改HOOK 空间无效
内存修改HOOK 控件有效