This post explains a trick that I have been using for a few years to discover application endpoints on Windows quickly.
It's a simple trick:
- Clear the DNS cache.
- Take a snapshot of the cache.
- Run the application and use different functionalities.
- Take another snapshot of the cache.
- Compare these two snapshots.
- ???
- Discover (most) endpoints.
Code is at:
Update May 2020: If you are doing this in a Hyper-V guest virtual machine,
it will not work. The default DNS server for a Hyper-V guest is the server. And
it does not populate the local DNS cache (I do not know the reason). The fix is
to manually configure a DNS server (e.g., 8.8.8.8
) in the guest's network
adapter.
Discovering Endpoints
Discovering application endpoints is one of the starting steps in thick client proxying. I have written about it so many times that I will just make a list here. Off the top of my head I can think of:
- Netmon or Microsoft Message Analyzer
- These tools isolate traffic by pid.
- Procmon (Process Monitor)
- Filter by process name and then
TCP/UDP Connect/Send/Receive
.
- Filter by process name and then
- Procexp (Process Explorer)
- The TCP/IP tab.
- TCP Catcher or 3rd party other tools.
The DNS Cache
You can interact with the DNS cache in different ways. Most common ways are:
- ipconfig
- View :
ipconfig /displaydns
- Clear:
ipconfig /flushdns
- View :
- PowerShell
- View : Get-DnsClientCache
- Clear: Clear-DnsClientCache
Creating a PasteOps Prototype
We will use PowerShell because the output of commands are objects. We can format the output at-will.
PasteOps v1.0
The first iteration of our commands is completely manual. We copy/paste the following command into the PowerShell console (or ISE during development):
Clear-DnsClientCache
- Start Google Chrome or
ping google.com
- I will explaint the reason for this step below.
$dns1 = Get-DnsClientCache
- Navigate to https://example.net.
$dns2 = Get-DnsClientCache
Compare-Object -ReferenceObject $dns2 -DifferenceObject $dns1
We have successfully discovered that the thick client (browser) has contacted
example.net
.
The Ping Step
In a real scenario, we want to clear the cache just right before starting the
application. In our PasteOps, $dns1
might be empty if we call it just
right after clearing the cache and that will return an error when doing the
compare.
What does Get-DnsClientCache Return?
Looking at the Get-DnsClientCache documentation, we can see it returns MSFT_DnsClientCache:
class MSFT_DNSClientCache : CIM_ManagedElement
{
string InstanceId;
string Caption;
string Description;
string ElementName;
string Entry;
string Name;
uint16 Type;
uint32 TimeToLive;
uint16 DataLength;
uint8 Section;
string Data;
uint32 Status;
};
As we will see later, not all fields are populated for every record.
Output Format
Table output in PowerShell is usually truncated but we can format the output as objects unlike Bash1.
Using Format Commands to Change Output View is a good introduction to different output formats.
We can use Format-Table
to get the output in a table and see truncated
results (it's fixable):
Get-DnsClientCache | Format-Table
We probably don't need to see all the fields, let's modify our command:
Get-DnsClientCache | Format-Table -Property Entry,RecordName,Data
Wait, what? RecordName
column is in the original output but does not exist
here. You might have also observed that you could use tab-complete for
the other two field names (e.g., -Pro [tab] Ent [tab]
to get
-Property Entry
) but not RecordName
.
We have to use field names based on the return value which is
MSFT_DNSClientCache
.
Get-DnsClientCache | Format-Table -Property Entry,Name,Type,Data
Some field values like Type
are different from the original command
output. Objects have some default printing formats. See the following link for
a similar command:
Compare-Object Output
We have enough to write a PowerShell script to do the job. We can get the output of both commands and then remove the duplicates with Compare-Object.
The output of Compare-Object
is a PSCustomObject
that wraps the original
object with a slide indicator.
$ Compare-Object -ReferenceObject $dns2 -DifferenceObject $dns1
InputObject SideIndicator
----------- -------------
MSFT_DNSClientCache (Entry = "example.net", Name = "example.net") <=
The -PassThru
switch will spit out the unwrapped objects.
$ Compare-Object -ReferenceObject $dns2 -DifferenceObject $dns1 -PassThru
Entry RecordName Record Status Section TimeTo Data Data
Type Live Length
----- ---------- ------ ------ ------- ------ ------ ----
example.net example.net A Success Answer 77102 4 93.184.216.34
PasteOps v2.0
Wrapped objects are not useful here. Let's add -PassThru
to our PasteOps.
|
|
We can directly work on objects and format the output in different ways or export them with something like Export-Csv for later use.
PowerShell Script
The next step after PasteOps is combining all these commands into a PowerShell script.
|
|
If we run the script and open up Google Chrome when prompted, we can see:
We can pass the command output (which is a list of objects) to pipes and manipulate it:
Limitations
Any connection method that does not end up in the DNS cache is not discoverable by this method. This usually happens when the application:
- Does its own DNS lookup.
- Contacts the endpoint by IP.
Full automation might be an issue. It's definitely feasible to integrate the script into an automation framework and harvest the endpoints. It will miss endpoints unless you know that your framework can call all application functionality.
What Did We Learn Here Today?
- We can use the Windows DNS cache to do endpoint discovery.
- A simple PowerShell script allows us to collect this endpoints and spits out objects that can be manipulated however you want.
Bash bashing. ↩︎