Patrick Wardle Profile picture
Mar 30 33 tweets 17 min read Twitter logo Read on Twitter
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

Mar 29
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 on Twitter!

:(