In This Article

Recently I was asked to analyze a blackbox Windows binary application and report back with any vulnerable findings. This turned out to be quite an interesting request considering that in a standard scenario we have access to the source code used for the compilation, however in this case not only was the source code not present, but there was also a lack of documentation. Considering these constraints there are three areas we could begin looking:

  1. Network traffic
  2. Memory footprint
  3. Application functions

The first two might seem obvious and straightforward, but how many would guess that you could have access to application functions in a compiled binary? The third area here is somewhat more involved and is primarily what I want to cover in this article today, but let's cover them all in order first.

copy link

Network traffic

First, we analyze network traffic so we can see what domains the application interacts with as well as the data it sends and receives.

Capturing network traffic coming from an application can be achieved in various ways. Some of the most common approaches involve using open-source tools such as WireShark (which is exactly what I resorted to in this instance); Generally, however, any tool that can capture packets off the local network card will do just fine.

When capturing network traffic, it's important to look for request destinations, open ports, network protocols used, and whether or not the connection is using encryption. Together, this can give some indication as to the binary's intended function in addition to revealing any potential malicious activity.

copy link

Memory footprint

Next, we can check the memory footprint of the running application to check for any interesting values. This can reveal configs, passwords, data objects, etc.

Process memory is used to store application data required at runtime. These typically include things like the binary's functions, instantiated objects, strings, etc…which is precisely what makes it a gold mine for vulnerability analysis. For example, applications that utilize authentication will typically store auth details in memory. Below is an example of just that very scenario which I obtained using ProcDump:

An XML object with the password stored as a plain string obtained from memory dump
An XML object with the password stored as a plain string obtained from memory dump

In general process memory is protected by the host OS, if the machine running the application is vulnerable to privilege escalation or has incorrectly configured their security settings, it will be possible to perform a memory dump of any running application. Beyond this, it is very difficult to store information in RAM in a secure way.

copy link

Application functions

Finally, we can look at the functions embedded within the application binary to see if any of them are vulnerable to exploits. This can give us information about whether or not more complicated attacks (privilege escalation, container breakout, etc.) can be levied against a host running the binary.

To do this, we will need a disassembler that supports the process architecture of the binary, in this case I've used Ida (the generally recognized standard of disassemblers at the time of this writing) in addition to WinDbg. First, I'll start off with Ida to identify the functions:

functions of the binary

As you can see, the functions of the binary have been loaded in and we can begin to identify functions that take inputs particular to our test case (in my case I am looking for functions with file inputs). Here I have identified "GdipLoadImageFromFile" which is imported from "gdiplus.dll" as the function I want to target. The next step is to calculate the address offset of the function within the binary, we can do that by taking the address of the function and subtracting it from the start address of the binary. In this case I will use WinDbg to identify both the start address of the binary and the address of the function we have identified:

Once we have opened the binary in WinDbg we can see the start address as it is the first module that gets loaded (here that module is named "image0140000"). Next we get the address of our target function by running "x <module name>!<module symbol (the function name in our case)>". Now that we have both of our addresses, let's do some subtraction. Since we know the application binary will be loaded in at the "00140000" address, we need to subtract that from our function address to calculate a target offset: 69f40af0 – 00140000 = 69e00af0. 

At this point there are a variety of different ways we can use this address to target our function but for this case I am going to use WinAFL, a Windows distribution of the popular open-source binary fuzzing tool AFL (American Fuzzy Lop):


Description automatically generated

WinAFL will start the binary and begin firing input at the running process and, more specifically, at the address in memory corresponding to the target offset which we specified earlier. WinAFL will take a sample of inputs, attempt to intelligently modify the bits of the input data, and then begin to use this data to try and crash the program:

Graphical user interface, text

Description automatically generated

If the application can be crashed by user specified input, it means that the application does not properly vet data or handle errors from invalid input. In that case, it then becomes possible to hijack the process and further compromise the system.

Thus concludes this short demonstration of working with blackbox binaries.

Learn how WWT can help your organization achieve application security.Contact us today