热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于进程内的API钩子

我的应用程序或VCL本身调用了API函数,但是我想在不改变VCL源码或本身应用程序的情况下,写一个钩子,这个钩子只对我这个应用程序有效。如我想我的程序在调用:CreateBitmapAPI函数时
我的应用程序或VCL本身调用了API函数,但是我想在不改变VCL源码或本身应用程序的情况下,写一个钩子,这个钩子只对我这个应用程序有效。
如我想我的程序在调用:CreateBitmap API函数时先调用我的函数。
谢谢各位高手。

20 个解决方案

#1


顶一下

#2


请大家帮助!

#3


高深没看懂

#4


http://www.xfocus.net/articles/200205/392.html

#5


按照楼上提供的地址,改了,但是没有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;

#6


呵呵,就是API Hook了
例子很多的:)

http://lysoft.7u7.net

#7


但是我的不成功,帮忙看看。

#8


xthmpro_cn(安徽农民*在外打工) 的可以

#9


测试了是不行的。

#10


sephil老大 那个 统计个数 问题还没帮我呢!

#11


确实不行 我看了 这个 逻辑 就 不太象行的样子很多写 文章的 都是 随便一写 
没有真实的把 源代码 放再那里给大家下载

#12


请大家推荐一个行的.!

#13


这样即可,请大家解释一下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.

#14


另外这个代码编译的Exe文件不能用Aspack压缩,压缩后就钩不住了。还请大家帮忙!

#15


mark

#16


原贴内容:
关于API的钩子,我已经可以在进程内钩住了,但是如果将Exe文件用Aspack压缩后就又钩不住了,不知有没有高招?谢谢!

Re:可以通过动态挂接技术,不使用Import Table的,直接就LoadLibrary后,修改由GetProcAddress获得的地址的前5Bytes为JMP XXX

流程为:
复制前+5Bytes(可能是6Bytes等,需要代码对齐)到某区域(可执行可写的区域)
修改为JMP到地址
新建立的区域中Call你的Hook过程,然后JMP到API入口+5后的地址

http://lysoft.7u7.net

#17


up

#18


谢谢:ly_liuyang(Liu Yang) 
目前我不使用Import Table,直接修改内存@MessageBoxA内存可以HOOK了,不受ASPACK等加壳软件的影响,但是,我HOOK不住控件对该API函数的调用,请指点一下,如果有源代码更好!

#19


基本思路是按照这个文章,但是这个文章是错误的,文章是不完整的。
http://www.xfocus.net/articles/200205/392.html

#20


任务完成!
导入表HOOK
内存修改HOOK 空间无效
内存修改HOOK 控件有效

#21


  • 钩子编程(HOOK) 安装进程内键盘钩子 (1)

推荐阅读
author-avatar
方彦
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有