挂钩(hook)具体的接口函数,比如挂钩(hook)gethostbyname接口等函数。
这些接口函数可不止gethostbyname,还包括 getaddrinfo,
WSALookupServiceBegin,WSALookupServiceNext,
DnsQuery_Xxx
至少我知道的起码有以上这些接口函数,应该还有更多,不过到时可以根据具体程序来查漏补缺。
至于如何hook具体程序的具体这些接口函数,这里不再赘述,反正是能实现的。
有兴趣可以去查阅我讲述的远程桌面系列文章中关于dxhook的相关文章,里边有阐述如何hook接口函数的内容。

除了hook具体的接口函数之外,难道没有别的办法了吗?
自然是有的,windows系统提供了NSP (Name Space Provider) 机制,类似于winsock中的LSP机制。
其实性质也是做具体接口函数的hook。

NSP的大致实现办法:
我们需要开发一个dll动态库,这个动态库必须导出 NSPStartup 接口函数,
而在这个接口函数中,会提供 NSP_ROUTINE 结构的参数,
里边我们必须填写正确对应的回调函数,其中包括三个核心函数:
NSPLookupServiceBegin
NSPLookupServiceNext
NSPLookupServiceEnd
只要dns查询接口函数发起调用,这三个核心函数就会被调用。
于是我们在此回调函数中就能找到dns域名和具体进程的对应关系。
并且把查询dns的请求正确路由到我们的代理中。
但是这里的回调函数调用与我们通常理解的hook又有些不同,
具体下面会讲述,这个也是把dns请求正确路由到我们的代理中的必须考虑的。

而且细心就会发现,系统导出的win32 api函数
WSALookupServiceBegin, WSALookupServiceNext, WSALookupServiceEnd
与上面的三个核心回调函数很像。
确实如此,比如 WSALookupServiceBegin调用的时候,就是查询nsp服务列表,然后调用这些nsp服务的回调函数,
也就是如果我们注册了自己的nsp服务,最终WSALookupServiceBegin 也会调用我们自己NSPLookupServiceBegin回调函数。
而系统的gethotbyname,getaddrinfo等其他函数,内部是通过调用 WSALookupServiceBegin 接口函数实现的。
这样就等于是一环扣一环,最终都会正确路由到nsp的回调函数中。

接着我们在程序中,调用 WSCInstallNameSpace 函数,安装我们的这个dll动态库,
这样我们nsp就能正常工作了。
是不是很简单!

不过也别高兴的太早,让nsp老老实实的为我们服务,也不大容易。
系统中存在一个系统默认的nsp服务,这个服务就是沟通dnscache,发起真正的dns请求nsp服务。
也就是如果不出意外的话,系统默认的nsp都会被调用。
举个例子,有三个NSP服务:
myself(M)我们自己的nsp; other(O)其他NSP; System(S)系统默认的NSP。

现在假设这三个服务的安装顺序是:M->O->S
按照我们通常hook的理解,当某个函数返回成功,就不再继续调用下一链条的函数。
比如 如果M.NSPLookupServiceBegin成功之后,
就不调用 O.NSPLookupServiceBegin 函数和S.NSPLookupServiceBegin 函数。
但实际情况是: 不管成功与否,都会按如下顺序,所有nsp的函数都会调用一遍:
M.NSPLookupServiceBegin -> O.NSPLookupServiceBegin ->S.NSPLookupServiceBegin
同样的,
M.NSPLookupServiceNext -> O.NSPLookupServiceNext -> S.NSPLookupServiceNext
也会跟着这样顺序调用一遍,并且最要命的是,会把 *Next函数的调用结果进行合并:
比如 M查询到地址是 1.1.1.1, S查询到的地址是 2.2.2.2,于是返回的DNS结果就有 1.1.1.1和2.2.2.2两个。

我们实现NSP的目标是完全拦截对dns请求,也就是只要处于设置的规则范围内的域名解析,
都交给我们自己处理,也不能再次通过dnscache缓存,再去查询一遍。

其他nsp我们暂时可以不必去关心,最讨厌的是如何让系统的nsp别调用,或者调用了也让它返回空值。
好在还是有办法解决这个问题:
在NSPLookupServiceBegin 函数中第2个参数,是 WSAQUERYSETW 结构的参数。
WSAQUERYSETW 里边有个参数 dwNameSpace, 这个就是关键所在。
这个dwNameSpace 有多个选项,比如NS_DNS就是dns查询,具体含义可以去msdn查询。
系统的nsp在调用NSPLookupServiceBegin 时候是会检测这个参数的。
如果我们把这个参数改成别的值,那系统nsp就会错误的调用。
最通用的就是设置 dwNameSpace = NS_TCPIP_HOSTS ,
这样让系统默认的nsp只查询 本地 /etc/hosts文件中域名对应关系,自然大部分情况下都查不到。

光这样设置还不够,因为上面说了,NSPLookupServiceBegin 是按照上面的安装顺序来调用的。
如果系统默认nsp在我们的nsp之前调用,其实是没效果的。
而WSCInstallNameSpace 函数安装后,我们的nsp是排到最后的,也就是 O->S->M 这样的顺序。
因此我们还得排个序,调用WSCWriteNameSpaceOrder来排序,排到最前面,变成 M->O->S 这样的顺序。

这样,我们的nsp才算基本上为我们服务。
至于如何截取dns域名和具体进程关系,我们在xFsRedir中如何再次处理dns请求,
这里不再赘述。

有兴趣可以下载 xfsredir使用,最新版本以后会更新上去。
GitHub – fanxiushu/xFsRedir
————————————————
原文链接:https://blog.csdn.net/fanxiushu/article/details/127371222

原文地址:http://www.cnblogs.com/bonelee/p/16881314.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性