导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/14 13:59:04
标题:
加入我的收藏
楼主:
首先非常感谢武哥提供的免费代码。 我用的是:Lsuper 修改过的代码 下面代码,已能钩到,但是导至目标进程崩溃,请大老们看看什么原因。 2016.10.01 - Lsuper } { } { 1、参考 wr960204 武稀松 的原始实现: } { https://code.google.com/p/delphi-hook-library  ; } { 2、修改 BeaEngine 引擎为 LDE64 长度反编译引擎,大幅降低大小 } { https://github.com/BeaEngine/lde64  ; } { http://www.beaengine.org/download/LDE64-x86.zip  ; } { http://www.beaengine.org/download/LDE64-x64.rar  ; } { 3、去除原始实现对多线程冻结的处理,通常建议 Hook/Unhook 放到单元 } { 初始化、析构中做,否则可能因改写内存没挂起其他线程造成错误 ////////// 我的目的就是 1:HOOK CALL 可以hook call前面,执行完我的过程再返回后继续执行call. 2:,直接hook 掉call,替换我的过程。然后返回。 3:等CALL执行完后,得到结果后再HOOK执行我的过程并返回。 下面的代码目的是第1种,HOOK CALL 前面,执行完我的过程再返回后继续执行call. ---------- unit hookUnit1; interface uses Winapi.Windows, System.SysUtils, System.Variants, System.Classes,HookUtils; var hook地址:DWORD; 备份地址: Pointer;//POldProc;// DWORD; hookadd: DWORD; apiaddr: Integer; dwRetAddr: DWORD; // = (DWORD)GetModuleHandle(L"unt.dll") + QrCodeOffset + 5; //返回地址 pEsi: DWORD = 0; //esi寄存器 procedure InitHook(); stdcall; procedure UninitHook(); stdcall; procedure 截取消息(); stdcall; implementation procedure OutputDebugStr(const ADebugInfo: string); //输出调试信息 begin OutputDebugString(PChar(ADebugInfo + #13 + #10)); end; procedure InitHook(); var //a1,a2:dword; p1, p2: Pointer; m_基址: dword; begin m_基址 := LoadLibrary('unt.dll'); OutputDebugStr(inttostr(m_基址)); hook地址 :=3492515;// 3495443; hookadd := m_基址 + hook地址; dwRetAddr:=m_基址 + hook地址+5; // = (DWORD)GetModuleHandle(L"unt.dll") + QrCodeOffset + 5; //返回地址 p1 := Pointer(hookadd); OutputDebugStr('hookadd=' + inttostr(hookadd) + ' 备份地址=' + inttostr(Integer(备份地址))); if HookProc(p1, @截取消息, 备份地址) then OutputDebugStr('hook OK') else OutputDebugStr('hook no'); OutputDebugStr('hookadd=' + inttostr(hookadd) + ' 备份地址=' + inttostr(Integer(备份地址))); end; procedure UninitHook(); var p: Pointer; begin p := @备份地址; UnHookProc(p); end; procedure saveCALL(); asm //备份寄存器 pushad; pushfd; //取出esi的内容 mov pEsi, esi;//ecx; end; procedure loadcall(); asm //恢复寄存器 popfd; popad; //跳转到返回地址 jmp dwRetAddr; end; procedure 截取消息(); begin saveCALL(); //这句去掉,有显示“有消息”说明已被钩中,不去掉,没显示。 是否去掉目标进程都崩溃. OutputDebugStr('有消息:'); loadcall(); end; end.
----------------------------------------------
永远是DELPHI初学者。
作者:
2020/3/14 18:43:08
1楼:
没有跳转到原来的函数.
----------------------------------------------
作者:
2020/3/14 19:26:38
2楼:
刚看看了DelphiHookUtils项目的Demos,你没有实现目标函数的引用声明,估计是内存被破坏了. library Dll; uses Windows, WinInet, HookUtils; var HttpOpenRequestWNext: function(hConnect: HINTERNET; lpszVerb: LPWSTR; lpszObjectName: LPWSTR; lpszVersion: LPWSTR; lpszReferrer: LPWSTR; lplpszAcceptTypes: PLPSTR; dwFlags: DWord; dwContext: DWORD_PTR): HINTERNET; stdcall; function HttpOpenRequestWCallBack(hConnect: HINTERNET; lpszVerb: LPWSTR; lpszObjectName: LPWSTR; lpszVersion: LPWSTR; lpszReferrer: LPWSTR; lplpszAcceptTypes: PLPSTR; dwFlags: DWord; dwContext: DWORD_PTR): HINTERNET; stdcall; var S: string; begin // 先直接调用原始函数 Result := HttpOpenRequestWNext(hConnect, lpszVerb, lpszObjectName, lpszVersion, lpszReferrer, lplpszAcceptTypes, dwFlags, dwContext); if Result = nil then begin // 打印错误... Exit; end; // 添加自定义的http标头 S := 'X-MyHttpHeader: HeaderValue'; if not Wininet.HttpAddRequestHeaders(Result, PChar(S), Length(S), Wininet.HTTP_ADDREQ_FLAG_ADD or Wininet.HTTP_ADDREQ_FLAG_REPLACE) then begin // 打印错误... Exit; end; end; ////////// //设计:Lsuper 2016.10.09 //功能:初始化、挂接 API //参数: //注意:如果 HookProc 的 DLL 没有被 LoadLibrary 下 Hook 会失败,建议先手工 Load ////////// procedure DllEntryPoint(dwReason: DWord); begin case dwReason of DLL_PROCESS_ATTACH: begin if HookUtils.HookProc('WinInet.dll', 'HttpOpenRequestW', @HttpOpenRequestWCallBack, @HttpOpenRequestWNext) then begin // Hook 成功... end else begin // Hook 失败... end; end; DLL_PROCESS_DETACH: begin if HookUtils.UnHookProc(@HttpOpenRequestWNext) then begin // UnHook 成功... end else begin // UnHook 失败... end; end; DLL_THREAD_ATTACH: begin end; DLL_THREAD_DETACH: begin end; end; end; begin DllProc := @DllEntryPoint; DllEntryPoint(DLL_PROCESS_ATTACH); end. function HookProc(const ATargetModule, ATargetProc: string; ANewProc: Pointer; out AOldProc: Pointer): Boolean; var nHandle: THandle; pProc: Pointer; begin Result := False; nHandle := GetModuleHandle(PChar(ATargetModule)); if nHandle = 0 then Exit; pProc := GetProcAddress(nHandle, PChar(ATargetProc)); if pProc = nil then Exit; Result := HookProc(pProc, ANewProc, AOldProc); end;
----------------------------------------------
作者:
2020/3/14 19:28:09
3楼:
你的代码编译应该没有问题,问题是错误的方式进行了Hook
----------------------------------------------
作者:
2020/3/15 10:47:05
4楼:
var hookaddr:dword; procedure HookCode(MyFunc:Pointer;HookAddr:Pointer); var OldAccess,NewAccess:DWORD; JmpCode:array[0..4] of Byte; begin OldAccess:=DWORD(MyFunc)-DWORD(HookAddr)-5; JmpCode[0]:=$E9; JmpCode[1]:=Byte(OldAccess shr 0); JmpCode[2]:=Byte(OldAccess shr 8); JmpCode[3]:=Byte(OldAccess shr 16); JmpCode[4]:=Byte(OldAccess shr 24); if VirtualProtect(Hookaddr,$10,128,@OldAccess)then begin CopyMemory(HookAddr,@JmpCode,5); VirtualProtect(HookAddr,$10,OldAccess,@NewAccess); end; end; procedure 截取消息(resi:dword);stdcall; begin end; procedure hookhandler() asm pushad push esi call 截取消息 popad //这里写上由于HOOK被替换掉的汇编代码 push hookaddr add dword ptr[esp],5 //根据实际被破坏的汇编指令的长度填写 end; procedure InitHook(); begin hookaddr:=LoadLibrary('unt.dll')+3492515; HookCode(@hookhandler,Pointer(hookaddr)); end; //调用InitHook();
----------------------------------------------
-
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/16 14:06:58
5楼:
helyna 谢谢您的回答。测试了您的代码,能编译通过,还是崩溃的。
----------------------------------------------
永远是DELPHI初学者。
作者:
2020/3/16 15:43:51
6楼:
@jingzu 你把你HOOK的那个地址附近的汇编代码贴出来。 崩溃应该是你什么地方写错了。我这代码是没有任何问题的。 你 截取消息 函数只需要一个参数吧?ESI的地址。
----------------------------------------------
-
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/16 19:51:12
7楼:
HOOK CALL 前面那一行。
此帖子包含附件: 大小: 48.2K
----------------------------------------------
永远是DELPHI初学者。
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/16 19:54:35
8楼:
偏移是:2392515 截取消息 函数只需要一个参数ESI的地址。
----------------------------------------------
永远是DELPHI初学者。
作者:
2020/3/16 21:24:52
9楼:
如果你需要的参数确定是ESI,而非ECX,建议HOOK我图中给你标出来的位置。 你之前HOOK的地址6ABE4AA3的汇编是mov ecx,unt.6BEC3C98 由于你HOOK的是DLL中的地址,这个6BEC3C98是经过重定位的地址,下次DLL基址改变的话,这个值也会改变,还需要自己重定位(unt模块地址+偏移)。 所以HOOK 6ABE4A84 mov dword ptr ds:[eax],0 这个地址。 你上面说偏移是2392515,16进制是2481C3,你HOOK的地址是6ABE4AA3, 6ABE4AA3 - 2481C3 = 6A99C8E0,这不是一个模块基址。 你之前发的3492515,16进制是354AA3,6ABE4AA3 - 354AA3 = 6A890000,这才是模块基址。 所以我按照基址6A890000给你说,HOOK的偏移6ABE4A84-6A890000=0x354A84 procedure hookhandler() asm pushad push esi call 截取消息 popad mov dword ptr [eax],0 push hookaddr add dword ptr[esp],6 end; procedure InitHook(); begin hookaddr:=LoadLibrary('unt.dll')+$354A84; HookCode(@hookhandler,Pointer(hookaddr)); end;
此帖子包含附件: 大小: 131.1K
----------------------------------------------
-
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/16 23:25:14
10楼:
在那个地方HOOK,还得不到消息。所以这个地方hook不好。
----------------------------------------------
永远是DELPHI初学者。
作者:
2020/3/17 10:13:21
11楼:
你不是需要ESI吗?这几段汇编根本没有对ESI的操作,说明ESI是之前赋值的,怎么会获取不到消息呢! 我怀疑你需要的是ECX,而不是ESI。
----------------------------------------------
-
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/17 10:53:10
12楼:
取到消息了。目标进程自己却没有消息了。目标有时还崩溃,问题是下面恢复原来的,对不对?如何解决?
此帖子包含附件: 大小: 102.5K
----------------------------------------------
永远是DELPHI初学者。
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/17 10:54:12
13楼:
执行了我们过程后返回来,不是原来两句代码,目标进程自己却没有消息了,问题出在那里?
----------------------------------------------
永远是DELPHI初学者。
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/17 17:36:18
14楼:
procedure hookhandler() asm pushad push esi call 截取消息 popad //mov dword ptr [eax],0 //push hookaddr // add dword ptr[esp],6 add esp,4 movzx eax,byte ptr ss:[ebp-$B] end; 谢谢!helyna指导。 add esp,4 movzx eax,byte ptr ss:[ebp-$B] 加上这两句就没有问题了。正常工作。原来是这两句HOOK时被复盖掉了。 这两句如何利用备份恢复方法恢复这两句汇偏并执行,而不用手动加上?
----------------------------------------------
永远是DELPHI初学者。
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/17 17:43:56
15楼:
也就是说: add esp,4 movzx eax,byte ptr ss:[ebp-$B] 如何在hook前备份这两句代码,执行完HOOK后再恢复并执行?
----------------------------------------------
永远是DELPHI初学者。
作者:
jingzu (123456)
★☆☆☆☆
-
盒子活跃会员
2020/3/20 9:17:46
16楼:
我已解决。 方法是申请一块内存,然后将HOOK复盖的代码,恢复到这块内存中 hook地址直接 jmp到申请的地址。下面是写法。就是地址计算搞得很头痛。百度DELPHI相关资料没找到。后来参照易语言计算方法才搞定。下面是先执行被 HOOK的指令,然后再执行我们的并返回。 恢复复盖的指令 pushad push esi call 截取消息 popad jmp 到hook地址
----------------------------------------------
永远是DELPHI初学者。
作者:
2022/8/13 17:26:12
18楼:
楼主能否能发我份HOOK CALL的源码我参考一下吗? 86726882@qq.com 万分感谢
----------------------------------------------
-