As “Sharing is Caring” I’ve uploaded the malicious binary LockBit to our public macOS malware collection. The password is: infect3d
Late Saturday (April 15the), @MalwareHunterTeam tweeted about a new LockBit ransomware variant targeting macOS:
"locker_Apple_M1_64": 3e4bbd21756ae30c24ff7d6942656be024139f8180b7bddd4e5c62a9dfbd8c79
— MalwareHunterTeam (@malwrhunterteam) April 15, 2023
As much as I can tell, this is the first Apple's Mac devices targeting build of LockBit ransomware sample seen...
Also is this a first for the "big name" gangs?
🤔@patrickwardle
cc @cyb3rops pic.twitter.com/SMuN3Rmodl
As shown in the tweet, the ransomware binary initially was undetected by any of the anti-virus engines on VirusTotal:
Shortly after @MalwareHunterTeam’s tweet, the fine folks of @vxunderground added their thoughts and shared samples:
Lockbit ransomware group has created their first MacOS-based payload. We believe this is the first time a large ransomware threat group has developed a payload for Apple products.
— vx-underground (@vxunderground) April 16, 2023
We have samples.
Intel via @malwrhunterteam & @BrettCallow
Download: https://t.co/bMGJXWYvc3 pic.twitter.com/My9ZtAHCcq
The relevance of this macOS specimen is well articulated in their tweet:
“Lockbit ransomware group has created their first MacOS-based payload. We believe this is the first time a large ransomware threat group has developed a payload for Apple products.” vx-underground
Ok, so even though it’s the weekend, we have what appears to be a new macOS malware specimen from one of the more notorious ransomware gangs! Coupled with the fact that this may be, (as noted by @VXUnderground), “the first time a large ransomware threat group has developed a payload for Apple products” …I was intrigued to decided to dig right in!
In this blog post we’ll tear apart the sample, showing that ultimately, while yes it can indeed run on Apple Silicon, that is basically the extent of it’s impact. Thus macOS users have nothing to worry about …for now!
The (SHA-1) hash for the binary (aptly named locker_Apple_M1_64
) is 2D15286D25F0E0938823DCD742BC928E78199B3D
Using macOS’s file
utility, we see the locker_Apple_M1_64
binary is a 64-bit arm64 Mach-O:
% file LockBit/locker_Apple_M1_64 LockBit/locker_Apple_M1_64: Mach-O 64-bit executable arm64
And what about it’s code signing information? Let’s take a peek via macOS’s codesign
and spctl
utilities:
% codesign -dvv LockBit/locker_Apple_M1_64 Executable=LockBit/locker_Apple_M1_64 Identifier=locker Format=Mach-O thin (arm64) CodeDirectory v=20400 size=3295 flags=0x20002(adhoc,linker-signed) hashes=100+0 location=embedded Signature=adhoc Info.plist=not bound TeamIdentifier=not set Sealed Resources=none Internal requirements=none % spctl -a -vvv -t install LockBit/locker_Apple_M1_64 LockBit/locker_Apple_M1_64: invalid signature (code or signature have been modified)
The codesign
utility shows that though it’s signed, it’s signed “ad-hoc” (say vs. an Apple Developer ID). This means if downloaded to a macOS system (i.e. deployed by the attackers) macOS won’t let it run. This is confirmed by the spctl
utility which shows “invalid signature” …or if you’re brave enough to try run it:
Let’s now run the strings
command (with the "-"
option which instructs it to scan the whole file), we find a few strings that appear to be related to standard ransomware activity including:
% strings - -n 3 locker_Apple_M1_64 curve25519xsalsa20poly1305 blake2b blake2b_final blake2b-ref.c sodium_crit_enter _sodium_malloc /dev/urandom /dev/random ... cmd ani adv msi msp com nls ocx mpa cpl mod hta prf rtp rdp bin shs wpx bat rom msc spl ics key exe dll ... restore-my-files.txt ... winmd ntldr ntuser.dat.log bootsect.bak autorun.inf thumbs.db iconcache.db
Also interesting are the strings related to Windows artifacts (e.g. autorun.inf
, ntuser.dat.log
, etc…). This may indicate the ransomware was originally written to target Windows platforms.
This wraps up our triage of the locker_Apple_M1_64
binary. Time to dive in deeper with our trusty friends: the disassembler and debugger!
locker_Apple_M1_64
In this section we’ll more deeply analyze the malicious logic of the locker_Apple_M1_64
binary …which is simplified by the fact that the binary’s symbols aren’t stripped. (So function and method names are left intact ….yay!)
First, we pointed out that the locker_Apple_M1_64
is an arm64 binary (Mach-O 64-bit executable arm64
). This means we better have at least a cursory understanding of AArch64. If you’re not familiar with this instruction set, here’s two of my favorite resources to get you up to speed:
“Arm’d & Dangerous: Analyzing arm64 Malware Targeting macOS” (P. Wardle)
“Blue Fox: Arm Assembly Internals and Reverse Engineering” (M. Markstedter)
Opening the malware in a disassembler, (starting at its main
) we spot some (fairly common) anti-debugging logic:
main
...
000000010000b108 bl imp___stubs__getppid
000000010000b10c mov x1, x0
000000010000b110 mov w0, #0x1f
000000010000b114 mov x2, #0x0
000000010000b118 mov w3, #0x0
000000010000b11c bl imp___stubs__ptrace
000000010000b120 cmn w0, #0x1
In short, this snippet of code invokes ptrace
with PT_DENY_ATTACH
(0x1f
) which will kill the process if a debugger is currently attached, and also prevent future attachments.
As we’ll want to debug the malware to gain a deeper understanding of its functionality, we’ll have to bypass this. Good news, this is trivial! Just set a breakpoint on the address of the call to ptrace
(b 0x000000010000b11c
), and once this is hit, simply skip over the call by modifying the instruction pointer to point it to the next instruction (reg write $pc 0x000000010000b120
). Since the call to ptrace
will now be skipped, we’re free to debug to our hearts content.
% lldb locker_Apple_M1_64 (lldb) target create "locker_Apple_M1_64" Current executable set to 'locker_Apple_M1_64' (arm64). (lldb) b 0x10000b11c (lldb) r * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 locker_Apple_M1_64`main: -> 0x10000b11c <+72>: bl 0x1000429cc ; symbol stub for: ptrace (lldb) reg write $pc 0x10000b120
Next the malware copies a chunk of encrypted data (size: 0x2468
bytes) from a variable named apple_config
to a variable named g_Config
.
000000010000b128 adr x21, #0x10005908c ;g_Config
000000010000b12c nop
000000010000b130 adr x1, #0x100058008 ;apple_config
000000010000b134 nop
000000010000b138 mov x0, x21
000000010000b13c mov w2, #0x2468
000000010000b140 bl imp___stubs__memcpy
The apple_config
variable is noteworthy as this is the only instance (I found) of any macOS specific references / customizations. (The rest of the malware’s binary simple looks like Linux code, compiled for macOS). Still as we’ll see this config doesn’t appear to contain anything specific to macOS.
Next, we find an XOR loop that decrypts this configuration.
000000010000b144 mov x8, #0x0
000000010000b148 mov w9, #0x2458
loc_10000b14c:
000000010000b14c and x10, x8, #0xf
000000010000b150 ldrb w10, [x21, x10]
000000010000b154 add x11, x21, x8
000000010000b158 ldrb w12, [x11, #0x10]
000000010000b15c eor w10, w12, w10
000000010000b160 strb w10, [x11, #0x10]
000000010000b164 add x8, x8, #0x1
000000010000b168 cmp x8, x9
000000010000b16c b.ne loc_10000b14c
Once de-XOR’d we find a few strings as "!!!-Restore-My-Files-!!!"
, "VMware vCenter Server"
, and XP_SP;Win10
. Clearly, nothing relating to macOS specifically …in fact more indications this code is simply a recompile of (pieces of?) LockBit’s ransomware that targets Windows/Linux, and also VMware ESXi.
The malware then initializes various global variables, either with hard-coded values, or from the decrypted configuration (now held in g_Config
).
For example, here we see it set the bdaemon
variable to 0x1, or ’true’ …even though its already set to that value.
_bdaemon:
0000000100059088 dd 0x00000001
...
000000010000b174 adrp x9, #0x100059000
...
000000010000b17c mov w8, #0x1
000000010000b180 nop
000000010000b184 str w8, [x9, #0x88] ; _bdaemon
Here’s the list of global variables that are referenced. Based on their names these provide insight into the malware configuration options:
iMinfilesize
iSpotMaximum
bdaemon
bSelfRemove
publickey
idelayinmin
wholefile
bfullog
bnostop
noext
no_log
bwipe
bVMDKmode
…also, by manually manipulating these values in a debugger (or as we’ll see via the command line) we can simplify analysis. For example, setting bdaemon
to false will prevent the binary from daemonizing (making it easier to debug), while setting bfullog
to true to coerce the malware to log its actions!
The malware then de-XORs other strings, with the hard-coded key of 0x39
. In the following disassembly, note the value of 0x39
is loaded into the w8
register. As w8
is the lower 32-bit of the 64-bit x8
register, only the 0x39
(of the 0x1964126200000039
) will be loaded into w8
.
Subsequent XOR instructions (eor
) then make use of the w8
register, which holds the XOR key (0x39
):
000000010000b260 ldr w8, =0x1964126200000039
...
000000010000b270 eor w10, w10, w8
...
000000010000b28c eor w10, w10, w8
Most of the strings are de-XOR’d in a function aptly named de_xor_all
. We could step through this and dump each string manually, or, as a hard-coded XOR key is used (0x39
), we can simply de-XOR the entire binary and see what falls out. This can be implemented in a few lines of Python:
with open("locker_Apple_M1_64", "rb") as f_in, open("strings", "wb") as f_out:
while True:
chunk = f_in.read(1024)
if not chunk:
break
encrypted_chunk = bytes(byte ^ 0x39 for byte in chunk)
f_out.write(encrypted_chunk)
This produces strings, including the ransomware’s command-line usage:
Usage: %s [OPTION]... -i '/path/to/crypt'
Recursively crypts files in a path or by extention.
Mandatory arguments to long options are mandatory for short options too.
-i, --indir path to crypt
-m, --minfile minimal size of a crypted file, no less than 4096
-r, --remove self remove this file after work
-l, --log prints the log to the console
-n, --nolog do not print the log to the file /tmp/locker.log
-d, --daemonize runs a program as Unix daemon
-w, --wholefile encrypts whole file
-b, --beginfile encrypts first N bytes
-e, --extentions encrypts files by extentions
-o, --nostop prevent to stop working VM
-t, --wipe wipe free space
-s, --spot upper bound limitation value of spot in Mb
-p, --pass password
-f, --full full log
-a, --delay start delay in minutes
-y, --noexts do not search for extentions
-v, --vmdk search for extentions inside VMDK files
Clearly these match to the global variables (that apparently can be set via the command-line as well). As we’ll set this makes analysis and trigger the malware’s core logic, even easier!
Also amongst the de-XOR’d strings, we find the full ransom note (here, truncated):
~~~ LockBit 3.0 the world's fastest and most stable ransomware from 2019~~~
>>>>> Your data is stolen and encrypted.
If you don't pay the ransom, the data will be published on our TOR darknet sites. Keep in mind that once your data appears on our leak site, it could be bought by your competitors at any second, so don't hesitate for a long time. The sooner you pay the ransom, the sooner your company will be safe.
Tor Browser Links:
http://lockbitapt2d73krlbewgv27tquljgxr33xbwwsp6rkyieto7u4ncead.onion
http://lockbitapt2yfbt7lchxejug47kmqvqqxvvjpqkmevv4l3azl3gy6pyd.onion
http://lockbitapt34kvrip6xojylohhxrwsvpzdffgs5z4pbbsywnzsbdguqd.onion
http://lockbitapt5x4zkjbcqmz6frdhecqqgadevyiwqxukksspnlidyvd7qd.onion
http://lockbitapt6vx57t3eeqjofwgcglmutr3a35nygvokja5uuccip4ykyd.onion
http://lockbitapt72iw55njgnqpymggskg5yp75ry7rirtdg4m7i42artsbqd.onion
http://lockbitaptawjl6udhpd323uehekiyatj6ftcxmkwe5sezs4fqgpjpid.onion
http://lockbitaptbdiajqtplcrigzgdjprwugkkut63nbvy2d5r4w2agyekqd.onion
http://lockbitaptc2iq4atewz2ise62q63wfktyrl4qtwuk5qax262kgtzjqd.onion
Links for normal browser:
http://lockbitapt2d73krlbewgv27tquljgxr33xbwwsp6rkyieto7u4ncead.onion.ly
http://lockbitapt2yfbt7lchxejug47kmqvqqxvvjpqkmevv4l3azl3gy6pyd.onion.ly
http://lockbitapt34kvrip6xojylohhxrwsvpzdffgs5z4pbbsywnzsbdguqd.onion.ly
http://lockbitapt5x4zkjbcqmz6frdhecqqgadevyiwqxukksspnlidyvd7qd.onion.ly
http://lockbitapt6vx57t3eeqjofwgcglmutr3a35nygvokja5uuccip4ykyd.onion.ly
http://lockbitapt72iw55njgnqpymggskg5yp75ry7rirtdg4m7i42artsbqd.onion.ly
http://lockbitaptawjl6udhpd323uehekiyatj6ftcxmkwe5sezs4fqgpjpid.onion.ly
http://lockbitaptbdiajqtplcrigzgdjprwugkkut63nbvy2d5r4w2agyekqd.onion.ly
http://lockbitaptc2iq4atewz2ise62q63wfktyrl4qtwuk5qax262kgtzjqd.onion.ly
...
>>>> Very important! For those who have cyber insurance against ransomware attacks.
Insurance companies require you to keep your insurance information secret, this is to never pay the maximum amount specified in the contract or to pay nothing at all, disrupting negotiations. The insurance company will try to derail negotiations in any way they can so that they can later argue that you will be denied coverage because your insurance does not cover the ransom amount. For example your company is insured for 10 million dollars, while negotiating with your insurance agent about the ransom he will offer us the lowest possible amount, for example 100 thousand dollars, we will refuse the paltry amount and ask for example the amount of 15 million dollars, the insurance agent will never offer us the top threshold of your insurance of 10 million dollars. He will do anything to derail negotiations and refuse to pay us out completely and leave you alone with your problem. If you told us anonymously that your company was insured for $10 million and other important details regarding insurance coverage, we
>>>>> If you do not pay the ransom, we will attack your company again in the future.
Once the malware has de-XOR’d all its strings, it invokes a method named go
. This parses command-line options (updating global variables if relevant), and performs various other initializations, such as invoking a function named sodium_init
(likely to initialize the commonly used Sodium crypto library). Interestingly, the malware invokes a function named get_password
to read from stdin
…it checks against the value of test
000000010000a618 bl imp___stubs__strcmp (lldb) x/s $x0 0x16fdfeb10: "hunter2" (lldb) x/s $x1 0x10005a0d2: "test
At this point, armed with an decent understanding of the malware (yah, its ransomware) plus understanding of command-line options (that also allow us to enable logging), coupled with the fact that it’s a Sunday (aka the day of rest, not reversing malware) I decided to switch to passive dynamic analysis. Also, maybe you’re tired of reading arm64
!? 😅
My goal was now to trigger the malware to encrypt (ransom) files, while passively observing this in action.
On my dedicated analysis machine, I first created a directory for it to encrypt (~/Downloads/lock_me_up
) which I filled with files to encrypt (for some reason, I thought it was be funny to put other malware samples in there for the ransomware to encrypt).
Then I kicked off a file monitor, filtering on the locker_Apple_M1_64
process:
# FileMonitor.app/Contents/MacOS/FileMonitor -pretty -json -filter locker_Apple_M1_64 ...
Next, I ran the malware with the following command line:
-f
: full log
-p pass
: password-i ~/Downloads/lock_me_up
: directory to encrypt / ransomFirst, the file monitoring detected the ransomware opening its log file (tmp/locklog
). We’ll take a peek at the log file’s contents shortly.
# FileMonitor.app/Contents/MacOS/FileMonitor -pretty -json -filter locker_Apple_M1_64 ... { "event" : "ES_EVENT_TYPE_NOTIFY_OPEN", "file" : { "destination" : "/private/tmp/locklog", "process" : { ... "pid" : 8231 "name" : "locker_Apple_M1_64", "path" : "/Users/user/Downloads/locker_Apple_M1_64", ... } } }
Then, we can see the malware accessing (opening) files in the specified directory, to encrypt them, and renaming the encrypted files with the .lockbit
extension:
# FileMonitor.app/Contents/MacOS/FileMonitor -pretty -json -filter locker_Apple_M1_64 ... { "event" : "ES_EVENT_TYPE_NOTIFY_OPEN", "file" : { "destination" : "/Users/user/Downloads/lock_me_up/DazzleSpy.zip", "process" : { ... "pid" : 8231 "name" : "locker_Apple_M1_64", "path" : "/Users/user/Downloads/locker_Apple_M1_64", ... } } }, { "event" : "ES_EVENT_TYPE_NOTIFY_RENAME", "file" : { "destination" : "/Users/user/Downloads/lock_me_up/DazzleSpy.zip.lockbit", "process" : { ... "pid" : 8231 "name" : "locker_Apple_M1_64", "path" : "/Users/user/Downloads/locker_Apple_M1_64", ... } } }
Finally, the ransomware creates a file named "!!!-Restore-My-Files-!!!"
which is ransom note with the decryption instructions:
# FileMonitor.app/Contents/MacOS/FileMonitor -pretty -json -filter locker_Apple_M1_64 ... { "event" : "ES_EVENT_TYPE_NOTIFY_CREATE", "file" : { "destination" : "/Users/user/Downloads/lock_me_up/!!!-Restore-My-Files-!!!", "process" : { ... "pid" : 8231 "name" : "locker_Apple_M1_64", "path" : "/Users/user/Downloads/locker_Apple_M1_64", ... } } }
Let’s take a peek at the log (/tmp/locker.log
), which show us details of the ransomware’s actions:
[19:16:45][74073472l][+] Launch parameters: ./locker_Apple_M1_64 -i '/Users/user/Downloads/lock_me_up' -m 16 -w 0 -b 0 -r 0 -l 1 -n 0 -d 1 -e '' -s 10 -p test -o 0 -t 0 -f 1 -a 0 -z 0 -y 0
~~~~~~~~~~~~~~~Hardware~~~~~~~~~~~~~~~~~~
[19:32:07][4329948544][+] Add directory to encrypt: /Users/user/Downloads/lock_me_up
[19:32:07][6140964864][+] Start encrypting file /Users/user/Downloads/lock_me_up/DazzleSpy.zip
[19:32:07][6140964864][+] Start encrypting file /Users/user/Downloads/lock_me_up/DazzleSpy.zip spot 0 from 1. Original checksum 2846984875
...
[19:32:07][6140964864][+] End file /Users/user/Downloads/lock_me_up/DazzleSpy.zip size 223464 time 1672883981 is encrypted. Checksum after encryption 3269819564
...
…easy enough to see it is, as expected, encrypting the files in the specified directory.
At this point, we’ve performed a fairly comprehensive analysis of the malware, and have confirmed it is (as wholly expected) ransomware. And, being able to trigger its ransomware logic is helpful to testing detection tools (discussed next).
Of course it goes without saying, having your files ransomed sucks! But good news, in this case the average macOS user is unlikely to be impacted by this LockBit macOS sample. Still the fact that a large ransomware gang has apparently set its sights on macOS, should give us pause for concern and also catalyze conversions about detecting and preventing this (and future) samples in the first place!
First, Apple has been fairly proactive about mitigating ransomware attacks on macOS (and maybe this is why we’ve yet seen a major ransomware outbreak on macOS). So, kudos to Cupertino. Specifically Apple has implemented SIP (and now read-only system volumes) to protect OS-level files. This means even if ransomware finds its way onto a macOS system it won’t (easily) be able to mess with core OS files. Apple has also added (TCC) protections to user files founds in (now) protected directories such as ~/Desktop
, ~/Documents
, etc. etc. This means, that without an exploit or explicit user-approval users files will remain protected.
Still an additional layer or detection/protection may be warranted, especially as we’ve all probably inadvertently clicked “Allow” on access prompts, while even Apple has been known to notarize malware.
If we stop to think specifically about ransomware, in theory, it should be trivial to detect (at least in most cases). Why? Simply put, ransomware’s actions provide us with a powerful detection heuristic.
In April 2016 (yes, wayyyy back then!) I posted a blog titled, “Towards Generic Ransomware Detection”. In this post, I mused,
“If we can monitor file I/O events and detect the rapid creation of encrypted files by untrusted processes, then ransomware may be generically detected” -(a younger) Patrick Wardle
To back this up, I released a free (and now open-source) tool called “RansomWhere?” that implemented this heuristic-based approach. Specifically it monitors file I/O events and for newly created files asks:
If these are all true, “RansomWhere?” will suspend the process as its likely ransomware and alert the user and handle the response (resume/terminate).
Most notably, “RansomWhere?” is slightly reactive, meaning several files maybe be encrypted (and thus ransomed) before the tool detects and blocks the ransomware.
And though “RansomWhere?” is a bit dated, it appears to be able to generically detect this LockBit sample …even though it had no a priori knowledge of this malware:
Today we dove into a macOS ransomware sample created by the infamous LockBit ransomware gang. And while this may be the first time a large ransomware group created ransomware capable of running on macOS, it worth nothing that this sample is far from ready for prime time. From it’s lack of a valid code-signing signature to its ignorance of TCC and other macOS file-system protections as it stands it poses no threat to macOS users.
Moreover, the variant is rather buggy …containing flaws such as buffer overflows that will cause it to prematurely exit, when run on macOS:
The likely explanation to all this, is that the specimen we looked at today is test (or beta):
“Cisco Talos researcher Azim Khodjibaev told BleepingComputer that based on their research, the encryptors were meant as a test and were never intended for deployment in live cyberattacks.” https://t.co/2fNWA6CH58
— Azim Khodjibaev (@AShukuhi) April 16, 2023
“Cisco Talos researcher Azim Khodjibaev told BleepingComputer that based on their research, the encryptors were meant as a test and were never intended for deployment in live cyberattacks.”
Still, as we stated earlier, the fact that a large ransomware gang (LockBit) has apparently set its sights on macOS, should give us all pause for concern. And, if nothing else, make sure we’re adequately prepared for future attacks that likely will be more polished and thus pose a greater risk …especially as (as noted in an excellent BleepingComputer writeup LockBit is actively developing this ransomware:
In response to questions from BleepingComputer, the public-facing representative of LockBit, known as LockBitSupp, said that the Mac encryptor is “actively being developed.” -BleepingComputer
You're in luck, as I've written a book on this topic! It's 100% free online while all royalties from sale of the printed version donated to the Objective-See Foundation.
|
|
Or, come attend our macOS security conference, "Objective by the Sea" v6.0 in sunny Spain! ...where I'm teaching a class on Mac Malware Detection & Analysis
|