怎样Hook系统函数???我想Hook EndDoc函数!(200分)

  • 主题发起人 主题发起人 hzlan
  • 开始时间 开始时间
H

hzlan

Unregistered / Unconfirmed
GUEST, unregistred user!
怎样在系统调用EndDoc函数时,先处理我的过程再调用EndDoc函数,是Hook系统的所有EndDoc函数!<br>谢
 
不会也请帮我顶一下,提前一下,我相信好多人都想问这个问题
 
这里有个例子,你看看:<br>在你的程序中做一个函数func(...) <br>调用 func1 = ApiSpy(NULL,"GDI32.DLL","TextOutA",(PROC)func)<br><br>那么你的程序没次调用TextOut时,就会调用func 为了不破坏原有功能<br><br>请在func中调用func1。如果想截获整个系统的api,你需要做一个全局HOOK<br><br>在HOOK的DLL里的初始化时调用本函数。主要代码如下:<br><br>PROC WINAPI<br><br>ApiSpy(PSTR pDllUse,PSTR pDllName,PSTR pApiName,PROC pNewPorc)<br>{<br>&nbsp; &nbsp; PIMAGE_DOS_HEADER &nbsp; pDosHeader;<br>&nbsp; &nbsp; PIMAGE_NT_HEADERS &nbsp; pNTHeader;<br>&nbsp; &nbsp; PIMAGE_IMPORT_DESCRIPTOR pImportDesc;<br>&nbsp; &nbsp; PIMAGE_THUNK_DATA &nbsp; pThunk;<br>&nbsp; &nbsp; PROC &nbsp; &nbsp; &nbsp;pOldProc;<br>&nbsp; &nbsp; DWORD oldpr;<br>&nbsp; &nbsp; static int Layer = 0;<br>&nbsp; &nbsp; if ( pDllUse == NULL )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Layer = 0;<br>&nbsp; &nbsp; pOldProc = GetProcAddress( GetModuleHandle(pDllName),pApiName );<br>&nbsp; &nbsp; if ( pOldProc == NULL )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return NULL;<br>&nbsp; &nbsp; pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(pDllUse); &nbsp; &nbsp;<br>&nbsp; &nbsp; if ( IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) )<br>&nbsp; &nbsp; &nbsp; &nbsp; return NULL;<br>&nbsp; &nbsp; if ( pDosHeader-&gt;e_magic != IMAGE_DOS_SIGNATURE )<br>&nbsp; &nbsp; &nbsp; &nbsp; return NULL;<br>&nbsp; &nbsp; pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader-&gt;e_lfanew);<br>&nbsp; &nbsp;if ( IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) )<br>&nbsp; &nbsp; &nbsp; &nbsp; return NULL;<br>&nbsp; &nbsp;if ( pNTHeader-&gt;Signature != IMAGE_NT_SIGNATURE )<br>&nbsp; &nbsp; &nbsp; &nbsp; return NULL;<br>&nbsp; pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDosHeader,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pNTHeader-&gt;OptionalHeader.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; VirtualAddress);<br>&nbsp; &nbsp; if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader )<br>&nbsp; &nbsp; &nbsp; &nbsp; return NULL;<br>&nbsp;__try{<br>&nbsp; &nbsp; &nbsp;while ( pImportDesc-&gt;Name ){<br>&nbsp; &nbsp; PSTR pszModName = MakePtr(PSTR, pDosHeader, pImportDesc-&gt;Name);<br>&nbsp; &nbsp; REM("[%s]",pszModName);<br>&nbsp; &nbsp; if ( stricmp(pszModName, pDllName) == 0 ){<br>&nbsp; &nbsp; &nbsp;pThunk = MakePtr(PIMAGE_THUNK_DATA, pDosHeader, pImportDesc-&gt;FirstThunk);<br>&nbsp; &nbsp; &nbsp;while ( pThunk-&gt;u1.Function ){ <br>&nbsp; &nbsp; &nbsp; REM("[%s:%s] &nbsp;? &nbsp;%s %8x ==&gt; %8x",pDllName,pApiName,pszModName,<br>&nbsp; &nbsp; &nbsp; // (DWORD)pOldProc,(DWORD)pThunk-&gt;u1.Function);<br>&nbsp; &nbsp; &nbsp; if ( pThunk-&gt;u1.Function == (PDWORD)pOldProc ){<br>&nbsp; &nbsp; &nbsp; &nbsp;if (!VirtualProtect(pThunk, 16, PAGE_READWRITE,&amp;oldpr)){<br>&nbsp; &nbsp; &nbsp; &nbsp; REM("VirtualProtect False");<br>&nbsp; &nbsp; &nbsp; &nbsp;}<br>&nbsp; &nbsp; &nbsp; &nbsp;REM("ApiSpy [%s:%s] OK !",pDllName,pApiName);<br>&nbsp; &nbsp; &nbsp; &nbsp;pThunk-&gt;u1.Function=(PDWORD)pNewPorc;<br>&nbsp; &nbsp; &nbsp; &nbsp;return pOldProc;<br>&nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; pThunk++; &nbsp;<br>&nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp;return NULL;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; else{<br>&nbsp; &nbsp; &nbsp;if ( Layer &lt; __Layer ){<br>&nbsp; &nbsp; &nbsp; Layer ++;<br>&nbsp; &nbsp; &nbsp; ApiSpy(pszModName,pDllName,pApiName,pNewPorc); &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp;}<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; pImportDesc++;<br>&nbsp; &nbsp;}<br>&nbsp; &nbsp; }<br>&nbsp;__except(TRUE){<br>&nbsp; return NULL;<br>&nbsp;}<br>&nbsp; &nbsp; return NULL; <br>}<br>&nbsp;<br><br><br>
 
可惜是C的,如果有Delphi的就好了,不过还是非常感谢!结贴时我会给你加分的,谢!
 
这个够明白了吧?(delphi的)<br><br>关于API HOOK,我相信大家比我知道的多,大家应该记得在DOS中编程,经常都要用截取中断向量的技术,这样我们可以设置新的中断服务程序,因此当一个新的程序调用这个中断向量的时候,它就会先调用我们自己设置的中断程序,然后调用原来的中断程序,这样我们就能够非凡的控制权,许多的病毒程序都是这样的。在WINDOWS中,也可以采用类似的技术,当系统调用某个API函数时,就会先进入我们设置的函数,其工作原理和DOS的中断差不多,这种技术也有很多的名称,像"陷阱技术","重入技术"。可我认为API HOOK好一些吧!这些技术再很多的软件中也有应用的,像"金山词霸"就是的了。呵呵~~~不是故意拿金山公司的产品说的啊!这个软件就运用了这个技术,像当你把鼠标指向一个单词,这时就会弹出一个窗口翻译单词了。这也就是用了钩子的原理。说了这么多废话,说正题了,要使自己的代码正确运行,函数必须和要改写的API函数有相同形式的参数。我在程序中,拦截了MessageBoxA和MessageBoxW这两个函数。如:<br>fuction MyBoxA(hwn:hwnd;Iptext:pcter;Ipcapion:pchar;utype:cardinal):interger;stdcall;<br>fuction MyBoxW(hwn:hwnd;Iptext:pchter;Ipcapiom:pchar;utype:cardinal):interger;stdcall;<br>这里我使用了stdcall关键字,这个我上面已经说了,函数的形参的进出栈顺序要和拦截的函数一样,在WIN32中并不允许直接修改内存中的代码,但可以调用一个函数来运用:WriteProcessMemory。当然有的人问这个不能改写,可我用着很好!也许用它会有些bug,可我不知道,知道的人请给我来信。<br>在PE文件中,当你呼叫另一模块中的函数列如:USER32.DLL中的GetMessage),编译出来的CALL指令并不会吧控制权直接传给DLL里的函数,而是传给了JMP DWORD PTR [XXXXXXXXX]指令,[XXXXXXXXXX]里有该函数的真正地址(进入点),要得到API函数,可以这样写:Address:=@MessageBoxA。像上面说的那样,这里只得到了一个跳转的指令,后面的MessageBoxA才是代码开始的地方。下面的程序我自己定义了一个结构(使用了packed关键字)<br>TlmportCode =packed record<br>&nbsp; &nbsp; Jumplnstruction: Word; //是$25FF,JUMP指令<br>AddressOfPointer ToFunction: PPointer;//真正开始的地址<br>end;<br>PlmportCode = ^TlportCode;<br>这里,Ppointer =^pointer ;用下面函数返回函数的真正地址:<br>function TrueFunctionAddress(func: Pointer): Pointer;<br>var<br>&nbsp; Code: PlmportCode;<br>Begin<br>&nbsp; Result:= func;<br>&nbsp; if func = nil then exit;<br>&nbsp; try<br>&nbsp; &nbsp;Code := func;<br>&nbsp; &nbsp;if (Code.jumplnstruction = $25FF) then begin<br>&nbsp; &nbsp; &nbsp;Result := Code.AddressOfPointer ToFunction^;<br>&nbsp; &nbsp;end;<br>&nbsp; &nbsp;except<br>&nbsp; &nbsp; &nbsp;Result :=nil;<br>&nbsp; end;<br>end;<br>这样,只要用自己的函数的地址代替它就可以了。替换函数:<br>Procedure PermuteFunction(OldFunc:Ppointer; NewFunc:Poiner);<br>var<br>&nbsp; written: DWORD;<br>begin<br>&nbsp; WriteProcessMemory(GetCurrentProcess,OldFunc,@NewFunc,4,written);<br>end;<br>新建一个API HOOK,把上面的保存就可以了。<br>新建一个Application Try1,主FORM的单元名称就用TRYUNIT1。把上面的HOOK加进来,再新建一个UNIT MESS,添加下面的代码:<br>unit mess<br><br>interface<br>uses<br>&nbsp; &nbsp;Windows,Message,SysUtils,Classes,APIHook;<br><br>procedure API_Hookup;<br>procedure Un_API_Hook;<br><br>var<br>&nbsp; &nbsp;FuncMessageboxA,FuncMessagew;PlmportCode;<br><br>implementation<br><br>type <br>&nbsp; &nbsp;TmessageA = function(hwn: hwnd; Iptext: pchar; Ipcapion:pchar; utype: cardinal): interger;stdcall;<br>&nbsp; &nbsp;TmessageW = function(hwn: hwnd; Iptext: pchar; Ipcapion:pchar; utype: cardinal): interger;stdcall;<br><br>var<br>&nbsp; &nbsp;OldMessageBoxA: TmessageA;<br>&nbsp; &nbsp;OldMessageBoxW: TmessageW;<br><br><br>functionj MyBoxA (hwn: hwnd; Iptext: pchar; Ipcapion:pchar; utype: cardinal): interger;stdcall;<br>begin<br>result :=OldMessageBoxA(hwn,'Succes Hook A!', Ipcapion,utype);<br>end;<br><br>functionj MyBoxW (hwn: hwnd; Iptext: pchar; Ipcapion:pchar; utype: cardinal): interger;stdcall;<br>result :=OldMessageBoxW(hwn,'成功挂上W!'Ipcapion,utype);<br>end;<br><br>procedure API_Hookup;<br>begin<br>&nbsp; &nbsp;if @OldMessageBoxA = nil then<br>@OleMessageBoxA = TrueFunctionAddress(@messageboxA);<br>&nbsp; &nbsp;if @OldMessageBoxW = nil then<br>@OleMessageBoxW = TrueFunctionAddress(@messageboxW);<br><br>PermuteFunction(FuncMessageboxA,AddressOfPointerToFunction,@MyBoxA);<br>PermuteFunction(FuncMessageboxW,AddressOfPointerToFunction,@MyBoxW);<br>end;<br><br>procedure Un_API_Hook;<br>begin<br>&nbsp; if @OldMessageBoxA &lt;&gt; nil then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PermuteFunction(FuncMessageboxA,AddressOfPointer ToFunction,@OldMessageboxA);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PermuteFunction(FuncMessageboxW,AddressOfPointer ToFunction,@OldMessageboxW);<br>&nbsp; end;<br>end;<br><br>initialization<br>&nbsp; &nbsp;FundMessageboxA := @MeesageboxA;<br>&nbsp; &nbsp;FundMessageboxW := @MeesageboxW;<br>end;<br>在主窗体中添加三按钮,添加Onclick事件的代码,如下:<br>procedure TForm1.Button1Click( Sender: TObject);<br>begin<br>&nbsp; &nbsp;API_Hook;<br>end;<br><br>procedure TForm1.Button3Click( Sender: TObject);<br>&nbsp; &nbsp;Un_API_Hook;<br>end;<br><br>procedure TForm1.Button2Click( Sender: TObject);<br>begin<br>&nbsp; MessageBoxA(Form1.Handle,'NO HOOK UP A','MessageBoxA',MB_OK);<br>&nbsp; MessageBoxW(Form1.Handle,'NO HOOK UP W','MessageBoxW',MB_OK);<br>&nbsp; MessageBox (Form1.Handle,'NO HOOK UP BOX','MessageBox',MB_OK);<br>end;<br>先运行TRY1,再运行TestTry。看看结果,APIHook仅仅再TRY1中挂上了,并没有在所以的系统进程中挂上,这个时想想鼠标钩子的时候做法,用SetWindowsHookEx挂上鼠标钩子,当其它的进程发出鼠标消息的时候,我们的程序就会拦截到并做出响应,还可以用UpHooklWindowsHookEx解除鼠标钩子,这样,我们就知道了,应该为我们的函数挂上钩子,当然你要知道鼠标钩子有各种的消息响应其它进程。有两种方法,一种是模仿SetWindowsHookEx,编制自己的MySetWindowsHookEx。还有一种也是WINDOWS所提供的另一个函数:GetMsgProc。这个函数在DELPHI帮助里说的很清楚得了。我们的目的也就是在动态链接库中挂上WH_GETMESSAGE消息钩子。当其它进程发出这个函数的时候,就会加载我们的动态链接库,如果我们的DLL加载时自动运行API_Hook,就可以让其它进程挂上我们的API Hook了
 
接受答案了.
 
后退
顶部