View RSS Feed

garage4hackers

Tutorial: Reverse Engineering GameoverZeus DGA code

Rating: 7 votes, 3.71 average.
DGA : Is it Game Over for GameoverZeus DGA

Name:  Screen Shot 2014-08-29 at 6.12.14 pm.jpg
Views: 3047
Size:  21.3 KB
GameoverZeus was brought down and it reincarnated again. The Gameover Zeus is a very authentic contender in our DGA series. So let us analyse it and try to reverse its DGA just like we did in case of PushDO in last article.
http://www.garage4hackers.com/entry.php?b=3080

We got lot of request whether we could have a tutorial on reverse engineering DGA codes. So in this series we would have a tutorial on how to Analyze an Gameover Zeus and its DGA code.

Several researchers have already dedicated their precious efforts in documenting its anti-debug/VM behaviour.


Reverse Engineering GameoverZeus DGA code Tutorial.

Step 1:

Put the sample in %temp%\anyname\filename.exe . Now kill the vmtoolsd.exe and double click the filename.exe.
The file.exe will start another child process in my case it is muolax.exe. attach debugger to it.

Now From where should we start? The obvious answers are two points:
1. Where DGA starts
2. Where DGA domains are used up

The DGA mostly starts with any api returning time and DGA returns its final product to network/socket handling
apis which resolve the domain names mostly gethostbyname, getaddrinfo etc.

A search for intermodular api references renders us with 3 calls to "GetSystemTime". The call at :

Code:
00430A9D   FF15 C4C24300    CALL DWORD PTR DS:[43C2C4]               ; kernel32.GetSystemTime
Looks promising as some arithmatic is going on with 0x3E8.

Code:
00430A77  ^72 CE            JB SHORT muolax.00430A47
00430A79   FF15 04C34300    CALL DWORD PTR DS:[43C304]               ; kernel32.GetTickCount
00430A7F   8BF8             MOV EDI,EAX
00430A81   85F6             TEST ESI,ESI
00430A83   74 14            JE SHORT muolax.00430A99
00430A85   B8 E8030000      MOV EAX,3E8
00430A8A   50               PUSH EAX
00430A8B   56               PUSH ESI
00430A8C   FF15 BCC24300    CALL DWORD PTR DS:[43C2BC]               ; kernel32.WaitForSingleObject
00430A92   3D 02010000      CMP EAX,102
00430A97   75 40            JNZ SHORT muolax.00430AD9
00430A99   8D45 F0          LEA EAX,DWORD PTR SS:[EBP-10]
00430A9C   50               PUSH EAX
; this is what we were finding:
00430A9D   FF15 C4C24300    CALL DWORD PTR DS:[43C2C4]               ; kernel32.GetSystemTime
00430AA3   33D2             XOR EDX,EDX
00430AA5   B9 E8030000      MOV ECX,3E8
00430AAA   8BC7             MOV EAX,EDI
00430AAC   F7F1             DIV ECX
00430AAE   8D4D C8          LEA ECX,DWORD PTR SS:[EBP-38]
00430AB1   52               PUSH EDX
00430AB2   8D55 F0          LEA EDX,DWORD PTR SS:[EBP-10]
00430AB5   E8 D3E5FFFF      CALL muolax.0042F08D
00430ABA   47               INC EDI
00430ABB   84C0             TEST AL,AL
00430ABD   74 11            JE SHORT muolax.00430AD0
00430ABF   56               PUSH ESI
00430AC0   FF75 08          PUSH DWORD PTR SS:[EBP+8]
00430AC3   8D45 C8          LEA EAX,DWORD PTR SS:[EBP-38]
00430AC6   50               PUSH EAX
00430AC7   E8 26FEFFFF      CALL muolax.004308F2
00430ACC   84C0             TEST AL,AL
00430ACE   75 0D            JNZ SHORT muolax.00430ADD
00430AD0   43               INC EBX
00430AD1   81FB F4010000    CMP EBX,1F4
00430AD7  ^72 A8            JB SHORT muolax.00430A81
00430AD9   32C0             XOR AL,AL
00430ADB   EB 13            JMP SHORT muolax.00430AF0
00430ADD   8D4D C8          LEA ECX,DWORD PTR SS:[EBP-38]
00430AE0   EB 07            JMP SHORT muolax.00430AE9
00430AE2   8B0CBD A8614000  MOV ECX,DWORD PTR DS:[EDI*4+4061A8]
00430AE9   E8 1F05FFFF      CALL muolax.0042100D
00430AEE   B0 01            MOV AL,1
00430AF0   5F               POP EDI
00430AF1   5E               POP ESI
00430AF2   5B               POP EBX
00430AF3   8BE5             MOV ESP,EBP
00430AF5   5D               POP EBP
00430AF6   C2 0800          RETN 8
After call to GetSystemTime we have a call to 0042F08D.
The interesting thing about this call is that if we search for words "com", "org" & "biz" in memory,
debugger will end up inside this subroutine's code, it confirms that we are on right track.

Code:
0042F08D   55               PUSH EBP
0042F08E   8BEC             MOV EBP,ESP
0042F090   83EC 30          SUB ESP,30
0042F093   53               PUSH EBX
0042F094   56               PUSH ESI
0042F095   57               PUSH EDI
0042F096   8BF1             MOV ESI,ECX
0042F098   8BFA             MOV EDI,EDX
0042F09A   6A 00            PUSH 0
0042F09C   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F09F   E8 1F0D0000      CALL muolax.0042FDC3
0042F0A4   6A 04            PUSH 4
0042F0A6   5B               POP EBX
0042F0A7   53               PUSH EBX
0042F0A8   8D45 08          LEA EAX,DWORD PTR SS:[EBP+8]
0042F0AB   C745 F4 01051935 MOV DWORD PTR SS:[EBP-C],35190501
0042F0B2   50               PUSH EAX
0042F0B3   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F0B6   E8 820D0000      CALL muolax.0042FE3D
0042F0BB   84C0             TEST AL,AL
0042F0BD   0F84 05010000    JE muolax.0042F1C8
0042F0C3   6A 02            PUSH 2
0042F0C5   57               PUSH EDI
0042F0C6   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F0C9   E8 6F0D0000      CALL muolax.0042FE3D
0042F0CE   84C0             TEST AL,AL
0042F0D0   0F84 F2000000    JE muolax.0042F1C8
0042F0D6   53               PUSH EBX
0042F0D7   8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]
0042F0DA   50               PUSH EAX
0042F0DB   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F0DE   E8 5A0D0000      CALL muolax.0042FE3D
0042F0E3   84C0             TEST AL,AL
0042F0E5   0F84 DD000000    JE muolax.0042F1C8
0042F0EB   6A 02            PUSH 2
0042F0ED   8D47 02          LEA EAX,DWORD PTR DS:[EDI+2]
0042F0F0   50               PUSH EAX
0042F0F1   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F0F4   E8 440D0000      CALL muolax.0042FE3D
0042F0F9   84C0             TEST AL,AL
0042F0FB   0F84 C7000000    JE muolax.0042F1C8
0042F101   53               PUSH EBX
0042F102   8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]
0042F105   50               PUSH EAX
0042F106   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F109   E8 2F0D0000      CALL muolax.0042FE3D
0042F10E   84C0             TEST AL,AL
0042F110   0F84 B2000000    JE muolax.0042F1C8
0042F116   6A 02            PUSH 2
0042F118   8D47 06          LEA EAX,DWORD PTR DS:[EDI+6]
0042F11B   50               PUSH EAX
0042F11C   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F11F   E8 190D0000      CALL muolax.0042FE3D
0042F124   84C0             TEST AL,AL
0042F126   0F84 9C000000    JE muolax.0042F1C8
0042F12C   53               PUSH EBX
0042F12D   8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]
0042F130   50               PUSH EAX
0042F131   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F134   E8 040D0000      CALL muolax.0042FE3D
0042F139   84C0             TEST AL,AL
0042F13B   0F84 87000000    JE muolax.0042F1C8
0042F141   51               PUSH ECX
0042F142   8D45 D4          LEA EAX,DWORD PTR SS:[EBP-2C]
0042F145   50               PUSH EAX
0042F146   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F149   E8 960D0000      CALL muolax.0042FEE4
0042F14E   84C0             TEST AL,AL
0042F150   74 76            JE SHORT muolax.0042F1C8
0042F152   33DB             XOR EBX,EBX
0042F154   32C0             XOR AL,AL
0042F156   8845 FB          MOV BYTE PTR SS:[EBP-5],AL
0042F159   0FB6C0           MOVZX EAX,AL
0042F15C   8D1433           LEA EDX,DWORD PTR DS:[EBX+ESI]
0042F15F   6A 08            PUSH 8
0042F161   8B4C05 D4        MOV ECX,DWORD PTR SS:[EBP+EAX-2C]
0042F165   E8 73000000      CALL muolax.0042F1DD
0042F16A   85C0             TEST EAX,EAX
0042F16C   78 5A            JS SHORT muolax.0042F1C8
0042F16E   03D8             ADD EBX,EAX
0042F170   8A45 FB          MOV AL,BYTE PTR SS:[EBP-5]
0042F173   04 04            ADD AL,4
0042F175   8845 FB          MOV BYTE PTR SS:[EBP-5],AL
0042F178   3C 10            CMP AL,10
0042F17A  ^72 DD            JB SHORT muolax.0042F159
0042F17C   C60433 2E        MOV BYTE PTR DS:[EBX+ESI],2E
0042F180   43               INC EBX
0042F181   F645 08 03       TEST BYTE PTR SS:[EBP+8],3
0042F185   75 0C            JNZ SHORT muolax.0042F193
0042F187   C70433 636F6D00  MOV DWORD PTR DS:[EBX+ESI],6D6F63
0042F18E   83C3 03          ADD EBX,3
0042F191   EB 2F            JMP SHORT muolax.0042F1C2
0042F193   8B45 08          MOV EAX,DWORD PTR SS:[EBP+8]
0042F196   33D2             XOR EDX,EDX
0042F198   6A 03            PUSH 3
0042F19A   59               POP ECX
0042F19B   F7F1             DIV ECX
0042F19D   85D2             TEST EDX,EDX
0042F19F   75 09            JNZ SHORT muolax.0042F1AA
0042F1A1   C70433 6F726700  MOV DWORD PTR DS:[EBX+ESI],67726F
0042F1A8   EB 16            JMP SHORT muolax.0042F1C0
0042F1AA   F645 08 01       TEST BYTE PTR SS:[EBP+8],1
0042F1AE   75 09            JNZ SHORT muolax.0042F1B9
0042F1B0   C70433 62697A00  MOV DWORD PTR DS:[EBX+ESI],7A6962
0042F1B7   EB 07            JMP SHORT muolax.0042F1C0
0042F1B9   C70433 6E657400  MOV DWORD PTR DS:[EBX+ESI],74656E
0042F1C0   03D9             ADD EBX,ECX
0042F1C2   C60433 00        MOV BYTE PTR DS:[EBX+ESI],0
0042F1C6   EB 02            JMP SHORT muolax.0042F1CA
0042F1C8   32DB             XOR BL,BL
0042F1CA   8D4D E4          LEA ECX,DWORD PTR SS:[EBP-1C]
0042F1CD   E8 3A0C0000      CALL muolax.0042FE0C
0042F1D2   5F               POP EDI
0042F1D3   5E               POP ESI
0042F1D4   8AC3             MOV AL,BL
0042F1D6   5B               POP EBX
0042F1D7   8BE5             MOV ESP,EBP
0042F1D9   5D               POP EBP
0042F1DA   C2 0400          RETN 4
The there are several calls to 0042FE3D. This is hashing routine. The subsequent calls to this subroutine
adds year, month, day, 35190501 (salt), and the nonce(generated from 0x3E8 and subsequent iterations)
The correct sequence is :
1. Nonce :
Code:
00430A9D   FF15 C4C24300    CALL DWORD PTR DS:[43C2C4]               ; kernel32.GetSystemTime
00430AA3   33D2             XOR EDX,EDX
00430AA5   B9 E8030000      MOV ECX,3E8
00430AAA   8BC7             MOV EAX,EDI ; EDI is teh counter/iterator
00430AAC   F7F1             DIV ECX
00430AAE   8D4D C8          LEA ECX,DWORD PTR SS:[EBP-38]
00430AB1   52               PUSH EDX	; EDX has nonce
00430AB2   8D55 F0          LEA EDX,DWORD PTR SS:[EBP-10]
00430AB5   E8 D3E5FFFF      CALL muolax.0042F08D
00430ABA   47               INC EDI ; counter increment : Nonce will be incremented
The EDX has nonce/salt. It is added to MD5 hash object.
2. Year is added to MD5 hash object
3. 35190501 (salt)
4. Month
5. 35190501 (Salt)
6. Day
7. 35190501 (Salt)
Generate MD5 hash. After generating MD5 hash a call to 0042F1DD is made at
Code:
0042F165   E8 73000000      CALL muolax.0042F1DD
The subroutine 0042F1DD do arithmatic+logical operations on 8 byte stringlets of MD5 has in 4 separate iterations :

Code:
0042F1DD   53               PUSH EBX
0042F1DE   55               PUSH EBP
0042F1DF   8B6C24 0C        MOV EBP,DWORD PTR SS:[ESP+C]
0042F1E3   56               PUSH ESI
0042F1E4   57               PUSH EDI
0042F1E5   8BFA             MOV EDI,EDX
0042F1E7   4D               DEC EBP
0042F1E8   03EF             ADD EBP,EDI
0042F1EA   8BF7             MOV ESI,EDI
0042F1EC   3BF5             CMP ESI,EBP
0042F1EE   73 41            JNB SHORT muolax.0042F231
0042F1F0   8BC1             MOV EAX,ECX
0042F1F2   33D2             XOR EDX,EDX
0042F1F4   6A 24            PUSH 24
0042F1F6   59               POP ECX
0042F1F7   F7F1             DIV ECX
0042F1F9   894424 14        MOV DWORD PTR SS:[ESP+14],EAX
0042F1FD   80FA 09          CMP DL,9
0042F200   8D42 30          LEA EAX,DWORD PTR DS:[EDX+30]
0042F203   8D5A 57          LEA EBX,DWORD PTR DS:[EDX+57]
0042F206   0FB6C8           MOVZX ECX,AL
0042F209   0FB6C3           MOVZX EAX,BL
0042F20C   0F47C8           CMOVA ECX,EAX
0042F20F   880E             MOV BYTE PTR DS:[ESI],CL
0042F211   46               INC ESI
0042F212   8B4C24 14        MOV ECX,DWORD PTR SS:[ESP+14]
0042F216   85C9             TEST ECX,ECX
0042F218  ^75 D2            JNZ SHORT muolax.0042F1EC
0042F21A   8BC6             MOV EAX,ESI
0042F21C   880E             MOV BYTE PTR DS:[ESI],CL
0042F21E   2BC7             SUB EAX,EDI
0042F220   4E               DEC ESI
0042F221   8A0F             MOV CL,BYTE PTR DS:[EDI]
0042F223   8A16             MOV DL,BYTE PTR DS:[ESI]
0042F225   880E             MOV BYTE PTR DS:[ESI],CL
0042F227   4E               DEC ESI
0042F228   8817             MOV BYTE PTR DS:[EDI],DL
0042F22A   47               INC EDI
0042F22B   3BFE             CMP EDI,ESI
0042F22D  ^72 F2            JB SHORT muolax.0042F221
0042F22F   EB 02            JMP SHORT muolax.0042F233
0042F231   33C0             XOR EAX,EAX
0042F233   5F               POP EDI
0042F234   5E               POP ESI
0042F235   5D               POP EBP
0042F236   5B               POP EBX
0042F237   C2 0400          RETN 4
Finally after creation of domain names, the TLD is attached as in
following code of subroutine 0042F08D :

Code:
MOV DWORD PTR DS:[EBX+ESI],67726F
0042F17C   C60433 2E        MOV BYTE PTR DS:[EBX+ESI],2E ; "."
0042F180   43               INC EBX
0042F181   F645 08 03       TEST BYTE PTR SS:[EBP+8],3
0042F185   75 0C            JNZ SHORT muolax.0042F193
0042F187   C70433 636F6D00  MOV DWORD PTR DS:[EBX+ESI],6D6F63 ; "com"
0042F18E   83C3 03          ADD EBX,3
0042F191   EB 2F            JMP SHORT muolax.0042F1C2
0042F193   8B45 08          MOV EAX,DWORD PTR SS:[EBP+8]
0042F196   33D2             XOR EDX,EDX
0042F198   6A 03            PUSH 3
0042F19A   59               POP ECX
0042F19B   F7F1             DIV ECX
0042F19D   85D2             TEST EDX,EDX
0042F19F   75 09            JNZ SHORT muolax.0042F1AA
0042F1A1   C70433 6F726700  MOV DWORD PTR DS:[EBX+ESI],67726F ; "org"
0042F1A8   EB 16            JMP SHORT muolax.0042F1C0
0042F1AA   F645 08 01       TEST BYTE PTR SS:[EBP+8],1
0042F1AE   75 09            JNZ SHORT muolax.0042F1B9
0042F1B0   C70433 62697A00  MOV DWORD PTR DS:[EBX+ESI],7A6962 ; "biz"
0042F1B7   EB 07            JMP SHORT muolax.0042F1C0
0042F1B9   C70433 6E657400  MOV DWORD PTR DS:[EBX+ESI],74656E ; "net"
The TLD are com, org, biz and net.
The following is the python code for GameoverZeus DGA :

Code:
'''
   Developer : Garage4Hackers
   Greets : b0nd, FB1H2S, vinnu, l0rdDeathStorm, nightrover and all g4h team
'''
import os, datetime, time, hashlib, socket

family = "GameoverZeus"
utility = family+"-DGA"
os.system("title "+utility)

def hasher(data, algorithm="md5"):
    h = hashlib.new(algorithm)
    h.update(data)
    return h.hexdigest()

def getDate():
    dt = str(datetime.datetime.now()).split(' ')[0]
    dstash = dt.split('-')
    dd = dstash[2]
    mm = dstash[1]
    yyyy = dstash[0]
    return int(dd),int(mm),int(yyyy)

def seeder(index, salt):
    ############
    edi = salt+index
    edx = 0
    ecx = 0x03E8
    eax = edi
    edx = eax % ecx
    eax = eax / ecx
    print "eax : %x edx : %x salt : %x" % (eax, edx, salt)
    day, month, year = getDate()
    h = hashlib.new("md5")
    dx = ("%08x"%socket.htonl(edx)).decode("hex")
    print "\tedx : "+dx.encode("hex")
    h.update(dx)
    y = ("%x"%socket.htons(year)).decode("hex")
    print "\tyear : "+y.encode("hex")
    h.update(y)
    s = ("%08x"%socket.htonl(salt)).decode("hex")
    print "\tsalt : "+s.encode("hex")
    h.update(s)
    m = ("%04x"%socket.htons(month)).decode("hex")
    print "\tmonth : "+m.encode("hex")
    h.update(m)
    print "\tsalt : "+s.encode("hex")
    h.update(s)
    d = ("%x"%socket.htons(day)).decode("hex")
    print "\tday : "+d.encode("hex")
    h.update(d)
    print "\tsalt : "+s.encode("hex")
    h.update(s)
    seed = h.hexdigest()
    return seed, edx

def generateDomain(hashlet):
    print "Generating domain"
    result = []
    print "Hashlet : %x" % hashlet
    #0042fef6:
    ##########
    ecx = hashlet
    ##########
    cl = 0
    dl = 0
    bl = 0
    eax = 0
    ebx = 0
    edx = 0
    esi = len(result)
    edi = 0
        
    while (ecx & 0xFFFFFFFF) :
        eax = ecx
        edx = 0
        ecx = 0x24
        edx = eax % ecx
        eax = eax/ecx
        esp14 = eax
        dl = edx & 0xFF
        #print "eax: %x ecx : %x edx : %x ebx : %x dl : %x" % (eax,ecx,edx,ebx, dl)
        eax = edx+0x30
        ebx = edx+0x57
        al = eax & 0xFF
        bl = ebx & 0xFF
        ecx = al
        eax = bl
        if dl > 9 :
            ecx = eax
        cl = ecx & 0xFF
        result.append(chr(cl))
        ecx = esp14
        #time.sleep(1)
    
    esi = len(result)
    eax = esi
    print "result : %s, esi : %x cl %x" %( ''.join(result), esi, cl)
    result[esi-1]= chr(cl)
    eax = eax-edi
    esi -= 1
    while edi < esi :
        cl = result[edi]
        dl = result[esi]
        print "\tesi: %x edi : %x cl : %s dl : %s result  :%s" % (esi,edi,cl, dl, ''.join(result))
        result[esi] = cl
        esi -= 1
        result[edi] = dl
        edi +=1
        #print "\t1esi: %x edi : %x cl : %s dl : %s result  :%s" % (esi,edi,cl, dl, ''.join(result))
        #time.sleep(1)
    
    return ''.join(result)


def engine(salt = 0x35190501, maxiter = 1000):
    domains = []
    #salt = 0x35190501
    #maxiter = 1000
    for i in range(maxiter) :
        hashit, edx = seeder(i, salt)
        print "hashit : "+hashit
        hashstash = [int(hashit[:8],16), int(hashit[8:16],16),int(hashit[16:24],16),int(hashit[24:],16)]
        domain = ''
        if True :
        #while len(domain) < 0x10 :
            index = 0
            for hashlet in hashstash:
                print "Hashlet : %x"% hashlet
                domain += generateDomain(socket.htonl(hashlet) & 0xFFFFFFFF)
                print "\t[%d] Domain : %s" % (index, domain)
                index += 1
        print "[%d] Domain : %s\n" % (i, domain)
        #########################
        if (edx & 3 == 0) :
            domain += ".\x63\x6F\x6D"
        elif (edx % 3 != 0 ) :
            if (edx & 1 != 0) :
                domain += ".\x6E\x65\x74"
            else :
                domain += ".\x62\x69\x7A"
        else :
            domain += ".\x6F\x72\x67"
        #########################
        domains.append(domain)
    return domains

index = 0
dt = str(datetime.datetime.now()).split(' ')[0]
domains = engine()
fp = open("gzdga_domains_"+dt+".txt","w")
for domain in domains:
    a = dt+" | %d | %s\n" % (index, domain)
    fp.write(a)
    print a
    index += 1
fp.close()
Sample hash for practicing : 3ff49706e78067613aa1dcf0174968963b17f15e9a6bc54396 a9f233d382d0e6
https://www.virustotal.com/en/file/3...d0e6/analysis/
---------------XXX-------------

Happy Reversing : Stay turned on our social media page for more update:

https://www.facebook.com/Garage4Hackers
https://twitter.com/garage4hackers

Regards,

Garage4HackersName:  Screen Shot 2014-08-29 at 6.12.14 pm.jpg
Views: 3047
Size:  21.3 KB
Tags: None Add / Edit Tags
Categories
Uncategorized

Comments

Trackbacks

Total Trackbacks 0
Trackback URL: