Skip to content
August 9, 2013 / Vadim Kotov

Crypto updates to crimeware toolkits

We’ve been tracking some of the recent updates to underground exploit kits such as Neutrino and Redkit. We noticed few interesting updates that we want to share:

  • Target fingerprinting: In this the exploit works only in presence of certain ‘Referrer’ or only when it encounters a specially crafted request query;
  • Data Encryption: Encrypting data between client and server sides of the kit;
  • De-obfuscation routine: In this, the malicious executable gets de-obfuscated after it lands on the victim’s hard drive.

The latter feature is somewhat new in the cybercrime business involving exploit kits. It helps to evade NIPS solutions analyzing network traffic. In this article we dissect the encryption algorithm used in a PDF exploit we found in the wild.

Some kits were reported to use AES algorithm in Java exploits to decrypt the malware binary, but it seems like some of the x86 shellcode also got this ‘feature’ update. Obviously any typical shellcode is way to ‘small’ to have a built-in AES implementation (or any other semantically secure cipher) so malware authors need more light weight solution. The PDF exploit we found in the wild  takes advantage of an old widely discussed CVE-2010-0188 (LibTIFF). Analysis of this vulnerability and its exploitation can be found here  and here .

Crypto_Updates_Image_1

This implementation uses JavaScript to exploit the vulnerability:

The de-obfuscated script depending on the version of Adobe Reader calls the corresponding payload:

Crypto_Updates_Image_2

The two shellcodes are almost identical except for the preamble. First the shellcode resolves the required APIs:

Crypto_Updates_Image_3

Then it generates a random name (using CPU counter) and downloads the encrypted executable to the user’s temporary folder. Then it calls the decryption function:

Crypto_Updates_Image_4

Finally it calls WinExec to run the downloaded file and then tries to register it as command component in the registry using Regsvr32.exe /s. This command takes a DLL path as an argument which means that the sequence of calls WinExec(“<binary>”), WinExec(“regsvr32 /s <binary>”) is used to launch for both executables and dynamic link libraries. This is another feature that was not used before in exploit kits.

The encryption algorithm is based on Linear Congruential Generator. Its formula is ax+c (mod m), where x is a seed, a and c are constants and m is the modulus. In this implementation values 0x343FD, 0x269EC3 and 32 were used respectively. The output of LCG is reduced to 31 byte (the sign bit is always 0).

It is some sort of a block cipher, which takes 1 byte at a time and encrypts/decrypts it. The 32 bit long key is stored as the first 4 bytes of the encrypted binary. First step of decryption is extracting these bytes and replacing them with 0x00905A4D (MZ header). Then it computes values x=key(mod 3) and y=key(mod 2). The decryption of one block looks like this:

Crypto_Updates_Image_5

The step keys k1 and k2 are derived from the key using LCG. For the i-th byte these values are calculated like this (i=[1, 2, …]):

  • k1 =LCG(2i, key)(mod 0xF1)+0xF
  • k2 = LCG(2i+1, key)(mod 6)+1

Permutation 1 cyclically shifts the input block by k2 bits to the right if y=0 and to the left otherwise. Permutation 2 XORs the input value with k1 if x=0, if x=1, then subtracts k1 from the input value, otherwise adds k1 to the input value. Here’s the python code for the file decryption and encryption:

import sys
import struct

def LCG(x):
    return ( ( (x*0x343FD)&0xFFFFFFFF )+0x269EC3)&0x7FFFFFFF

def rol(a,b):
    return ((a<<b)|(a>>(8-b)))&0xFF

def ror(a,b):
    return ((a>>b)|(a<<(8-b)))&0xFF

def decrypt(key, data):
    a = key%3
    b = key%2
    data = list(data)
    data[0]='\x4d'
    data[1]='\x5A'
    data[2]='\x90'
    data[3]='\x00'

    for i in range(4, len(data)):
        key = LCG(key)
        k1 = (key%0xF1)+0xF
        key = LCG(key)
        k2 = (key%0x6)+1
        byte = ord(data[i])

        if b==0:
            byte = rol(byte, k2)
        else:
            byte = ror(byte, k2)

        if a==0:
            byte = (byte^k1)
        elif a==1:
            byte-=k1
        else:
           byte+=k1

        data[i]=chr(byte&0xFF)

    return ''.join(data)

def encrypt(key, data):
    a = key%3
    b = key%2
    data = list(data)
    key = struct.pack('<I', key)
    data[0]=keystr[0]
    data[1]=keystr[1]
    data[2]=keystr[2]
    data[3]=keystr[3]

    for i in range(4, len(data)):
        key = LCG(key)
        k1 = (key%0xF1)+0xF
        key = LCG(key)
        k2 = (key%0x6)+1
        byte = ord(data[i])

        if a==0:
            byte = byte^k1
        elif a==1:
            byte = byte+k1
        else:
            byte = byte-k1

        byte&=0xFF

        if b==0:
            byte = ror(byte, k2)
        else:
            byte = rol(byte, k2)

        data[i]=chr(byte)
    return ''.join(data)

def main():
    if len(sys.argv)!=4:
        print 'Usage %s   <encrypt|decrypt>'%sys.argv[0]
        sys.exit()

    fd = open(sys.argv[1])
    filecontents = fd.read()
    fd.close()
    key = int(sys.argv[2], 16)

    if sys.argv[3]=='encrypt':
        data = encrypt(key, filecontents)
    elif sys.argv[3]=='decrypt':
        data = decrypt(key, filecontents)
    else:
        print 'Unknown argument %s'%sys.argv[3]
        sys.exit()

    sys.stdout.write(data)

if __name__ == '__main__':
    main()

The encryption scheme is analogous; it requires us to apply permutations in reverse order. The cipher has all that it needs to effectively evade traffic analysis:

  • it is small enough to implemented in the shellcode;
  • it is good enough to skew structure and frequency distribution of the PE file.

Below are the character distributions of 4 Windows executables encrypted with randomly generated keys:

Crypto_Updates_Image_6

Although the distribution is a bit biased (red line on each plot shows how the perfectly random distribution would look like) it’s good enough to be confused by a network inspection device like NIDS with some other binary data (say, an archive, compressed image, etc).

This might indicate another step of evolution of the windows shellcode used in drive-by-download attacks like obfuscation and hash-based API resolving which was seen some years ago.

While loaders (executables bearing obfuscated payload) provide a certain level of stealthiness on the hard drive, the encryption scheme used in our example protects the file on its way from malicious server to the target system. It will be quite difficult to write a signature for such kind of file since it’s just a binary blob which could be anything. It clearly shows that crimeware business lives and evolves. It appears that instead of discovering new attack techniques for Windows 7+, Chrome, Adobe Reader X+ etc. malware authors try to take as much as possible from the older and more vulnerable systems by increasing the quality of malicious content delivery.

These developments call for the use of new endpoint based techniques for protection and analysis as network based inspection technologies are effectively blind to these new developments.  As obfuscation techniques continue to evolve, the need for a robust analysis environment increases.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: