拦截的API,留下记号 不指定

青色咖啡 , 2011/04/12 19:21 , 转载文章 , 评论(1) , 阅读(414) , Via 本站原创 | |

要拦截的API如下:

   MessageBoxA、MessageBoxW、MessageBeep 和 OpenProcess 。

   首先,大家都知道要在整个系统范围中拦截,需要使用Dll来完成。现在我们打开Delphi 2009,新建一个Dll工程:hookDll。需要说明的是,Delphi是完全面向对象的编程语言,所以我们不要浪费,这个Dll打算用类的方式完成。于是,在新建的DLL工程中在添加一个Unit Pas,命名为unitHook, 用来写拦截类的处理。unitHook.pas中的代码如下:

unit unitHook;interfaceuses  Windows, Messages, Classes, SysUtils;type  //NtHook类相关类型  TNtJmpCode=packed record  //8字节    MovEax:Byte;    Addr:DWORD;    JmpCode:Word;    dwReserved:Byte;  end;  TNtHookClass=class(TObject)  private    hProcess:THandle;    NewAddr:TNtJmpCode;    OldAddr:array[0..7] of Byte;    ReadOK:Boolean;  public    BaseAddr:Pointer;    constructor Create(DllName,FuncName:string;NewFunc:Pointer);    destructor Destroy; override;    procedure Hook;    procedure UnHook;  end;implementation//==================================================//NtHOOK 类开始//==================================================constructor TNtHookClass.Create(DllName: string; FuncName: string;NewFunc:Pointer);var  DllModule:HMODULE;  dwReserved:DWORD;begin  //获取模块句柄  DllModule:=GetModuleHandle(PChar(DllName));  //如果得不到说明未被加载  if DllModule=0 then DllModule:=LoadLibrary(PChar(DllName));  //得到模块入口地址(基址)  BaseAddr:=Pointer(GetProcAddress(DllModule,PChar(FuncName)));  //获取当前进程句柄  hProcess:=GetCurrentProcess;  //指向新地址的指针  NewAddr.MovEax:=$B8;  NewAddr.Addr:=DWORD(NewFunc);  NewAddr.JmpCode:=$E0FF;  //保存原始地址  ReadOK:=ReadProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved);  //开始拦截  Hook;end;//释放对象destructor TNtHookClass.Destroy;begin  UnHook;  CloseHandle(hProcess);  inherited;end;//开始拦截procedure TNtHookClass.Hook;var  dwReserved:DWORD;begin  if (ReadOK=False) then Exit;  //写入新的地址  WriteProcessMemory(hProcess,BaseAddr,@NewAddr,8,dwReserved);end;//恢复拦截procedure TNtHookClass.UnHook;var  dwReserved:DWORD;begin  if (ReadOK=False) then Exit;  //恢复地址  WriteProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved);end;end.

至此,unitHook.pas的代码OK了,其中加了详细的注释,在此就不再多做解释。现在切换到Dll的代码页,写入以下代码:
 
library hookdll;uses  SysUtils, Windows,  Classes,  unitHook in 'unitHook.pas';{$R *.res}const  HOOK_MEM_FILENAME  =  'tmp.hkt';var  hhk: HHOOK;  Hook: array[0..3] of TNtHookClass;  //内存映射  MemFile: THandle;  startPid: PDWORD;   //保存PID{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}//拦截 MessageBoxAfunction NewMessageBoxA(_hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;type  TNewMessageBoxA = function (_hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;begin  lpText := PAnsiChar('已经被拦截 MessageBoxA');  Hook[0].UnHook;  Result := TNewMessageBoxA(Hook[0].BaseAddr)(_hWnd, lpText, lpCaption, uType);  Hook[0].Hook;end;//拦截 MessageBoxWfunction NewMessageBoxW(_hWnd: HWND; lpText, lpCaption: PWideChar; uType: UINT): Integer; stdcall;type  TNewMessageBoxW = function (_hWnd: HWND; lpText, lpCaption: PWideChar; uType: UINT): Integer; stdcall;begin  lpText := '已经被拦截 MessageBoxW';  Hook[2].UnHook;  Result := TNewMessageBoxW(Hook[2].BaseAddr)(_hWnd, lpText, lpCaption, uType);  Hook[2].Hook;end;//拦截 MessageBeepfunction NewMessageBeep(uType: UINT): BOOL; stdcall;type  TNewMessageBeep = function (uType: UINT): BOOL; stdcall;begin  Result := True;end;//拦截 OpenProcess , 防止关闭function NewOpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall;type  TNewOpenProcess = function (dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall;begin  if startPid^ = dwProcessId then begin    result := 0;    Exit;  end;  Hook[3].UnHook;  Result := TNewOpenProcess(Hook[3].BaseAddr)(dwDesiredAccess, bInheritHandle, dwProcessId);  Hook[3].Hook;end;{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}//安装API Hookprocedure InitHook;begin  Hook[0] := TNtHookClass.Create('user32.dll', 'MessageBoxA', @NewMessageBoxA);  Hook[1] := TNtHookClass.Create('user32.dll', 'MessageBeep', @NewMessageBeep);  Hook[2] := TNtHookClass.Create('user32.dll', 'MessageBoxW', @NewMessageBoxW);  Hook[3] := TNtHookClass.Create('kernel32.dll', 'OpenProcess', @NewOpenProcess);end;//删除API Hookprocedure UninitHook;var  I: Integer;begin  for I := 0 to High(Hook) do  begin    FreeAndNil(Hook[I]);  end;end;{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}//内存映射共想procedure MemShared();begin  MemFile:=OpenFileMapping(FILE_MAP_ALL_ACCESS,False, HOOK_MEM_FILENAME);   //打开内存映射文件  if MemFile = 0 then begin  //打开失败则衉c2建内存映射文件    MemFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,                              4, HOOK_MEM_FILENAME);  end;  if MemFile <> 0 then    //映射文件到变量    startPid := MapViewOfFile(MemFile,FILE_MAP_ALL_ACCESS,0,0,0);end;//传递消息function HookProc(nCode, wParam, lParam: Integer): Integer; stdcall;begin  Result := CallNextHookEx(hhk, nCode, wParam, lParam);end;//开始HOOKprocedure StartHook(pid: DWORD); stdcall;begin  startPid^ := pid;  hhk := SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hInstance, 0);end;//结束HOOKprocedure EndHook; stdcall;begin  if hhk <> 0 then    UnhookWindowsHookEx(hhk);end;//环境处理procedure DllEntry(dwResaon: DWORD);begin  case dwResaon of    DLL_PROCESS_ATTACH: InitHook;   //DLL载入    DLL_PROCESS_DETACH: UninitHook; //DLL删除  end;end;exports  StartHook, EndHook;begin  MemShared;  { 分配DLL程序到 DllProc 变量 }  DllProc := @DllEntry;  { 调用DLL加载处理 }  DllEntry(DLL_PROCESS_ATTACH);end.

     这样,我们用来hook API 的 Dll 就完工了。 在Dll中,我们还使用到了内存映射,用来实现在拦截全局时的内存共享,如这个例子中需要保存调用此hook的进程句柄,以防止通过任务管理器关闭示例程序。

   编译生成 hookdll.dll 文件,就可以使用了。现在我们再来建立一个测试用的程序。

     如附图所示,画3个按钮,分别为"Hook"、"UnHook"、"MessageBox",前两个用来安装和删除钩子,第三个用来显示一个消息框,你将会看到被Hook后的情况。测试工程的代码如下:
unit FMain;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;type  TfrmMain = class(TForm)    btnHook: TButton;    btnUnhook: TButton;    Button1: TButton;    procedure btnHookClick(Sender: TObject);    procedure btnUnhookClick(Sender: TObject);    procedure Button1Click(Sender: TObject);    procedure FormCreate(Sender: TObject);  private    { Private declarations }  public    { Public declarations }  end;var  frmMain: TfrmMain;  procedure StartHook(pid: DWORD); stdcall; external 'hookdll.dll';  procedure EndHook; stdcall; external 'hookdll.dll';implementation{$R *.dfm}procedure TfrmMain.btnHookClick(Sender: TObject);begin  StartHook(GetCurrentProcessId);end;procedure TfrmMain.btnUnhookClick(Sender: TObject);begin  EndHook;end;procedure TfrmMain.Button1Click(Sender: TObject);begin  MessageBox(0, 'abdfadfasdf', nil, 0);end;procedure TfrmMain.FormCreate(Sender: TObject);beginend;end.
 
    完成后运行,先不点击"hook"按钮,直接点击MessageBox,你会发现现在已经被拦截了。为什么我们还没有安装钩子就被拦截了呢?程序出错了吗?呵呵。当然没有出错。反过来看看DLL中的一处代码:
.............//环境处理procedure DllEntry(dwResaon: DWORD);begin  case dwResaon of    DLL_PROCESS_ATTACH: InitHook;   //DLL载入    DLL_PROCESS_DETACH: UninitHook; //DLL删除  end;end;............begin  MemShared;  { 分配DLL程序到 DllProc 变量 }  DllProc := @DllEntry;  { 调用DLL加载处理 }  DllEntry(DLL_PROCESS_ATTACH);end.
 
   可以看到,在DLL装入内存的时候其实就已经调用了InitHook,将要拦截的API拦截了。这时候看看任务管理器能不能关闭我们的程序,试一下就知道还可以,因为我们还没有调用StartHook来传入我们程序的PID,所以还可以被关闭。
  
   到此这篇文章就结束了, 本人从小语文没及过格(^_^),文章写的不太好,不过源代码都贴上了,有详细的注释,相信大家也能看明白。如果你发现有什么错误的地方,要记得告诉我哦!

   最后感谢 cxwr(菜新)大大的支持,能完成这篇文章少不了他的功劳。

作者:青色咖啡@极点博客 - 青色咖啡的博客
地址:http://www.t522.com/post/138/
极点博客版权所有©转载时必须以链接形式注明作者和原始出处及本声明!

klgfs9ad2 Email Homepage
2012/02/17 14:55
Finding handbags, most of women go out with a handbag, they seek fashion and practical, We know as a stylish and modern women you expect a lot from their bags. You should ba absolutely elegance, practicality and to be at the cutting edge of fashion. we experienced Italian designers have worked with many of the top Italian fashion houses and bring you innovative new designs every season, as well as perfecting the tried and tested classics. Each bag is carefully designed to be practical and comfortable, as well as beautiful, with compartments and pockets to help you be efficient and organised, wherever you go.
分页: 1/1 第一页 1 最后页
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]