Win10 FQDN解析时绕过hosts文件

Guest的hosts文件中有一条

127.0.0.1 geo2.adobe.com

ping它时确实解析成127地址。现在想通过调试手段达成一种效果,绕过hosts文件,
使得ping时看到真实IP。

Guest环境如下

—————————————————

Win10

Win10企业版2016 LTSB 1607(OS Build 14393.4704)

dnsapi.dll

10.0.14393.4350 (rs1_release.210407-2154)

dnsrslvr.dll

10.0.14393.4350 (rs1_release.210407-2154)

—————————————————–

参看

《DNS系列(11)–研究Win10 FQDN解析》
http://scz.617.cn:8/windows/202103071208.txt

《用RPC/ALPC调试手段分析Win10 FQDN解析过程》
https://blog.nsfocus.net/rpc-alpc/

Win10 FQDN解析绝大多数时候都要过dnsrslvr!R_ResolverQuery,在Dnscahce服务中。

参看

https://docs.microsoft.com/en-us/windows/win32/api/windns/nf-windns-dnsquery_w
https://docs.microsoft.com/en-us/windows/win32/api/windns/nf-windns-dnsqueryex
https://docs.microsoft.com/en-us/windows/win32/api/windns/ns-windns-dns_query_request
https://docs.microsoft.com/en-us/windows/win32/dns/dns-constants

可从DNSAPI!DnsQuery_W、DNSAPI!DnsQueryEx等函数推测dnsrslvr!R_ResolverQuery
部分形参。下面是逆向工程得到的dnsrslvr!R_ResolverQuery函数原型,不一定靠谱,
但就原始需求而言,够用了。

dnsrslvr!R_ResolverQuery
(
a1, // rcx
a2, // rdx
/*
* FQDN
/ LPWSTR pwsName, // r8 /
* DNS Record Types
*
* DNS_TYPE_A(1)
* DNS_TYPE_AAAA(0x1c)
/ WORD wType, // r9 a5, // poi(@rsp+0x28) /
* 该值为TRUE时,不调用dnsrslvr!Cache_GetRecordsForRpc,忽略所有
* DNS Cahce条目
/ BOOL BypassCache, // poi(@rsp+0x30) a7, // poi(@rsp+0x38) /
* DNS Query Options
*
* DNS_QUERY_BYPASS_CACHE(8)
* DNS_QUERY_NO_HOSTS_FILE(0x40)
*
* “*pOptions”为0x48时,不调用dnsrslvr!Cache_GetRecordsForRpc
* “*pOptions”为0x40时,忽略DNS Cache中源自hosts文件的条目
* “*pOptions”为0x8时,忽略DNS Cache中非源自hosts文件的条目
*
* 该参与BypassCache互不相干,但都能达到绕过hosts文件的效果
*/
PDWORD pOptions, // poi(@rsp+0x40)
a9, // poi(@rsp+0x48)
a10 // poi(@rsp+0x50)

)

—————————————————

在Guest中确定Dnscache(DNS Client)服务所在进程PID

$ tasklist /svc /fi “services eq dnscache”

Image Name PID Services
========================= ========
svchost.exe 564 CryptSvc, Dnscache, LanmanWorkstation,
NlaSvc, TermService

调试Guest的svchost(564),设置条件断点

bp dnsrslvr!R_ResolverQuery “r $t0=@r8;.if(qwo(@$t0)==0x32006f00650067 and qwo(@$t0+8)==0x6f00640061002e and qwo(@$t0+0x10)==0x63002e00650062 and dwo(@$t0+0x18)==0x6d006f){kpn}.else{du @$t0;gc}”

FQDN是”geo2.adobe.com”时断下,否则显示FQDN后继续。dnsrslvr!R_ResolverQuery
会被频繁命中,若不设过滤条件,无法有效调试。

先在Guest中修改hosts,注释掉”127.0.0.1 geo2.adobe.com”。然后在Guest中
“ping geo2.adobe.com”触发上述断点,停在dnsrslvr!R_ResolverQuery入口。在
Guest中用Process Monitor监控svchost(564)的的网络行为。回到cdb中,gu让
dnsrslvr!R_ResolverQuery正常执行,这会触发53/UDP通信,Process Monitor中查
看UDP通信的调用栈回溯。

—————————————————

0 ntoskrnl.exe EtwpTraceNetwork+0x60 0xfffff802b7e2bf5c
1 tcpip.sys UdpSendMessagesOnPathCreation+0xcd3 0xfffff8054d82bb53
2 tcpip.sys UdpSendMessages+0x1f3 0xfffff8054d82a083
3 tcpip.sys UdpTlProviderSendMessagesCalloutRoutine+0x15 0xfffff8054d829e85
4 ntoskrnl.exe KeExpandKernelStackAndCalloutInternal+0x85 0xfffff802b7cb0c25
5 tcpip.sys UdpTlProviderSendMessages+0x6c 0xfffff8054d80314c
6 afd.sys AfdFastDatagramSend+0x543 0xfffff8054e6aa673
7 afd.sys AfdFastIoDeviceControl+0x15ed 0xfffff8054e69309d
8 ntoskrnl.exe IopXxxControlFile+0x7e1 0xfffff802b8013ed1
9 ntoskrnl.exe NtDeviceIoControlFile+0x56 0xfffff802b80136e6
10 ntoskrnl.exe KiSystemServiceCopyEnd+0x13 0xfffff802b7d75103
11 ntdll.dll NtDeviceIoControlFile+0x14 0x7fff88d95d64
12 mswsock.dll MSAFD_WSPSendMsg+0x37d 0x7fff84a989fd
13 mswsock.dll WSPIoctl+0x7f0 0x7fff84a949f0
14 WS2_32.dll WSAIoctl+0x1be 0x7fff87efb5de
15 WS2_32.dll WSASendMsg+0x112 0x7fff87efaf72
16 DNSAPI.dll Send_MessagePrivateEx+0x2c8 0x7fff848394c8
17 DNSAPI.dll sendUsingServerInfo+0x6b 0x7fff84838e8b
18 DNSAPI.dll sendUdpToNextDnsServers+0x180 0x7fff84838d20
19 DNSAPI.dll Send_AndRecvUdpWithParam+0x27c 0x7fff8483868c
20 DNSAPI.dll Send_AndRecv+0x1c2 0x7fff848377a2
21 DNSAPI.dll Query_Wire+0x4ef 0x7fff8483748f
22 DNSAPI.dll Query_SingleNamePrivate+0x6da 0x7fff848336da
23 DNSAPI.dll Query_SingleNameDualAddr+0xf6 0x7fff84835446
24 DNSAPI.dll Query_NextName+0x38b 0x7fff8482d93b
25 DNSAPI.dll Query_Main+0x904 0x7fff848315e4
26 dnsrslvr.dll ResolverQuery+0x103 0x7fff7c354863
27 dnsrslvr.dll R_ResolverQuery+0x233 0x7fff7c354733
28 RPCRT4.dll Invoke+0x73 0x7fff8817a583
29 RPCRT4.dll Ndr64AsyncServerWorker+0x392 0x7fff881d6162
30 RPCRT4.dll DispatchToStubInCNoAvrf+0x24 0x7fff8814a284
31 RPCRT4.dll RPC_INTERFACE::DispatchToStubWorker+0x1bd 0x7fff8814919d
32 RPCRT4.dll RPC_INTERFACE::DispatchToStub+0xcb 0x7fff88149a4b
33 RPCRT4.dll LRPC_SCALL::DispatchRequest+0x34c 0x7fff881310ac
34 RPCRT4.dll LRPC_SCALL::HandleRequest+0x2bc 0x7fff8813152c
35 RPCRT4.dll LRPC_ADDRESS::HandleRequest+0x36c 0x7fff8811ae1c
36 RPCRT4.dll LRPC_ADDRESS::ProcessIO+0x91b 0x7fff8811c67b
37 RPCRT4.dll LrpcIoComplete+0xaa 0x7fff88143a2a
38 ntdll.dll TppAlpcpExecuteCallback+0x25e 0x7fff88d0d35e
39 ntdll.dll TppWorkerThread+0x8d9 0x7fff88d0ecc9
40 KERNEL32.DLL BaseThreadInitThunk+0x14 0x7fff885b84d4

41 ntdll.dll RtlUserThreadStart+0x21 0x7fff88d41791

结合其他调试分析,一个简化版调用栈回溯如下

dnsrslvr!R_ResolverQuery
dnsrslvr!R_ResolverQuery+0x22e
dnsrslvr!ResolverQuery
dnsrslvr!ResolverQuery+0xfd
DNSAPI!Query_Main
DNSAPI!Query_Main+0x8ff
DNSAPI!Query_NextName
DNSAPI!Query_NextName+0x386
DNSAPI!Query_SingleNameDualAddr
DNSAPI!Query_SingleNameDualAddr+0xf1
DNSAPI!Query_SingleNamePrivate
DNSAPI!Query_SingleNamePrivate+0xee
ntdll!LdrpDispatchUserCallTarget
dnsrslvr!Cache_Query
dnsrslvr!Cache_Query+0x27 // cmp al,48h
// 检查Options
// DNS_QUERY_BYPASS_CACHE、DNS_QUERY_NO_HOSTS_FILE同时置位时
// 返回FALSE,不调用dnsrslvr!Cache_GetRecordsForRpc
dnsrslvr!Cache_Query+0x3c // cmp dword ptr [rcx+120h],edi
// 检查BypassCache
// 为TRUE时返回FALSE,不调用dnsrslvr!Cache_GetRecordsForRpc
dnsrslvr!Cache_Query+0xa6
dnsrslvr!Cache_GetRecordsForRpc
dnsrslvr!Cache_GetRecordsForRpc+0x14f
dnsrslvr!Cache_FindEntry // du @rcx
// 在DNS Cache中寻找FQDN
dnsrslvr!Cache_GetRecordsForRpc+0x1d0 // test byte ptr [r14+14h],40h
// 0x40置位时表示该DNS Cache条目来自hosts文件
dnsrslvr!Cache_GetRecordsForRpc+0x1db // test dil,8
// 检查Options
// DNS_QUERY_BYPASS_CACHE(8)置位时
// 忽略DNS Cache中非源自hosts文件的条目
dnsrslvr!Cache_GetRecordsForRpc+0x2b2 // test dil,40h
// 检查Options
// DNS_QUERY_NO_HOSTS_FILE(0x40)置位时
// 忽略DNS Cache中源自hosts文件的条目
DNSAPI!Query_SingleNamePrivate+0x6d5
DNSAPI!Query_Wire
DNSAPI!Query_Wire+0x4ea
DNSAPI!Send_AndRecv
DNSAPI!Send_AndRecv+0x1bd
DNSAPI!Send_AndRecvUdpWithParam
DNSAPI!Send_AndRecvUdpWithParam+0x277
DNSAPI!sendUdpToNextDnsServers
DNSAPI!sendUdpToNextDnsServers+0x17b
DNSAPI!sendUsingServerInfo
DNSAPI!sendUsingServerInfo+0x66
DNSAPI!Send_MessagePrivateEx
DNSAPI!Send_MessagePrivateEx+0x2c2

WS2_32!WSASendMsg // 53/UDP通信

下列断点均让hosts文件整体失效,可配合条件断点,只让hosts中匹配FQDN失效。

bp dnsrslvr!R_ResolverQuery “ed @rsp+0x30 1;du @r8;gc”
bp dnsrslvr!R_ResolverQuery “ed poi(@rsp+0x40) dwo(poi(@rsp+0x40)) | 0x48;du @r8;gc”
bp dnsrslvr!R_ResolverQuery “ed poi(@rsp+0x40) dwo(poi(@rsp+0x40)) | 0x40;du @r8;gc”

其中前两个断点基本等价,完全忽略DNS Cache。最后的断点只忽略DNS Cache中源自
hosts文件的条目,不忽略DNS Cache中非源自hosts文件的条目。

强调一下,对Guest所在Win10环境,拦截dnsrslvr!R_ResolverQuery,给Options或
上DNS_QUERY_BYPASS_CACHE(8),无法绕过hosts文件。

简单说说调试分析思路。再说一遍,Process Monitor是一种调试器,用它看调用栈
得到逻辑框架。看微软文档再结合逆向工程,测出dnsrslvr!R_ResolverQuery的
BypassCache、pOptions形参意义。动态调试,用数据断点找出几个关键代码点。

版权声明

本站“技术博客”所有内容的版权持有者为绿盟科技集团股份有限公司(“绿盟科技”)。作为分享技术资讯的平台,绿盟科技期待与广大用户互动交流,并欢迎在标明出处(绿盟科技-技术博客)及网址的情形下,全文转发。
上述情形之外的任何使用形式,均需提前向绿盟科技(010-68438880-5462)申请版权授权。如擅自使用,绿盟科技保留追责权利。同时,如因擅自使用博客内容引发法律纠纷,由使用者自行承担全部法律责任,与绿盟科技无关。

Spread the word. Share this post!

Meet The Author

C/ASM程序员

Leave Comment