All About HackingBlackhat Hacking ToolsFree CoursesHacking

A Case Study of Information Stealers: Part 2

This article is about A Case Study of Information Stealers.

Introduction [A Case Study of Information Stealers]:

In the second part of this analysis, we will examine how Pony steals data and sends it to the C&C server. We also wonder if Pony does any cleanup before it exits execution!

In the previous section, we stopped at deciphering a list of words. So let’s see what the demo does next.

Preparing for information theft:

Before you actually start calling the functions responsible for collecting software passwords from disk. Pony calls the WSAStartup function to initialize the process to use the Winsock DLL. It then allocates an OLE stream (similar to the ones we saw in the first part) that will be used to store some kind of data. The function at 00410772 is then called with the current pointer as an argument.

An interesting thing that the sample will do next is save both strings “PWDFILE0” and “1.0” to the stream. These 2 strings will actually serve as a header to the buffer, and with each step of encrypting the buffer, this header will change to tell a lot about the contents of the buffer. The offset “headers” that Pony uses are as follows:


After storing the header that will precede the data, Pony is very close to starting to search the system for passwords. But just before doing that, it checks the debugger using the embedded version of IsDebuggerPresent.

If a debugger is detected, 00401026 will be called and an exception will be thrown. It is a very easy technique to implement and work around. So it won’t cause us any problems.

Related article:Everything you need to know about Ethical Hacking as a Career by Blackhat Pakistan 2023

The sample now loads the callback address into EDI and enters a loop to iterate through all these functions and call them one by one. The callback table is located at: 00417D03 and contains 134 functions.

It’s also worth noting that each of these callbacks takes a single argument. This argument is nothing more than a pointer to the stream that was allocated earlier. It is now safe to conclude that each of these functions actually writes something to this stream. Looking at the random function from this table, we can also see that these callbacks are actually responsible for stealing information from the disk files and saving them to the stream.

As I mentioned in the first part, we won’t be able to go through each of these functions. However, we will examine the first function in the table because it stores some interesting information in the stream. This feature is at 004044A0

View of 004044A0 (Callbacks0):

The routine starts by copying these 8 bytes to the stream (02 00 4D 4F 44 55 01 01). It then separately adds another 4 bytes (01 00 EF BE). Next, it calls both GetVersionExA and GetLocalInfoA APIs and then saves their results to the stream.

After saving the Windows version and locale information, it tries to uniquely identify the computer by collecting its hardware ID. This is very useful for tracking the machine the information is coming from, as using something non-specific such as IP addresses is unreliable.

To get the hardware ID, the sample first checks if the computer has Winrar installed, and then reads the HWID value from the key: HKEY_CURRENT_USERSoftwareWinRAR, since Winrar stores the computer’s HWID in the registry.

Now, if Winrar is not installed on the machine, which may be the case, the sample will get the path to the AppDataTemp directory for the current user and look for a file called HWID. If a file is found, all it does is read from those files what Pony thinks is a unique hardware ID for the machine. However, the computer I tested did not have this sample on file.

What Pony does in this last case is just generate a random unique GUID to identify the machine, the function used to generate this GUID is CoGreateGuid. Then the sample copies the HWID (or GUID if the previous tests failed) into the stream to be sent to the server after all the steals are done.

Information about the theft:

At this stage, the malware does what it was designed to do, steal information. It iterates through the callback table we saw earlier when calling each function until it exhausts the entire array. The callback function is characterized in Pony (generally):

  • Checking if the software to steal from is installed. Return if not.
  • Collecting information from files, registry keys…
  • Writing information to the application details stream.

Data compression:

After all callbacks are called, all stolen data (if any) is stored in the global data stream. In this phase, Pony prepares the data to be sent to the server, and before doing so, it must complete a list of tasks. First, it compresses the data to reduce its size and send it to the server faster. It uses the aPLib v1.01 library for this. It is actually a compression library based on the algorithm used in aPACK, a tool created by the same author of aPLib.

After compressing the data, the sample erases the decompressed data and writes the compressed data to the stream. In the first part of this second part, I mentioned the various headers that precede the data. They are actually used to know what type of data is stored in the stream: is it clear text, wrapped or encrypted data?

The previous header that indicated data in plain text format (PWDFILE01) is now compressed. So what Pony does is insert an extra header to define the data as compressed (PKDFILE0) and in memory it looks like this:

Preparing to encrypt data:

After the data compression is complete, it is now time to encrypt. The routine that is responsible for all the tasks needed to encrypt the data can be found at: 004019E0.

The first thing that is done is to copy the data stream (starting with the PDKFILE0 header) to a separate dynamically allocated memory location. For now, Pony doesn’t touch the copied data, so we’ll come back to that later. Instead, the length of the hardcoded string “babajay@1234” is calculated, in fact we saw Pony decrypt this string from “dcdclc{B3456” in the first part and wondered about its nature.

An array of 257 bytes is then created and initialized as follows:

buffer[0] = buffer[1] = 0;

for (int i=2;i<257;i++)

    buffer[i] = i;

At this stage, the string “babajay@1234” is used to “encrypt” the byte sequence as follows:

UCHAR* Key = “babajay@1234”, Sum = 0,Char;

     int j=0,i;
         Old = buffer[i];
         Sum += Old;
         Character = key[j];
         Sum += Sign;
         buffer[i] = buffer[Sum];
         buffer[Sum] = Old;
         if (++j == strlen(key))
             j = 0;

Which finally gives this sequence that will be used to encrypt the packed data in the stream:


In this second part, we saw how Pony prepares itself (locale, Windows version, and unique machine identifier) ​​and then steals information. We also revealed specific details about how it compresses data and then prepares to encrypt it.

In the next part, we will see how Pony actually encrypts data, how it sends it, and what tasks it performs after it serves its purpose.

Sample [download]

Leave a Reply

Your email address will not be published. Required fields are marked *