Tales from Crisis, Chapter 1: The dropper’s box of tricks

Mac malware is back to news spotlight, this time with Crisis (insert one of the other thousand names here _____). This malware is nothing more than commercial spy software being sold by a lot of money to governments or something (oh boy, I could make a good living out of this).

I’m lucky enough to have a sample of it (thank you, you know who you are!) and also lucky to be able to talk about it (it uses some similar tricks that I knew about).

This post is very long so I decided to change its format. The main page will just display the beginning of the article and you need to click to read the rest. I’m not a great fan of this solution, although most blog readers are from RSS feed. Let’s give it a try with these long articles.

I started reversing Crisis because I’m mostly interested in the rootkit. It is able to hide itself by modifying sLoadedKexts, something that I briefly attempted and failed in the past. More on that in next posts.

Crisis has a dropper application that is responsible for installing the backdoors, spy modules and rootkit. It’s a x86 Mach-O binary, with SHA256 checksum of 10fa7fa952dfc933b96d92ccd254a7655840250a787a1b4d9889bf2f70153791.

The first interesting detail is a segment called __INIT_STUB with code execution permissions (that’s why I recommend you to always give a look at the headers). This is unusual and you understand why if you look at the entrypoint, 0x0000409c – it’s located inside that segment.

init stub section

It was fun to reverse the dropper – some of the tricks are described at my presentation slides!

System calls are executed via the classic interrupt 80 call. There’s no obfuscation of the call being made so it’s a matter of cross referencing with XNU syscall list (available at xnu_source/bsd/kern/syscall.h). A small example right at the beginning, in this case a bogus handler is being set for SIGSEV (to avoid core dumps?).

int80 syscall

The next step is to find dyld address in process memory. This will be used to manually solve symbols using a simple hashing algorithm. It uses the fact that dyld is the first image in a process and can be easily located even with ASLR. It can be done by starting to search at address 0x8FE00000 for Mach-O magic value 0xFEEDFACE for 32 bit processes.

find dyld base

Crisis explicitly supports Snow Leopard (10.6) and Lion (10.7). Leopard support appears to be implicit (probably that’s why Intego calls it crash-prone). Confirmation comes from the fact that /System/Library/CoreServices/SystemVersion.plist is read and processed. The string ”>10.” is searched for and if found, the next character is read, which is the current Mac OS X version installed on target system. A local variable is set, 1 if Snow Leopard, 2 for Lion.

read os version
set os version

With this information it can proceed to solve the symbols it needs. This is where things get a bit more interesting. First it will try to mmap some files, which are Lion specific due to symbols removal from dyld (I’m doing this by memory but I think I’m not mistaken here!). Then it will push a 32bits hash into a function to find the symbol from dyld. There are two functions, one for Snow Leopard and another for Lion.

find dyld symbols

I’m still using Snow Leopard so analysis will be presented on its specific functions. The function that I labeled find_symbol_from_dyld_SL will process the dyld header, looking for the __LINKEDIT segment and then search for the symbol requested to be found – the two arguments are the symbol’s hash and dyld base address previously found. The hash algorithm can be found at address 0x4363. It’s a very simple algorithm as you can see from the following C implementation:

hash algo

Update: Dcoder pointed me to the fact that this hash function is sdbm. Thanks for the tip 😃.

The piece of code that is processing dyld Mach-O header searching for __LINKEDIT segment:

process dyld header

With the hash algorithm reversed we can easily find the dyld symbols that are trying to be solved (there are a couple more next). One easy way is to use nm to dump /usr/lib/dyld symbols and feed them to that sample algorithm implementation. Then you can load those pairs into IDA database and write a quick IDC script to find and comment the symbol hash (or just use IDAPython for everything).

The first symbols from dyld to be solved are: __dyld_image_count, __dyld_get_image_name, __dyld_get_image_header. The first one returns the total number of images mapped by dyld, the second the image name at the given image index and the last one a pointer to the Mach-O header of the given image index. For more details do a man 3 dyld.

These dyld symbols will be used to iterate thru all the loaded images in this process and search for /usr/lib/libSystem.B.dylib. When the base address of this library is found, another function will be used to solve its exported symbols such as open, lseek, close, chdir, mkdir, etc.

get libsystemb address

The find_symbol_from_libsystemB_SL function will return the pointer to the symbol that we are looking for. The same hash algorithm is used so once again we can use the same trick and dump libSystem.B.dyld symbols and quickly solve all symbols being solved by Crisis. I will include my lame & dirty IDC scripts at GitHub repo for this analysis.
After solving all symbols that is interested at (symbol pointers will be stored in local variables), it will read the strings that are located at address 0x4000, which is the start of the __INIT_STUB segment. Some of the strings are HOME, Library, Preferences, and some format strings. They will be used to get the $HOME environment variable and unpack the next code and data payloads to $HOME/Library/Preferences/jlc3V7we.app/ folder. The code responsible for the unpacking starts at 0x5683.

What happens here is that a series of Mach-O binaries are embedded into the dropper. The unpacking code will read it and write the data to that folder. This is the main reason why I wrote the ExtractMachO IDA plugin, which you can found here (original post here). The list of the files and their location inside the dropper is the following:

IZsROY7X.-MP 0x05977 Main backdoor module
eiYNz1gd.Cfp 0x67ad7 data file, configuration?
WeP1xpBU.wA- 0x684bf rootkit, 32bits
6EaqyFfo.zIK 0x6be43 rootkit, 64bits
lUnsA3Ci.Bz7 0x70b2b fat binary, bundle
mWgpX-al.8Vq 0xe26eb fat binary
q45tyh 0xf0557 TIFF file

After unpacking all the code and data, it will fork and execute the main backdoor module, IZsROY7X.-MP. The original entrypoint at __TEXT segment will be called, which does nothing and just exits. The analysis of the backdoor module will be done in another post.

execute backdoor

To recap the main interesting points from the dropper:

  • Uses int80 trick to use system calls.
  • Searches for dyld address exploiting the fact that it’s located at a rather easy to find location, and then searches __LINKEDIT for interesting symbols.
  • Searches its loaded images for libSystemB.dylib and solves interesting symbols from there, using a simple hashing algorithm to match the symbols.
  • All payloads are contained in the dropper itself and are unpacked into a $HOME/Library/Preferences folder.
  • And that’s it for the dropper. It’s cute and I had some fun analyzing it – it looks like I wrote it.

The scripts are uploaded to https://github.com/gdbinit/Crisis-Analysis-Tools and also a small tool to hash the exported symbols from a binary or library (its output will be used by the scripts).



Contagio dump has released samples of Crisis. Grab’em here.