Thursday, April 12, 2012

Flashback Trojan: domain generator algorithm demystified

We already heard a lot about Flashback, a trojan targeting users of Apple's Mac OS X that has currently infected more than 600,000 machines around the world, taking advantage of a java vulnerability  (CVE-2012-0507).
                
Kaspersky has conducted a good analysis: 
https://www.securelist.com/en/blog/208193441/Flashfake_Mac_OS_X_botnet_confirmed

Information from a user perspective has already been published: you can find removal scripts, patches, detection routines, and so on, easily all over the net. However the most interesting  data about this malware, from a security standpoint, is its spreading functionality.
I recently got a sample of this malware, and analyzed a bit of code. It was easy to determine the domain generator algorithm as I noticed the piece of code that set up the url:
                
                mov     edi, [ebp+StrParam1]
                mov     [esp+10h], eax  ; string param2 
                mov     dword ptr [esp+8], offset aSS ; char format 
                mov     dword ptr [esp+4], 200h ; size_t
                mov     [esp+0Ch], edi  ; string param1
                mov     [esp], ebx      ; dest
                call     snprintf
                
                aSS             db '%s%s',0
                
The domain generator algorithm is immediately before this part.
I studied it for a while and rewrote it in C language:
              
                #include <stdio.h> 
                #include <stdlib.h>
                #include <string.h>
                #include <time.h>

                
                void GenDomain(void)
                {
                    struct tm *ptm;
                    time_t rawtime;

                    unsigned int day, month, year;

                    unsigned int day1, day2, day3, month1, year1, year2, year3;
                    unsigned int i, j, size;
                    char *domain;  

                    time(&rawtime);
                    ptm = gmtime(&rawtime);
                    year = ptm->tm_year;
                    month = ptm->tm_mon;
                    day = ptm->tm_mday;
                 // compute day
                    day1 = day ^ (day << 16);
                    if((day ^ (day << 16)) <= 1 )
                    {
                      day2 = day << 24;
                      day3 = ~(day << 24);
                      if(day2 > 1)
                        day3 = day2;
                      day1 = day3;
                    }
                 // compute month
                    month1 = month ^ (month << 16);
                    if(month1 <= 7)
                    {
                      month1 = month << 24;
                      if((month << 24) <= 7)
                        month1 = ~(month << 24);
                    }
   
                 // compute year
                    year1 = year ^ (year << 16);
                    if((year ^ (year << 16)) <= 15)
                    {
                      year2 = year << 24;
                      year3 = ~year2;
                      if(year2 > 15)
                        year3 = year2;
                      year1 = year3;
                    }
                    size = (((16 * (month1 & 0xF8) ^ ((month1 ^ 4 * month1) >> 25) ^ ((day1 ^ (day1 << 13)) >> 19)) ^ ((year1 ^ (8 * year1)) >> 11)) & 3)+13;
                    j = size -1;
                    domain = (char*)malloc(size);
                    memset(domain, 0, size);

                    for(i = 0; i < j; i++)
                    {
                      day1 = ((day1 ^ (day1 << 13)) >> 19) ^ ((day1 & 0xFFFFFFFE) << 12);
                      month1 = ((month1 ^ 4 * month1) >> 25) ^ 16 * (month1 & 0xFFFFFFF8);
                      year1 = ((year1 ^ 8 * year1) >> 11) ^ ((year1 & 0xFFFFFFF0) << 17);

                      domain[i] = ((year1 ^ month1 ^ day1) % 25) + 97;
                    }

                 printf("Domain: %s \n", (char *)domain);
                }

                int main(void)
                {
                 GenDomain();
                 return 0;
                }

Basically it generates a stream of characters calculated from the current date (using day, month and year), so that every day a new domain is generated and contacted.
For example,  the domain of the day (12/04/2012) is:
                
                Domain: fhnqskxxwloxl 
                
Note that this routine generates only the domain name, and not the TLD. It seems that the possible TLDs used by the malware are encrypted with strong encryption and the key is uniquely generated from the infected machine at install time, therefore I'm unable to find them as I got only the payload and not the full installer.

We can do a little research using Google anyway and it seems that the following TLDs have been observed:

.com
.net
.kz
.in
.info

Now that the domain generator algorithm is demystified you can try to register one of the domains (if you can find one still available!) and perform your own traffic analysis!


No comments:

Post a Comment