線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1106
推到 Plurk!
推到 Facebook!

拦截API的元件,以栈的方式管理(2)

 
mustapha.wang
資深會員


發表:89
回覆:409
積分:274
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-12-17 17:45:42 IP:218.1.xxx.xxx 未訂閱
另一种拦截方式: http://www.swissdelphicenter.ch/de/showcode.php?id=1422 我包成另一个元件TTrapStorage,它传入dll和API名称,方便你拦截bpl里的全局函数。附demo
unit TrapAPI;
interface
uses
  Classes,Windows;
type
  PCodeRec=^TCodeRec;
  TCodeRec=record
    NewFunc:Pointer;
    Next:PCodeRec;
  end;
  PTrapRec=^TTrapRec;
  TTrapRec=record
    Addr:Pointer;
    Code:array[0..4] of Byte; //origin memory
    CodeList:PCodeRec; //hooked address list
  end;
  TTrapStorage=class
  private
    FList:TStringList;
  protected
    function FindTrapRec(Dll,API:string):PTrapRec;
    function FindCodeRec(ATR:TTrapRec;NewFunc:Pointer):PCodeRec;
    procedure DelteTrapRec(PTR:PTrapRec);
  public
    constructor Create;virtual;
    destructor Destroy;override;
    function Trap(Dll,API:string;NewFunc:Pointer):Boolean;
    function UnTrap(Dll,API:string;NewFunc:Pointer):Boolean;
  end;
var
  TrapStorage:TTrapStorage;
implementation
type
  PMemoryRec=^TMemoryRec;
  TMemoryRec=packed record
    JMP:Byte;
    Distance:Integer;
  end;    { TTrapStorage }    constructor TTrapStorage.Create;
begin
  FList:=TStringList.Create;
  FList.Sorted:=true;
end;    procedure TTrapStorage.DelteTrapRec(PTR: PTrapRec);
var
  i:integer;
begin
  for i:=FList.Count-1 downto 0 do
  begin
    if Pointer(FList.Objects[i])=PTR then
    begin
      FList.Delete(i);
      break;
    end;
  end;
end;    destructor TTrapStorage.Destroy;
var
  i:integer;
  PTR:PTrapRec;
  PCR,Next:PCodeRec;
  OldProtect:Cardinal;
begin
  for i:=0 to FList.Count-1 do
  begin
    PTR:=PTrapRec(FList.Objects[i]);
    Next:=PTR^.CodeList;
    repeat
      PCR:=Next;
      Next:=Next^.Next;
      Dispose(PCR);
    until Next=nil;
    VirtualProtect(PTR^.Addr,5,PAGE_EXECUTE_READWRITE,OldProtect);
    Move(PTR^.Code,PTR^.Addr^,5);
    VirtualProtect(PTR^.Addr,5,OldProtect,OldProtect);
    Dispose(PTR);
  end;
  FList.Free;
  inherited;
end;    function TTrapStorage.FindCodeRec(ATR: TTrapRec;NewFunc:Pointer): PCodeRec;
begin
  Result:=ATR.CodeList;
  while Result<>nil do
  begin
    if Result^.NewFunc=NewFunc then exit;
    Result:=Result^.Next;
  end;
  Result:=nil;
end;    function TTrapStorage.FindTrapRec(Dll, API: string): PTrapRec;
var
  Index:integer;
begin
  if FList.Find(Dll+#9+API,Index) then
    Result:=PTrapRec(FList.Objects[Index])
  else Result:=nil;
end;    function TTrapStorage.Trap(Dll, API: string; NewFunc: Pointer):Boolean;
var
  PTR:PTrapRec;
  hModule:Cardinal;
  P:Pointer;
  PCR,NewCR:PCodeRec;
  MR:TMemoryRec;
  OldProtect:Cardinal;
begin
  Result:=false;
  PTR:=FindTrapRec(Dll,API);
  if PTR=nil then
  begin
    hModule:=GetModuleHandle(PChar(Dll));
    if hModule<=0 then exit;
    P:=GetProcAddress(hModule,PChar(API));
    if P=nil then exit;
    New(PTR);
    New(PTR.CodeList);
    PTR^.CodeList^.Next:=nil;
    PTR^.CodeList^.NewFunc:=nil;
    PTR^.Addr:=P;
    Move(P^,PTR^.Code,5);  //save memory
    FList.AddObject(Dll+#9+API,Pointer(PTR));
  end;
  PCR:=FindCodeRec(PTR^,NewFunc);
  if PCR=nil then
  begin
    New(NewCR);
    NewCR^.Next:=nil;
    NewCR^.NewFunc:=NewFunc;        PCR:=PTR^.CodeList;
    while PCR^.Next<>nil do PCR:=PCR^.Next;
    PCR^.Next:=NewCR;  //link to end        MR.JMP:=$E9;
    MR.Distance:=Integer(NewFunc)-Integer(PTR^.Addr)-5;
    VirtualProtect(PTR^.Addr,5,PAGE_EXECUTE_READWRITE,OldProtect);
    Move(MR,PTR^.Addr^,5);
    VirtualProtect(PTR^.Addr,5,OldProtect,OldProtect);
  end;
  Result:=true;
end;    function TTrapStorage.UnTrap(Dll, API: string; NewFunc: Pointer):Boolean;
var
  PTR:PTrapRec;
  PCR,Next:PCodeRec;
  MR:TMemoryRec;
  OldProtect:Cardinal;
begin
  Result:=false;
  PTR:=FindTrapRec(Dll,API);
  if PTR=nil then exit;
  PCR:=FindCodeRec(PTR^,NewFunc);
  if PCR=nil then exit;
  Next:=PTR^.CodeList;
  while Next^.Next<>nil do
  begin
    if Next^.Next=PCR then
    begin
      Next^.Next:=PCR^.Next; //skip link to next
      if PCR^.Next<>nil then Next:=PCR^.Next;
      PCR^.Next:=nil;
    end
    else
      Next:=Next^.Next;
  end;
  Dispose(PCR);      if Next=PTR^.CodeList then  //no hook
  begin
    VirtualProtect(PTR^.Addr,5,PAGE_EXECUTE_READWRITE,OldProtect);
    Move(PTR^.Code,PTR^.Addr^,5);
    VirtualProtect(PTR^.Addr,5,OldProtect,OldProtect);
    DelteTrapRec(PTR);
    Dispose(PTR^.CodeList);
    Dispose(PTR);
  end
  else
  begin  //hook to last
    MR.JMP:=$E9;
    MR.Distance:=Integer(Next^.NewFunc)-Integer(PTR^.Addr)-5;
    VirtualProtect(PTR^.Addr,5,PAGE_EXECUTE_READWRITE,OldProtect);
    Move(MR,PTR^.Addr^,5);
    VirtualProtect(PTR^.Addr,5,OldProtect,OldProtect);
  end;
  Result:=true;
end;    initialization
  TrapStorage:=TTrapStorage.Create;
finalization
  TrapStorage.Free;
end.
久病成良医--多试 千人之诺诺,不如一士之谔谔--兼听
------
江上何人初见月,江月何年初照人
附加檔案:42288_TrapAPI.rar
mustapha.wang
資深會員


發表:89
回覆:409
積分:274
註冊:2002-03-13

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-12-18 11:14:56 IP:218.1.xxx.xxx 未訂閱
我觉得这种方式可能不安全,是否每个“API”都有5个Byte以上的地址空间呢,如果不是的话,强制把头5个字节写成jmp +$xxxxxxxx可能破坏到别的函数的数据。 而方式1有对jmp指令$25FF的判断,如果头2个字节不是$25FF就不会去试图Hook,它适合那种用external引入的API。    是不是这样?是否每个函数都有5个Byte以上的地址空间?望精通汇编语言的人解答一下。     久病成良医--多试 千人之诺诺,不如一士之谔谔--兼听 發表人 - mustapha.wang 於 2003/12/18 16:18:07
------
江上何人初见月,江月何年初照人
系統時間:2024-07-04 4:55:10
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!