Tuesday, July 6, 2010

Decrypting encrypted strings in Zeus

There are a few strings in the latest Zeus bot that are stored in an encrypted format. When a function needs one of them, it calls another function to decrypt the string and store it in a buffer on the stack. There are only about 50 of these encrypted strings, and as I found out, they aren't very interesting. They aren't exposing any hidden functionality - I suspect they were just included to make reversing the bot a little bit harder.

The strings are referenced by a table where each entry has a structure that looks like this:

struct {
  ushort XorKey;
  ushort Length;
  char *EncryptedString;
} encrypted_string;

In IDA, the table looks like this at first:

To figure out what these strings were, I first reverse-engineered the decryption routine. There were actually two separate routines - one that returns the strings as ASCII and the other as wide characters. This is the decryption routine for returning ASCII data:

It's very simple - each encrypted character gets the string length subtracted from it, then XOR'd with an 8-bit key which is different for each string.

To get a decrypted string, a function will put the requested string's index into EAX and put pointer to hold the decrypted string in EDI (ESI is used for the wide character version), then call the function I labeled GetEncryptedString(). The actual code used by the bot will PUSH a 32 bit immediate value and then POP it into EAX:

To make it easier to understand the disassembly, I wrote an IDC script that will first decrypt and label the strings in the encrypted string table, then search the code for references to the GetEncryptedStringA() and GetEncryptedStringW() functions to add comments to those.

Here's the script:

After running the script, the string table now looks like this:

And code that calls the GetEncryptedStringA/W functions looks like this:

This makes reading and annotating the disassembly a little easier.

1 comment: