Win10域名解析时绕过hosts文件
2021-11-19 01:00:00 Author: mp.weixin.qq.com(查看原文) 阅读量:21 收藏

创建: 2021-11-18 12:24
http://scz.617.cn:8/windows/202111181224.txt

Guest的hosts文件中有一条

127.0.0.1   geo2.adobe.com

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

有人要问,直接删掉hosts中相关条目不就是了?不错,有化繁为简的心智,后面的内容不用看了。

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解析过程》
http://scz.617.cn:8/windows/202111161210.txt

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 [email protected];.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+0x1d// test byte ptr [r14+14h],40h
                                                    // 0x40置位时表示该DNS Cache条目来自hosts文件
              dnsrslvr!Cache_GetRecordsForRpc+0x1d// 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形参意义。动态调试,用数据断点找出几个关键代码点。

有意复现者,请在PC上用浏览器看排好版的TXT原文

本篇对绝大多数人而言,属于无用的知识,但肯定对某些人有价值。好了,就说这么多。


文章来源: http://mp.weixin.qq.com/s?__biz=MzUzMjQyMDE3Ng==&mid=2247484946&idx=1&sn=362e589519a75eefc3e2f47d4d94c94f&chksm=fab2c52dcdc54c3bf7235c89e6d441922fa32716359dbb5878d13f0f29eedd3a0e3f35d4325e#rd
如有侵权请联系:admin#unsafe.sh