Patrick Wardle Profile picture
Mar 30, 2023 โ€ข 33 tweets โ€ข 17 min read โ€ข Read on X
RE: The 3CX VOIP supply chain attack, vendors have stated that macOS was also targeted - but I couldn't find any specific technical details (yet) ๐ŸŽ๐Ÿ›โ˜ ๏ธ

One vendor stated, "we cannot confirm that the Mac installer is similarly trojanized"

...let's dive in! 1/n ๐Ÿงต
We'll start with 3CXDesktopApp-18.12.416.dmg
(SHA 1: 3DC840D32CE86CEBF657B17CEF62814646BA8E98)

It contains a *notarized* app ("3CX Desktop App.app") ...meaning Apple checked it for malware "and none was detected" ๐Ÿ˜œโ˜ ๏ธ 2/n
This app is massive - 381mb ๐Ÿคฏ
...let's focus on libffmpeg.dylib
found in the App's /Contents/Frameworks/Electron\ Framework.framework/Versions/A/Libraries directory

(SHA 1: 769383fc65d1386dd141c960c9970114547da0c2)

It was submitted to VT today:
virustotal.com/gui/file/a64faโ€ฆ 3/n
It's a Mach-O universal binary w/ 2 architectures: x86_64 & arm64

At the start of (only?) the Intel version, a thread is spawned via a function called "run_avcodec"

This kicks off a (thread) function at 0x48430
...this is where things get shady ๐Ÿ‘€ 4/n
Shady how?

...a simple triage shows xor loops, timing checks, dynamically resolved APIs, and string obfuscations ๐Ÿ‘€

Shady ya?
...and means static analysis is going to be painful, and thus not recommended! 5/n
So, let's debug it! ๐Ÿ”ฌ

Debugging a dylib is a bit tricky - so I wrote a simply loader that will dlopen it.

% lldb dlopen libffmpeg.dylib

We can then run the loader in a debugger and set a breakpoint the dlopen function ...which breaks when the libffmpeg.dylib is loaded 6/n
We can then just instruct the debugger to jump to and begin executing the shady thread function at 0x48430 by changing the $pc register.

(lldb) reg write $pc 0x100048430

Now we can start stepping through the code to coerce it to reveal its secrets ๐Ÿค— 7/n
First, it de-xors the following path: ~/Library/Application Support/3CX Desktop App/.session-lock

It then attempts to open this file. If it does not exist it bails (so you'll have to create it to keep debugging). 8/n
It then queries the host to get the OS version, computer name, etc, etc.

It appears to encrypt then write out this info another file in the same 3CX Desktop App directory, named ".main_storage": 9/n
After various anti-debugging logic (e.g. timing checks) it builds a URL to query. We can easily dump this in the debugger: https[://]pbxsources[.]com/queue

This URL is mentioned as an IOC by @Sophos, who performed analysis on the Windows version

news.sophos.com/en-us/2023/03/โ€ฆ 10/n
After setting a static user-agent and adding host info, it connects out ๐Ÿ“ก

This may trigger an firewall alert (initially on the DNS resolution).

Note: alert will originate from the program hosting the malicious dylib (e.g. loader or "3CX Desktop App.app" ) 11/n
Unfortunately the URL (pbxsources[.]com) is now offline ...so the malware doesn't get the HTTP 200 OK it wants, and thus goes off to snooze ๐Ÿฅฒ 12/n
Continued static analysis appears to show the malware expects to download a 2nd-stage payload.

This appears to be saved as "UpdateAgent" (in the Application Support/3CX Desktop App/ directory).

I don't have access to this binary, so what it does is a mystery!๐Ÿคท๐Ÿฝโ€โ™‚๏ธ 13/n
For IoCs, I don't know what "3CX Desktop App.app" normally does, but the malicious .dylib interacts w/ the following files (~/Library/Application Support/3CX Desktop App/):

UpdateAgent
.session-lock
.main_storage

C&C URLs appear to be same as Window variant 14/n
I've just added a sample of the malicious .dylib to @objective_see's public macOS malware repo on GitHub: github.com/objective-see/โ€ฆ (password: infect3d) #SharingIsCaring

...it's still notarized by @Apple and has 0 detections on VT ๐Ÿคฆ๐Ÿปโ€โ™‚๏ธโ˜ ๏ธ 15/n
Hooray, @Apple finally appears to be atoning for their sins of originally approving (notarizing) the application ๐Ÿ™Œ๐Ÿฝ 16/n
Now there's (a more detailed) blog post on this all!

Just posted: "Ironing out (the macOS details) of a Smooth Operator"

objective-see.org/blog/blog_0x73โ€ฆ
Interested in learning more about Mac malware & analysis? ๐Ÿ‘พ๐ŸŽ๐Ÿ”ฌ

You're in luck! I've written a whole book on this topic: taomm.org

It's 100% free online, while all royalties from sales of the printed version are donated to the Objective-See Foundation ๐Ÿ˜‡
Better yet, I want to invite you to our Mac Security conference, "Objective by the Sea" (#OBTS) which will be held in Spain this October: objectivebythesea.org/v6/index.html

There, I'm also teaching a 3-day training on Mac malware detection & analysis: objectivebythesea.org/v6/taomm.html

Come join! ๐Ÿค—
Let's keep this thread on the #3CX / #3CXpocalypse supply-chain attack going! ๐Ÿค—

Today let's talk about the 2nd-stage (macOS) payload named "UpdateAgent"

Recall this is downloaded & executed (via popen) by the malicious libffmpeg.dylib:
Using the file command we can see the "UpdateAgent" binary is an x86_64 (Intel) Mach-O.

Via codesign we see though "signed" its signature is adhoc (and thus not notarized):
Also from UpdateAgent's code signing information, its identifier: "payload2-55554944839216049d683075bc3f5a8628778bb8"

Other Lazarus group (๐Ÿ‡ฐ๐Ÿ‡ต) payloads are signed adhoc and use a similar identifier scheme ๐Ÿง

For example compare UpdateAgent & another ๐Ÿ‡ฐ๐Ÿ‡ต payload, AppleJuice.C ๐Ÿ‘€
In terms of hashes, this UpdateAgent's SHA-1 is 9E9A5F8D86356796162CEE881C843CDE9EAEDFB3
Running the strings command (with the "-" option which instructs it to scan the whole file), we find strings that appear to be related to:

โ–ซ๏ธConfig files
โ–ซ๏ธConfig parameters
โ–ซ๏ธAttacker server (sbmsa[.]wiki)
โ–ซ๏ธMethod names of networking APIs
Enough triage ๐Ÿ˜… Off to a disassembler/debugger!

First, we find some (basic) anti-analysis logic. The malware forks (making debugging a bit more difficult) and then self-deletes via unlink()

We can observe the self-deletion in a file monitor (event: ES_EVENT_TYPE_NOTIFY_UNLINK)
The rest of UpdateAgent's core logic is also found in its main()

Thanks to non-stripped symbols we see it:

โ–ซ๏ธ Calls "parse_json_config"
โ–ซ๏ธ Calls "read_config"
โ–ซ๏ธ Calls "enc_text"
โ–ซ๏ธ Builds a string ("3cx_auth_id=..." + ?)
โ–ซ๏ธ Calls "send_post" to sbmsa[.]wiki

...and that's it!
First up, the "parse_json_config" function.

This attempts to open a file, config.json (found in ~/Library/Application Support/3CX Desktop App).

It then extracts values from the keys: "url" & "AccountName":

(I made a fake config.json file, so the malware would keep executing).
With the "url" & "AccountName" extracted from the config.json, the malware then calls a function named "read_config"

This opens/reads in the contents of the .main_storage file (recall that created by libffmpeg.dylib, and contains a UUID) and de-XORs it with the key 0x7a
Next it concats/encrypts the "url" & "AccountName" values via a function named "enc_text". Then combines this + the UUID (from .main_storage) w/ the following format:

3cx_auth_id=UUID;3cx_auth_token_content=encryted url;account name;__tutma=true"

Let's dump this in a debugger:
On to the "send_post" function. This takes as its parameters the URI "https://sbmsa[.]wiki/blog/_insert" and the "3cx_auth_id=..." string:
First, it configures an url request with a hardcoded user-agent string ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...") and stores the "3cx_auth_id=..." string in the "Cookie" HTTP header.

Then, it makes the request to https://sbmsa[.]wiki/blog/_insert
If you're running a network tool such as DNSMonitor (objective-see.org/products/utiliโ€ฆ) you'll be able to see capture/view this request.

...and associate it with the pid/process signing id of the malware:
Once UpdateAgent has made the request ...it simply exits ๐Ÿง

Maybe this sample is incomplete or is a basic "placeholder" binary that could be updated/swapped out at any time for specific targets of interest. (Supply-chain attacks provide a lot of "non-relevant" targets). ๐Ÿค”

โ€ข โ€ข โ€ข

Missing some Tweet in this thread? You can try to force a refresh
ใ€€

Keep Current with Patrick Wardle

Patrick Wardle Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @patrickwardle

Apr 16, 2023
New Blog Post:
"The LockBit ransomware (kinda) comes for macOS": objective-see.org/blog/blog_0x75โ€ฆ ๐ŸŽ๐Ÿ”

Includes full technical analysis of LockBit's macOS arm64 variant ("locker_Apple_M1_64") + sample for download + heuristic methods of detection ๐Ÿ”ฅ

H/T @malwrhunterteam @vxunderground
First, (can't stress this enough), this variant though *compiled* for macOS is not specifically designed for macOS.

It's buggy (crashes), has an invalid signature, nor takes into account as of macOS's file-system security mechanisms.

So, impact to macOS users (for now): 0 Image
Still as noted by others, the fact that a large ransomware gang (LockBit) has apparently set its sights on macOS, should give us all pause for concern.

So, wise to dig into this (test?) sample & gain a throughout understanding of its capabilities and approaches ๐Ÿ‘พ๐Ÿ”ฌ๐Ÿ‘ฉ๐Ÿผโ€๐Ÿซ
Read 5 tweets
Mar 29, 2023
Ever wondered what it's like writing security tools for macOS? ๐Ÿค”

As Apple provides no official way to detect what app is using the webcam/mic, OverSight simply monitored the system log.

This was (independently) reported to Apple, who decided to assign it a CVE/patch it ๐Ÿฅฒ๐Ÿคฆ๐Ÿปโ€โ™‚๏ธ
Unfortunately this means OverSight is now broken on macOS 13.3

Apple still doesn't provide a method for security tools to determine what app is accessing the mic/camera, even after years of requesting (begging) for this capability ๐Ÿ˜ญ
There are other log msgs that can still be used (even on macOS 13.3+) to determine what App is using the mic/camera

...but I'm reluctant to update OverSight if they will just be reported and given CVEs ๐Ÿ˜‘
Read 5 tweets
Oct 10, 2022
I've just posted slides from my #OBTS v5 talk: "Making oRAT, Go" ๐ŸŽ๐Ÿ€

speakerdeck.com/patrickwardle/โ€ฆ

After creating a custom C&C server, we can uncover the malwareโ€™s full capabilities - simply by asking (tasking) the right questions! ๐Ÿคญ
1๏ธโƒฃ First, we must understand how the malware figures out how to find its C&C server - so we can coerce it to talk to our C&C instead!

As this (encrypted) info is embedded within the malware, we can write a simple decryptor/encryptor to (re)configure the malware ๐Ÿ‘พ๐Ÿ”“โœ๐Ÿผ๐Ÿ”’ โ†’ ๐Ÿ–ฅโœ…
2๏ธโƒฃ Second, we need to understand its protocol, so we can task the malware to reveal its capabilities.

A brief triage of the malware's binary shows us it sets up a local server and registers various "routes" - taskable via requests from a remote C&C server.
Read 7 tweets
Sep 21, 2021
โš ๏ธ Latest macOS 0day (credit: Park Minchan)
...bypasses File Quarantine, Gatekeeper, etc.

Advisory:
๐Ÿ“ "macOS Finder RCE" ssd-disclosure.com/ssd-advisory-mโ€ฆ

๐Ÿ˜… Confirmed Big Sur & Monterey are vulnerable

๐Ÿงฎ I've posted Park's PoC (pops Calc) if you'd like to play: objective-see.com/downloads/PoCsโ€ฆ
The PoC once downloaded still has to be manually executed by the user.

macOS should, via File Quarantine/Gatekeeper, alert/warn/block as this is an 'executable' item from the Internet.

Apple attempted to patch (blocking file:// prefix), but File:// or fIle:// still work ๐Ÿคฃ๐Ÿคฃ๐Ÿคฃ Image
โ„น๏ธ The initial patch, will as noted, block items that attempt to abuse the "file://" prefix: (but not "File://" etc.): Image
Read 4 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us!

:(