Recently, a friend of mine has asked for my help in an investigation. In his SIEM system, he saw that a machine generated some DNS sinkhole events, but he couldn’t find the originally requested DNS by the host. The events were generated because the machine tried to resolve a DNS hostname which was marked as malicious in the DNS Server. Unfortunately due to the huge amount of DNS requests in a network, this company did not store the DNS events in the SIEM. Without that information the incident needed some host-based investigation. Since I’m more familiar with Windows-based analysis he asked me to help him find the original target domain on the given Windows system. I didn’t have any deep knowledge about DNS artifacts on Windows that time. Thus, I decided to examine the behavior of Windows 10 in case of DNS requests and document it here. I’m going to show you some Windows-based artifacts, test Edge as well as Firefox, but the deeper tests were made with Chrome/Chromium.
Besides the relevant artifacts, I also documented other interesting DNS related activities. Even though these weren’t too much of a help in the resolution of this case they can be useful in the future and are good-to-know.
DNS Sinkholing mechanism was designed to intercept DNS requests which contain malicious or unwanted URLs. During DNS sinkholing, the DNS request is hijacked by the DNS server by sending back a non-valid IP address or an administrator defined IP. This IP is going to be the sinkhole IP.
When a system/user tries to communicate with a domain, first it has to gather its IP address. This is done by sending a Domain Name Resolution (DNS) request to a DNS server and asking it for the IP of the given domain. If the DNS server recognizes this domain as malicious, it is sending back the IP of the sinkhole. The host is going to use the sinkhole IP to connect to the target server, therefore the whole communication is done between the host and the administrator owned sinkhole server and not between the host and a malicious site. This way C2 (C&C) and drive-by-download infections can be prevented since the host won’t be able to gather the IP address of the malicious system.
Malicious DNS request without the sinkhole.
And the same request with sinkhole.
In case of the previously mentioned infection, we had an event generated by the sinkhole mechanism. This means we knew that a machine wanted to communicate with an unwanted URL and we knew which machine was the one. That was all the information we had in that specific case.
So what are the places I would check to find information about the visited URL?
- First I would check the sinkhole event itself in the SIEM system. Unfortunately, these events didn’t contain the URL in the given case so this one didn’t help me out. (After my investigation the affected company decided to add the URL into the sinkhole events.)
- DNS logs in the SIEM. Sadly, a host can generate a huge amount of events. Since the license for the SIEM has to be paid based on the number of the handled events, many companies opt-in to get rid of DNS events. Firms also tend to turn off these events because a lot of information in the DNS logs can also be found in other logs like HTTP(s) ones. Therefore turning them off is a good method to spare some money. Unfortunately, this was the situation in this case as well, so there weren’t any DNS logs.
- The other logs which generally contain DNS information are the HTTP/HTTPs logs. In lots of cases, these are eliminated for the same reason as the DNS logs. Similar information can be found somewhere else. In this case, the reasoning was that the same information will be stored in the proxy logs so catching HTTP traffic on the line with taps won’t be needed. But HTTP traffic towards the sinkhole IP wasn’t routed through any logging proxy so no proxy logs were generated for this traffic.
- Since I could not find any network-based logs, I decided to move to host-based logs and this was when I checked Windows and browser caches. The latter one can’t be directly accessed for a long time due to security reasons. The former one, the Windows DNS cache was already gone, at least the relevant one since this is only stored in the memory. And the machine has already been restarted at the time of the collection. (The machine was also re-imaged at the time I was asked so I don’t know whether the communication continued after the restart or not. But when I checked the memory there weren’t any suspicious DNS entries.)
- While in this particular investigation checking the hosts file weren’t useful, in normal cases it can contain practical information. If an entry had been in the hosts file no DNS sinkholing would have been done at all. In case of DNS sinkholing, the host is asking a DNS server to translate a URL to an IP. But if the hosts file has an entry with the given URL, then DNS querying, and therefore URL sinkholing won’t be done.
- Checking related Windows events can also be useful. I have never done any DNS checking on a machine before the above-mentioned investigation so finding some DNS based events was new and advantageous for me too.
- Checking NetBIOS name resolution traffic. (Checking either network or host-based artifacts.) This bullet point is again something that wasn’t helpful in this particular case. NetBIOS traffic won’t be sent to a DNS server therefore sinkholing traffic won’t be generated. However it is good to know that some of the SIEMs and network-based security systems are categorizing NetBIOS name resolution events as DNS over port 137 for some reason.
One can see from the list above that there are various sources that can be used to find one specific piece of information. There can be even more in different networks. Whether a given log souce is necessary or not depends on the provided service. There is a big difference in the necessary log sources and information when someone tries to provide a Tier 1 Security or a full Incident Response/Threat Hunting service. In case of the former one, a lot of companines want to create an alert for every log type. If there is no alert(rule) for a specific event type (like DNS logs) the management thinks it’s just a waste of money. Thus either a rule is going to be created for that log or it is removed from the SIEM. This is especially true when the analysts are not trained enough to look for other evidence than the information collected by the alert.
In the latter cases (Threat Hunting) even events not yet used can be useful in the future. In those cases, one can’t properly predict the necessity of a specific log type based on its past usage. When it comes to Threat Hunting, one either tries to find something new in the already provided logs OR attempts to get some new events to hunt and then create alerts based on them. The fact that the company does not have an alert based on an event does not mean that the event lacks of useful information hidden inside of it.
Of course I don’t mean that every logs are needed. Unnecessary redundancy can be eliminated and also the price and usefulness of new events have to be considered surely. For instance, the above-mentioned situation could have been easily solved with either DNS logs, or HTTP logs captured from the wire. Even a little bit modified sinkhole event would have been more useful because we only needed the DNS information in addition. But the proxy logs, which I think can be found in every SIEM systems nowadays, weren’t really usable for us. To sum up, think carefully when you have to choose between log sources or when you have to turn them on or off.
The browser-based DNS cache doesn’t need too deep explanation. It simply can’t be checked. I did not find any way to check the DNS cache for the specific browsers.In the past, there were some tabs for checking the specific DNS entries in various browsers but it looks like this function was removed from every browser I tested (Chrome/Chromium, Firefox, Edge). However there is still a cache in at least some of them. An entry is going to be removed from the cache after some time defined by the expiration date or when the browser is closed.
Here are some browser-specific tests I made:
I opened a random site in the browser to check what kind of a DNS traffic is generated. In case of site opening, it made A(IPv4) and AAAA(IPv6) requests. The browser used the A one, so the IPv4 address to open the site. Firefox was the only one which generated A and AAAA queries as well.
After this test, I was curious whether the browser uses its own cache or not. To find this out I closed the opened tab with the checked domain in it, but I left the browser itself open. Then I removed the OS cache with the “ipconfig /flushdns” command and re-opened the URL in the running browser. No new DNS request was sent which means the browser used its own cache rather than reading it from the OS cache. If it had called the OS cache, DNS requests would have been sent since the OS cache did not contain the DNS (due to flushdns).
Different from Firefox is that Chrome only generates A queries and not AAAA queries. This means Firefox initially generated more packets than Chrome. When I opened a page in Chrome it only tried to query the IPv4 address and used that one to open the page so no IPV6-related traffic was generated at all.
I also performed the other test I did for Firefox. Removed the OS DNS cache, closed the tab in Chrome, but left the browser open and opened the same domain again. No new traffic was generated which means Chrome used its own cache.
Only A queries were generated in case of domain opening. It looks like only Firefox triggered an AAAA DNS request and the other browsers didn’t. The other test showed interesting results though. After removing the OS cache and reopening a site (without closing the browser) new DNS entries were generated. It looks the browser doesn’t store DNS entries in its own cache. While Chrome and Firefox don’t generate DNS queries for this activity, Edge does. This means Edge might not have an internal cache or it is working differently than Firefox’s and Chrome’s cache.
When I pinged a site from command line the same DNS request was seen in Wireshark. In this case, only an A record was caught on the wire.
Based on these tests we can see that the memory will contain the DNS requests in the cache. The DNS cache of the browsers is not observable directly but we can find the same information in the OS DNS cache. The browsers are using the DNS resolve function of Windows so every DNS request is going to be stored in the OS cache. Browsers have their own cache but it is only temporary. After every machine or browser restart, this information is lost. Therefore the browsers have to ask the OS to provide the IP for a domain again, which information is going to be saved into the OS cache.
On Windows 10 the entries in the DNS cache can be checked via command line with the ipconfig /displaydns command. And the cache can be emptied with the ipconfig /flushdns command.
Since the cache is stored in the memory, it is going to be removed after OS restart. An entry is also removed after the expiration time. Besides displaying the entries on a live system with ipconfig, the entries can be parsed out from a memory dump as well. There is a plugin for volatility which can help you parse the given values from a dump. The given plugin is named dnscache.
I tested some functions on Chrome and Chromium which I read about. Some of these function can exist or work differently on other browsers but I only tested them on Chrome and Chromium. Since the results were the same, I’m not going to differentiate between these two browsers. The tested functions are all related to DNS prefetch:
- Prefetch controls on web pages
- DNS activity during browser startup
- Omnibox usage
- Top Sites DNS resolve
DNS resolution time is the time that is needed to translate a DNS to an IP. Latency due to DNS resolution can be highly variable between the range of 1ms (cached DNS) to several seconds. To address this issue the browser vendors implemented DNS prefetch. This function starts the DNS resolution before the user actually clicks on a link or tries to open a site. For Chromium, the developer of the website can also define prefetch HTML tags. The DNSs in these tags are going to be prefetched. There are two ways to define prefetch in HTML. Links can be defined to be prefetched 1-by-1 (manual prefetch) or the developer can use commands and restrictions for the whole site (prefetch control mechanism).
Manual prefetch can be used with the following HTML tag and settings:
<link rel="dns-prefetch" href="forensixchange.com">
In this situation, forensixchange.com is going to be prefetched if the html page is opened in Chromium while it won’t change the look of the site. So it is not normally visible to the user, but one can see it in the source-code. This tag is just a command to the browser to prefetch a DNS.
Prefetch Control mechanism in Chromium is used to turn DNS prefetch for HTTPs pages on or turn it off for HTTP pages. By default, DNS prefetch for HTTPs pages is turned off for privacy reasons. With this function turned-on every link on a site is going to be prefetched. To use this solution one can define the following HTML tag:
<meta http-equiv="x-dns-prefetch-control" content="on">
In case of a HTTPs site, no DNS is going to be prefetched before this entry and everything is going to be prefetched after this entry. If a page explicitly opts out of DNS prefetch, further attempts to opt in are ignored. Also, the prefetch control applies only to hyperlinks and not to the manual prefetch settings. I’m going to explain it based on the following HTML code:
<link rel="dns-prefetch" href="//manual_a.com"> <a href="//control_a.com"> A_site </a> <meta http-equiv="x-dns-prefetch-control" content="on"> <a href="//control_b.com"> B_site </a> <meta http-equiv="x-dns-prefetch-control" content="off"> <link rel="dns-prefetch" href="//manual_b.com"> <a href="//control_c.com"> C_site</a> <meta http-equiv="x-dns-prefetch-control" content="on"> <a href="//control_d.com"> D_site </a> <link rel="dns-prefetch" href="//manual_c.com">
There are three manual prefetch tags (manual_a.com, manual_b.com and manual_c.com URLs). And there are four normal links on the page. These are normal clickable links and not prefetch tags. This means whether they are going to be prefetched or not depends on the global prefetch control mechanism. When opening this site, the following DNS entries can be seen in this order:
- control_b.com: The reason this is the first one is that manual prefetches are handled with lower priority, so first the normal links are going to be prefetched. Beside that control_a.com is not going to be prefetched, because HTTPs sites won’t make any DNS prefetch before it is turned on explicitly. In the third row, I turned it on so the control_b.com URL is the first one prefetched from the fourth row.
- manual_a.com: In the fifth row I opted out of DNS prefetch so no automatic DNS prefetch is going to be made in this site anymore. Since I opted-out from automatic prefetch, Chrome started to prefetch the manual ones starting with manual_a.com.
- manual_b.com: As we are loading the manual ones and manual_a.com is already loaded so Chrome continued with manual_b.com which was the second one.
- manual_c.com: The last manual one prefetched as well.
Be aware that these are only working in Chrome and Chromium, but not working in Edge or in Firefox. One can see based on these tests that a DNS request doesn’t mean the user opened that site. Therefore some DNSs can be found in the cache or in the SIEM which weren’t actually opened by the user intentionally but by the DNS prefetching mechanism.
According to Chromium’s documentation during startup, the browser is going to resolve the first 10 domains that were resolved the last time the browser was started. However, I couldn’t observe this behavior. During restarts, my browser did not resolve any URLs visited by me earlier. (none of the tested browsers produced this behavior during my tests)
However, I have found some odd DNS requests done by Chrome/Chromium. This activity is a mitigation against DNS hijacking attempt. With these queries, Chrome tries to find out whether somebody is messing with the DNS, like a MitM attacker, or the ISP itself. Chrome checks this by issuing three DNS queries towards randomly generated domains. Normally these requests will result in a “No such name” response, but in case of a DNS hijack, the owner of the DNS server can use a wildcard to match every DNS. Due to the usage of the wildcard even non-existent domains can get an answer which is a suspicious behavior. In case of hujacking, the response is going to be the IP of the owner’s choice which can be malicious or at least an unwanted one. So by getting a response with IP in it for a non-existent domain Chrome can detect DNS hijack attempts.
Observed examples on my machine:
According to forensicswiki (modified on 2 March 2019, at 02:38.) this should be a non-existing hostname that consists of 10 random characters, however in my case the domain names had various lengths.
Also, Chrome tried to translate wpad.home as well. The interesting thing is that Chrome also used NetBIOS Name Name Service protocol to get information about the domains. NetBIOS traffic was generated for wpad and for the hijack detection domains as well. Three NetBIOS packets were captured for every above-mentioned domain. (Not all of them are on the picture though.)
When the user types something into the title search bar in Chromium, the browser suggests an auto-completion. According to the Chromium documentation this domain proposal is also going to be automatically prefetched. I could observe this behavior but it did not happen every time. I don’t exactly know what the trigger condition for this is. I tested three domains in the same environment and only one of them was prefetch based on Chrome’s suggestion. It is good to know that there is a function like this built-in to Chrome, but I couldn’t confirm why this is happening in case of some URLs but not for others. (When I typed ebay, Chrome immediately prefetch the ebay.org domain name, but nothing happened when I typed amazon or paypal even though Chrome provided me suggestions.)
On the other hand by using Omnibox I encountered an interesting behavior. While the auto-completion itself does not trigger any name resolution traffic, the search in the Omnibox does. Typing a word into the Omnibox and clicking on “Google Search” (generally the first or second suggestion) the browser opens google.com and fills the search bar with the typed word. It also creates some DNS and NBNS queries.
For example, I put the word “amazon” into the search bar and hit enter. Google navigated to the Google Search page. The first match was amazon.de but it was an advertised match. The second one was amazon.com. I assume this second one or the first non-advertised one is the keyword google tries to translate. First I caught an amazon.home DNS query, then an amazon.com DNS query and at the end I got three NBNS queries with the domain AMAZON in them.
Interesting behavior for Omnibox-based searches:
- If I search something on Google by opening the search engine manually I will get DNS query for the first match but there won’t be any NBNS requests. NBNS is only generated if Omnibox is used.
- NBNS traffic is going to be generated only if the search term is 1 word. More precisely NBNS is going to be generated if the search term does not contain any characters which are not allowed in a NetBIOS name. The search term “ama-zon” in the Omnibox will generate a DNS request to ama-zon.home, one to amazon.com (since this is the first match) and three NBNS to AMA-ZON.(see the first picture below) But the term “ama zon” only generates one DNS queries to amazon.com.(see the second picture below)
Chrome showed me a suggestion for the “ama-zon” search term.
When I clicked on the suggestion I was redirected to the Google Search page. The first match on the site was amazon.de, but it was an advertised match. The first non-advertised one was amazon.com. Besides the DNS traffic, NBNS communication was generated as well. See the following figures:
After the previous tests I put the search term “ama zon” into the Omnibox. This time only DNS traffic was generated. The first non-advertised match was amazon.de in this case. One can see on the next picture that only amazon.de was prefetched but there weren’t any prefetch towards the .home top-level domain. While in the previous case “ama-zon.home” was also translated.
One can say that NetBIOS traffic is not relevant in the case of DNS sinkholing. And it is true. On the other hand, some SIEM system handles NBNS and DNS traffic the same way. The two traffic and their data can be represented the same way in a SIEM. They are so similar to each other, that I already encountered multiple systems where these two types of logs were stored under the same event type or source type. In these cases, only the port number can show the difference. DNS is normally using port 53 (UDP) while NBNS is using port 137 (UDP). Sometimes DNS sinkhole is not implemented rather the SIEM is filled with malicious domains and it tries to catch name resolution traffic for these domains. Since the representation of DNS and NetBIOS can be similar in the SIEM, it can create alerts regardless of the type of the name resolution protocol. So it is important to see that an alert named “Malicious Name Resolution” or, due to the similar data representation and incorrect alert naming even the title “Malicious DNS request” could mean that the traffic is NetBIOS traffic and not DNS.
In case of our investigation it couldn’t be NetBIOS traffic of course. DNS sinkhole was generated by the DNS server and NetBIOS traffic is not sent to DNS servers. Therefore in this case it could only be a DNS traffic.
Top Sites are the most visited sites by that browser. These sites are shown in the new tab page. This is what it looks like:
I tested whether these domains are queried during the browser startup but it looks like Chrome does not resolve these domains. Interestingly enough while Chrome doesn’t do this, Firefox is resolving every DNS from the Top Sites list.
Microsoft Edge also doesn’t resolve the domains from the Top Sites list. Looks like right now this is a specialty of Firefox.
DNS cache information in the memory is really useful, but it is just a temporary cache so it is volatile. Entries from the DNS cache are going to be removed after their expiration time and also the cache is removed during a machine restart. Windows Events are more permanent though so it can be a good step to check these artifacts on the investigated machine as well. The relevant events are named:Microsoft-Windows-DNS-Client/Operational.
These logs can be found in the Windows Event Viewer in the following path: Application and Service Logs / Microsoft / Windows / DNS Client Events / Operational. The logging of these events is turned off by default, so to use them, first one has to turn the logging on. Sadly in case of the above-mentioned investigation, the logging was disabled so no DNS events were saved. Also, that affected company wasn’t doing live forensics on machines, they only performed investigation on a triage image of them. This collected information set did not contain Windows events except for some basic ones. So, in this situation, the following events wouldn’t be useful at all but I made some research about them anyway.
To test what Windows Events are going to be generated during site opening I made 6 scenarios. I opened a site with empty OS DNS cache, then I opened the same site with its IP already in the cache and finally, I made a request towards a domain which was in the hosts file. These are three different tests and I performed them in Chrome browser and from Windows command line as well so this makes 6 scenarios altogether.
This is how an event looked like in the Event Viewer:
In the future I’m not going to printscreen the events I’m only showing the event IDs and its content in text format. I also replace the IPs in the logs with the string “IPv4” or “IPv6”.
Generated events during an initial site opening by Chrome:
- Event ID: 3006: DNS query is called for the name forensixchange.com, type 1, query options 140738562228224, Server List , isNetwork query 0, network index 0, interface index 0, is asynchronous query 0. Explanation: type 1 means it is an A query, so it a an IPv4 address resolution. In this case type 28; which is the IPv6 address resolution request; wasn’t done at all. This event shows that a DNS query has been requested by Chrome.
- Event ID: 3009: Network query initiated for the name forensixchange.com (is parallel query 1) on network index 0 with interface count 1 with first interface name Ethernet, local addresses IPv6;IPv4 and Dns Servers IPv4;IPv4. Explanation: The mentioned DNS servers are going to be asked about the given URL. But no message was sent yet at this point.
- Event ID: 3016: Cache lookup called for name forensixchange.com, type 1, options 2392538375913472 and interface index 0 Explanation: Windows tries to collect the IP from local sources.
- Event ID: 3018: Cache lookup for name forensixchange.com, type 1 and option 2392538375913472 returned 9701 with results Explanation: The results is empty, therefore no entry was found in the cache.
- Event ID: 3019: Query wire called for name forensixchange.com, type 1, interface index 0 and network index 0
- Event ID: 3010: DNS Query sent to DNS Server IPv4 for name forensixchange.com and type 1 Explanation: The first DNS server was asked about the domain. DNS servers are generally working in pairs. If the first one can’t answer or times out the second one is going to be queried as well.
- Event ID: 3009: Network query initiated for the name forensixchange.com (is parallel query 1) on network index 1 with interface count 1 with first interface name Npcap Loopback Adapter, local addresses IPV6,IPv4 and Dns Servers
- Event ID: 3019: Query wire called for name forensixchange.com, type 1, interface index 0 and network index 1
- Event ID: 3020: Query response for name forensixchange.com, type 1, interface index 0 and network index 1 returned 1460 with results Explanation: response to the first 3019 request, which wasn’t successful. (cache lookup)
- Event ID: 3011: Received response from DNS Server IPv4 for name forensixchange.com and type 1 with response status 0 Explanation: Response arrived from the DNS server.
- Event ID: 3020: Query response for name forensixchange.com, type 1, interface index 0 and network index 0 returned 0 with results IPv4; Explanation: IPv4 is the IP of the requested domain.
- Event ID: 3008: DNS query is completed for the name forensixchange.com, type 1, query options 2392538375913472 with status 0 Results IPv4
After the previous test, I restarted Chrome to remove any browser-based cache information, but I did not flush the OS cache. So with this particular experiment I checked what kind of events are going to be created if the necessary information is already in the OS cache but not in the browser cache. These were the generated events:
- Event ID: 3006: DNS query is called for the name forensixchange.com, type 1, query options 140738562228224, Server List , isNetwork query 0, network index 0, interface index 0, is asynchronous query 0
- Event ID: 3009: Network query initiated for the name forensixchange.com (is parallel query 1) on network index 0 with interface count 1 with first interface name Ethernet, local addresses IPv6;IPv4 and Dns Servers IPv4;IPv4.
- Event ID: 3016: Cache lookup called for name forensixchange.com, type 1, options 2392538375913472 and interface index 0
- Event ID: 3018: Cache lookup for name forensixchange.com, type 1 and option 2392538375913472 returned 0 with results IPv4; Explanation: In the previous case the DNS information wasn’t in the cache therefore event 3018 couldn’t contain the IP address, the results field was empty. In this situation however, the IP was cached and therefore the results had the value “IPv4”.
- Event ID: 3008: DNS query is completed for the name forensixchange.com, type 1, query options 2392538375913472 with status 0 Results IPv4;
Finally, I tested what happens when the URL is in the hosts file. The first 5 events were the same as in the previous case. A query has been started, cache lookup has been done and we found the IP in the hosts file. Every event so far looked absolutely the same. (except the IP which I set to 127.0.0.1). But after that, I got some other events which weren’t generated in the previous case. Be aware that at this point I already have the IP 127.0.0.1 for the domain. Here are the other events:
Event ID: 3006: DNS query is called for the name www.forensixchange.com, type 1, query options 140738562121728, Server List , isNetwork query 0, network index 0, interface index 0, is asynchronous query 0
Event ID: 3008: DNS query is completed for the name www.forensixchange.com, type 1, query options 140738562121728 with status 87 Results Explanation: Results field is empty. But with the Event 3008 the second query was closed.
Event ID: 3006: DNS query is called for the name www.forensixchange.com, type 28, query options 140738562252800, Server List , isNetwork query 0, network index 0, interface index 0, is asynchronous query 0 Explanation: A third query has been started for this third scenario, but in this case it was an IPv6 - AAAA query.
Event ID: 3009: Network query initiated for the name www.forensixchange.com (is parallel query 1) on network index 0 with interface count 1 with first interface name Ethernet, local addresses IPv6;IPv4 and Dns Servers IPv4,IPv4
Event ID: 3016: Cache lookup called for name www.forensixchange.com, type 1, options 2392538375938048 and interface index 0 Explanation: Interestingly enough the cache lookup was performed for type 1. While the whole third DNS query was started for type 28 DNS lookup.
Event ID: 3018: Cache lookup for name www.forensixchange.com, type 1 and option 2392538375938048 returned 0 with results type: 5 forensixchange.com;127.0.0.1;
Event ID: 3016: Cache lookup called for name www.forensixchange.com, type 28, options 2392538375938104 and interface index 0 Explanation: In this event type 28 cache lookup was done finally. But without a response. Only IPv4 address was hardcoded into the hosts file by me.
Event ID: 3018: Cache lookup for name www.forensixchange.com, type 28 and option 2392538375938104 returned 9701 with results
Event ID: 3008: DNS query is completed for the name www.forensixchange.com, type 28, query options 2392538375938048 with status 0 Results type: 5 forensixchange.com;::ffff:127.0.0.1; Explanation: Closure of the IPv6 lookup. For some reason IPv6 lookup only happened when the ULR was in the hosts file but not in the other cases.
So there were three different queries for this last test. The first one was the same as in case of the second scenario. The second query was just an opening and ending event without any results. And the last one was an IPv6 query.
For the last test, I put the domain into the hosts file and set the IP to 127.0.0.1. This IP is the localhost and since there weren’t any websites hosted from my machine, the browser couldn’t open anything. This is why the DNS resolution did not stop after the first 5 events. When I set the IP to the real IP of my website instead of 127.0.0.1, I got different results. Actually, this result shows the same event as the second test (see the reasoning at the last test):
- Event ID: 3006
- Event ID: 3009
- Event ID: 3016
- Event ID: 3018
- Event ID: 3008
Note: entries from the hosts file are autmatically loaded into the DNS cache. These entries are always in the DNS cache even after flushing the storage.
The other three tests were performed from the command line with the ping command. During the first test I pinged forensixchange.com site with an empty OS DNS cache. The following events were generated:
- Event ID: 3006: DNS query is called for the name forensixchange.com, type 1, query options 1073766400, Server List , isNetwork query 0, network index 0, interface index 0, is asynchronous query 0
- Event ID: 3008: DNS query is completed for the name forensixchange.com, type 1, query options 1073766400 with status 87 Results Explanation: This completed immediately without any results.
- Event ID: 3006: DNS query is called for the name forensixchange.com, type 28, query options 1073897472, Server List , isNetwork query 0, network index 0, interface index 0, is asynchronous query 0
- Event ID: 3009: Network query initiated for the name forensixchange.com (is parallel query 1) on network index 0 with interface count 1 with first interface name Ethernet, local addresses IPv6;IPv4 and Dns Servers IPv4,IPv4
- Event ID: 3016: Cache lookup called for name forensixchange.com, type 1, options 2251800887582720 and interface index 0
- Event ID: 3018: Cache lookup for name forensixchange.com, type 1 and option 2251800887582720 returned 9701 with results
- Event ID: 3019: Query wire called for name forensixchange.com, type 1, interface index 0 and network index 0
- Event ID: 3010: DNS Query sent to DNS Server IPv4 for name forensixchange.com and type 1
- Event ID: 3009: Network query initiated for the name forensixchange.com (is parallel query 1) on network index 1 with interface count 1 with first interface name Npcap Loopback Adapter, local addresses IPv6;IPv4 and Dns Servers
- Event ID: 3011: Received response from DNS Server IPv4 for name forensixchange.com and type 1 with response status 0
- Event ID: 3020: Query response for name forensixchange.com, type 1, interface index 0 and network index 0 returned 0 with results IPv4;
- Event ID: 3016: Cache lookup called for name forensixchange.com, type 28, options 2251800888107008 and interface index 0
- Event ID: 3018: Cache lookup for name forensixchange.com, type 28 and option 2251800888107008 returned 9701 with results
- Event ID: 3008: DNS query is completed for the name forensixchange.com, type 28, query options 2251800887582720 with status 0 Results IPv6;
For the second test for command line I’m only going to list the Event IDs because they don’t contain anything new. In this test I pinged the same site which was already resolved.
- Event ID: 3006
- Event ID: 3008
- Event ID: 3006
- Event ID: 3009
- Event ID: 3016
- Event ID: 3018
- Event ID: 3016
- Event ID: 3018
- Event ID: 3008
Generated events by the command line test when the domain is in the hosts file are the same as in the previous test. The reason behind this is that every entry from the hosts file is copied into the cache automatically. So after adding an entry to the hosts file that entry is immediately going to be copied into the cache, so during the lookup, only the cache has to be checked but not the hosts file.
- Event ID: 3006
- Event ID: 3008
- Event ID: 3006
- Event ID: 3009
- Event ID: 3016
- Event ID: 3018
- Event ID: 3016
- Event ID: 3018
- Event ID: 3008
So how are these events useful for us? As it was mentioned at the beginning of the post, my friend only had the source IP of the machine and the IP of the sinkhole. The requested information was the domain name (DNS). So we wanted to look at the logs which contain the sinkhole IP and the domain name as well. The useful events for us are event: 3008, 3018, 3020.
I checked these events and all three of them contain the IP address in the QueryResults field and the domain in the QueryName field. With the following Windows Event filter, I could gather every log which contains: (I only used this to double check myself):
<QueryList> <Query Id="0" Path="Microsoft-Windows-DNS-Client/Operational"> <Select Path="Microsoft-Windows-DNS-Client/Operational">* [EventData[Data[@Name='QueryName'] and (Data='forensixchange.com')]] and * [EventData[Data[@Name='QueryResults'] and (Data='IP_of_the_server;')]]</Select> </Query> </QueryList>
But of course the URL was unknown to me in the original investigation so I removed that part of the filter and replaced it with the three chosen Event IDs:
<QueryList> <Query Id="0" Path="Microsoft-Windows-DNS-Client/Operational"> <Select Path="Microsoft-Windows-DNS-Client/Operational">* [System[(EventID='3008') or (EventID='3018') or (EventID='3020')]] and * [EventData[Data[@Name='QueryResults'] and (Data='IP_of_the_server;')]]</Select> </Query> </QueryList>
Executing this filter on the investigated machine (or at least on the correct logs) one can find every domain which was translated to the IP: ‘IP_of_the_server’. This IP is the address of the sinkhole server, so every domain which is translated to this IP was recognized as malicious by the DNS sinkhole mechanism. One can use powershell as well to collect the necessary logs. The following Powershell command is going to list every “Microsoft-Windows-DNS-Client/Operational” event thats ID is 3008, 3018 or 3020 and returned with the IP: ‘IP_of_the_server;’. For this script to work, you only have to change to string “IP_of_the_server” to the IP you are interested in.
Get-WinEvent -LogName "Microsoft-Windows-DNS-Client/Operational" -FilterXPath "* [System[(Ev entID='3008') or (EventID='3018') or (EventID='3020')]] and * [EventData[Data[@Name='QueryResults'] and (Data='IP_of_the_server;')]]"
As I have already mentioned, this whole post started with an investigation I was asked to help out in. It may have become clear for you by now that I wasn’t able to solve the issue. Some of the necessary information wasn’t logged and I was also involved after the machine re-image took place, so we weren’t able to pull down any additional information. Even though I couldn’t determine the malicious DNS I still want to share my thoughts during the investigation as a closure note.
The only thing I was asked to do is find the malignant domain name the machine tried to connect to. Since I did not have access to the SIEM I could only check the host-based triage image. First I checked the DNS cache in the memory but without a success. I was told the machine had been restarted before the memory dump was taken. At that point, I wasn’t sure whether the malware wasn’t a permanent one, stopped communicating or just did not use that particular domain anymore. I checked the running processes to find out whether anything ran at the time of the collection but again, I couldn’t find anything suspicious.
After this, I thought maybe the user took his laptop home and connected to the internet from a non-company environment. There weren’t any VPN solutions on the machine which would force the user to login to the company network. I thought a malware could have been connected to the internet from a non-supervised place, gather the IP and save it somewhere. Entries in the hosts file are automatically loaded into the OS DNS Cache so I was sure no malicious entry was added to this file. (I still checked it but without success). But without access to the files I couldn’t check whether any IPs were saved into any files permanently. I had access to the $MFT, but there were too many entries without context so I couldn’t find any related files.
My last idea was to check the relevant Windows events. Sadly, I had to realize out that they are not collecting these events into the triage image. There was a chance that the malware was still on the machine and it was only dormant during the collection. I asked the company whether they can turn on DNS events logging and collect the necessary events but I was informed that the laptop has already been re-imaged. While they couldn’t find out which the malicious domain was, they could confirm the infection from other sources so they remediated the machine.
I couldn’t help out my friend in this case. However, I learned a lot during my investigation. I could also give the company some recommendations on how they could modify their security infrastructure to make a similar investigation quicker. They simply added the DNS information to the sinkhole event which was perhaps the simplest way to handle this situation.
OS: MS Windows 10 Pro Version: 10.0.17134 Build 17134
Win 10 Chrome: Version 74.0.3729.108 (Official Build) (64-bit) Win 10 Chromium: Version 76.0.3775.0 (Developer Build) (64-bit) Win 10 Firefox: 66.0.3 (64-bit) Win 10 Edge: Microsoft Edge 42.17134.1.0