-
-
Save NMHai/9ba25ff1dd569790956f32b28a88db5d to your computer and use it in GitHub Desktop.
BLATSTING
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Wladimir van der Laan 2016. This document is in the public domain. | |
| BLATSTING reverse-engineering notes. Based on files from Firewall/BLATSTING/BLATSTING_201381/LP/lpconfig | |
| In https://musalbas.com/2016/08/16/equation-group-firewall-operations-catalogue.html, | |
| BLATSTING is described as "A firewall software implant that is used with EGREGIOUSBLUNDER | |
| (Fortigate) and ELIGIBLEBACHELOR (TOPSEC)". | |
| If true, it's interesting how this implant can target both vendors. Presumably they both use the same Linux | |
| kernel version (2.4.x = FortiOS 5.2). | |
| Ironically they have both been part of GPL disputes: | |
| - https://osdir.com/ml/law.gpl.violations.technical/2006-05/msg00007.html | |
| > TOPSEC is a chinese security provider that provide firewall based Linux and netfilter... claims the | |
| > entire software is (C) Copyright TOPSEC | |
| - https://en.wikipedia.org/wiki/Gpl-violations.org#Fortinet | |
| > In 2005, the gpl-violations.org project uncovered evidence that Fortinet had used GPL code in | |
| > its products against the terms of the license, and used cryptographic tools to conceal the violation. | |
| Overview | |
| =============== | |
| BLATSTING "modular rootkit" implant modules | |
| (not showing implied dependencies, e.g. everything depends on core mod) | |
| ┌───────────┐ | |
| │ m00000003 │ | |
| │ core │ | |
| └─────┬─────┘ | |
| ┆ | |
| ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┬┄┄┄┄┄┄┄┄┄┄┄┄┄┄┬┄┄┄┄┄┴┄┄┄┄┄┄┄┬┄┄┄┄┄┄┄┄┄┄┄┄┄┬┄┄┄┄┄┄┄┄┄┄┄┄┄┐ | |
| v v v v v v | |
| ┌─────┴─────┐ ┌─────┴──────┐ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ | |
| │ m01010001 │ │ m01020000 │ │ m0c010001 │ │ m03010000 │ │ m05000003 │ │ m08010001 │ | |
| │ crypto │ │ crypto_rsa │ │ bpf │ │ network │ │ install │ │ hash │ | |
| └─────┬─────┘ └──────┬─────┘ └─────┬─────┘ └─┬──┬─┬────┘ └─┬───┬──┬──┘ └───────────┘ | |
| ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ | |
| └┄┄┄┄┄┄┄┄┄┄┄┄┬┄┘ ┆ ┆ ┆ ┆ ┆ ┆ ┆ | |
| ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ | |
| ┌┄┄┄┄┄┄┄┄┄┄┄ ┆ ┄┄┄┄┄┄┬┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┴┄ ┆ ┆ ┄┄┄┄┄┄┄┘ ┆ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐ | |
| ┆ ┆ ┆ ┆ ┆ ┆ ┆ | |
| ┆ ┆ ┆ ┆ └┄┄┄┄┄┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┄┐ ┆ | |
| ┆ ┆ ┆ ┆ ┆ ┆ | |
| ┆ ┆ ┆ ┌┄┄┴┄┄┄┄┄┄┄┄┄┐ ┆ ┆ | |
| v ┆ v v v v v | |
| ┌─────┴───────────┐┆ ┌─────┴─────┐ ┌───────┴────┐ ┌─────┴─────┐ ┌───────┴───┐ ┌─────┴─────┐ | |
| │ m0d000001 │┆ │ m10000001 │ │ m0e000001 │ │ m07000001 │ │ m09000002 │ │ m02000001 │ | |
| │ networkProfiler │┆ │ sniffer │ │ seconddate │ │ cnc │ │ tunnel │ │ file │ | |
| └─────────────────┘┆ └───────────┘ └────────────┘ └───────────┘ └───────────┘ └─────┬─────┘ | |
| ┆ ┆ | |
| └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┬┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘ | |
| v | |
| ┌─────┴──────┐ | |
| │ m12000000 │ | |
| │ tadaqueous │ | |
| └────────────┘ | |
| Interfaces | |
| ============ | |
| m00000003 core | |
| Imports: | |
| Exports: i00000003 | |
| m01010001 crypto | |
| Imports: i00000003 | |
| Exports: i01010000 | |
| m01020000 crypto_rsa | |
| Imports: i00000003 | |
| Exports: i01020000 | |
| m0c010001 bpf | |
| Imports: i00000003 | |
| Exports: i0c010000 | |
| m03010000 network | |
| Imports: i00000003 | |
| Exports: i03010001 i11000000 | |
| m05000003 install | |
| Imports: i00000003 | |
| Exports: i05000000 | |
| m08010001 hash | |
| Imports: i00000003 | |
| Exports: i08010000 | |
| m0e000001 seconddate | |
| Imports: i00000003 i03010001 | |
| Exports: | |
| m02000001 file | |
| Imports: i00000003 i05000000 | |
| Exports: i02000000 i04000000 | |
| m0d000001 networkProfiler | |
| Imports: i00000003 i03010001 i05000000 i0c010000 | |
| Exports: i0d000000 | |
| m09000002 tunnel | |
| Imports: i00000003 i03010001 i05000000 | |
| Exports: i09000000 | |
| m10000001 sniffer | |
| Imports: i00000003 i03010001 i05000000 i0c010000 | |
| Exports: i10000000 | |
| m07000001 cnc | |
| Imports: i00000003 i03010001 | |
| Exports: i07000000 | |
| m12000000 tadaqueous | |
| Imports: i00000003 i01010000 i01020000 i04000000 | |
| Exports: | |
| Other notes | |
| ================= | |
| - It looks like BLATSTING is a Linux kernel module (or at least: runs in the Linux kernel). Various | |
| references symbol such as `skb_linearize` point in this direction. The BLATSTING modules then, in their | |
| turn, are submodules. | |
| - `the_interface` is a pointer to the main interface of the modules to the outside world. It is part | |
| of the `core` module, and points to a table of function pointers. Modules register their own | |
| interface(s) using `call *(*the_interface+0x40)`. Other modules (which depend on this interface) | |
| can then request this interface (using ??) and use it. | |
| - All interfaces are represented by a function call table (a list of pointers to .text segment, | |
| prefixed with the interface ID and the module ID). | |
| - There is an executable `./Firewall/BLATSTING/BLATSTING_20322/sei/cored`, which is probably the dropper | |
| for BLATSTING. It is the only file, apart from the `core` module which contains the mysterious | |
| symbol `UYO8_U7c5D`. It also contains the symbol `UWV1S` in obfuscated form, also referenced in other modules. | |
| Kernel injection | |
| ================== | |
| ╔════════════════╗ ╔════════════════╗ | |
| ║ kernel ║ ║ cored ║ | |
| ╟┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╢ ╟┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╢ | |
| ║ ║ ║ ║ | |
| ║ Symbol table ───────────> Symbols hash ║ | |
| ║ ║ ║ table ║ | |
| ║ ║ ║ ║ | |
| ║ Syscall table <───────── Hook syscall ║ | |
| ║ ^ ║ ║ 137 ║ | |
| ║ │ ║ ║ ║ | |
| ║ v ║ ║ ║ | |
| ║ Injected <──────────── .data ║ | |
| ║ code ║ ║ ║ | |
| ╚════════════════╝ ╚════════════════╝ | |
| The executable `./Firewall/BLATSTING/BLATSTING_20322/sei/cored` performs Linux kernel injection, | |
| and appears to host the other modules. | |
| Some notes on what it does: | |
| - Uses `setrlimit` system call with `RLIMIT_CORE` to prevent dumping core files (avoid leaving evidence). Exit if this fails. | |
| - Swap is disabled later on with the sys_swapoff system call. Possibly for a similar reason. | |
| - Get the kernel version (`/proc/version` as well as `/proc/sys/kernel/version`). Pad up to 256 bytes and compute SHA1 hash (what is this used for?). Exit if this fails. | |
| - Looks in `/data/.tos_cores/` for `b%03x%03x.%03x` and `bs%03x%03x.%03x` files, where | |
| the %...x is prinf syntax. These appear to be modules and data files respectively. | |
| - First, a configuration file is read, bse226a3.f24. This directs it to open other | |
| modules and load them in to memory. | |
| - If opening the configuration file fails it tries to look inside the executable itself | |
| for information and modules. | |
| - The SHA1 hash computed earier of /proc/version || /proc/sys/kernel/version is compared against | |
| a predefined set of hashes: | |
| d66347bcad1c62daba8f3683251bf60d09d34a01 | |
| 3c1084e94c1679223269deb81882e8ccd8fffcc4 | |
| 6bd6cc8e463ce36e843af9325bc9bbd4989bdc02 | |
| 13b20dfe138cc894e273c10414ad1c2bd1c536c0 | |
| Each of these is associated with a two parameter words that are used later in the injection process. | |
| The set of hashes, as well as a 663-byte configuration area is read from the end of the executable. | |
| Likely there exists an off-line configuration utility to prepare the executable for a certain target | |
| kernel and environment. | |
| - See also `BLATSTING_20040/utils/procversionhashmaker`, an utility described as | |
| "Get the hash bpinsmod uses during implant load." | |
| - One of these parameters is the kernel-space base address. | |
| If none of them matches the proces exits (with return code 26). | |
| - It finds `Kernel code` and `Kernel data` in `/proc/iomem`. | |
| - Then mmaps `/dev/mem` directly. It maps the range encompassing kernel code and kernel data. | |
| Note that this trick to gain access to kernel space is no longer possible in kernels newer | |
| than about 2009 (see http://lwn.net/Articles/267427/) at least if NONPROMISC_DEVMEM, | |
| nowadays called CONFIG_STRICT_DEVMEM is enabled. All distributions enable this on x86, that I know of. | |
| This points at the age of this software. Newer loaders may exist that use an alternative mechanism. | |
| - Looks for symbol `__tos_kmalloc` in the kernel. This is not a stock kernel symbol. I suspect | |
| it is specific to TopSec/TOS? There are no Google hits on this symbol at all. | |
| - Without finding this symbol, or finding the rest of the symbol table, the program exits with code 4. | |
| - Creates a hash table of kernel symbols. | |
| - Looks for various symbols in the kernel, mostly associated with memory management. | |
| - It seems to hook a syscall interface at some point, and communicate through syscall 137 | |
| (`sys_afs_syscall`/`sys_ni_syscall`, a reserved value). | |
| - There is a minimal ELF-loader, which is used to load and relocate the modules. After loading | |
| they, along with initialization data, are copied to kernel memory. | |
| Modules | |
| ========= | |
| Each mXXXXXXXX directory contains one of, or both of: | |
| - An `impmod` file which is an ELF file embedded in a special format. To be loaded at | |
| the implant side. | |
| - An `lpmod` file which is an ELF dynamic library loaded by a 'listening post' backend, which is | |
| the command-and-control side of things. These communicate with the associated module | |
| at the implant side. | |
| ## IMPlant MODules | |
| - These are likely loaded into the kernel, but are not Linux kernel modules themselves. | |
| They lack the information and symbols normally associated with Linux kernel modules. | |
| - The format describes the module ID, as well as the interfaces exported and imported by the module. | |
| The latter determine the dependency relationships between modules. All modules depend on `core`, | |
| which has module ID `m00000003` and exports the core interface `i00000003`. | |
| - Symbols: | |
| - `the_interface`: The core interface (`i00000003`) - only exported by core module | |
| - `UWV1S`/`UVW1S`: Unknown - exported by `cored`, used by the install module. The | |
| name of these symbols is chosen somewhat clever: designed to not stand out in hexdumps/ | |
| strings, as they look like the typical x86 "push ebp..." function prelude. However adding the '1' | |
| character makes it invalid as instructions and unique and easy to grep for. | |
| - `UYO8_U7c5D`: OS information/parameters structure - exported by `cored` | |
| - `init_bp_module`: Initialization function - exported by every module | |
| - `cleanup_bp_module`: Deinitialization function - exported by every module | |
| - `cleanup_core_module`: Deinitialization function - exported by core module | |
| - One module, `tadaqueous`, has two ELF files embedded. The first one | |
| is a module as normal, the other is an executable. It seems related to process | |
| management. | |
| What do the modules do? | |
| ========================= | |
| m00000003 core | |
| --------------------- | |
| Exposes functionality to interface with the kernel and host process, register | |
| and unregister interfaces, memory allocation and de-allocation. | |
| - Besides initializing internal data structures it creates a kernel thread on initialization. | |
| - This thread looks through task structures, and find the task structure for process 1 (init). | |
| - Then it reparents to init. | |
| - It does a few modifications in the thread's task_struct, based on that of init. | |
| I suspect this is to hide the rootkit, but lack of the kernel attacked makes it hard to | |
| interpret what is being done. | |
| - The thread then goes into a loop. | |
| - On module cleanup the thread is stopped. The rootkit does attempt to neatly clean up after itself. | |
| m01010001 crypto | |
| --------------------- | |
| Symmetric cryptography functions. This module implements RC5 or RC6. | |
| The constants 0xb7e15163 and 0x61c88647 are used in the same way as described in | |
| chapter 16 of https://securelist.com/files/2015/02/Equation_group_questions_and_answers.pdf | |
| This suggest that BLATSTING is using the same, or similar crypto implementation as | |
| other malware attributed to the Equation Group. | |
| m01020000 crypto_rsa | |
| --------------------- | |
| RSA cryptography functions (no details known). | |
| m0c010001 bpf | |
| --------------------- | |
| Berkeley Packet Filter functionality. BPFs are programs for a simple | |
| virtual machine that can inspect(among other things) network packets, | |
| and accept or reject them. | |
| Expressions in network sniffers such as pcap are often compiled to this | |
| representation. See also: | |
| - https://blog.cloudflare.com/bpf-the-forgotten-bytecode/ | |
| - https://www.kernel.org/doc/Documentation/networking/filter.txt | |
| It looks like this module implements a dialect of BPF, not the same | |
| BPF as used in the Linux kernel. Instructions are still 8 bytes and have the | |
| same global format, however while trying to decompile the predefined filters | |
| there are 4xxx instructions that are different from normal BPF instructions: | |
| 4027 | |
| 402f | |
| 4037 | |
| These take an argument in the 'k' field, but I have no idea what. | |
| m03010000 network | |
| --------------------- | |
| Network functionality (no details known). | |
| m05000003 install | |
| --------------------- | |
| Installation/persistence? | |
| m08010001 hash | |
| --------------------- | |
| Apparent from some of the constants in the code (0x5a827999, 0xca62c1d6) this likely implements SHA1 hashing algorithm. | |
| Note that there are no consumers of interface i08010000. No module depends on this one. | |
| m0e000001 seconddate | |
| --------------------- | |
| This is by far the most interesting, also the largest binary. | |
| - SECONDDATE is an exploitation technique that takes advantage of web-based | |
| protocols and man-in-the-middle (MitM) positioning. | |
| - SECONDDATE influences real-time communications between client and | |
| server and can quietly redirect web-browsers to FOXACID servers | |
| for individual client exploitation. | |
| - This allows mass exploitation potential for clients passing through | |
| network choke points, but is configurable to provide surgical target | |
| selection as well. | |
| From: https://edwardsnowden.com/2014/03/12/willowvixen-and-seconddate/ (third slide). | |
| See https://gist.github.com/laanwj/96841340cecb5ada220af39551df2896#file-seconddate-3-1-1-0-c-L119 for a | |
| few data structures that are likely used in communication with this module. | |
| m02000001 file | |
| --------------------- | |
| No details known. | |
| m0d000001 networkProfiler | |
| --------------------- | |
| Execute predefined or custom (passive) scans based on BPF rules, | |
| collect statistics. | |
| See e.g. `Firewall/BLATSTING/BLATSTING_201381/LP/lpconfig/m0d000000/predefinedScans`. | |
| These files contain a description of the filter, and a compiled BPF program in | |
| binary form. | |
| m09000002 tunnel | |
| --------------------- | |
| No details known. | |
| m10000001 sniffer | |
| --------------------- | |
| Sniff network traffic. | |
| m07000001 cnc | |
| --------------------- | |
| Command-and-control functions. | |
| m12000000 tadaqueous | |
| --------------------- | |
| Something with OS processes. The non-conventional name seems to apply this is another | |
| internal project such as SECONDDATE. | |
| Kernel interface | |
| ==================== | |
| After injection into the kernel a spare syscall, number 137 (0x89), is hooked to provide an | |
| interface from user space to specific kernel functionality. | |
| Register ebx seems to be used to communicate a sub-function, which is one of. | |
| 0x9d3d143a kernel_alloc(size,flags) | |
| 0x384713aa copy_to_kernel(kaddr,uaddr,size) | |
| 0x93b4e2d2 (unk) | |
| 0xe53c2e96 (unk) | |
| 0xfd13acf3 kernel_free(addr) | |
| Other trivia | |
| ============== | |
| - Various strings in the `cored` executable are obfuscated using a simple substitution | |
| cipher. It makes use of multiplication mod 256, which is a clever little trick | |
| I've not seen before for obfuscation. For example: multiply with 29 to decrypt then | |
| multiply with its multiplicative inverse mod 256, 53, to encrypt again. | |
| - The "SHA1" function in `cored` (0x0804ae38) is actually a variant of SHA1. This does cause | |
| the output hashes to be completely different. Not sure if they botched this or this is a subtle | |
| change on purpose: | |
| - Instead of adding 0x80 at the end of the input then padding with zeros, this function | |
| processes the input in 4-byte words, and adds 0x80000000 (little-endian) at the end of the | |
| input, then pads with zeros. This is before the endian-swap at the beginning of the transform | |
| (necessary on little-endian architectures), so for example the buffer for 'test' will end up looking: | |
| 74 65 73 74 00 00 00 80 <zeros> 00 00 00 00 20 00 00 00 | |
| Whereas it would normally be: | |
| 74 65 73 74 80 ...<zeros>... 00 00 00 00 00 00 00 20 | |
| - Also note that the endian of the bit count at the end is flipped per 32-bit unit. | |
| - Due to a bug in this padding method, only a multiple of 4 bytes can be processed without | |
| ignoring up to three bytes of input. It looks like the function is only used to hash 256 bytes, | |
| so this bug does not surface in practice. | |
| - However if the `hash` module also implements this variant (it seems that way), and | |
| this module is actually used by anything, things are different. | |
| - The hash module implements an almost-correct SHA1. The buffer itself is built in the same | |
| way as previously, and in the inner function all endian swapping normally required for implementing | |
| SHA-1 on little-endian architectures is left out. But this is handled in an outer function, which | |
| works around the problems: allocates a new buffer (padded to 4 with zeros), copies the input, endian-swapped | |
| intothis new buffer, calls the inner function on this buffer, then frees the buffer, byte-swaps the result | |
| and returns that digest. It's kind of circuitous, but for buffers where the size is a multiple of 4 | |
| this returns the same as 'normal' SHA1. For other sizes it return a different output due to the padding. | |
| - BLATSTING's implementers are a big fan of mmap. It seems to be used for all file access, not just | |
| for manipulating kernel memory through `/dev/mem`. Is it done this way to reduce the number | |
| of system calls, to be less conspicious, as well as not reveal what exactly is accessed when | |
| running in `strace`? Or maybe a later stage of the rootkit blocks certain kinds of syscalls | |
| on certain "hidden" files. | |
| - While reverse engineering I haven't found any explicit countermeasures or anti-debugging tricks. | |
| However: | |
| - BLATSTING's implementers took a lot of care not to leak string that could help with | |
| reverse engineering. This is true for `cored`, but also for the modules themselves. There are no | |
| log messages, no debug prints, no error messages, nothing. | |
| - The few strings that are absolutely necessary (such as symbol names) are obfuscated. | |
| - The code was compiled with `-fomit-frame-pointers` (or similar), which makes it somewhat harder | |
| to keep track of the stack frame while reading assembly. | |
| - The code of `cored` is a strange mix of static and dynamic linking. For example, at one point it uses | |
| a direct `sys_open` syscall to open a file then performs `mmap` through the C library. | |
| In the same function. | |
| - The abbreviation `bp_` in symbols likely stands for BEECHPONY. According to | |
| https://marcoramilli.blogspot.nl/2016/08/summing-up-shadowbrokers-leak.html this is | |
| "BEECHPONY A firewall implant that is a predecessor of BANANAGLEE." I haven't looked at | |
| BANANAGLEE much but to me it looks like BUZZDIRECTION is a newer version of this framework. | |
| It wouldn't surprise me if BLATSTING was the oldest of the bunch. | |
| - Looking at the core module, it indeed appears that this rootkit is ancient. The kernel thread | |
| spawned by `init_bp_module`, `0x08001384`, relies on the pre-2.6 functionality where the beginning | |
| of the kernel stack was the `task_struct` (nowadays it is `thread_info`, a much smaller structure). | |
| This means the rootkit will only work on Linux 2.4. There is no way that this is a risk to modern kernels, | |
| though some routers in active use may still be based on old kernels such as that. | |
| - The offsets inside the `task_struct` don't match any kernel I could find, though a manually compiled | |
| 2.4.25 kernel came closer than debug symbols I found for an RHEL3 2.4.21 kernel. It looks like | |
| this rootkit is specific to an extrememly narrow range of kernel versions. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment