拦截API的元件,以栈的方式管理(2) |
|
mustapha.wang
資深會員 發表:89 回覆:409 積分:274 註冊:2002-03-13 發送簡訊給我 |
另一种拦截方式:
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 發送簡訊給我 |
我觉得这种方式可能不安全,是否每个“API”都有5个Byte以上的地址空间呢,如果不是的话,强制把头5个字节写成jmp +$xxxxxxxx可能破坏到别的函数的数据。
而方式1有对jmp指令$25FF的判断,如果头2个字节不是$25FF就不会去试图Hook,它适合那种用external引入的API。 是不是这样?是否每个函数都有5个Byte以上的地址空间?望精通汇编语言的人解答一下。
久病成良医--多试
千人之诺诺,不如一士之谔谔--兼听 發表人 - mustapha.wang 於 2003/12/18 16:18:07
------
江上何人初见月,江月何年初照人 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |