Add Punycode to your Threat Hunting Routine
IDNs or “International Domain Names” have been with us for a while now (see RFC3490[1]). They are (ab)used in many attack scenarios because.. it works! Who can immediately spot the difference between:
https://youtube.com/
And:
https://youtube.com/
The magic is to replace classic characters by others that look almost the same. In the example above, the letter “o” has been replaced by Greek character “o”.
If they are very efficient for attackers, they remain below the radar in many organizations. To avoid issues when printing unusual characters, Punycode[2] helps to encode them in plain characters. The example above will be encoded as:
xn--yutube-wqf.com
This format is based on:
- “xn--“ : the common prefix for all IDNs requests.
- “yutube.com”: The normal ASCII characters
- “wqf” : The Punycode encoded version of the Unicode character
Python can decode them easily:
$ python3
Python 3.12.3 (main, Jan 8 2026, 11:30:50) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> domain = "xn--yutube-wqf.com"
>>> decoded = domain.encode("ascii").decode("idna")
>>> print(decoded)
y?utube.com
>>> for c in decoded:
... print(f"{c} -> {ord(c)}")
...
y -> 121
? -> 1086
u -> 117
t -> 116
u -> 117
b -> 98
e -> 101
. -> 46
c -> 99
o -> 111
m -> 109
>>>
You can see the value of “o” is not “usual” (not in the ASCII range). They are plenty of online tools that can (de|en)code Punycode[3].
If not all IDNs are suspicious, they are not very common and deserve some searches in your logs. If you already collect your DNS resolver logs (I hope you do!), it’s easy to search for such domains:
$ grep "xn--" queries.log* queries.log:19-Jan-2026 19:54:38.399 queries: info: client @0x999999999999 192.168.255.13#47099 (in.xn--b1akcbzf.xn--90amc.xn--p1acf): query: in.xn--b1akcbzf.xn--90amc.xn--p1acf IN A +E(0) (192.168.254.8) queries.log:20-Jan-2026 04:38:25.877 queries: info: client @0x999999999999 192.168.255.13#49850 (in.xn--b1akcbzf.xn--90amc.xn--p1acf): query: in.xn--b1akcbzf.xn--90amc.xn--p1acf IN A +E(0) (192.168.254.8) queries.log.0:18-Jan-2026 15:22:11.741 queries: info: client @0x9999999999 192.168.255.13#60763 (in.xn--b1akcbzf.xn--90amc.xn--p1acf): query: in.xn--b1akcbzf.xn--90amc.xn--p1acf IN A +E(0) (192.168.254.8) queries.log.0:18-Jan-2026 17:27:23.127 queries: info: client @0x99999999999 192.168.255.13#44141 (in.xn--b1akcbzf.xn--90amc.xn--p1acf): query: in.xn--b1akcbzf.xn--90amc.xn--p1acf IN A +E(0) (192.168.254.8) queries.log.0:18-Jan-2026 22:54:36.841 queries: info: client @0x99999999999 192.168.255.13#35963 (in.xn--b1akcbzf.xn--90amc.xn--p1acf): query: in.xn--b1akcbzf.xn--90amc.xn--p1acf IN A +E(0) (192.168.254.8)
The detected Punycode domain is decoded to:

Another good proof that DNS is a goldmine for threat hunting!
[1] https://datatracker.ietf.org/doc/html/rfc3490
[2] https://en.wikipedia.org/wiki/Punycode
[3] https://regery.com/en/domains/tools/punycode-decoder
Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
| Reverse-Engineering Malware: Advanced Code Analysis | Amsterdam | Mar 16th - Mar 20th 2026 |

Comments