Bytes over DNS, (Mon, Oct 27th)
嗯,用户让我用中文帮他总结一下这篇文章,控制在100字以内,而且不需要以“文章内容总结”或者“这篇文章”这样的开头。直接写文章描述即可。 首先,我需要通读整篇文章,理解其主要内容。这篇文章讲的是通过DNS传输二进制数据的可能性,特别是使用BASE64编码。作者Didier Stevens讨论了在不同DNS基础设施(如CloudFlare、Google和ISP)下传输字节值的可行性。 文章中提到,在使用操作系统API进行DNS查询时,Windows和Ubuntu在不同DNS提供商下有不同的限制。例如,在Windows使用CloudFlare时可以传输字母、数字、连字符和下划线,而使用Google时则只能传输数字、连字符和下划线,并且字母可能因为反欺骗措施而改变大小写。 进一步的测试显示,使用Python的dnspython库时,可以传输更多的ASCII字符,但仍然有一些限制。最后,通过自定义DNS数据包的传输和解析,作者发现可以更可靠地传输所有字节值,包括0x2E(点),特别是在CloudFlare的情况下。 结论是,在CloudFlare上通过自定义DNS包可以可靠传输所有字节值;而在Google上虽然也能传输,但字母的大小写可能会变化。作者还提到他计划进一步研究检测这种异常DNS流量的方法。 现在我需要将这些要点浓缩到100字以内。重点包括:研究通过DNS传输二进制数据的可能性;测试了不同基础设施下的情况;发现通过自定义DNS包可以在CloudFlare上可靠传输所有字节值,在Google上则有部分限制;以及结论部分提到检测异常流量的研究计划。 最后,确保语言简洁明了,并且符合用户的要求。 </think> 本文探讨了通过DNS传输二进制数据的可能性。测试显示,在CloudFlare上可可靠传输所有字节值(包括点),但在Google上字母大小写可能变化。研究结果表明,自定义DNS包可提升数据传输能力,并为检测异常DNS流量提供了思路。 2025-10-27 09:10:1 Author: isc.sans.edu(查看原文) 阅读量:5 收藏

I was intrigued when Johannes talked about malware that uses BASE64 over DNS to communicate. Take a DNS request like this: label1.label2.tld. Labels in a request like this can only be composed with letters (not case-sensitive), digits and a hyphen character (-). While BASE64 is encoded with letters (uppercase and lowercase), digits and special characters + and /. And also a special padding character: =.

So when sticking to the standards, it is not possible to use BASE64 in a label. What happens when we don't stick to the standards?

So I wanted to know what byte values I could transmit over DNS when using third-party DNS infrastructure over which I have no control, like my ISP, CloudFlare, Google, ...

Here is a schema:

In red, you have the machines I have control over: my workstation on the left, where I do the DNS queries, and my server on the Internet on the right, where I have my DNS software running (dnsresolver.py).

In blue are the servers of the DNS infrastructure I'm using, over which I have no control.

In a first test, I'm using the name resolution API of the OS.

My queries look like this: bytes.41.A.mydomain.com. In this example, 41 is the hexadecimal value of the byte value I'm transmitting, and A is the ASCII representation of the byte value I'm transmitting. On the other end, I have my dnsresolver.py software running with a custom function, that checks the incoming request to see if the hexadecimal value still corresponds to the ASCII value. It logs the result in a log file, and replies with 127.0.0.1 if it matches, and with NXDOMAIN if it doesn't.

Then on my workstation, I do these queries for all byte values between 0x00 and 0xFF.

On Windows using CloudFlare (1.1.1.1), I can only reliably transmit letters (uppercase and lowercase), digits, a hyphen (-) and an underscore (_).

On Windows using Google (8.8.8.8), I can only reliably digits, a hyphen (-) and an underscore (_). Letters can not be reliably transmitted, because of an anti DNS-spoofing measure: Google will change the case of letters (for example, google.com becomes GoOgLe.com). You don't see that as an enduser, but my DNS software sees it.

So in theory, I could use BASE64 in a DNS C2 channel, provided CloudFlare is used and provided I replace + and / with - and _. And provided I don't use a padding character.

On Ubuntu, I can transmit reliably all ASCII characters (0x00 - 0x7F), except 0x00 and 0x2E (.). That's for CloudFlare. Google is the same, except for letters.

So I could do even better than BASE64, since I have 126 byte values at my disposition.

All byte values between 0x80 and 0xFF fail, most of them because they get converted to punicode.

Second test is to use a DNS library in stead of the OS API (I use Python module dnspython/dns.resolver).

On Windows and Ubuntu, I can transmit reliably all ASCII characters (0x00 - 0x7F), except 0x2E (.). That's for CloudFlare. Google is the same, except for letters.

The reason that the library cannot transmit a dot (.), so that's request bytes.2E...mydomain.com., is that in a DNS packet, a query is a encoded as a sequence of run-length encoded labels, and dots are not represented. 

So mydomain.com. becomes:

0x08 is the length of label mydomain, 0x03 is the length of label com, and 0x00 is the length of the root label (the . at the end of mydomain.com.).

All byte values between 0x80 and 0xFF fail, most of them because they get converted to PUNICODE.

And as a third test, I'm going to craft and transmit my own DNS packets, so that I have full control:

On Windows and Ubuntu, I can transmit reliably all ASCII characters (0x00 - 0x7F), also 0x2E (.). That's for CloudFlare. Google is the same, except for the letters.

And I can reliably transmit all values between 0x80 and 0xFF, but my dnsresolver.py tool that uses the dnslib Python library, can not parse them. So I would need to find a DNS packet parser that handles this, or write my own. I verified that values between 0x80 and 0xFF arrive reliably, but doing a packet capture on my server.

Conclusion

All byte values (even 0x2E .) can be reliably transmitted over the CloudFlare DNS infrastructure, provided one crafts and parses their own DNS packets.

On Google, all values are accepted too, but the case of letters can change because of Google's anti-spoofing measure.

If you want to perform your own DNS tests, you can find more details on my blog post "Bytes over DNS Tools".

Next on my todo list is to perform research to detect abnormal DNS traffic like this.

Didier Stevens
Senior handler
blog.DidierStevens.com


文章来源: https://isc.sans.edu/diary/rss/32420
如有侵权请联系:admin#unsafe.sh