Wednesday, January 15, 2020

MMD-0065-2020 - Linux/Mirai-Fbot's new encryption explained


I setup a local brand new ARM base router I bought online around this new year 2020 to replace my old pots, and yesterday, it was soon pwned by malware and I had to reset it to the factory mode to make it work again (never happened before). When the "incident" occurred, the affected router wasn't dead but it was close to a freeze state, allowing me to operate enough to collect artifacts, and when rebooted that poor little box just won't start again. So for some reason the infection somehow ruined the router system.

As the summary for this case, in the router I found an infection trace of Mirai Linux malware variant called "FBOT", an ARM v5 binary variant, and it is just another modified version of original Mirai malware (after a long list of other variants beforehand). The infection came from a malware spreader/scanner attack from "another" infected internet of things explained later on.

There is an interesting new encryption logic on its configuration section in the binary, alongside with the usage of "legendary" Mirai table's encryption, so hopefully this write-ups will be useful for others to dissect the threat. This may not be an easy reading one you and is a rather technical post, but if you are in forensics or reverse engineering on embedded platforms i.e. IoT or ICS security, you may like it, or, please bear with it. To make the post small and neat I won't go to further detail on router matter itself, and just go straight to the malicious binary that caused the problem, Mirai, is also a malware with a well-known functionality by now. It would be helpful if you know how it works beforehand. So I'll focus to the new decryption part of the artifact.

I changed my analysis platform since SECCON 2019, I use "Tsurugi Linux SECCON edition", a special built version by Giovanni, with hardened/tested by me, supported by the "Trufae" for radare2's r2ghidra & r2dec pre-installing process during the SECCON 2019 time. It's a Linux distribution for binary & forensics analysis, Tsurugi is enriched with pre-compiled r2 with many architecture decompilers (i.e.: r2ghidra, r2dec and pdc), along with ton of useful open source binary analysis, DFIR tools with the OSINT/investigator's mode switch. This OS should suffice the analysis purpose. A new feature of r2ghidra (also r2dec) are used a lot. (The thank's list is in the Epilogue part).

The tool's version info:

:> !r2 -v
radare2 4.1.0-git 24455 @ linux-x86-64 git.4.0.0-235-g982be50
commit: 982be504999364c966d339c4c29f20da80128e14 build: 2019-12-17__10:29:05
:> !uname -a
Linux tsurugiseccon 5.4.2-050402-tsurugi #1 SMP Tue Dec 10 21:18:57 CET 2019 x86_64 x86_64 x86_64 GNU/Linux

(click the image to check details..)

Okay, let's write this, here we go..

The infection

After successfully getting logs and cleaning them up, below is the timeline (in JST) that contains the infection detail:

We can see one IP address 93(.)157(.)152(.)247 was gaining a user's login access, after checking of infection condition and following by confirming previous infection binary instance, it downloaded and executed the ".t" payload that was fetched from other IP 5(.)206(.)227(.)65 afterwards. Other interesting highlights from this infection are: It flushes all the rules in the "filter" table of iptables; Scanning (previous) infections; The usage of SATORI keyword during checking (which is actually not the original one since the original author has been arrested) and the downloading tool used is either the tftp or wget.

fbot-arm: ELF 32-bit LSB executable, ARM, version 1, statically linked, stripped
3ea740687eee84832ecbdb202e8ed743  fbot-arm

The compromised IoT that was infecting my device is this kind --> [link] a made-in-China(PRC) "GPON OLT" device. It is important to know that they are vulnerable to this Mirai variant's infection.

During firstly detected, FBOT was running as per Mirai suppose to work, and from the COMM serial connection (telnet & SSH wasn't accessible due to high load average) we can see it runs like below list of file result:

The IP 5(.)206(.)227(.)65 is also functioned as this FBOT C2 server that looks "out of service" during the above snapshot was taken.

So the binary that was executed was somehow deleted the itself. I can not recover it. An interesting randomized process name is running on a memory area that is showing a successful infection. So, being careful not to shutting down the load average 10 something small system I dumped the binary from memory as per I explained in the R2CON2018 [link] and 2019.HACK.LU [link] presentations I did, then, I saved and renamed the binary into "fbot-arm" for the further analysis purpose.

The memory maps is a good guidance for this matter, the rest of memory and user space are clean, note: you have to be very careful to not freezing the kernel or stopping the malware during the process. I was lucky to install tools needed for hot forensics before the infection occurred.

The binary analysis

The dumped ARM binary can be seen in radare2 like this detail, which it looks a plain stripped ARM may came up as result from cross compilation.

The binary headers, entry points and sections don't show any strange things going on too, I think we can deal with the binary contents right away..

The new encryption and the decryption

When seeing Fbot binary's strings, I found it very interesting to see that there's a "Satori botnet's signature", that was used for scanning vulnerable telnet by Satori botnets, that string is also written hard-coded in this FBOT binary:

The same string is also detected during the infection log too. this coincidence(?) is really a "Deja Vu" to logs seen in the Mirai Satori infection era within 2017-2018. But let's focus to the encryption strings instead.

There are two groups of encrypted configuration data (Mirai usually uses encrypted configuration data before being self-decrypted during the related execution process), but one of group of data looks like encrypted in a new different logic.

The first group of the data (the orange colored one) is in a form of encryption pattern that is not commonly found in Mirai binaries before, which is the point of this post actually. And the blue-colored one is the data configuration that have been encrypted in pattern that is being used in table.c:table_init() of bot client, to then unlocking them for the further usage in malicious process like telnet scanning (scanner_init), or the other functions in Mirai operation. The blue color part's encryption method is a known one, we can later see its decrypted values too.

The first configuration (encrypted) data will be firstly loaded by table.c:add_entry() variant function of MIrai, but during the further process it is processed using a new different decryption. Summarizing this method in a simpler words: that different decryption is a shuffle of alphabetical character set, based on a XOR''ed key that permutes its position.

Let's access the .rodata section in address 0xf454 where the first group data-set is located. When you get there, after checking the caller reference, it will lead you to a function at 0x9848 that's using those crypted values, see below:

If you go to the top of the function and see (address 0x984c and 0x9858) how two string-sets are loaded from addresses 0x10020 and 0x10062 to be passed into a function in 0x975C with their length of 0x42 as secondary argument.

The two set loaded string-sets are saved in the ARM binary in this location:

There is a XOR key with value 0x59 applied to obfuscate the strings that was previously mentioned..

Back to the function in 0x9848, the rest of the encrypted configuration data (the rest of "orange" ones) is parsed into function in 0x9780.

Function 0x9780 seems to be a modification of a table.c:add_entry() function in the original Mirai code (or similar variants), the modified (or additional) part is a decoder logic of the parsed data. The parsed data will be translated against the character map formed after XOR'ed that is stored in the memory, to have its desired result.

I hope the below loop graph is good enough to explain how the decoder works statically (I have adjusted everything to fit into one image file).

I think it would be better for you to see this first modified encryption config data process in the way it is called from the Mirai's table_init() function reversed as per below:

This should be close enough to what adversary has coded.

Dynamically, the character mapping process used to translate the encrypted strings can also be simulated in radare2 during on-memory analysis (it will be in the heap memory area somewhere if you want to confirm it) as per below result:

So, additionally, static or dynamic reversing can produce same result. I always prefer the static one since I don't have to run any malware code just to crack its configuration.

The encoder table, in text! (enjoy!)

// The decoder is at [0x00009780] , translated crypt into charmap below:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./ -

I announced it yesterday in twitter [link], below is the decryption result:

Since Mirai is coded in a way to make reverse engineering difficult, what you reverse in its binary's code-flow is not what has actually had been coded in C, please noted this, in example, In Mirai, the usage of global variables and the global structs, the #define or #ifdef directives used, the method to unlock encryption process-used-variable values and then lock them all back afterwards, and many other tricks used and designed for the sake of obstruction the reverse engineering. There is no shame in not reversing the overall codes into original ones, especially what you get is embeded-platform system's binary like ARM or MIPS or SH with way simpler assembly code. Reversers know this. Don't let this discourage you for not be proactive in reversing, but keep learning from it and learning it more.

Back to our binary, the timing on when the first and second encrypted configuration were decrypted during malware execution process is different too. This is is the rough C flow of what this ARM binary process looks like during being executed, it's enough to explain my point, which is, the timing when the first configuration was executed is when the process of infection is happening, and the second configuration is used for the spreading/scanning purpose, which will be used afterward.

(Warning! The function's namings above are self-made naming for my reversing purpose and not the actual ones, I don't have ESP power to read the mind of the coder by reading his stripped binary, so please bear with differences etc..)

The static code above can be easily filled with its argument values with two ways, following the registers or after you see how the malicious binary can be simulated its system calls, below is the snip code of what I did (the latter method) to show how this binary was executed as per flow above to reveal its values:

Now we know for sure why I didn't get the file because it was self-deleted after running at the first time.

No. We are not done yet..

As you can see in the decrypted strings, it has mentioned "pizza dongs helper". And the C2 for this Mirai variant has been obviously shown during infection stage (the data is saved in the configuration part that can be achieved by table.c at "init" process), it is on IP 5(.)206(.)227(.)65, if you do OSINT and seeking passive DNS data of the IP address, you will see some similar hostnames and domains to the wording used in the decryption data.

Below is the example of hostnames & domains linked to the C2 IP from a passive database:

It's same domain that also has been registered in multiple IP around the globe:

We keep on monitoring the spreader movement of this malware, these are several pickups of IoT devices log that is actively seeking for other vulnerable ARM devices. I sorted out in timeline base. I hope the carriers that's having vulnerable devices on the list can pay attention to address this issue.

The IOC and STIX2 of this threat is in the posting process to usual portals.

Lastly, as additional, the alleged botnet coder/owner has just sent his compliment, which is rare, so I attached in this blog too:


This post is dedicated to wonderful people who fight tirelessly against IoT threat that keep on aiming our devices until now, and also to people who try very hard to push new policy to have us defend better for the threat. I hope this post helps you.

Thank you very much to r2ghidra, r2dec, r2 folks, tsurugi linux folks, MMD mates and friends, and all I can not mention in here, for supporting our effort in analyzing Linux malicious code all the time.

[Edit] Thu Jan 23 2020, thank you Security Affairs for the historical background and insights of Mirai and Fbot.

This technical analysis and its contents is an original work and firstly published in the current MalwareMustDie Blog post (this site), the analysis and writing is made by @unixfreaxjp.

The research contents is bound to our legal disclaimer guide line in sharing of MalwareMustDie NPO research material.

Malware Must Die!