极难!hook大师刘麻子请进:hookapi的重入问题。 ( 积分: 300 )

应该是允许重入的, 但是要避免公共资源冲突<br><br>不编写 DLL 应该也是可以实现这种 API 的HOOK 的吧
 
hzm7512,大概是你说的那样。看一下有关pe结构的资料,可能你能更清楚我说的意思。<br>另外,如果你是用注入dll的方式去“修改旧的api地址所指向函数的地址”,不需要用WriteProcessMemory,先virtualprotect在用指针直接修改即可。
 
to tt.t&amp;lichengbin<br>我使用引用表式拦截shfileoperationw这个api,根本没有反映呀.怎么搞的?两位大侠能不能看看我的源码到底出现什么问题呀.
 
增加不少见识,HOOK
 
wsock32.dll 和 ws2_32.dll 中的一些函数的地址居然是相同的,真是奇怪了
 
使用陷阱式 APIHook 的一种新的思路:<br>调用自定义代码后,不需要再恢复原来的代码,<br>将原来的代码挪至其它地方,<br><br>这样,也就不存在函数的重入的冲突问题了,<br>也不需要使用临界区等技术了<br><br>经过测试,这种方法对很多API函数都是可行的
 
而且这种方法可以用非DLL 的方式来完成,<br>可以采用远程线程注入的方法来安装自己的代码
 
楼主上面贴的应该不是引入表式APIHook的源代码吧,呵呵,没看到一丁点的跟引入表相关的代码<br>引入表式APIHook的代码可以参考: 刘麻子大虾的《Windows核心编程》附书代码Pascal版 http://www.2ccc.com/article.asp?articleid=2303 第22章
 
lich,<br>&quot;wsock32.dll 和 ws2_32.dll 中的一些函数的地址居然是相同的,真是奇怪了&quot;<br>这是因为wsock32.dll中一些函数在导出表中标明了是forward,其实际实现是在s2_32.dll中。pe格式导出表部分有说明。<br><br>&quot;调用自定义代码后,不需要再恢复原来的代码,将原来的代码挪至其它地方&quot;<br>这种方法也有局限性,必须对挪走的代码进行分析,如果挪走的代码有对自身绝对地址的访问,则必须修正为新的地址。或者是函数的长度小于5字节,则根本无法使用陷阱式hook。当然,这些都属于极端情况,一般不会发生。
 
unit Unit1;<br><br>interface<br><br>uses<br> &nbsp;Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br> &nbsp;Dialogs, StdCtrls;<br><br>type<br><br> &nbsp;TInstallHook=function :Boolean;Stdcall;<br> &nbsp;TUnHook=function :Boolean;Stdcall;<br><br> &nbsp;PJmpCode = ^TJmpCode;<br> &nbsp;TJmpCode = packed record<br> &nbsp; &nbsp;JmpCode: BYTE;<br> &nbsp; &nbsp;Address: TInstallHook;<br> &nbsp;end;<br><br> &nbsp;TForm1 = class(TForm)<br> &nbsp; &nbsp;Button1: TButton;<br> &nbsp; &nbsp;Memo1: TMemo;<br> &nbsp; &nbsp;procedure Button1Click(Sender: TObject);<br> &nbsp; &nbsp;procedure FormShow(Sender: TObject);<br> &nbsp;private<br> &nbsp; &nbsp;{ Private declarations }<br> &nbsp; &nbsp;InstallHook,InstallHook1:TInstallHook;<br> &nbsp; &nbsp;UnHook:TUnHook;<br> &nbsp; &nbsp;JmpCode:TJmpCode;<br> &nbsp;public<br> &nbsp; &nbsp;{ Public declarations }<br> &nbsp;end;<br><br>var<br> &nbsp;Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br>function ElevPrivileges(): Boolean;<br>const<br> &nbsp;ADJUST_PRIV &nbsp; &nbsp; &nbsp;= TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES;<br> &nbsp;PRIV_SIZE &nbsp; &nbsp; &nbsp; &nbsp;= SizeOf(TTokenPrivileges);<br>var<br> &nbsp;Len &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: DWORD;<br> &nbsp;TokenPriv, Dummy : TTokenPrivileges;<br> &nbsp;Token &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: THandle;<br>begin<br> &nbsp;Result:=False;<br> &nbsp;try<br> &nbsp; &nbsp;if not OpenProcessToken(GetCurrentProcess(), ADJUST_PRIV, Token) then Exit;<br> &nbsp; &nbsp;if not LookupPrivilegeValue(nil,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'SeDebugPrivilege',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TokenPriv.Privileges[0].Luid) then exit;<br> &nbsp; &nbsp;TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;<br> &nbsp; &nbsp;TokenPriv.PrivilegeCount := 1; <br> &nbsp; &nbsp;if not AdjustTokenPrivileges(Token, False, TokenPriv, PRIV_SIZE,Dummy, Len) then &nbsp;Exit;<br> &nbsp; &nbsp;Result:=True;<br> &nbsp;except<br> &nbsp;end; &nbsp; &nbsp;<br>end;<br><br>function MyInstallHook:Boolean;Stdcall;<br>begin<br> &nbsp;form1.Memo1.Text:='ok';<br> &nbsp;result:=true;<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br> &nbsp;DllHandle:LongWord;<br> &nbsp;dwSize: cardinal;<br>begin<br> &nbsp;DllHandle:=LoadLibrary('Hook.dll');<br> &nbsp;if DllHandle&gt;0 then<br> &nbsp;begin<br> &nbsp; &nbsp;@InstallHook:=GetProcAddress(DllHandle,'InstallHook');<br> &nbsp; &nbsp;@UnHook:=GetProcAddress(DllHandle,'UnHook');<br> &nbsp; &nbsp;@InstallHook1:=GetProcAddress(DllHandle,'InstallHook1');<br> &nbsp; &nbsp;if (@InstallHook=Nil) or (@UnHook=nil) or (@InstallHook1=Nil) then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;showmessage('No Add');<br> &nbsp; &nbsp; &nbsp;Exit;<br> &nbsp; &nbsp;end else<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;ReadProcessMemory(OpenProcess(PROCESS_ALL_ACCESS, True, GetCurrentProcessId),<br> &nbsp; &nbsp; &nbsp; &nbsp;@InstallHook,<br> &nbsp; &nbsp; &nbsp; &nbsp;@JmpCode,<br> &nbsp; &nbsp; &nbsp; &nbsp;5,<br> &nbsp; &nbsp; &nbsp; &nbsp;dwSize);<br> &nbsp; &nbsp; &nbsp;JmpCode.JmpCode:=StrToInt('$B8');<br> &nbsp; &nbsp; &nbsp;JmpCode.Address := @InstallHook1;<br> &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp;WriteProcessMemory(OpenProcess(PROCESS_ALL_ACCESS, True, GetCurrentProcessId),<br> &nbsp; &nbsp; &nbsp; &nbsp;@InstallHook,<br> &nbsp; &nbsp; &nbsp; &nbsp;{@InstallHook1}@JmpCode,<br> &nbsp; &nbsp; &nbsp; &nbsp;{Integer(@InstallHook1)-Integer(@InstallHook)}5,<br> &nbsp; &nbsp; &nbsp; &nbsp;dwSize);<br> &nbsp; &nbsp; &nbsp;sleep(100);<br> &nbsp; &nbsp; &nbsp;InstallHook;<br> &nbsp; &nbsp;end;<br> &nbsp;end else<br> &nbsp;begin &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp;showmessage('no Dll');<br> &nbsp; &nbsp;Exit;<br> &nbsp;end;<br>end;<br><br>procedure TForm1.FormShow(Sender: TObject);<br>begin<br>ElevPrivileges;<br>end;<br><br>end.<br>我的好像这样也没有用啊
 
很高兴这么多高手来指导,都是排名非常靠前的前辈,有你们的指导我估计,我很快能解决问题了.
 
其实我也是才开始研究这个,挫折重重啊
 
搞定了:<br>unit Unit1;<br><br>interface<br><br>uses<br> &nbsp;Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br> &nbsp;Dialogs, StdCtrls;<br><br>type<br><br> &nbsp;TInstallHook=function :Boolean;Stdcall;<br> &nbsp;TUnHook=function :Boolean;Stdcall;<br><br> &nbsp;PJmpCode = ^TJmpCode;<br> &nbsp;TJmpCode = packed record<br> &nbsp; &nbsp;JmpCode: BYTE;<br> &nbsp; &nbsp;Address: Dword;<br> &nbsp;end;<br><br> &nbsp;TForm1 = class(TForm)<br> &nbsp; &nbsp;Button1: TButton;<br> &nbsp; &nbsp;Memo1: TMemo;<br> &nbsp; &nbsp;procedure Button1Click(Sender: TObject);<br> &nbsp; &nbsp;procedure FormShow(Sender: TObject);<br> &nbsp;private<br> &nbsp; &nbsp;{ Private declarations }<br> &nbsp; &nbsp;InstallHook,InstallHook1:TInstallHook;<br> &nbsp; &nbsp;UnHook:TUnHook;<br> &nbsp; &nbsp;JmpCode:TJmpCode;<br> &nbsp;public<br> &nbsp; &nbsp;{ Public declarations }<br> &nbsp;end;<br><br>var<br> &nbsp;Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br>function ElevPrivileges(): Boolean;<br>const<br> &nbsp;ADJUST_PRIV &nbsp; &nbsp; &nbsp;= TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES;<br> &nbsp;PRIV_SIZE &nbsp; &nbsp; &nbsp; &nbsp;= SizeOf(TTokenPrivileges);<br>var<br> &nbsp;Len &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: DWORD;<br> &nbsp;TokenPriv, Dummy : TTokenPrivileges;<br> &nbsp;Token &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: THandle;<br>begin<br> &nbsp;Result:=False;<br> &nbsp;try<br> &nbsp; &nbsp;if not OpenProcessToken(GetCurrentProcess(), ADJUST_PRIV, Token) then Exit;<br> &nbsp; &nbsp;if not LookupPrivilegeValue(nil,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'SeDebugPrivilege',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TokenPriv.Privileges[0].Luid) then exit;<br> &nbsp; &nbsp;TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;<br> &nbsp; &nbsp;TokenPriv.PrivilegeCount := 1; <br> &nbsp; &nbsp;if not AdjustTokenPrivileges(Token, False, TokenPriv, PRIV_SIZE,Dummy, Len) then &nbsp;Exit;<br> &nbsp; &nbsp;Result:=True;<br> &nbsp;except<br> &nbsp;end; &nbsp; &nbsp;<br>end;<br><br>function MyInstallHook:Boolean;Stdcall;<br>begin<br> &nbsp;form1.Memo1.Text:='ok';<br> &nbsp;result:=true;<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br> &nbsp;DllHandle:LongWord;<br> &nbsp;dwSize: cardinal;<br>begin<br> &nbsp;DllHandle:=LoadLibrary('Hook.dll');<br> &nbsp;if DllHandle&gt;0 then<br> &nbsp;begin<br> &nbsp; &nbsp;@InstallHook:=GetProcAddress(DllHandle,'InstallHook');<br> &nbsp; &nbsp;@UnHook:=GetProcAddress(DllHandle,'UnHook');<br> &nbsp; &nbsp;@InstallHook1:=GetProcAddress(DllHandle,'InstallHook1');<br> &nbsp; &nbsp;if (@InstallHook=Nil) or (@UnHook=nil) or (@InstallHook1=Nil) then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;showmessage('No Add');<br> &nbsp; &nbsp; &nbsp;Exit;<br> &nbsp; &nbsp;end else<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;ReadProcessMemory(OpenProcess(PROCESS_ALL_ACCESS, True, GetCurrentProcessId),<br> &nbsp; &nbsp; &nbsp; &nbsp;@InstallHook,<br> &nbsp; &nbsp; &nbsp; &nbsp;@JmpCode,<br> &nbsp; &nbsp; &nbsp; &nbsp;5,<br> &nbsp; &nbsp; &nbsp; &nbsp;dwSize);<br> &nbsp; &nbsp; &nbsp;JmpCode.JmpCode:=233;<br> &nbsp; &nbsp; &nbsp;//JmpCode.Address := @InstallHook1;<br> &nbsp; &nbsp; &nbsp;JmpCode.Address := Integer(@InstallHook1)-Integer(@InstallHook) -5;<br> &nbsp; &nbsp; &nbsp;WriteProcessMemory(OpenProcess(PROCESS_ALL_ACCESS, True, GetCurrentProcessId),<br> &nbsp; &nbsp; &nbsp; &nbsp;@InstallHook,<br> &nbsp; &nbsp; &nbsp; &nbsp;{@InstallHook1}@JmpCode,<br> &nbsp; &nbsp; &nbsp; &nbsp;{Integer(@InstallHook1)-Integer(@InstallHook)}5,<br> &nbsp; &nbsp; &nbsp; &nbsp;dwSize);<br> &nbsp; &nbsp; &nbsp;sleep(100);<br> &nbsp; &nbsp; &nbsp;InstallHook;<br> &nbsp; &nbsp;end;<br> &nbsp;end else<br> &nbsp;begin &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp;showmessage('no Dll');<br> &nbsp; &nbsp;Exit;<br> &nbsp;end;<br>end;<br><br>procedure TForm1.FormShow(Sender: TObject);<br>begin<br>ElevPrivileges;<br>end;<br><br>end.<br><br>我的DLL:<br>library Hook;<br><br>{ Important note about DLL memory management: ShareMem must be the<br> &nbsp;first unit in your library's USES clause AND your project's (select<br> &nbsp;Project-View Source) USES clause if your DLL exports any procedures or<br> &nbsp;functions that pass strings as parameters or function results. This<br> &nbsp;applies to all strings passed to and from your DLL--even those that<br> &nbsp;are nested in records and classes. ShareMem is the interface unit to<br> &nbsp;the BORLNDMM.DLL shared memory manager, which must be deployed along<br> &nbsp;with your DLL. To avoid using BORLNDMM.DLL, pass string information<br> &nbsp;using PChar or ShortString parameters. }<br><br>uses<br> &nbsp;SysUtils,<br> &nbsp;windows,<br> &nbsp;Messages,<br> &nbsp;Controls,<br> &nbsp;ExtCtrls;<br><br>var<br> &nbsp;HookHandle:LongWord;<br><br>{$R *.res}<br>function replace:Boolean;<br>begin<br> &nbsp;if Not FileExists('abcd.txt') then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;FileCreate('abcd.txt');<br> &nbsp; &nbsp;end;<br> &nbsp;Result:=True;<br>end;<br><br>function InstallHook:Boolean;Stdcall;<br>begin<br> &nbsp;if Not FileExists('abc.txt') then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;FileCreate('abc.txt');<br> &nbsp; &nbsp;end;<br> &nbsp;Result:=True;<br>end;<br><br>function InstallHook1:Boolean;Stdcall;<br> &nbsp;type TInstallHool=Function:Boolean;<br>begin<br> &nbsp;TInstallHool(@replace);<br> &nbsp;result:=True;<br>end;<br><br>function UnHook:Boolean;Stdcall;<br>begin<br> &nbsp;UnhookWindowsHookEx(HookHandle);<br> &nbsp;Result:=True;<br>end;<br><br>exports<br> &nbsp;InstallHook,UnHook,InstallHook1;<br> &nbsp;<br>begin<br>end.
 
看下这个可能有帮助<br>http://www.delphibbs.com/delphibbs/dispq.asp?lid=2878699
 
可以比较一下<br>InstallHook函数 在HOOK前后生成两个不同的文件abc.text和abcd.txt
 
俺不是大师, 俺也不是大虾, 俺很惭愧, 俺来听课, 拜托别砸俺, [:D]
 
tt.t :<br>原来如此, 以前没有留意到这种现象<br><br>&gt;&gt;&gt;<br>&quot;调用自定义代码后,不需要再恢复原来的代码,将原来的代码挪至其它地方&quot;<br>这种方法也有局限性,必须对挪走的代码进行分析,如果挪走的代码有对自身绝对地址的访问,则必须修正为新的地址。或者是函数的长度小于5字节,则根本无法使用陷阱式hook。当然,这些都属于极端情况,一般不会发生。 <br>&gt;&gt;&gt;<br><br>局限性是有的,但是不可否认,陷阱式的HOOK应该是最好的方式<br>函数长度小于5个字节的话,肯定会包含对其它函数的调用,或相对跳转<br>可以在HOOK子函数,或者在跳转的目标地址进行HOOK<br>如果一个函数只有5个字节的机器码, 又没有跳转和调用,<br>那么这样的一个函数,恐怕我们也是不需要对其进行HOOK 的吧?<br><br>但是如果使用代码恢复的方法,会带来函数重入和互斥的问题<br><br>复制代码到别的地方,只要策略得当,<br>根本不需要对代码指令进行分析,以及对相对地址和绝对地址作出修正<br><br>方法简单, 但是却能解决最棘手的函数重入的问题,楼主的难点也就在这里<br>我已经验证了其可行性,代码也很简单
 
”局限性是有的,但是不可否认,陷阱式的HOOK应该是最好的方式“<br>这个基本同意。<br>&quot;复制代码到别的地方,只要策略得当,根本不需要对代码指令进行分析,以及对相对地址和绝对地址作出修正&quot;<br>这点不能同意。<br>上面说的例子都属于极端情况,如果仅仅将函数第一条指令替换为一个长跳转的话,一般不会发生。<br>其实我考虑这两点主要是因为某些壳会对其用到的函数进行检测,如果函数第一个字节为E9或函数前n条指令中有长跳转,则认为函数已被hook,拒绝执行或出错。这时就需要用垃圾代码替换函数的前n条指令,在垃圾代码的最后在跳到我们的函数,以躲过检测。这时因为替换了很多指令,就需要对挪走的指令进行分析、修改,才能确保不会出错。<br><br>所以,要不要分析就要看希望做什么样的程序了。如果想做通用的api监视软件,则必须考虑壳的检测问题,如果是针对特定程序则只需采用刚刚够用的方法就可以了。<br><br>另,忽然想到长跳转指令好像不一定非E9开头,可能可以用其他形式的长跳转来欺骗壳的检测。
 
hehe, 如果同时还要考虑加壳软件的防HOOK 技术<br><br>那只能针对使用的防止HOOK 的方法了,<br>不过不是有句话说: 道高一尺,魔高一丈<br>也许没有直接的方法,但会有其它的方法<br><br>我的这个方法也仅仅是为了处理被HOOK函数的重入问题,<br>对于程序中使用的防止HOOK的技术,没有考虑<br>我想除了我说的方法之外,别的HOOK API的方法,也存在同样的问题吧
 
HOOK 的远跳转指令,不一定要放在函数的开头,<br>只要放在一个合适的位置就可以了,<br>那当然就需要对指令代码进行分析了,<br>最起码也要知道你选择的位置不能把一条指令给拆开或破坏了,<br>需要保持指令数据的完整性
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
919
DelphiTeacher的专栏
D
I
回复
0
查看
615
import
I
顶部