Tales from Crisis, Chapter 2: Backdoor’s first steps

Let’s continue our cute story about OS.X/Crisis, this time with the startup flow of the main backdoor module. Please apologize for the delay on this chapter – I had some fun with the rootkit and that diverted me to other things.

The first curious detail about the backdoor module (installed as /Users/USERNAME/Library/Preferences/jlc3V7we.app/IZsROY7X.-MP) is that no obfuscation/anti-debugging tricks are used (except one) so its analysis is easier than the dropper. It also uses Objective-C heavily, which is still a bit annoying in IDA but has the advantage of the code being very descriptive.

The main() starts at 0x3B5C and the start of hostilities is with overriding asl_send() function using mach_override package. This is a function of Apple System Log facility, a replacement for the syslog API. The objective is to avoid error & warning messages to be written to the log files.

override asl send

The replacement function does nothing besides returning 1, a failure value.

asl replacement

A command-line argument is supported by this module (at least one variant of Flashback’s dropper also had arguments). Its syntax is -p PID. The PID argument will be passed to a function named _lionSendEventToPid. I just skimmed thru its contents and its main purpose is to send a kASAppleScriptSuite/kGetAEUT (ascr/gdut) event to the target PID. This event loads scripting additions in that process (this post and this note explain what happens in detail). The backdoor will exit after calling this function.

The next step is to verify is a file called off.flg exists at the backdoor executable location, /Users/USERNAME/Library/Preferences/jlc3V7we.app/.
If it does exist, then the following will happen:

  • Remove off.flg file.
  • Call method makeBackdoorResident, which will create the Launch Agent com.apple.mdworker.plist at ~/Library/LaunchAgents. This will be responsible for starting the backdoor module.
  • Launch again the backdoor module, using a method called executeTask:withArguments:waitUntilEnd:.
  • Try to remove the “old” com.apple.mdworker launchctl job.
  • Exit the current backdoor module execution.

When off.flg does not exist anymore the backdoor will enter into its core startup code with a method called runMeh (starts at address 0xFBFC). Before this happens there is a classic anti-debugging trick – our “old” friend AmIBeingDebugged sysctl. The method detachNewThreadSelector:toTarget:withObject: is called with the selector xfrth (address 0xf09b). This is essentially a new thread using the sysctl trick to detect the debugger and sleeping for 50 seconds until next check.

anti debug code

You can easily skip this by NOP’ing the call at address 0x3F26 or breakpoint on that address and set EIP to address 0x3F2B. The following GDB scripted breakpoint does the job:

b *0x3F26
command 1
set $eip=0x3f2b
tb *0x3f2b
c
end

These initial features are somewhat weird because they are duplicated inside runMeh method. Most probably it’s some debug feature?

Let’s move ahead to the juicy stuff 😄.
The first important operation that is executed is to verify if the current OS is supported, using getSystemVersionMajor:minor:bugFix: method. Lion and Snow Leopard are valid targets, but also Leopard (Intego says it’s crash-prone there). That method uses Gestalt to retrieve the OS information (the original source code is available here, from CocoaDev. Many thanks to @fdfalcon for noticing the mistake below since it’s a JB and not a JBE (I manipulated myself into believing Leopard wasn’t supported hehehe). What happens is that Leopard support is not explicit in userland code, but there are specific functions for it in the rootkit.

check os version

It is followed by a components upgrade feature with a catchy method named called shouldUpgradeComponents. What happens here is that 3 filenames are verified to exist and if they do, they will replace the old files with the new versions. The config file and the input manager can be upgraded and I can’t find the correspondence to the third file – there are no immediate operations on it. The following table describes the relation between the files and components.

UPDATE FILENAME TARGET FILENAME DESCRIPTION
nc-7-8dv.cfg eiYNz1gd.Cfp Configuration file
od-8-8dv.dlb lUnsA3Ci.Bz7 input manager
pe-9-8dv.cpx N/A ???

If the file /Users/USERNAME/Library/Preferences/jlc3V7we.app/00 exists then the method makeBackdoorResident will be called. Execution will continue with a method called _resizeSharedMemoryWindow. Here some kernel shared memory settings will be changed. They are kern.sysv.shmmax, kern.sysv.shmall. Since this requires root privileges, it will only work if the backdoor module was installed as root. More on this later.
My guess is that the shared memory will be used by the spy module to communicate with the main module (especially from sandboxed applications?).

If you want to debug the backdoor module in a already infected machine, you need to be careful with the method _checkForOthers that follows. It will check if the backdoor module is already running by launchctl so you may want to skip the call at address 0xFDF3 (scripted GDB breakpoint or patching to the rescue!).

shared mem and others check

Two operations modes appear to be supported and the active mode is hardcoded into the backdoor module. There is a symbol called _gMode that points to a string located at address 0x54640. This string can be either Ah56K or Ah57K – my sample contains the first one.

The difference between the two modes is that the Ah56K mode does not try to escalate privileges, while the other one tries it using a spoofed authentication dialog with System Preferences icon (this is the image contained in the TIFF file created by the dropper). The trick here is that the backdoor executable creates a copy of itself named System Preferences and launches it.

give me root please

This explains why I couldn’t get the rootkit to be installed with my sample even when running the dropper as root. I had to manually SUID the backdoor module and patch some stuff to get it installed. If you modify the string to Ah57K at the dropper (file offset 0x57FFB) and run the dropper as a normal user, you will get the above dialog and the rootkit installed (you can’t see anymore the backdoor folder at ~/Library/Preferences and other hidden stuff).

mode check

Both modes verify if a filename mdworker.flg file exists and will create it if not. It’s a zero bytes file to signal if the backdoor module is installed as a LaunchAgent.

If mode is Ah57K and target is Snow Leopard then the method _UISpoof will be called. Here the System Preferences backdoor copy will be made and launched, the mdworker.flg will be set, and also make the backdoor module SUID root.
If mode is Ah57K and target is Lion, the /etc/authorization file will be modified by the method enableSetugidAuth. It modifies the privilege system.privilege.setugid_appkit, which will allow AppKit apps to run setuid/setgid (the backdoor module will be set SUID root if higher privileges are obtained). I haven’t tested this with Lion so I’m not sure how it works here (I don’t see the code path to call _UISpoof for Lion). Blame my old 3GB ram MBP.

After all this fuss, the ~/Library/LaunchAgents folder will be created if it does not already exist, and backdoor plist existence verified by method isBackdoorAlreadyResident. If answer is negative our old friend makeBackdoorResident will be called.

The spoofed System Preferences is used only to escalate privileges. Due to this, a check is made before creating the shared memory segment – only created if we are running in “normal” backdoor mode. Shared memory is created and initialized by the method _createAndInitSharedMemory, located at address 0xCAA5.

init shared memory

If mdworker.flg is found then the method _createInternalFilesAndFolders will be called. Its name is pretty self describing. It will create the rootkit bundle, located at /Users/USERNAME/Library/Preferences/jlc3V7we.app/Contents/Resources/WeP1xpBU.wA-.kext, fix the permissions to root:wheel, and also create the Info.plist for the backdoor module (don’t know why since the Contents folder only executable is the kext inside Resources).

Next task is to install the Input Manager (method _dropOsaxBundle, address 0xd871). It will be located at /Users/USERNAME/Library/ScriptingAdditions/appleHID, and it’s one of the upgradeable components. I haven’t reversed yet this bundle but I’m pretty sure it’s the spying component being injected into applications.

The folder /System/Library/Frameworks/Foundation.framework/XPCServices/ referred in some AV posts is only used if target OS is Lion and backdoor has root privileges.

A new thread is created to capture shutdown notifications. I’m not sure why the interest in being notified on shutdowns. The method name is _registerForShutdownNotifications at 0xE80E).

If the backdoor is running as root, it will try to connect to the rootkit or load it if connection failed. I will leave this part for Chapter 3, dedicated to the rootkit.

The OsaxBundle will be injected into running applications (method injectRunningApp) by listing them and sending the kASAppleScriptSuite/kGetAEUT (ascr/gdut) event. Two notifiers will be installed by the backdoor, one for DidLaunchApplication and another for DidTerminateApplication. The former will use the selector injectBundle: and the later **willStopCrisis: ** (oh, there’s the Crisis name 😃).

receive notifications

Configuration files will be loaded, loadInitialConfiguration, and backdoor status changed to Running. I haven’t decrypted yet the configuration files (it uses AES128 and CCCrypt() function). One interesting thing is a check for the demo mode. A quick lookup at the method involved here and it seems to set background to a probably descriptive name called infected.bmp.

The last interesting bit is the method name called _communicateWithAgents. It’s big and still not reversed but it seems to involve shared memory, so I dare to speculate that agents are the infected applications with the spying module, which dump information to the main backdoor module or it could be the logging agents that will receive events from infected apps. It will be the subject of a chapter if I have time and motivation to reverse it.

And this ends Chapter 2! It’s a very long post, which forced me to reverse and look into quite a few things that I didn’t on the first run. It was a good exercise for me and I hope it’s interesting information for you.

The next chapter will be dedicated to the rootkit, the component that I was most interested at when I heard about Crisis. It should be a fun post.

Have fun,
fG!