开启DNS Client Service日志

假设当前OS是64-bits Win7。至少从2002.11.21开始,有些文章提到DNS Client Service自带一种日志。

对应:

%systemroot%\system32\dnsrslvr.log

Google for dnsrslvr.log,估计能找到一些对它的介绍。我本来对这个没啥兴趣,因为我常年禁用这个服务。但周大因故问起,我就用IDA逆了一下:

%systemroot%\system32\dnsrslvr.dll

为啥逆它呢?因为从注册表里看到:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Dnscache\Parameters

ServiceDll REG_EXPAND_SZ %systemroot%\system32\dnsrslvr.dll

好吧,承认装X了,其实我是在Process Explorer中看到相应svchost.exe加载了它。

那么多svchost.exe,怎么快速知道哪个是该服务的宿主?

我可不是一个个找过去的,至少可以这样:

tasklist /svc /fi "services eq dnscache"

这是个64-bits进程,加载的是64-bits dll。

IDA64虽然用于反汇编64-bits PE,但其本身是个32-bits PE。

假设OS是64-bits Win7,IDA64访问%systemroot%\system32\dnsrslvr.dll时会报告无此文件。

64-bits OS上32-bits程序会碰上”File System Redirector”,比如:

%systemroot%\system32
%systemroot%\syswow64

如果自己写程序,可以禁用这种文件系统重定向:

Wow64DisableWow64FsRedirection
Wow64RevertWow64FsRedirection

IDA64是已经存在的PE,用不上这招。

有个很矬的办法,因为cmd是64-bits的,从中copy时不会重定向,可以复制dnsrslvr.dll到其他不涉及重定向的普通目录,比如x:\tmp\,然后再用IDA64打开。

只是这样真地好吗?

我们是谁,我们是非正常人类研究中心的被研究人员,达文西是我们的同类。

说人话:

32-bits程序用%systemroot%\sysnative\可以访问原始的%systemroot%\system32\

TNND,说了半天已经离题万里了,现在回到IDA64逆向dnsrslvr.dll。

在Strings中搜dnsrslvr.log,查看交叉引用,定位如下代码:

ResolverInitialize ( x )
{
...
DnsLogInit( "dnsrsvlr.log", "Logging for DNS resolver service" );
DnsLogIt( "dnsrslvr.log", "DNS Caching Resolver Service - ResolverInitialize" );
...
}

顾名思义,初始化日志文件、向日志文件写入日志,一切多么美好。等等,这两个破函数的第一形参有那么一点点不同:

dnsrsvlr.log // 这是哪位大哥手抖了一下?
dnsrslvr.log // 这是我们期望的

DnsLogInit()、DnsLogIt()不在dnsrslvr.dll中,而在dnsapi.dll中,继续逆后者。

int __fastcall DnsLogInit ( char * logfile )
{
...
LoggingMode = 0;
LineCount = 0;
...
/*
* 读写打开
*/
logfd = fopen( logfile, "r+" );
if ( logfd )
{
/*
* 开启日志
*/
LoggingMode = 1;
fclose( logfd );
...
/*
* 追加模式
*/
logfd = fopen( logfile, "a" );
if ( logfd )
{
/*
* 输出日志
*/
fprintf( logfd, ... );
fclose( logfd );
}
}
...
}
void DnsLogIt ( char * logfile, char *fmtstr, ... )
{
...
va_list va;

va_start( va, fmtstr );
/*
* 这是个全局变量,位于dnsapi.dll中
*/
if ( LoggingMode )
{
if ( LineCount %systemroot%\system32\dnsrsvlr.log
cacls %systemroot%\system32\dnsrsvlr.log /E /G "NETWORK SERVICE":W

用Administrator提前创建dnsrsvlr.log,让”NETWORK SERVICE”对之有写权限。

验证一下:

$ cacls %systemroot%\system32\dnsrsvlr.log
C:\Windows\system32\dnsrsvlr.log BUILTIN\Administrators:F
NT AUTHORITY\SYSTEM:F
NT AUTHORITY\Authenticated Users:C
BUILTIN\Users:R
NT AUTHORITY\NETWORK SERVICE:(special access:)
READ_CONTROL
SYNCHRONIZE
FILE_GENERIC_WRITE
FILE_WRITE_DATA
FILE_APPEND_DATA
FILE_WRITE_EA
FILE_EXECUTE
FILE_WRITE_ATTRIBUTES

对付dnsrsvlr.log只是让LoggingMode为1。

真正写日志是输出到dnsrslvr.log,同要需要提前处理dnsrslvr.log:

type nul > %systemroot%\system32\dnsrslvr.log
cacls %systemroot%\system32\dnsrslvr.log /E /G "NETWORK SERVICE":W

提前处理dnsrsvlr.log、dnsrslvr.log只涉及NTFS的DACLs,保持空文件就足够了,不需要提前填任何内容。

在dnsrslvr.dll中查看DnsLogInit()的交叉引用,看到两个:

ResolverInitialize()
Areg_RegisterInit()

前者已经分析过了,后者有如下片段:

Areg_RegisterInit ()
{
...
DnsLogInit( "asyncreg.log", "Logging for DNS client registration" );
DnsLogIt( "asyncreg.log", "Inside function Areg_RegisterInit" );
...
}

这次这位大哥没有手抖,只有一个文件:

%systemroot%\system32\asyncreg.log

考虑到DnsLogInit()中一上来就有一句”LoggingMode = 0″,我不确认是否存竞争环境。

想像这样一种情况,ResolverInitialize()成功,LoggingMode置1,Areg_RegisterInit()因为asyncreg.log的权限问题而失败,LoggingMode清零。

因此保险起见,也提前处理一下asyncreg.log好了:

type nul > %systemroot%\system32\asyncreg.log
cacls %systemroot%\system32\asyncreg.log /E /G "NETWORK SERVICE":W

测试时碰上过dnsrsvlr.log、dnsrslvr.log被写入初始化日志,然后就没有下文了,再怎么刺激它,都没有新的日志被写入。

用64-bits cdb调试它:

$ tasklist /svc /fi "services eq dnscache"
$ "C:\Program Files\Windows Kits\8.0\Debuggers\x64\cdb.exe" -noinh -snul -hd -o -p

> dd dnsapi!LoggingMode l 1

发现不知何故LoggingMode为0,在cdb中手工将之置1即可达到预期效果:

> ed dnsapi!LoggingMode 1

当然,前提是相应文件权限已经调整到位。这种现象只出现过一次,再未复现,记录于此备忘。
在dnsapi.dll中检查LoggingMode的交叉引用,只在DnsLogInit()有机会将之置1。
简单看一下日志长什么样:

dnsrslvr.log

DNS_INFO_NO_RECORDSDNS Caching Resolver Service -
R_ResolverQuery Arguments: Name: www.nsfocus.net Type: 1 Flags: 0x40006000
R_ResolverQuery - Returning status: 0x000025E5
DNS_ERROR_RECORD_DOES_NOT_EXISTDNS Caching Resolver Service -
R_ResolverQuery Arguments: Name: www.nsfocus.net Type: 28 Flags: 0x40006000
R_ResolverQuery - Returning status: 0x00000000

asyncreg.log

Inside function Areg_RegisterInitDNS client registrationSystem Time Information

R_ResolverQuery()是dnsrslvr.dll中的函数,里面大量调用DnsLogIt()。

这种日志开销太大,不推荐。

我不负责地YY一下,ETW机制应该有完善的DNS日志支持,有兴趣者放狗搜搜。

至此技术细节都已到位,来个小结:

Q: 如何开启DNS Client Service日志

A: 以Administrator权限执行

net stop dnscache

type nul > %systemroot%\system32\dnsrsvlr.log
type nul > %systemroot%\system32\dnsrslvr.log
type nul > %systemroot%\system32\asyncreg.log

cacls %systemroot%\system32\dnsrsvlr.log /E /G "NETWORK SERVICE":W
cacls %systemroot%\system32\dnsrslvr.log /E /G "NETWORK SERVICE":W
cacls %systemroot%\system32\asyncreg.log /E /G "NETWORK SERVICE":W

net start dnscache

Q: 假设已经启用这种日志,如何重新禁用

A: 以Administrator权限执行

net stop dnscache

del %systemroot%\system32\dnsrsvlr.log
del %systemroot%\system32\dnsrslvr.log
del %systemroot%\system32\asyncreg.log

net start dnscache

如果您需要了解更多内容,可以

加入QQ群:570982169
直接询问:010-68438880

Spread the word. Share this post!

Meet The Author

C/ASM程序员

Leave Comment