作者:方彦 | 来源:互联网 | 2023-08-25 18:11
我的应用程序或VCL本身调用了API函数,但是我想在不改变VCL源码或本身应用程序的情况下,写一个钩子,这个钩子只对我这个应用程序有效。如我想我的程序在调用:CreateBitmapAPI函数时
我的应用程序或VCL本身调用了API函数,但是我想在不改变VCL源码或本身应用程序的情况下,写一个钩子,这个钩子只对我这个应用程序有效。
如我想我的程序在调用:CreateBitmap API函数时先调用我的函数。
谢谢各位高手。
20 个解决方案
http://www.xfocus.net/articles/200205/392.html
按照楼上提供的地址,改了,但是没有Hook成功。
代码如下:
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;
呵呵,就是API Hook了
例子很多的:)
http://lysoft.7u7.net
xthmpro_cn(安徽农民*在外打工) 的可以
sephil老大 那个 统计个数 问题还没帮我呢!
确实不行 我看了 这个 逻辑 就 不太象行的样子很多写 文章的 都是 随便一写
没有真实的把 源代码 放再那里给大家下载
这样即可,请大家解释一下RepointAddrInModule递归函数的意思,我具体还不是很明白。
以下主要代码来自CSDN:
unit uhook;
interface
uses
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;
implementation
var
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 控件有效