Inside Brazil’s Financial Malware Ecosystem: Deep Dive into the Astaroth
This post is the second part of a three-part series of analyses concerning the ecosystem of Brazilian banking malware. We began with a sample from a recent Eternidade Stealer campaign, examining its infection chain all the way to the banking malware deployed on the victim’s device. Now, we will continue using the same analytical methodology, this time focusing on a sample from a recent Astaroth campaign, collected by Bradley Duncan and featured on his website, malware-analysis-traffic.net (thank you so much man…).
Through this analysis, you may have noticed a recurring pattern in the structure of the infection chain, as well as in the technologies employed, such as the use of AutoIT scripts and the choice of Delphi for developing the malware. Ultimately, however, you will see that, despite certain similarities, Astaroth is a far more complex piece of malware than Eternidade Stealer, particularly regarding its code obfuscation.
Threat Summary
Astaroth, also known as Guildma, is one of the most well-established families of banking trojans within the Latin American ecosystem. Developed primarily in Delphi and publicly documented since at least 2017, the malware has a history of campaigns targeting users, predominantly in Brazil, by employing social engineering, multi-stage infection chains, the abuse of legitimate Windows binaries, and evasion techniques to compromise systems and facilitate financial fraud.
Throughout 2025 and 2026, Astaroth operators has shown significant evolution in its distribution and control mechanisms. In addition to traditional email-based phishing campaigns, its operators have incorporated automated propagation components via WhatsApp Web (wich we’ll not cover in this post). These capabilities allow the malware to exploit existing trust-based relationships between contacts, thereby extending the reach of its campaigns.
Below is a summary profile of the Astaroth threat.
| Attribute | Characterization |
|---|---|
| Malware family | Astaroth |
| Alternative name | Guildma |
| MITRE ATT&CK Software ID | S0373 |
| Classification | Banking Trojan / Information Stealer / RAT |
| Publicly documented | Since at least 2017 |
| Primary targeting | Brazil |
| Target platform | Microsoft Windows |
| Main payload language | Delphi |
| Infection-chain technologies | LNK, ADS, AutoIt, Delphi, Python and JavaScript, depending on campaign |
| Primary objectives | Banking credential theft and financial fraud |
| Persistence mechanisms | Startup-folder shortcuts and other campaign-dependent mechanisms |
| C&C architecture of this campaign | Raw TCP via Pinggy relay and HTTP configuration/update channel |
| Attribution | Financially motivated cybercrime operators |
Below you can see an simplified overview of the infection chain, that we will analyze in this post.

As we can observe, the infection chain for the Astaroth campaign actually contains more layers than those we saw in the previous post regarding Eternidade Stealer. Astaroth makes interesting use of the NTFS Alternate Data Stream, loading the scrobj.dll DLL via regsvr32.exe, with the aim of remotely downloading the entire set of components necessary for the continuation of the infection chain, in the C:\Users\Public\Libraries.cache\PLAX directory.
Below, we can observe the Tactics, Techniques, and Procedures (TTPs) correlated with each phase of the Cyber Kill Chain that are persistently executed by Astaroth in its campaign analyzed in this post.
| ATT&CK ID | Technique Name | Kill Chain Phase |
|---|---|---|
| T1566.002 | Phishing: Spearphishing Link | Delivery |
| T1204.001 | User Execution: Malicious Link | Exploitation |
| T1204.002 | User Execution: Malicious File | Exploitation |
| T1059.003 | Command and Scripting Interpreter: Windows Command Shell | Exploitation |
| T1027.010 | Obfuscated Files or Information: Command Obfuscation | Exploitation |
| T1218.010 | System Binary Proxy Execution: Regsvr32 | Exploitation |
| T1059.010 | Command and Scripting Interpreter: AutoHotKey & AutoIT | Installation |
| T1564.004 | Hide Artifacts: NTFS File Attributes | Installation |
| T1027 | Obfuscated Files or Information | Installation |
| T1027.007 | Obfuscated Files or Information: Dynamic API Resolution | Installation |
| T1027.009 | Obfuscated Files or Information: Embedded Payloads | Installation |
| T1027.013 | Obfuscated Files or Information: Encrypted/Encoded File | Installation |
| T1036.008 | Masquerading: Masquerade File Type | Installation |
| T1140 | Deobfuscate/Decode Files or Information | Installation |
| T1055.012 | Process Injection: Process Hollowing | Installation |
| T1547.001 | Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder | Installation |
| T1059.001 | Command and Scripting Interpreter: PowerShell | Installation |
| T1057 | Process Discovery | Installation |
| T1518.001 | Software Discovery: Security Software Discovery | Installation |
| T1622 | Debugger Evasion | Installation |
| T1497.001 | Virtualization/Sandbox Evasion: System Checks | Installation |
| T1497.002 | Virtualization/Sandbox Evasion: User Activity Based Checks | Installation |
| T1564.003 | Hide Artifacts: Hidden Window | Installation |
| T1083 | File and Directory Discovery | Installation |
| T1012 | Query Registry | Installation |
| T1016 | System Network Configuration Discovery | Installation |
| T1106 | Native API | Installation |
| T1071.001 | Application Layer Protocol: Web Protocols | Command and Control |
| T1095 | Non-Application Layer Protocol | Command and Control |
| T1090.002 | Proxy: External Proxy | Command and Control |
| T1105 | Ingress Tool Transfer | Command and Control |
| T1082 | System Information Discovery | Actions on Objectives |
| T1614.001 | System Location Discovery: System Language Discovery | Actions on Objectives |
| T1010 | Application Window Discovery | Actions on Objectives |
| T1056.001 | Input Capture: Keylogging | Actions on Objectives |
| T1115 | Clipboard Data | Actions on Objectives |
| T1113 | Screen Capture | Actions on Objectives |
| T1059.007 | Command and Scripting Interpreter: JavaScript/JScript | Actions on Objectives |
| T1529 | System Shutdown/Reboot | Actions on Objectives |
| T1070.004 | Indicator Removal: File Deletion | Actions on Objectives |
| T1041 | Exfiltration Over C2 Channel | Actions on Objectives |
Let’s deep dive into the Astaroth infection chain!!
Analyzing the Phishing E-mail and Zip/LNK File
As is quite characteristic of Astaroth campaigns, initial access is gained through phishing emails containing malicious links. The image below shows an email received by a victim of the campaign we are analyzing in this post, it is in Brazilian Portuguese and centers on the signing of contracts via DocuSign.

When the link in this email is clicked, the traffic is redirected until it reaches the server containing the malicious ZIP file, which is then downloaded onto the victim’s device, as we can see on the image below.

Inside this ZIP file, there is a Windows shortcut that bears the same name as the ZIP file itself.

This shortcut essentially executes cmd.exe, containing an obfuscated command line, as can be seen in the image below.

In short, when the shortcut is executed, a loop is implemented that will rebuild the regsvr32.exe command, which will execute the scrobj.dll DLL in an NTFS ADS located in the file C:\Users<user>\AppData\Local\Temp\n1LUQ7.log:h6JSb, which will download it via the URL https[:]//plosancol[.]aguamammillaria[.]cfd/?1/_x. Below, we can see that the NTFS ADS h6JSb present in the n1LUQ7.log artifact is indeed the scrobj.dll DLL.

This download will place all components into the directory C:\Users\Public\Libraries.cache\PLAX\ and create a PowerShell script for persistence in the directory C:\Users<user>\AppData\Roaming\ Microsoft\Windows\Start Menu\Programs\Startup. Upon system logon, this script will execute the binary Beatz.LEDPRO.09662.8729.422.exe, using Beatz.LEDPRO.09662.8729.422.log as an argument.

Within the C:\Users\Public\Libraries.cache\PLAX\ directory, there are also several components that will be used later in the infection chain, such as metrics.mca and dump.log, as well as components related to a WhatsApp spambot.
Analyzing the AutoIT Loader
The binary Beatz.LEDPRO.09662.8729.422.exe is an AutoIT interpreter, as can be seen below.

We can reasonably assume that the artifact presented as evidence is an AutoIT script. This hypothesis is confirmed, as can be seen below.

As we can see in the excerpt shown in the image below, the AutoIT script appears more complicated than it actually is. Essentially, it concatenates data, represented in hexadecimal format as strings, into a single blob, which is then converted into binary data. With a little experience, it’s possible to see that the first 4 hexadecimal bytes of the blob are 4D 5A, that is, the magic bytes of every PE executable file for Windows systems.

With a few simple modifications to the large blob present in the AutoIT script, combined with a hex-decode transform, we have the PE artifact in our hands.

Analyzing the Delphi Loader
This binary, which the AutoIT script loads into memory, is a DLL developed in Delphi, a combination typical of Brazilian malware, as is the use of AutoIT, tasked with decoding and injecting Astaroth into a sacrificial process.

The CAPA rule matches provide a strong clue regarding the loading implementation methods, while disregarding false positives, such as matches related to the RC4 algorithm.

The final Astaroth sample is encrypted in the metrics.mca artifact, which this loader is responsible for collecting, decoding, and injecting into memory.
The first relevant action the loader takes is to search for the metrics.mca artifact located in the same directory as the other components downloaded in the previous phase of the infection chain.

To locate this artifact, a search routine is implemented, which incorporates the use of WinAPIs such as FindFirstFileW.


Upon encountering this artifact and loading it, the loader initiates a decoding routine for it, using 0x2a as a single-byte key.

The algorithm is extremely simple, essentially consisting of a loop that subtracts the byte 0x2a from each byte of the artifact.

By performing this decoding using Malcat’s transform sub feature, we obtain the next decoded stage.

The loader also implements the injection of this decoded payload into the memory of a sacrificial process. Although it attempts to hide the name of the process to be used for the injection, employing a technique known as “Stack Strings“, Binary Ninja was able to easily recover the string within the HLIL. Below we can see that this sacrificial process is RegSvcs.exe, part of the .NET framework.


Since the binary is developed in Delphi, Binary Ninja (and any other reverse engineering software) struggles to reconstruct pseudocode that is both simple and illustrative. Therefore, to make it easier to understand, I used scripting to generate the output below, which clearly illustrates the code flow of the function I’ve named ‘loader_hollow_process‘.

This function implements the Process Hollowing technique on a sacrificial process, specifically, by injecting and executing Astaroth within the context of the RegSvcs.exe process.
Astaroth Reverse Engineering
The final payload of Astaroth is also an executable developed in Delphi, following the pattern typical of the Brazilian banking malware ecosystem (AutoIT loaders paired with Delphi-based malware). It features a very broad range of targets, encompassing Brazilian banks and fintechs.
Its capabilities include credential harvesting with browser detection, monitoring of the foreground window, targeted collection of keystrokes and clipboard data, the use of exclusion lists to evade analysis, the receipt of remote commands, a user interface that simulates software updates, modification of browser settings, management of temporary files (staging), and the remote execution of JScript. The execution flow of Astaroth’s actions is outlined at a high level below.

As can be seen in the image above, there are two distinct layers of obfuscation:
- String encryption;
- Encryption of the C&C/logging configuration file.
Resolving these layers of obfuscation is crucial for the execution of Astaroth’s subsequent capabilities. Therefore, we will first examine how the strings are decrypted, and how the file containing C&C information is decrypted.
Reconstructing Astaroth’s String Decryption Routine
During the reverse engineering of Astaroth’s final payload, I identified a custom string protection mechanism designed to conceal information used throughout the malware’s execution, including browser identifiers, banking targets, and anti-analysis artifacts.
Rather than relying on a conventional cryptographic algorithm, the analyzed sample implements multiple reversible transformations involving XOR operations, byte arithmetic, character substitution, and custom encoding.
An important characteristic of this implementation is that not every protected string follows the same decoding path. While some strings require only the primary decoding routine, others contain an additional encoded representation that must be processed before the original plaintext can be recovered.

Below, you can see a snippet where the function responsible for decrypting strings receives an encrypted blob as an argument, along with comments generated by running the decryption script for Binary Ninja (link provided at the end of the post).

Before processing its protected strings, Astaroth initializes a decoding key derived from a hardcoded encoded seed.
Interestingly, the initialization routine introduces random alphanumeric characters around this seed. Three padding distributions were observed in the analyzed code: 9+3, 6+6, and 3+9 characters, corresponding to a total of 12 padding characters.

Although this may suggest that a different key is generated during each execution, the selected prefix and suffix lengths are passed to ExtractAndDecodeEmbeddedKeySeed function (named by me.. of course).
This routine removes exactly those characters and recovers the fixed 43-character seed EMBMAMDMSLXLWMQLVMONEMRMDMMMHNHNJNKLVNCMBNI. The random padding therefore has no influence on the effective decoder key. After derivation, the resulting Delphi UnicodeString is cached in global variable called (by me) real_key.

The recovered seed is not Base64. It consists of one salt character followed by 21 encoded character pairs. The initial E produces a salt value of 4. For each pair, DecodeSaltedBase25Pairs function computes:
salt = seed[0] - 'A'
intermediate =
25 × (first - 'A') + (second - 'A') - salt - 100
Below, we can observe the implementation within the Astaroth code.

This operation produces 21 intermediate characters. Their CP1252 byte representation is:
c5 c4 c7 d6 c2 c1 d4 c0 d2 e1 d5
c7 d0 cb e4 e6 e7 c0 df c5 e5
TransformKeyBytesByLength function then transforms each intermediate byte using:
key_byte = (input_length + 2 - intermediate_byte) mod 256
Because the intermediate sequence contains 21 bytes, the effective operation for this sample is:
key_byte = (23 - intermediate_byte) mod 256

The resulting 21-byte decoder key is:
RSPAUVCWE6BPGL310W8R2
The following Python snippet, executed in the Binary Ninja Python Console, reproduces both seed-decoding stages and recovers the effective key.

After reconstructing the key, the malware processes its protected strings through a sequence of reversible transformations. First, the hexadecimal representation of the encrypted data is converted into bytes. The decoder then applies the reconstructed key cyclically, combining XOR operations with a subtraction involving adjacent ciphertext bytes.
The resulting byte sequence is reversed and subjected to further arithmetic transformations, followed by a salted, base-25-like character-pair decoding stage. Finally, the decoded sequence is reversed again and transformed using an arithmetic constant derived from the key length.
At this point, the routine produces the first-layer output. However, this output does not necessarily correspond to the final plaintext.
Some protected strings undergo an additional encoding stage. In these cases, the output of the primary decoder contains an encoded payload surrounded by wrapper characters. The nested decoder reverses this intermediate string, removes the wrapper, and interprets the remaining characters as pairs representing positions in a custom alphabet.
Below we can see the macro function that orquestrate this decode routine. The routine hex-decodes the encoded UnicodeString, applies the chained XOR/delta transformation, performs two reversals and two byte-arithmetic stages, and decodes the salted radix-25 representation as I explain earlier.

Parses a protected UTF-16 hexadecimal string into ciphertext bytes. The first byte initializes the chaining state. Each subsequent byte is XORed with the cyclic decoder key, subtracted from the previous ciphertext byte using a one-based modulo-255 operation, and appended to the output as a Unicode character.

The decoder uses a chained one-based modulo-255 subtraction. When the XORed byte is not greater than the previous ciphertext byte, it adds 255 before subtracting. This differs from conventional byte subtraction modulo 256.

By understanding the string decryption algorithm, we can test implementations within the Binary Ninja Python Console. I captured an example string and passed it to a Python implementation of this decryption routine, as we can see below.


As we can see on imagem above, the decryption occur successfully, showing the name of a debugging tool.
By understanding the string decryption algorithm, it was possible to implement a script integrated into Binary Ninja designed to identify encrypted strings, pass them through the decryption algorithm, and generate output in the console, as well as add comments to both the Disassembly and the HLIL views.
This automation substantially reduces the manual effort required to analyze functions that reference protected strings. More importantly, recovering these strings provides additional context for understanding the malware’s internal logic, including browser identification, target selection, and anti-analysis functionality.
The reconstructed algorithm and its automated implementation demonstrate how reversing a custom obfuscation mechanism can transform otherwise difficult-to-interpret code into meaningful information for further reverse engineering of this sample (the link to the code is at the end of the post.).

The extractor recovered 732 first-layer strings. Of these, 453 matched the nested format, producing 426 unique nested plaintext values.
Financial Target Selection
Astaroth does not compare the active browser context against one flat list. The main routine decrypts every token in a rule group and requires all of them to occur in the candidate string. The caller of encrypted strings to iterates the groups and returns a match when any complete group succeeds. In simplified form, the logic is:
match(candidate, rule_groups) = any(
all(token in candidate for token in group)
for group in rule_groups
)
This design permits both simple rules, such as a single domain, and context-sensitive rules composed of a domain plus a path or page fragment. The Banco do Brasil matcher at the function code snippet below, for example, builds groups containing values such as internacional.bb.com.br, bblam.bb.com.br, brasil.com, and bb.com before applying the generic matching engine to the monitored browser/window string.

The decrypted corpus contains 426 unique nested plaintext values, including at least 146 strict domain-shaped strings. After removing internal classifier tags and normalizing obvious domain fragments, the following targets were recovered.
Banks, Investment Platforms, and Financial Institutions
It was identified the following targeted platforms:
- Banco do Brasil, Caixa Econômica Federal, Banco Inter, Banestes, Banco Original, Superdigital, Grafeno, Banese, Itaú, Santander, Bradesco, Sicredi, Banrisul, and Sicoob.
- ViaInvest, Banco Master, Agibank, Cora, Cetelem, Banco Alfa, Banco Afro, Social Bank, PJBank, Banco Guanabara, Flow Banco, Will Bank, Banco do Nordeste, BRB, Banpará, NBC Bank, Banco ABC Brasil, TotalBank, NetBank, Paraná, and Banco Arbi.
- BTG Pactual, Banco BMG, Mercantil do Brasil, Banco da Amazônia, Modal, Ágora Investimentos, XP, C6 Bank, Nubank, Neon, Toro Investimentos, Clear, BS2, Banco Fibra, Pine, Safra, Genial Investimentos, Sofisa, Méliuz, and Rico.
- YetBank, WQ3, NewBank, BV, GFT Bank, BIP, CCB Brasil, MokaBank, Maybank, O Agro Bank, Banco Pan, Banco Paulista, and BK Bank.
- Unicred and Uniprime, in addition to the cooperative targets listed separately below.
Representative literal rules include caixa.gov.br, gerenciador.caixa.gov.br, loginx.caixa.gov.br, itau.com.br, santander.com.br, ib12.bradesco.com.br, ibpf.sicredi.com.br, ibpj.sicredi.com.br, banrisul.com.br, sicoob.com.br/sicoobnet, safraempresas.com.br, bancointer.com.br, and nubank.
A local path, C:\Sicoobnet, also appears in the decrypted corpus, suggesting awareness of the locally installed Sicoob environment in addition to browser-based targeting.
Credit cooperatives
- Ailos, ViaCredi, Transpocred, Acentra, Civia, Evolua, Credifoz, ViaCredi Alto Vale, Unilos, Credicomin, Crevisc, CredCrea, and Acredi.
The generic .coop.br token broadens the matching surface beyond the explicitly named cooperatives.
Payment, fintech, merchant, and business platforms
- XPAG/Idez, PayPal, Stone, Asaas, Omie, Aegro, Mercado Pago, MoneyP, Mercado Livre, Bling, Concil, Dattos, WK, Coinscrap Finance, OpenGalaxy, Procfy, and MagaluPay.
- eWally, PicPay, BanQi, Coiban, RMSS, Malga, Celcoin, IOPay, Appmax, Efí, Bazk, InovaPay, Stripe, Click2Pay, Ebanx, PagBrasil, Iugu, PayBrokers, and BraPay.
- Shopify, ShopeePay, Shopee, Fstatui, and WBA/IWBA Recebíveis.
Additional broad fragments such as banking, banco., .bank, .banco, and pay. allow to recognize services not represented by a dedicated brand rule. Internal values such as xBB, xCEF, xST, and xMPAGO are classifier tags assigned after a match, they are not domains or network indicators.
Cryptocurrency services
- OKX, Polygon, NovaDAX, CEX.IO, Paxful, Bitstamp, Bitpanda, Bitfinex, Bitfy, eToro, Bybit, Bitso, Huobi, Blockchain.com, NiceHash, OKCoin, Paybis, Luno, Trust Wallet, and Gemini.
- PooCoin, CoinMarketCap, Uniswap, BscScan, Etherscan, Binance, BitcoinTrade, PancakeSwap, MetaMask, Foxbit, LocalBitcoins, Mercado Bitcoin, and Coinbase.
The MetaMask rules are particularly revealing. One group combines metamask.io, home.html, import, and phrase, another combines metamask.io, home.html, and -phrase. Because all tokens in a group must match, these rules specifically identify seed-phrase import contexts rather than the MetaMask domain in general.
Gambling and gaming services
- KTO, Eskybet, PG Soft, Blaze, Onebra, Bet4, Jonbet, Superbet, and CassinoPix.
These strings are evidence of the pages and applications the malware recognizes. They do not demonstrate outbound connections to the named organizations.
Context-aware keylogging and clipboard theft
The credential-capture path is custom code rather than a capability inferred from imports. Astaroth installs a global low-level keyboard hook:

Before collecting a key, the callback verifies that GetForegroundWindow still corresponds to the window selected by the controller. It then obtains the current keyboard state with GetKeyboardState, uses the target thread’s keyboard layout, translates the virtual key through ToAscii, and appends the result to the capture buffer.

The decrypted strings show how non-printing keys are represented in the log:
[Backspace]
[END]
[HOME]
[Delete]
[UP]
[RIGHT]
[DOWN]
[Enter]
[Numlock]
[LEFT]
[Control+
The marker === is written when the foreground-window title changes, while xXxXx is used when the capture session is initialized. As a result, the captured input is associated with the page or application in which it was entered rather than being stored as an undifferentiated keystroke stream.
Clipboard theft is part of the same callback. When Control is held and the virtual key is V, the code calls ReadUnicodeClipboardText function, named by me.

That function opens the clipboard, requests CF_UNICODETEXT, locks the returned global-memory object, and copies the text. Values shorter than 999 characters are inserted into the same capture stream with delimiters. This lets Astaroth collect pasted credentials, account identifiers, cryptocurrency addresses, and other values that may never be typed one character at a time.
The input-blocking hooks must be described separately from the keylogger. Remote commands 0x52 and 0x53 install and remove a second pair of hooks: the keyboard callback function suppresses Windows keys and selected Alt/Control shortcuts, while the mouse callback function blocks WM_MOUSEWHEEL. These hooks constrain the victim’s interaction; they are not the primary credential-capture routine.
Banking-software and browser interference
Remote command 0x3D reaches the process-control routine. The decrypted process list is exact:
AplicativoBradesco.exe
NavegadorExclusivoBradesco.exe
java.exe
iexplore.exe
opera.exe
MicrosoftEdge.exe
msedge.exe
firefox.exe
chrome.exe
Below we can see on the code.
The malware supports two termination paths for every entry. One constructs taskkill /f /im and passes it to the common WinExec wrapper.



The other resolves the process ID by image name and calls OpenProcess followed by TerminateProcess. A check for the decrypted value AVAST Software influences which path is selected. This is stronger evidence than the presence of process-name strings alone: the names are passed directly into confirmed termination functions.


The core also checks for the names Topaz OFD and AppBrad.

These checks indicate awareness of banking/security software associated with the Bradesco environment, although the static code should be described as an environment check rather than proof that either product is disabled.
Command 0x3B reaches and modifies browser configuration. For Chrome and Edge, the malware opens each browser’s Local State file and replaces the enabled hardware-acceleration setting with:
"hardware_acceleration_mode":{"enabled":false},"hardware_acceleration_mode_previous":false


For Firefox, it creates or updates user.js in profile directories with:
user_pref("layers.acceleration.disabled", true);

Afterwards, a loop that modifies the configuration file is executed via the same WinExec wrapper.

The confirmed behavior is the disabling of hardware acceleration in Chrome, Edge, and Firefox. Making overlays or browser manipulation more reliable is a plausible purpose, but remains an inference.
Fake-update distraction
The decrypted UI strings expose a Portuguese Windows Update screen:
Trabalhando em Atualizações
Instalando Atualizações
Configurando Atualizações
Concluídas.
Não desligue o computador.
Timer-driven code rotates the displayed phase and updates a progress value. This provides a full-screen distraction while other operator-controlled actions take place. The fake-update implementation is confirmed; the exact action concealed during any individual activation depends on the command sequence received from the controller.
Remote command execution and host control
The interactive dispatcher function parses the first command value as an integer, masks it with 0x7F, and selects a handler from a large switch table. The batch parser splits tilde-delimited records, and forwards parsed arrays to the dispatcher. More than 70 numeric identifiers are accepted, only handlers whose behavior is supported by code review are named below.
| Command | Confirmed or strongly supported behavior |
|---|---|
| 0x11 | Responsive delay while continuing to pump messages |
| 0x17 | Build and send the victim/controller profile |
| 0x1D | Force a system restart |
| 0x1E | Force a system shutdown |
| 0x1F | Execute DisplaySwitch.exe 1 |
| 0x20 | Parse and apply a multi-field runtime configuration |
| 0x22 / 0x23 | Perform a file/stream operation on a generated or directly supplied path |
| 0x24 | Run a shell-link and power-control sequence |
| 0x38 | Launch the Chrome/Google workflow |
| 0x3B | Disable hardware acceleration in Chrome, Edge, and Firefox |
| 0x3D | Terminate the banking applications and browser processes listed above |
| 0x40 / 0x41 | Base64-decode supplied content and write it to a generated or directly supplied path |
| 0x49 | Close a stored handle |
| 0x52 / 0x53 | Install or remove the input-blocking keyboard and mouse hooks |
| 0x61 / 0x62 | Create a date-triggered shutdown link using a supplied date or the current date |
| 0x65-0x70 | Create, delete, or toggle selected staged module files |
| 0x71 | Delete the principal staging artifacts |
| 0x72 | Terminate the malware process with ExitProcess(0) |
| 0x75 | Clear a controller-state flag |
The Chrome workflow constructs a path ending in Google\Chrome\Application\chrome.exe, appends http[:]//www.google[.]com, and can execute the result. This is a browser-launch or connectivity path, not a C2 URL.
The common execution sink converts a Delphi Unicode string to an ANSI command line and calls WinExec. The decrypted command strings show support for hidden PowerShell and minimized cmd.exe execution:
WindowsPowerShell\v1.0\powershell.exe
-windowstyle hidden -Command
cmd.exe
/c "start /MIN
The Astaroth prepares WinInittemp.log or WinInittemp.out, initializes COM, and creates a .lnk under the current user’s Startup folder. The function also removes older numbered link candidates. The most accurate description is therefore command execution through a Startup-folder shell link with cleanup, static analysis alone does not establish how long each linkpersists.
Immediate host-control commands are implemented with both PowerShell and command-shell variants:
WindowsPowerShell\v1.0\powershell.exe Restart-Computer -Force
cmd /V /C shutdown -r -t 2 -f
WindowsPowerShell\v1.0\powershell.exe stop-computer -force
cmd /V /C shutdown -s -t 2 -f
Commands 0x61 and 0x62 create a separate Startup link whose command compares the current date with a selected date and executes shutdown /s /t 0 on a match. The associated decrypted artifact name is WinInittempUpdates.log.
The HTTP configuration channel provides an additional execution path that is separate from the numeric socket dispatcher. A response field named upjs is isolated and passed to ScriptControl, the malware selects the JScript language, adds the received code, and invokes the selected function through COM dispatch. A party controlling a selected update endpoint or its response can therefore execute JScript inside on it’s own process.
Decrypted staging and cleanup artifacts
The following operational names are assembled under the malware’s staging directory and are relevant for host-based detection:
r.log iotec.log intec.log datatemp.log at.log metrics.mca <generated>.exe <generated>.log prev.log digs.log ax.mod ay.mod aw.mod dump.log temfic.mca dbl.log re.log retrics.mca inc.inf db\ WinInittemp.log WinInittemp.out WinInittempUpdates.log
Command 0x71 calls the cleanup routine, which initializes the principal paths and passes them to the deletion helper. In this sample, dump.log is not an activity log: it is the encrypted runtime network configuration and can also be replaced by a server-supplied response.
Anti-analysis and environment detection
The process blacklist recovered from the first string layer contains:
Sysmon.exe splunkd.exe splunk-winevtlog x32dbg.exe x64dbg.exe WinDbg.exe Wireshark.exe OLLYDB.exe DbgX.Shell SbieSvc.exe QEMU-GA.exe VBoxService.exe ProcessHacker.exe SystemInformer.exe Fiddler.exe Charles.exe CrowdStrike.exe SentinelAgent.exe Procmon.exe dnSpy.exe
A second blacklist initialized, contains tool names, window titles, and window-class fragments:
OllyDBG
ImmunityDebugger
WinDbg
IDA Pro
Process Explorer
Process Monitor
Regmon
Filemon
TCPView - Sysinternal
Autoruns - Sysinternals
Wireshark
Dumpcap
Process Hacker
SysAnalyzer
HookExplorer
SysInspector
ImportREC
PETools
LordPE
JoeBox
Sandbox
x32dbg
dbgviewClass
DbgX.Shell.exe
WinObj - Sysinternals
Sysinternal
Qt5152QWindowIcon
System Informer
These lists cover debuggers, packet analyzers, Sysinternals utilities, sandboxes and virtual machines, EDR/monitoring products, and reverse-engineering tools. They should be presented as anti-analysis and environment-detection configuration, not as processes that command 0x3D terminates.The latter is limited to the nine Bradesco, Java, and browser images shown earlier.
External Configuration and Command-and-Control
The apparent absence of a C&C address from Astaroth’s protected-string corpus is intentional. The live network configuration is externalized in dump.log, a 21,256-byte file staged beside the malware core. Despite its name, the file is not an execution log. It is an obfuscated bootstrap configuration used to initialize two related communication planes:
- A raw TCP channel for victim registration and interactive numeric commands;
- An HTTP channel for configuration rotation, update delivery, and optional JScript execution.
Below we can see the macro routine of the dump.log decoding.

After the outer Base64 layer, the first character encodes a salt. The decoder removes it and consumes the remaining text two characters at a time.

The disassembly above implements a similar process to the one we saw earlier in string decryption; however, in the context of decoding the dump.log file, they only share a similar transformation of radix-25 pairs, but use distinct algorithms, constants, and routines.
salt = ord(input[0]) - ord('A')
input = input[1:]
for each pair (c1, c2):
value = ((ord(c1) - ord('A')) * 25
+ (ord(c2) - ord('A'))
- salt
- 0x3F2)
output += wchar(value)
The multiplication by 25 is visible as two consecutive lea instructions:
lea edx, [edx+edx*4] ; digit * 5
lea edx, [edx+edx*4] ; digit * 25
The output is a newline-separated stream of records. Each record has a plaintext key and a Base64-encoded value:
ips5=<Base64 value>
dt=<Base64 value>
ips1=<Base64 value>
ips=<Base64 value>
out=<Base64 value>
ips4=<Base64 value>
ips0=<Base64 value>
tp=<Base64 value>
ips3=<Base64 value>
ips2=<Base64 value>
This gives dump.log three distinct layers:
- Base64 over the complete file;
- the salt-prefixed radix-25 pair transform;
- Base64 over each individual configuration value.
Below we can see the execution of a script to decode the file

The code of this script, is on final of this post.
Recovered campaign configuration
| Key | Entries | Decoded value | Use and confidence |
|---|---|---|---|
| ips | 50 | omzagdmspc.a.pinggy[.]link:21601 repeated 50 times | Primary raw TCP list; selection and connection path confirmed in code and the endpoint observed in the matching PCAP |
| ips0–ips5 | 30 per key | 1.tcp.sa.ngrok[.]io:21131 repeated 30 times in each list | Additional or fallback-like lists; present in configuration, but their complete selection policy and use were not established |
| out | 2 | hxxps://bit[.]ly/4zzRb4P, hxxps://cutt[.]ly/cygeRswH | HTTP configuration/update candidates; configured but not observed in the available PCAP |
| dt | 1 | 40000005 | Configuration scalar; exact timing, date, version, or sequence semantics remain unresolved |
| tp | 1 | 0 | Mode/transport scalar; exact semantics remain unresolved |
The repetitions appear to provide redundant selection slots rather than dozens of independent servers. Only the primary ips path is fully connected to an observed network session. The ngrok value and both shortened URLs must be labeled configured, not contacted.
Communication Flow with C&C Servers
The communication flow begins when the installer writes dump.log, which the malware decodes through three layers, outer Base64, a salted radix-25 transformation, and Base64 encoding around each value, to recover dt, tp, and the ips and out lists. These values initialize two parallel controllers. In the HTTP plane, the malware selects a URL from out, performs a GET request through WinHTTP, and parses the response. If it contains a valid configuration, the malware replaces dump.log, immediately reloads the new endpoints, and restarts the cycle. If the upjs field is present, its contents may also be executed as JScript through COM automation.
In the raw TCP plane, the malware selects an endpoint from the primary ips list, omzagdmspc.a.pinggy [.]link:21601 in this campaign, resolves the hostname, opens a socket, and sends the victim registration profile. The public Pinggy relay forwards the connection to an operator-controlled backend, which returns command batches over the same channel. These batches are split into records, validated, converted into numeric command identifiers, and dispatched to actions such as browser capture, file or DLL execution, power control, and cleanup.
The dump.log file also contains 1.tcp.sa.ngrok[.]io:21131 in the secondary ips0 through ips5 lists, possibly as alternative or fallback infrastructure. However, this endpoint was only configured: its selection policy was not established, and no communication with it was observed in the analyzed PCAP provided by our dearst friend Bradley Duncan.
Thus, as shown in the diagram, HTTP maintains and refreshes the configuration and may deliver scripts, while TCP supports victim registration and interactive control, there is no evidence that the dump.log decoder is applied to C&C traffic.
Below, we can see a macro view of the flow.

Indicators of Compromise
The indicators below were recovered from the analyzed the current Astaroth campaign artifacts in this post and the matching packet capture (identified through malware-traffic-analysis.net). Network indicators are defanged, of course.
File Indicators
Malicious and Campaign-Specific Artifacts
| Artifact | Role | SHA-256 |
|---|---|---|
| 868283789726483.zip | Initial ZIP archive | cc44782356cb0effc528a7ab22c19ab360a55ebbbe01feb0967031aa191c5869 |
| 868283789726483.lNk | Malicious Windows shortcut extracted from the ZIP | 454339578b870730d146ad8fec776a9d59360417ab1c2e0e5f88414baf92a13d |
| log204017cd0477.lnk | Persistence shortcut placed in the Startup folder | 32e5b7089317f4167b429606f5418b9e53a8278f2f89fa767edffe8056c9d70b |
| Beatz.LEDPRO.09662.8729.422.log | Compiled malicious AutoIt script | f62a958faf0491b2b2803be2ee69b664b58e4a1261f64e8530cdc1a3ff666aa4 |
| Beatz.LEDPRO.09662.8729.422inc.inf | Encoded campaign companion data | bdf75e22ee42ed6606f6db771ca5c50d8fc68929e6bee634d50df96409eaa33d |
| Beatz.LEDPRO.09662.8729.422re.log | Add-0x2A encoded Delphi payload | e60fe033235c71dd4cb8e7b718851c2f95b4e7ba3a93d7064c97e81bebb0b411 |
| embeeded_log_loader_astaroth.exe | Extracted x86 Delphi loader and process-hollowing component | d7bfb7daa2feed448d3c1ad9bb3799c75e39ead2bb42e297a44ec804ab77c9b4 |
| metrics.mca | Add-0x2A encoded Astaroth banking core | e8f7ff8b9e8133a2b36854a33484235d53780be8358c0b07569c41b94ebb3b49 |
| decrypted_metrics_stage.exe | Analyst-recovered Astaroth/Guildma core; internal name pxsaltisthimgruklia.exe | 74ab591bf4a271f136a65316f729dfb98b3f2270435ba688d1a030501e3d6938 |
| dump.log | Obfuscated runtime C2 configuration | 9d749b90a29f1802329c7b677db725377c894db2e2dfb5352f654dfa57d6bc0c |
decrypted_metrics_stage.exe and embeeded_log_loader_astaroth.exe are the recovered artifacts, named by me. Their hashes are useful for malware identification and retrospective hunting.
Legitimate or Dual-Use Components Abused by the Campaign
The following files are part of the infection chain, but their hashes must not be treated as malware-only indicators.
| Artifact | Role in the Chain | SHA-256 |
|---|---|---|
| n1LUQ7.log:h6JSb / recovered as n1LUQ7.log-ADS-h6JSb.bin | Apparently legitimate Microsoft scrobj.dll copy stored in an NTFS alternate data stream and abused through regsvr32.exe | a6044786991afdb9d42ceb350943987765a7d0e8537369b2092e3f019c0f63ca |
| Beatz.LEDPRO.09662.8729.422.exe | Renamed legitimate AutoIt interpreter used to execute the malicious .log script | bdd2b7236a110b04c288380ad56e8d7909411da93eed2921301206de0cb0dda1 |
Network Indicators
Observed Delivery and Command-and-Control Infrastructure
| Indicator | Type | Role |
|---|---|---|
| relatorio01a.colombstracciatella[.]cfd | Domain | Malspam sender infrastructure |
| 185.254.222[.]105 | IPv4 | Historical sending host for the malspam domain |
| sistema-ekg3h4htc0h0ggdh.canadacentral-01.azurewebsites[.]net | Domain | Initial delivery link and redirector |
| hxxps://static.50.121.238.62.clients.your-server[.]de/868283789726483.zip | URL | ZIP download location |
| plosancol.aguamammillaria[.]cfd | Domain | Component retrieval through the LNK/regsvr32.exe chain |
| hxxps://plosancol.aguamammillaria[.]cfd/?1/_x | URL | Component-retrieval URL reconstructed from the obfuscated LNK command |
| crironxil.aguasedum[.]cfd | Domain | Post-delivery component infrastructure |
| omzagdmspc.a.pinggy[.]link:21601 | Domain and port | Primary raw TCP C2 relay |
Configured but Not Observed in the Available PCAP [malware-traffic-analysis.net]
| Indicator | Type | Role |
|---|---|---|
| 1.tcp.sa.ngrok[.]io:21131 | Domain and port | Secondary/fallback-like TCP endpoint |
| hxxps://bit[.]ly/4zzRb4P | URL | HTTP configuration/update candidate |
| hxxps://cutt[.]ly/cygeRswH | URL | HTTP configuration/update candidate |
Historical DNS Resolutions Observed in the PCAP [malware-traffic-analysis.net]
| Domain | Resolved IPv4 Address | Operational Note |
|---|---|---|
| sistema-ekg3h4htc0h0ggdh.canadacentral-01.azurewebsites[.]net | 52.228.84[.]36 | Shared Microsoft Azure infrastructure |
| static.50.121.238.62.clients.your-server[.]de | 62.238.121[.]50 | ZIP delivery host |
| plosancol.aguamammillaria[.]cfd | 104.21.68[.]199, 172.67.198[.]43 | Shared Cloudflare infrastructure |
| crironxil.aguasedum[.]cfd | 104.21.58[.]188, 172.67.206[.]66 | Shared Cloudflare infrastructure |
| omzagdmspc.a.pinggy[.]link | 172.235.51[.]109 | Shared Pinggy relay infrastructure |
These resolutions are historical and provider-shared. Prefer the complete domain, port, process ancestry, and surrounding behavior over standalone IP blocking.
Host and Persistence Indicators
| Indicator | Description |
|---|---|
| C:\Users\%USERNAME%\AppData\Local\Temp\n1LUQ7.log:h6JSb | NTFS alternate data stream containing the abused scrobj.dll copy |
| C:\Users\Public\Libraries\.cache\ | Campaign staging directory |
| C:\Users\Public\Libraries\.cache\PLAX\ | Main malware and configuration directory |
| C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\wininittemp.log204017cd0477.lnk | Startup persistence shortcut |
| C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegSvcs.exe | Legitimate process created suspended and hollowed with the recovered Astaroth core |
| metrics.mca | Encoded Astaroth core |
| dump.log | External C2 configuration |
Conclusion
This post examined a recent Astaroth campaign, tracing its infection chain from the initial phishing email and malicious Windows shortcut to the AutoIt and Delphi loaders responsible for executing the final banking malware.
The reverse engineering of Astaroth’s core revealed a custom string protection mechanism combining deterministic key reconstruction, chained byte transformations, and an optional nested decoding layer. By reconstructing these algorithms and integrating them into Binary Ninja, I was able to automate the recovery of hundreds of protected strings, providing additional visibility into the malware’s internal functionality.
Further analysis revealed a context-aware financial targeting mechanism, targeted keyboard and clipboard capture, browser configuration manipulation, process termination capabilities, anti-analysis checks, and an extensive numeric command dispatcher.
Another important finding was the role of the external dump.log configuration file. Its multilayer encoding conceals the endpoints used by two distinct communication mechanisms: a raw TCP channel supporting interactive control and an HTTP-based configuration and update mechanism with potential JScript execution capabilities.
The available network evidence supports communication with the configured Pinggy endpoint, while the secondary ngrok endpoint and HTTP update URLs were identified in the configuration but were not observed being contacted in the analyzed capture. This distinction is essential when interpreting infrastructure indicators recovered through static analysis.
From a defensive perspective, these findings highlight opportunities to investigate multistage execution chains, suspicious browser configuration changes, context-dependent credential capture, unusual process termination activity, and network connections associated with malware staging and remote control.
Ultimately, this analysis illustrates how reversing custom obfuscation mechanisms can expose not only hidden strings and configuration data, but also the operational logic of a sophisticated banking malware family targeting the Brazilian financial ecosystem.
I hope this post has provided useful information to the malware research community, particularly regarding the Brazilian landscape, as well as to students of malware analysis. Below, you will find links to the YARA rules and Python scripts I used to automate certain tasks during the analysis.
Additional Information
- Yara Rules of each Astaroth Infection Chain Component;
- Binary Ninja’s Python Script for String Decryption;
- Python script to decode the C&C Configuration File.