View RSS Feed


Hesperbot DGA : Everything is Dynamically generated using GA

Rating: 7 votes, 4.29 average.
Hesperbot DGA : Everything is Dynamically generated using GA
Our next contender for DGA series is Hesperbot. It generates all strings/object-names dynamically using various "Generation Algorithms"
similar to DGA. Though its DGA differs from NGA (Name generation algorithm) used for name generation for objects like filenames, foldernames,
mutexes etc.

But both DGA & NGA utilises same seed generator. Hesperbot's DGA is free from date/time and generates same series of domain names
for any salt/magic-number. The salt/magic-number may differ across different samples. Also it generates TLD
dynamically all this makes this DGA non-spottable & unconventional.

So where should we start now? Its bit difficult to track the DGA in action as it may either start in legitimate
Explorer.exe otherwise in child process. Hesperbot starts a child named "explorer.exe" and also injects same code inside legitimate
"Explorer.exe" & terminates original parent process. We can debug both explorers or initially only child explorer.exe as you wish.

We are again only interested in DGA and not going to discus how the the sample unpacks/injects the code etc.

From api tracing we discovered that "RtlFreeHeap" is called several times. We set a breakpoint on "RtlFreeHeap".
It pops several times including the generation of mutex which starts like "lock_....." like that.

Let the RtlFreeHeap return and we check the executing code trail. One specific call which looks interestign and is made across several
other subroutines as well is for a subroutine at 0x0009FC4B which is

0009FC4B   55               PUSH EBP
0009FC4C   8BEC             MOV EBP,ESP
0009FC4E   83EC 10          SUB ESP,10
0009FC51   837D 08 00       CMP DWORD PTR SS:[EBP+8],0
0009FC55   57               PUSH EDI
0009FC56   8BF9             MOV EDI,ECX
0009FC58   C745 F4 810349B0 MOV DWORD PTR SS:[EBP-C],B0490381
0009FC5F   B9 F988E254      MOV ECX,54E288F9
0009FC64   C745 FC 7C683106 MOV DWORD PTR SS:[EBP-4],631687C
0009FC6B   8945 F8          MOV DWORD PTR SS:[EBP-8],EAX
0009FC6E   74 53            JE SHORT 0009FCC3
0009FC70   53               PUSH EBX
0009FC71   56               PUSH ESI
0009FC72   EB 03            JMP SHORT 0009FC77
0009FC74   8B4D F0          MOV ECX,DWORD PTR SS:[EBP-10]
0009FC77   8BC7             MOV EAX,EDI
0009FC79   C1E0 0B          SHL EAX,0B
0009FC7C   33C7             XOR EAX,EDI
0009FC7E   8B7D F4          MOV EDI,DWORD PTR SS:[EBP-C]
0009FC81   894D F4          MOV DWORD PTR SS:[EBP-C],ECX
0009FC84   8B4D FC          MOV ECX,DWORD PTR SS:[EBP-4]
0009FC87   894D F0          MOV DWORD PTR SS:[EBP-10],ECX
0009FC8A   C1E9 0B          SHR ECX,0B
0009FC8D   33C8             XOR ECX,EAX
0009FC8F   C1E9 08          SHR ECX,8
0009FC92   33C8             XOR ECX,EAX
0009FC94   314D FC          XOR DWORD PTR SS:[EBP-4],ECX
0009FC97   6A 04            PUSH 4
0009FC99   5E               POP ESI
0009FC9A   3975 08          CMP DWORD PTR SS:[EBP+8],ESI
0009FC9D   73 03            JNB SHORT 0009FCA2
0009FC9F   8B75 08          MOV ESI,DWORD PTR SS:[EBP+8]
0009FCA2   85F6             TEST ESI,ESI
0009FCA4   74 13            JE SHORT 0009FCB9
0009FCA6   8B4D F8          MOV ECX,DWORD PTR SS:[EBP-8]
0009FCA9   8D45 FC          LEA EAX,DWORD PTR SS:[EBP-4]
0009FCAC   2BC1             SUB EAX,ECX
0009FCAE   8BD6             MOV EDX,ESI
0009FCB0   8A1C08           MOV BL,BYTE PTR DS:[EAX+ECX]
0009FCB3   8819             MOV BYTE PTR DS:[ECX],BL
0009FCB5   41               INC ECX
0009FCB6   4A               DEC EDX
0009FCB7  ^75 F7            JNZ SHORT 0009FCB0
0009FCB9   0175 F8          ADD DWORD PTR SS:[EBP-8],ESI
0009FCBC   2975 08          SUB DWORD PTR SS:[EBP+8],ESI
0009FCBF  ^75 B3            JNZ SHORT 0009FC74
0009FCC1   5E               POP ESI
0009FCC2   5B               POP EBX
0009FCC3   5F               POP EDI
0009FCC4   C9               LEAVE
0009FCC5   C3               RETN
It appears like seed generator as it generates long binary string.
Let us check which subroutines are calling it? A reference check returns following results :

References in 00090000..000A7FFF to 0009FC4B
Address    Disassembly                               Comment
000966D3   CALL 0009FC4B
0009ACBB   CALL 0009FC4B
0009ADA1   CALL 0009FC4B
0009CE25   CALL 0009FC4B
0009FC4B   PUSH EBP                                  (Initial CPU selection)
000A083B   CALL 0009FC4B
Its not easy to land in Hesperbot's DGA directly. Let us one-by-one check all these routines
and set breakpoints on them accordingly in each fresh execution. Also Give network access to your VM after
you set BP on those routines.
I would suggest to search for similar codeblock across all memory blocks and set breakpoints in references in
all blocks.

Most of the referencing routines are generating other stuff, but only interesting routine that has reference to this seed generator
is one that is calling it from
0009CE25   CALL 0009FC4B
Let us check the routine and its logical execution flow:

0009CDF4   55               PUSH EBP
0009CDF5   8BEC             MOV EBP,ESP
0009CDF7   8B06             MOV EAX,DWORD PTR DS:[ESI]
0009CDF9   83EC 18          SUB ESP,18
0009CDFC   57               PUSH EDI
0009CDFD   85C0             TEST EAX,EAX
0009CDFF   75 07            JNZ SHORT 0009CE08
0009CE01   8D7E 10          LEA EDI,DWORD PTR DS:[ESI+10]
0009CE04   6A 1A            PUSH 1A
0009CE06   EB 4B            JMP SHORT 0009CE53
0009CE08   50               PUSH EAX
0009CE09   E8 BFFFFFFF      CALL 0009CDCD  ; Salt generator

; This section determines the length of domain name 
0009CE0E   59               POP ECX
0009CE0F   6A 19            PUSH 19
0009CE11   5F               POP EDI
0009CE12   33D2             XOR EDX,EDX
0009CE14   8BC8             MOV ECX,EAX
0009CE16   F7F7             DIV EDI
0009CE18   6A 08            PUSH 8
0009CE1A   5F               POP EDI
0009CE1B   3BD7             CMP EDX,EDI
0009CE1D   76 02            JBE SHORT 0009CE21
0009CE1F   8BFA             MOV EDI,EDX
0009CE21   57               PUSH EDI

0009CE22   8D45 E8          LEA EAX,DWORD PTR SS:[EBP-18]
0009CE25   E8 212E0000      CALL 0009FC4B ; Call to seed generator
0009CE2A   59               POP ECX
0009CE2B   33C9             XOR ECX,ECX
0009CE2D   85FF             TEST EDI,EDI
0009CE2F   74 1C            JE SHORT 0009CE4D
0009CE31   53               PUSH EBX
0009CE32   0FB6440D E8      MOVZX EAX,BYTE PTR SS:[EBP+ECX-18] ; The seed
0009CE37   99               CDQ
0009CE38   6A 1A            PUSH 1A  ; 0x1A == 26 == number of alfabets
0009CE3A   5B               POP EBX
0009CE3B   F7FB             IDIV EBX
0009CE3D   41               INC ECX
0009CE3E   8A82 783D0A00    MOV AL,BYTE PTR DS:[EDX+A3D78]  ; "abcdefghijklmnopqrstuvwxyz"
0009CE44   88440E 0F        MOV BYTE PTR DS:[ESI+ECX+F],AL  ; Byte Appended to domain name
0009CE48   3BCF             CMP ECX,EDI
0009CE4A  ^72 E6            JB SHORT 0009CE32
0009CE4C   5B               POP EBX
0009CE4D   8D7C31 10        LEA EDI,DWORD PTR DS:[ECX+ESI+10]
0009CE51   6A 19            PUSH 19
0009CE53   59               POP ECX
0009CE54   E8 17A8FFFF      CALL 00097670 ; Appends Top-Level-Domain i.e. ".com"
0009CE59   33C0             XOR EAX,EAX
0009CE5B   40               INC EAX
0009CE5C   5F               POP EDI
0009CE5D   C9               LEAVE
0009CE5E   C3               RETN

0009CE5F   56               PUSH ESI
0009CE60   57               PUSH EDI
0009CE61   6A 2F            PUSH 2F
0009CE63   8BF0             MOV ESI,EAX
0009CE65   33FF             XOR EDI,EDI
0009CE67   58               POP EAX
0009CE68   48               DEC EAX
0009CE69   C60430 00        MOV BYTE PTR DS:[EAX+ESI],0 ; Memset
0009CE6D  ^75 F9            JNZ SHORT 0009CE68
0009CE6F   8B4424 0C        MOV EAX,DWORD PTR SS:[ESP+C]
0009CE73   8906             MOV DWORD PTR DS:[ESI],EAX
0009CE75   B8 BB010000      MOV EAX,1BB 
0009CE7A   66:8946 2D       MOV WORD PTR DS:[ESI+2D],AX
0009CE7E   E8 71FFFFFF      CALL 0009CDF4 ; Call to Domain Name Generator
0009CE83   85C0             TEST EAX,EAX
0009CE85   74 03            JE SHORT 0009CE8A
0009CE87   33FF             XOR EDI,EDI
0009CE89   47               INC EDI
0009CE8A   8BC7             MOV EAX,EDI
0009CE8C   5F               POP EDI
0009CE8D   5E               POP ESI
0009CE8E   C3               RETN

; Salt generator :
0009CDCD   33C9             XOR ECX,ECX
0009CDCF   B8 8F897827      MOV EAX,2778898F ; 0x2778898F is Magic number. It may differ in some samples.
0009CDD4   394C24 04        CMP DWORD PTR SS:[ESP+4],ECX
0009CDD8   76 19            JBE SHORT 0009CDF3
0009CDDA   8BD1             MOV EDX,ECX
0009CDDC   C1E2 09          SHL EDX,9
0009CDDF   0FAFD0           IMUL EDX,EAX
0009CDE2   81F2 3D44BD4E    XOR EDX,4EBD443D
0009CDE8   03D1             ADD EDX,ECX
0009CDEA   03C2             ADD EAX,EDX
0009CDEC   41               INC ECX
0009CDED   3B4C24 04        CMP ECX,DWORD PTR SS:[ESP+4]
0009CDF1  ^72 E7            JB SHORT 0009CDDA
0009CDF3   C3               RET
TLD generator :
00097670   56               PUSH ESI
00097671   33F6             XOR ESI,ESI
00097673   3934CD 04540A00  CMP DWORD PTR DS:[ECX*8+A5404],ESI
0009767A   76 28            JBE SHORT 000976A4
0009767C   53               PUSH EBX
0009767D   33D2             XOR EDX,EDX
0009767F   6A 29            PUSH 29
00097681   8BC6             MOV EAX,ESI
00097683   5B               POP EBX
00097684   F7F3             DIV EBX
00097686   8B04CD 00540A00  MOV EAX,DWORD PTR DS:[ECX*8+A5400]
0009768D   8A92 8C500A00    MOV DL,BYTE PTR DS:[EDX+A508C]
00097693   321430           XOR DL,BYTE PTR DS:[EAX+ESI]
00097696   88143E           MOV BYTE PTR DS:[ESI+EDI],DL
00097699   46               INC ESI
0009769A   3B34CD 04540A00  CMP ESI,DWORD PTR DS:[ECX*8+A5404]
000976A1  ^72 DA            JB SHORT 0009767D
000976A3   5B               POP EBX
000976A4   C6043E 00        MOV BYTE PTR DS:[ESI+EDI],0
000976A8   5E               POP ESI
000976A9   C3               RETN
The reversed Hesperbot DGA in python is as follow :

   Developer : Garage4Hackers
   Greets : nightrover, b0nd, FB1H2S, "vinnu", l0rdDeathStorm and all g4h team
import time, os

family = "Hesperbot"
utility = family+"-DGA"

def initSeed(maxnum, salt):
    ecx = 0x54E288F9
    stack = [0xB0490381, # ebp-c
             0x0631687C, # ebp-4
             ecx         # ebp-0x10 
    edi = salt
    rindex = maxnum
    i = maxnum
    buf = ''
    while i > 0 :
        ecx = stack[3]
        eax = edi
        print "[0] eax : %08x ecx : %08x edi : %08x"% (eax, ecx, edi)
        eax = (eax << 0x0B) & 0xFFFFFFFF
        print "[1] eax : %08x ecx : %08x edi : %08x"% (eax, ecx, edi)
        eax = eax ^ edi
        print "[2] eax : %08x ecx : %08x edi : %08x"% (eax, ecx, edi)
        edi = stack[0]
        stack[0] = ecx
        print "[3] eax : %08x ecx : %08x edi : %08x"% (eax, ecx, edi)
        ecx = stack[2]
        print "[4] eax : %08x ecx : %08x edi : %08x"% (eax, ecx, edi)
        stack[3] = ecx
        ecx = (ecx >> 0x0B) & 0xFFFFFFFF
        ecx = ecx ^ eax
        ecx = (ecx >> 0x08) & 0xFFFFFFFF
        ecx = ecx ^ eax
        print "eax : %08x ecx : %08x"% (eax, ecx)
        stack[2] = stack[2] ^ ecx
        print "stack[2] : %08x"% (stack[2])
        esi = 4
        if rindex <= esi :
            esi = rindex
        print "esi : %08x"% (esi)
        print "stack[2] : %x" % (stack[2])
        tmp = "%08x" % (stack[2])
        tmp = tmp.decode("hex")
        buf += tmp[::-1]
        print "tmp[::-1] : %s" % (tmp[::-1]).encode("hex")
        i -= esi
    print "buf : "+buf.encode("hex")
    return buf           

def addSalt(iteration):
    i = 0;
    magic = 0x2778898F # May differ across different samples
    #magic = 0x2461156F
    if iteration > 0:
        for i in range(iteration):
            magic = (magic + ( i + ((magic * (i << 9 & 0xffffffff) & 0xffffffff) ^ 0x4EBD443D) & 0xffffffff) & 0xffffffff) & 0xffffffff
    return magic

def generateDomain(domlen, seed):
    alphabets = "abcdefghijklmnopqrstuvwxyz"
    domain = ""
    if domlen > 0:
        for j in range(domlen):
            index = ord(seed[j]) % 0x1A
            domain += alphabets[index]
    domain += ".com"
    print "domain : "+domain
    return domain
def initDGA() :
    maxnum = 0x40 # 0x01BB
    domains = []
    for i in range (maxnum):
        magic = addSalt(i)
        edi = 0x19
        edx = 0
        eax = magic / edi
        edx = magic % edi
        edi = 8
        if edx > edi :
            edi = edx
        seed = initSeed(edi, magic)
        domain = generateDomain(edi, seed)
    return domains

def init() :
    print "[+] "+utility+" : initiated"
    domains = initDGA()
    fp = open("hesperdomains.log", "w")
    i = 0
    for domain in domains :
        if i == 0 :
            i += 1
        line = "[%d] %s\n" % (i, domain)
        i += 1



Total Trackbacks 0
Trackback URL: