UnhookWindowsHookEx为什么不起作用?(20分)

  • 主题发起人 主题发起人 sy0116
  • 开始时间 开始时间
S

sy0116

Unregistered / Unconfirmed
GUEST, unregistred user!
我发现在用了UnhookWindowsHookEx后挂上的钩子并没有立刻卸载而要过很久才会被卸载,在网上查资料得知要用Sendmessage(HWND_BROADCAST,WM_SETTIINGCHANGE,0,0)才可以,但是我挂的不是系统钩子,于是我把HWND_BROADCAST改成进程的handle,却发现没用,钩子还是没卸载,而用Sendmessage(HWND_BROADCAST,WM_SETTIINGCHANGE,0,0)却要用很长时间,请问有什么好办法
 
使用这个试试<br>unit UnitNt2000Hook;<br><br>interface<br><br>uses classes, Windows,SysUtils, messages,dialogs;<br><br>type<br> &nbsp;TImportCode = packed record<br> &nbsp; &nbsp; JumpInstruction: Word;<br> &nbsp; &nbsp; AddressOfPointerToFunction: PPointer;<br> &nbsp;end;<br> &nbsp;PImage_Import_Entry = ^Image_Import_Entry;<br> &nbsp;Image_Import_Entry = record<br> &nbsp; &nbsp;Characteristics: DWORD;<br> &nbsp; &nbsp;TimeDateStamp: DWORD;<br> &nbsp; &nbsp;MajorVersion: Word;<br> &nbsp; &nbsp;MinorVersion: Word;<br> &nbsp; &nbsp;Name: DWORD;<br> &nbsp; &nbsp;LookupTable: DWORD;<br> &nbsp;end;<br> &nbsp;PImportCode = ^TImportCode;<br> &nbsp;TLongJmp = packed record<br> &nbsp; &nbsp; JmpCode: ShortInt; {指令,用$E9来代替系统的指令}<br> &nbsp; &nbsp; FuncAddr: DWORD; {函数地址}<br> &nbsp;end;<br><br> &nbsp;THookClass = class<br> &nbsp;private<br> &nbsp; &nbsp; Trap:boolean; {调用方式:True陷阱式,False改引入表式}<br> &nbsp; &nbsp; hProcess: Cardinal; {进程句柄,只用于陷阱式}<br> &nbsp; &nbsp; AlreadyHook:boolean; {是否已安装Hook,只用于陷阱式}<br> &nbsp; &nbsp; AllowChange:boolean; {是否允许安装、卸载Hook,只用于改引入表式}<br> &nbsp; &nbsp; Oldcode: array[0..4]of byte; {系统函数原来的前5个字节}<br> &nbsp; &nbsp; Newcode: TLongJmp; {将要写在系统函数的前5个字节}<br> &nbsp;private<br> &nbsp;public<br> &nbsp; &nbsp; OldFunction,NewFunction:Pointer;{被截函数、自定义函数}<br> &nbsp; &nbsp; constructor Create(IsTrap:boolean;OldFun,NewFun:pointer);<br> &nbsp; &nbsp; constructor Destroy;<br> &nbsp; &nbsp; procedure Restore;<br> &nbsp; &nbsp; procedure Change;<br> &nbsp;published<br> &nbsp;end;<br><br>implementation<br><br>{取函数的实际地址。如果函数的第一个指令是Jmp,则取出它的跳转地址(实际地址),这往往是由于程序中含有Debug调试信息引起的}<br>function FinalFunctionAddress(Code: Pointer): Pointer;<br>Var<br> &nbsp;func: PImportCode;<br>begin<br> &nbsp;Result:=Code;<br> &nbsp;if Code=nil then exit;<br> &nbsp;try<br> &nbsp; &nbsp;func:=code;<br> &nbsp; &nbsp;if (func.JumpInstruction=$25FF) then<br> &nbsp; &nbsp; &nbsp;{指令二进制码FF 25 &nbsp;汇编指令jmp [...]}<br> &nbsp; &nbsp; &nbsp;Func:=func.AddressOfPointerToFunction^;<br> &nbsp; &nbsp;result:=Func;<br> &nbsp;except<br> &nbsp; &nbsp;Result:=nil;<br> &nbsp;end;<br>end;<br><br>{更改引入表中指定函数的地址,只用于改引入表式}<br>function PatchAddressInModule(BeenDone:Tlist;hModule: THandle; OldFunc,NewFunc: Pointer):integer;<br>const<br> &nbsp; SIZE=4;<br>Var<br> &nbsp; Dos: PImageDosHeader;<br> &nbsp; NT: PImageNTHeaders;<br> &nbsp; ImportDesc: PImage_Import_Entry;<br> &nbsp; rva: DWORD;<br> &nbsp; Func: PPointer;<br> &nbsp; DLL: String;<br> &nbsp; f: Pointer;<br> &nbsp; written: DWORD;<br> &nbsp; mbi_thunk:TMemoryBasicInformation;<br> &nbsp; dwOldProtect:DWORD;<br>begin<br> &nbsp;Result:=0;<br> &nbsp;if hModule=0 then exit;<br> &nbsp;Dos:=Pointer(hModule);<br> &nbsp;{如果这个DLL模块已经处理过,则退出。BeenDone包含已处理的DLL模块}<br> &nbsp;if BeenDone.IndexOf(Dos)&gt;=0 then exit;<br> &nbsp;BeenDone.Add(Dos);{把DLL模块名加入BeenDone}<br> &nbsp;OldFunc:=FinalFunctionAddress(OldFunc);{取函数的实际地址}<br><br> &nbsp;{如果这个DLL模块的地址不能访问,则退出}<br> &nbsp;if IsBadReadPtr(Dos,SizeOf(TImageDosHeader)) then exit;<br> &nbsp;{如果这个模块不是以'MZ'开头,表明不是DLL,则退出}<br> &nbsp;if Dos.e_magic&lt;&gt;IMAGE_DOS_SIGNATURE then exit;{IMAGE_DOS_SIGNATURE='MZ'}<br><br> &nbsp;{定位至NT Header}<br> &nbsp;NT :=Pointer(Integer(Dos) + dos._lfanew);<br> &nbsp;{定位至引入函数表}<br> &nbsp;RVA:=NT^.OptionalHeader.<br> &nbsp; &nbsp; DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;<br> &nbsp;if RVA=0 then exit;{如果引入函数表为空,则退出}<br> &nbsp;{把函数引入表的相对地址RVA转换为绝对地址}<br> &nbsp;ImportDesc := pointer(DWORD(Dos)+RVA);{Dos是此DLL模块的首地址}<br><br> &nbsp;{遍历所有被引入的下级DLL模块}<br> &nbsp;While (ImportDesc^.Name&lt;&gt;0) do<br> &nbsp;begin<br> &nbsp; &nbsp;{被引入的下级DLL模块名字}<br> &nbsp; &nbsp;DLL:=PChar(DWORD(Dos)+ImportDesc^.Name);<br> &nbsp; &nbsp;{把被导入的下级DLL模块当做当前模块,进行递归调用}<br> &nbsp; &nbsp;PatchAddressInModule(BeenDone,GetModuleHandle(PChar(DLL)),OldFunc,NewFunc);<br><br> &nbsp; &nbsp;{定位至被引入的下级DLL模块的函数表}<br> &nbsp; &nbsp;Func:=Pointer(DWORD(DOS)+ImportDesc.LookupTable);<br> &nbsp; &nbsp;{遍历被引入的下级DLL模块的所有函数}<br> &nbsp; &nbsp;While Func^&lt;&gt;nil do<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;f:=FinalFunctionAddress(Func^);{取实际地址}<br> &nbsp; &nbsp; &nbsp;if f=OldFunc then {如果函数实际地址就是所要找的地址}<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp; VirtualQuery(Func,mbi_thunk, sizeof(TMemoryBasicInformation));<br> &nbsp; &nbsp; &nbsp; &nbsp; VirtualProtect(Func,SIZE,PAGE_EXECUTE_WRITECOPY,mbi_thunk.Protect);{更改内存属性}<br> &nbsp; &nbsp; &nbsp; &nbsp; WriteProcessMemory(GetCurrentProcess,Func,@NewFunc,SIZE,written);{把新函数地址覆盖它}<br> &nbsp; &nbsp; &nbsp; &nbsp; VirtualProtect(Func, SIZE, mbi_thunk.Protect,dwOldProtect);{恢复内存属性}<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp;If Written=4 then Inc(Result);<br>// &nbsp; &nbsp; &nbsp;else showmessagefmt('error:%d',[Written]);<br> &nbsp; &nbsp; &nbsp;Inc(Func);{下一个功能函数}<br> &nbsp; &nbsp;end;<br> &nbsp; &nbsp;Inc(ImportDesc);{下一个被引入的下级DLL模块}<br> &nbsp;end;<br>end;<br><br>{HOOK的入口,其中IsTrap表示是否采用陷阱式}<br>constructor THookClass.Create(IsTrap:boolean;OldFun,NewFun:pointer);<br>begin<br> &nbsp; {求被截函数、自定义函数的实际地址}<br> &nbsp; OldFunction:=FinalFunctionAddress(OldFun);<br> &nbsp; NewFunction:=FinalFunctionAddress(NewFun);<br><br> &nbsp; Trap:=IsTrap;<br> &nbsp; if Trap then{如果是陷阱式}<br> &nbsp; begin<br> &nbsp; &nbsp; &nbsp;{以特权的方式来打开当前进程}<br> &nbsp; &nbsp; &nbsp;hProcess := OpenProcess(PROCESS_ALL_ACCESS,FALSE, GetCurrentProcessID);<br> &nbsp; &nbsp; &nbsp;{生成jmp xxxx的代码,共5字节}<br> &nbsp; &nbsp; &nbsp;Newcode.JmpCode := ShortInt($E9); {jmp指令的十六进制代码是E9}<br> &nbsp; &nbsp; &nbsp;NewCode.FuncAddr := DWORD(NewFunction) - DWORD(OldFunction) - 5;<br> &nbsp; &nbsp; &nbsp;{保存被截函数的前5个字节}<br> &nbsp; &nbsp; &nbsp;move(OldFunction^,OldCode,5);<br> &nbsp; &nbsp; &nbsp;{设置为还没有开始HOOK}<br> &nbsp; &nbsp; &nbsp;AlreadyHook:=false;<br> &nbsp; end;<br> &nbsp; {如果是改引入表式,将允许HOOK}<br> &nbsp; if not Trap then AllowChange:=true;<br> &nbsp; Change; {开始HOOK}<br> &nbsp; {如果是改引入表式,将暂时不允许HOOK}<br> &nbsp; if not Trap then AllowChange:=false;<br>end;<br><br>{HOOK的出口}<br>constructor THookClass.Destroy;<br>begin<br> &nbsp; {如果是改引入表式,将允许HOOK}<br> &nbsp; if not Trap then AllowChange:=true;<br> &nbsp; Restore; {停止HOOK}<br> &nbsp; if Trap then{如果是陷阱式}<br> &nbsp; &nbsp; &nbsp;CloseHandle(hProcess);<br>end;<br><br>{开始HOOK}<br>procedure THookClass.Change;<br>var<br> &nbsp; nCount: DWORD;<br> &nbsp; BeenDone: TList;<br>begin<br> &nbsp;if Trap then{如果是陷阱式}<br> &nbsp;begin<br> &nbsp; &nbsp;if (AlreadyHook)or (hProcess = 0) or (OldFunction = nil) or (NewFunction = nil) then<br> &nbsp; &nbsp; &nbsp; &nbsp;exit;<br> &nbsp; &nbsp;AlreadyHook:=true;{表示已经HOOK}<br> &nbsp; &nbsp;WriteProcessMemory(hProcess, OldFunction, @(Newcode), 5, nCount);<br> &nbsp;end<br> &nbsp;else begin{如果是改引入表式}<br> &nbsp; &nbsp; &nbsp; if (not AllowChange)or(OldFunction=nil)or(NewFunction=nil)then exit;<br> &nbsp; &nbsp; &nbsp; BeenDone:=TList.Create; {用于存放当前进程所有DLL模块的名字}<br> &nbsp; &nbsp; &nbsp; try<br> &nbsp; &nbsp; &nbsp; &nbsp; PatchAddressInModule(BeenDone,GetModuleHandle(nil),OldFunction,NewFunction);<br> &nbsp; &nbsp; &nbsp; finally<br> &nbsp; &nbsp; &nbsp; &nbsp; BeenDone.Free;<br> &nbsp; &nbsp; &nbsp; end;<br> &nbsp;end;<br>end;<br><br>{恢复系统函数的调用}<br>procedure THookClass.Restore;<br>var<br> &nbsp; nCount: DWORD;<br> &nbsp; BeenDone: TList;<br>begin<br> &nbsp;if Trap then{如果是陷阱式}<br> &nbsp;begin<br> &nbsp; &nbsp;if (not AlreadyHook) or (hProcess = 0) or (OldFunction = nil) or (NewFunction = nil) then<br> &nbsp; &nbsp; &nbsp; &nbsp;exit;<br> &nbsp; &nbsp;WriteProcessMemory(hProcess, OldFunction, @(Oldcode), 5, nCount);<br> &nbsp; &nbsp;AlreadyHook:=false;{表示退出HOOK}<br> &nbsp;end<br> &nbsp;else begin{如果是改引入表式}<br> &nbsp; &nbsp;if (not AllowChange)or(OldFunction=nil)or(NewFunction=nil)then exit;<br> &nbsp; &nbsp;BeenDone:=TList.Create;{用于存放当前进程所有DLL模块的名字}<br> &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp;PatchAddressInModule(BeenDone,GetModuleHandle(nil),NewFunction,OldFunction);<br> &nbsp; &nbsp;finally<br> &nbsp; &nbsp; &nbsp;BeenDone.Free;<br> &nbsp; &nbsp;end;<br> &nbsp;end;<br>end;<br><br>end.
 
完全不懂
 
接受答案了.
 
后退
顶部