暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Windows域名解析保护机制深度分析

青衣十三楼飞花堂 2021-11-24
980
创建: 2021-11-24 11:29
http://scz.617.cn:8/windows/202111241129.txt

复制

2006年4月Dave Korn在[Full-disclosure]邮件列表中发言,指责微软干扰hosts文件的使用。一般FQDN的解析顺序都是hosts文件优先,但XP SP2在解析某些FQDN时不再尊重hosts中的设置。XP SP2的dnsapi.dll中固化了一批FQDN,据Dave Korn测试,至少如下两个FQDN被特殊对待了

go.microsoft.com
office.microsoft.com

即使在hosts文件中将这两个FQDN解析成127.0.0.1,也会成功访问它们。当年我测过,XP SP1尚无此行为。

现在要是放狗搜,有很多相关讨论,不过都流于表象,并未从逆向工程角度阐述此事。本来我也不关心这事的技术细节,但前几天搞Win10 RPC调试时拿Dnscache服务做靶子,遇到hosts中的"download.windowsupdate.com"无法生效,好奇心起,逆向工程了一把。本文没有直接给结论,展示一下探索过程。

在Guest中编辑hosts

127.0.0.1   settings-win.data.microsoft.com
127.0.0.1   sls.update.microsoft.com
127.0.0.1   fe2.update.microsoft.com
127.0.0.1   download.windowsupdate.com
127.0.0.1   au.download.windowsupdate.com
127.0.0.1   ctldl.windowsupdate.com
127.0.0.1   geo.prod.do.dsp.mp.microsoft.com

无法阻止Win10更新。简单测试表明,如下FQDN不受hosts影响

sls.update.microsoft.com
fe2.update.microsoft.com
download.windowsupdate.com
au.download.windowsupdate.com
ctldl.windowsupdate.com

下列FQDN不受保护

settings-win.data.microsoft.com
geo.prod.do.dsp.mp.microsoft.com

假设Dnscache服务位于svchost(564)中,调试之

bp dnsrslvr!Cache_FindEntry "du @rcx"

该函数第1形参是FQDN。假设断下时正在请求解析"download.windowsupdate.com",gu之后rax为0,表示没找到。从而确认DNS Cache中没有相应FQDN,表明hosts中条目未被加入DNS Cache。可以换其他非微软FQDN测试,hosts中条目正常进入DNS Cache。

编辑hosts,保存,让文件产生时间戳变动。用Process Monitor监控svchost(564),发现有

svchost.exe 564 NotifyChangeDirectory   C:\Windows\System32\drivers\etc

应该是提醒Dnscache重读hosts文件。

ipconfig /flushdns
ping download.windowsupdate.com

用Process Monitor监控svchost(564),发现Dnscache服务读取hosts,调用栈如下


0   FLTMGR.SYS      FltpPerformPreCallbacksWorker+0x480
1   FLTMGR.SYS      FltpPassThroughInternal+0x88
2   FLTMGR.SYS      FltpPassThrough+0x1a6
3   FLTMGR.SYS      FltpDispatch+0x9e
4   ntoskrnl.exe    IopSynchronousServiceTail+0x1a0
5   ntoskrnl.exe    NtReadFile+0x670
6   ntoskrnl.exe    KiSystemServiceCopyEnd+0x13
7   ntdll.dll       NtReadFile+0x14
8   KERNELBASE.dll  ReadFile+0x74
9   DNSAPI.dll      hostsFileSniffBom+0x5b
10  DNSAPI.dll      HostsFile_Open+0x14e
11  dnsrslvr.dll    LoadHostFileIntoCache+0x53
12  dnsrslvr.dll    Cache_Initialize+0xda
13  dnsrslvr.dll    Cache_Lock+0x80
14  dnsrslvr.dll    Cache_GetRecordsForRpc+0xa0
15  dnsrslvr.dll    Cache_Query+0xab
16  DNSAPI.dll      Query_SingleNamePrivate+0xf4
17  DNSAPI.dll      Query_SingleNameDualAddr+0xf6
18  DNSAPI.dll      Query_NextName+0x38b
19  DNSAPI.dll      Query_Main+0x904
20  dnsrslvr.dll    ResolverQuery+0x103
21  dnsrslvr.dll    R_ResolverQuery+0x233
22  RPCRT4.dll      Invoke+0x73
23  RPCRT4.dll      Ndr64AsyncServerWorker+0x392
24  RPCRT4.dll      DispatchToStubInCNoAvrf+0x24
25  RPCRT4.dll      RPC_INTERFACE::DispatchToStubWorker+0x1bd
26  RPCRT4.dll      RPC_INTERFACE::DispatchToStub+0xcb
27  RPCRT4.dll      LRPC_SCALL::DispatchRequest+0x34c
28  RPCRT4.dll      LRPC_SCALL::HandleRequest+0x2bc
29  RPCRT4.dll      LRPC_ADDRESS::HandleRequest+0x36c
30  RPCRT4.dll      LRPC_ADDRESS::ProcessIO+0x91b
31  RPCRT4.dll      LrpcIoComplete+0xaa
32  ntdll.dll       TppAlpcpExecuteCallback+0x25e
33  ntdll.dll       TppWorkerThread+0x8d9
34  KERNEL32.DLL    BaseThreadInitThunk+0x14
35  ntdll.dll       RtlUserThreadStart+0x21

复制

从前述调用栈中关注到"DNSAPI!HostsFile_*"

> x DNSAPI!HostsFile_*
00007fff`84841c10 DNSAPI!HostsFile_Query (void)
00007fff`8483cda0 DNSAPI!HostsFile_ReadLine (void)
00007fff`8483d710 DNSAPI!HostsFile_Close (void)
00007fff`8483d330 DNSAPI!HostsFile_Open (void)
00007fff`8485bfe8 DNSAPI!hostsFile_ScreenName (hostsFile_ScreenName)

IDA中静态分析DNSAPI!HostsFile_ReadLine,注意到DNSAPI!BuildHostfileRecords。用wt分析DNSAPI!BuildHostfileRecords内部执行情况,搞个对比实验,一次是微软域名,另一次是非微软域名,用.logopen/.logclose记录wt输出。

对比BuildHostfileRecords_bad.txt、BuildHostfileRecords_ok.txt,很容易发现分叉点

   25     0 [  0] DNSAPI!BuildHostfileRecords
                      call at 00007fff8483bfed
  777     0 [  1]   DNSAPI!Dns_NameCompareEx rax = 0
   37   777 [  0] DNSAPI!BuildHostfileRecords
                      call at 00007fff8483bfed
  821     0 [  1]   DNSAPI!Dns_NameCompareEx rax = 2

复制

前者第二次调用DNSAPI!Dns_NameCompareEx时返回2,后者5次调用DNSAPI!Dns_NameCompareEx均返回0。

用IDA查看DNSAPI!BuildHostfileRecords+0x7d附近代码,DNSAPI!Dns_NameCompareEx对源自hosts文件的RightName进行检查,LeftName源自DNSAPI!DomainScreenList[5]

windowsupdate.microsoft.com
windowsupdate.com
microsoftupdate.com
download.microsoft.com
update.microsoft.com

前述DNSAPI!Dns_NameCompareEx返回2那次

LeftName    windowsupdate.com
RightName   download.windowsupdate.com
CharSet     DnsCharSetUnicode(1)
Return      DnsNameCompareLeftParent(2)

正是这次匹配使得download.windowsupdate.com未能进入DNS Cache。

除了DNSAPI!DomainScreenList[5],还有DNSAPI!HostsScreenList[18]

microsoft.com
www.microsoft.com
support.microsoft.com
wustats.microsoft.com
download.microsoft.com
microsoftupdate.microsoft.com
office.microsoft.com
msdn.microsoft.com
go.microsoft.com
msn.com
www.msn.com
msdn.com
www.msdn.com
technet.microsoft.com
technet.com
www.technet.com
activation-v2.sls.microsoft.com
validation-v2.sls.microsoft.com

当DNSAPI!DomainScreenList[5]均不匹配时,继续检查DNSAPI!HostsScreenList[18]。

> u DNSAPI!BuildHostfileRecords+0x41 l 6
00007fff`8483bfb1 488b05f8430500  mov     rax,qword ptr [DNSAPI!DomainScreenList (00007fff`848903b0)]
...
00007fff`8483bfcb 4885c0          test    rax,rax
00007fff`
8483bfce 743b            je      DNSAPI!BuildHostfileRecords+0x9b (00007fff`8483c00b)

> u DNSAPI!BuildHostfileRecords+0x9b l 5
00007fff`
8483c00b 4c8b05ce430500  mov     r8,qword ptr [DNSAPI!HostsScreenList (00007fff`848903e0)]
...
00007fff`
8483c01e 4d85c0          test    r8,r8
00007fff`8483c021 7466            je      DNSAPI!BuildHostfileRecords+0x119 (00007fff`8483c089)

复制

从上述两段代码逻辑看,只要DNSAPI!DomainScreenList[0]、
DNSAPI!HostsScreenList[0]为NULL,这两种微软域名保护检查将被绕过。

Patch

eq DNSAPI!DomainScreenList 0
eq DNSAPI!HostsScreenList 0

假设hosts修改如下

127.0.0.1   sls.update.microsoft.com
127.0.0.1   fe2.update.microsoft.com
127.0.0.1   download.windowsupdate.com

ipconfig /flushdns

之后Guest的"Checking for updates"报错

We couldn't connect to the update service. We'll try again later, or you can check now. If it still doesn't work, make sure you're connected to the Internet.

热Patch绕过微软域名保护需要上调试器。若不想上调试器,可在Guest上启动一个定制版DNS Server,由它负责Guest的所有FQDN解析;当它发现需要劫持的FQDN出现,直接返回指定IP,否则转发给其他正常DNS Server。这种工具很多,以前我分享过一个superdns.exe。

vi some.hosts

127.0.0.1   ^.+\.update\.microsoft\.com.$
127.0.0.1   ^.+\.windowsupdate\.com.$

复制

将Guest的DNS Server指向127.0.0.1,执行superdns

superdns.exe -q -m udp -i 192.168.65.2 some.hosts

假设192.168.65.2是其他正常DNS Server,若是VMware环境,这就是Host所在。some.hosts中劫持了正则表达式匹配之FQDN。-q表示安静模式,去掉后可以看到调试信息,比如请求解析的FQDN以及响应报文解码后的内容。这样干,效果同热Patch。

去掉-q,确认Win10自动更新首先检查

sls.update.microsoft.com

实际只需劫持这一个FQDN即可干扰Win10自动更新。该FQDN会被解析成不同IP,并不固定,否则可在PFW中对出站请求的目标IP设置阻断规则。

bluerust  有意思啊,我都不知道还有这回事
scz       你看,虽然我没有MCSE证,也能勉强用用Windows


文章转载自青衣十三楼飞花堂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论