{
	"id": "524d681f-72b9-4247-8268-5de201c6d15d",
	"created_at": "2026-04-06T00:11:51.953212Z",
	"updated_at": "2026-04-10T03:21:45.79945Z",
	"deleted_at": null,
	"sha1_hash": "b57552b2713ecde8fa0c3959b9f95150c272de4d",
	"title": "Chasing Chaes Kill Chain",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 6464871,
	"plain_text": "Chasing Chaes Kill Chain\r\nBy Threat Research TeamThreat Research Team\r\nArchived: 2026-04-05 15:06:38 UTC\r\nIntroduction\r\nChaes is a banking trojan that operates solely in Brazil and was first reported in November 2020 by\r\nCybereason. In Q4 2021 , Avast observed an increase in Chaes’ activities, with infection attempts detected from\r\nmore than 66,605 of our Brazilian customers. In our investigation, we found the malware is distributed\r\nthrough many compromised websites, including highly credible sites. Overall, Avast has found Chaes’ artifacts in\r\n800+ websites. More than 700 of them contain Brazilian TLDs. All compromised websites are WordPress\r\nsites, which leads us to speculate that the attack vector could be exploitation of vulnerabilities in WordPress CMS .\r\nHowever, we are unable to perform forensics to confirm this theory. We immediately shared our findings with the\r\nBrazilian CERT (BR Cert) with the hope of preventing Chaes from spreading. By the time of this publication,\r\nChaes’ artifacts still remain on some of the websites we observed.\r\nChaes is characterized by the multiple-stage delivery that utilizes scripting frameworks such as JScript ,\r\nPython , and NodeJS , binaries written in Delphi , and malicious Google Chrome extensions . The ultimate\r\ngoal of Chaes is to steal credentials stored in Chrome and intercept logins of popular banking websites in\r\nBrazil .\r\nIn this posting, we present the results of our analysis of the Chaes samples we found in Q4 2021 . Future updates\r\non the latest campaign will be shared via Twitter or a later post.\r\nInfection Scheme\r\nWhen someone reaches a website compromised by Chaes, they are presented with the below pop-up asking users\r\nto install the Java Runtime application:\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 1 of 19\n\nIf the user follows the instructions, they will download a malicious installer that poses as a legitimate Java\r\nInstaller . As shown below, the fake installer closely imitates the legitimate Brazilian Portuguese Java\r\ninstaller in terms of appearance and behavior.\r\nOnce the installation begins, the user’s system is compromised. After a few minutes, all web credentials, history,\r\nuser profiles stored by Chrome will be sent to attackers. Users may experience Google Chrome getting closed and\r\nrestarted automatically. This indicates any future interactions with the following Brazilian banking websites will\r\nbe monitored and intercepted:\r\nmercadobitcoin.com.br\r\nmercadopago.com.[ar|br]\r\nmercadolivre.com.br\r\nlojaintegrada.com.br\r\nTechnical Analysis\r\nInfected websites\r\nUpon inspecting the HTML code of the compromised websites, we found the malicious script inserted as shown\r\nbelow:\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 2 of 19\n\nIn this case, the V=28 likely represents the version number. We also found a URL with other versions as well:\r\nhttps://is[.]gd/EnjN1x?V=31\r\nhttps://is[.]gd/oYk9ielu?D=30\r\nhttps://is[.]gd/Lg5g13?V=29\r\nhttps://is[.]gd/WRxGba?V=27\r\nhttps://is[.]gd/3d5eWS?V=26\r\nThe script creates an HTML element that stays on top of the page with “Java Runtime Download” lure. This\r\nelement references an image from a suspicious URL\r\nhttps://sys-dmt[.]net/index.php?D\\\r\nhttps://dmt-sys[.]net/\r\nand an on-click download of a Microsoft Installer from\r\nhttps://bkwot3kuf[.]com/wL38HvYBiOl/index.php?get or\r\nhttps://f84f305c[.]com/aL39HvYB4/index.php?get or\r\nhttps://dragaobrasileiro[.]com.br/wp-content/themes/getCorsFile.php\r\nMicrosoft Installer\r\nThe flowchart below shows the infection chain following the malicious installer execution.\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 3 of 19\n\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 4 of 19\n\nInside the MSI package\r\nThe installer contains 3 malicious JS files install.js , sched.js , and sucesso.js renamed to Binary._ as\r\nshown above. Each of them handles a different task, but all are capable of reporting the progress to the specified\r\nCnC :\r\nImplementation of the logging function across all 3 scripts\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 5 of 19\n\ninstall.js\r\nThe purpose of this script is to download and execute a setup script called runScript that will prepare the\r\nproper Python environment for the next stage loader. After making an HTTP request to a hardcoded domain, the\r\nobfuscated runScript is downloaded and then executed to perform the following tasks:\r\nCheck for Internet connection (using google.com )\r\nCreate %APPDATA%\\\\\u003cpseudo-random folder name\u003e\\\\extensions folder\r\nDownload password-protected archives such as python32.rar/python64.rar and unrar.exe to that\r\nextensions folder\r\nWrite the path of the newly created extensions folder to\r\nHKEY_CURRENT_USER\\\\Software\\\\Python\\\\Config\\\\Path\r\nPerforms some basic system profiling\r\nExecute unrar.exe command with the password specified as an argument to unpack\r\npython32.rar/python64.rar\r\nConnect to C2 and download 32bit and 64bit  __init__.py scripts along with 2 encrypted payloads.\r\nEach payload has a pseudo-random name.\r\nrunScript.js content\r\nsched.js\r\nThe purpose of this script is to set up persistence and guarantee the execution of __init__.py downloaded by\r\nrunScript from the previous step. Sched.js accomplishes this by creating a Scheduled Task as its primary\r\nmeans and creating a  Startup link as its backup means. Ultimately, they are both able to maintain the after-reboot execution of the following command:\r\n  ...\\\\\u003cpython32|python64\u003e\\\\pythonw.exe __init__.py /m\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 6 of 19\n\nScheduledTask Configuration\r\nsucesso.js\r\nThis script reports to CnC that the initial installation on the victim’s computer has succeeded and is ready for the\r\nnext stage\r\nPython Loader Chain\r\nThe Scheduled Task created by sched.js eventually starts  __init__.py which initiates the Python in-memory loading chain. The loading chain involves many layers of Python scripts, JS scripts, shellcode, Delphi\r\nDLLs, and .NET PE which we will break down in this section. Impressively, the final payload is executed within\r\n__init__.py process ( PID 2416 and 4160 ) as shown below:\r\n__init__.py\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 7 of 19\n\nObfuscated content\r\nThe __init__.py xor decrypts and decompresses the pseudo-random filename downloaded by runScript.js\r\ninto another Python script. The new Python script contains 2 embedded payloads: image and shellcode in\r\nencrypted form. Image represents the Chaes loader module called chaes_vy.dll while shellcode is an in-memory PE loader. We found this particular loader shellcode reappearing many times in the later stages of Chaes.\r\nRunning the shellcode using CreateThread API with proper parameters pointing to chaes_vy.dll , the Python\r\nscript eventually loads chaes_vy.dll into memory:\r\nchaes_vy.dll is loaded into memory by an embedded shellcode\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 8 of 19\n\nChaes_vy.dll\nChaes_vy is a Delphi module that loads an embedded .NET executable that in turn runs 2 JavaScripts :\nscript.js and engine.js . These two scripts hold the core functionalities of the Chaes_vy module.\nscript.js\nThis script acts as the interface between .NET framework and JScript framework, providing the necessary utilities\nto execute any scripts and modules that engine.js downloads in the future. By default, script.js will try to\nretrieve the paths to payloads specified in the argument of __init__.py . If nothing is found it will execute\nengine.js\nengine.js\nThis script employs 2 methods of retrieving a JS payload: getBSCode() and getDWCode() both are called every\n6 minutes.\nGetBSCode is the primary method, also the only one we are able to observe serving payload. The encrypted\npayload is hidden as commented-out code inside the HTML page of a Blogspot which is shown below. Without\nbeing infected by Chaes, this site is completely harmless.\nView of the Blogpost page contains hidden malicious code\nOn the other hand, when executed, engine.js will parse the string starting from\n\nwhich is\nthe marker of the encrypted payload:\nHidden code\nAfter decrypting this text using AES with a hardcoded key, instructions.js is retrieved and executed. This\nscript is in charge of downloading and executing Chaes’ malicious Chrome “extensions”. More info about\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\nPage 9 of 19\n\ninstructions.js is provided in the next section.\r\ngetDWCode is the secondary method of retrieving instruction.js . It employs a DGA approach to find an\r\nactive domain weekly when getBSCode fails. Since we are not able to observe this method being used\r\nsuccessfully in the wild, we have no analysis to present here. However, you can check out the full algorithm\r\nposted on our Github.\r\nInstructions.js\r\nInstructions.js is the last stage of the delivery chain. Nothing up to this point has gained the attacker any true\r\nbenefits. It is the job of instructions.js to download and install all the malicious extensions that will take\r\nadvantage of the Chrome browser and harm the infected users. The address of all payloads are hardcoded as\r\nshown below:\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 10 of 19\n\nThe extensions are separated into password-protected archives vs encrypted binaries. The non-compressed\r\npayloads are PE files that can be run independently while compressed ones add necessary NodeJS packages for\r\nthe extension to run. Below is the example of chremows63_64 archive contents:\r\nAll the binaries with dll_filename argument such as chromeows2.bin are encrypted, including the ones inside\r\nthe RAR archive. The decryption algorithm is located inside script.js as we mentioned in the previous section.\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 11 of 19\n\nTo decrypt and run each binary, Chaes needs to call __init__.py with the file path specified as an argument.\r\nThe extension installation can be simplified into the following steps:\r\nAn HTTP Request ( aws/isChremoReset.php )  is sent to check if Google Chrome from a particular uid\r\nhas been hooked. If not, Chrome and NodeJS will be closed. More information about uid in the “Online”\r\nsection below.\r\nThe download request is constructed based on 3 scenarios: 32bit, 64bit, and no Google Chrome found.\r\nEach scenario will contain suitable versions of the extensions and their download links.\r\nThe extension is downloaded. The compressed payload will be unpacked properly.\r\nA hosts file is created for the newly downloaded module. Inside the file is the CnC randomly picked\r\nfrom the following pool:\r\nEach extension will use the address specified in hosts for CnC communication\r\nLaunch each extension through python.exe __init__.py with proper arguments as shown below\r\nExtensions\r\nOnline\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 12 of 19\n\nonline.dll is a short-lived Delphi module that is executed by instruction.js before other modules are\r\ndeployed. Its main purpose is to fingerprint the victim by generating a uid which is a concatenation of drive C:\r\nVolumeSerialNumber , UserName , and Computername . The uid is written to a register key\r\nSOFTWARE\\\\Python\\\\Config\\uid before being included inside the beaconing message.\r\nThis registry key is also where instruction.js previously gets the uid asking CnC if the victim’s Chrome has\r\nbeen hooked. The first time instruction.js gets launched this registry has not been created yet, therefore the\r\nChrome process is always killed.\r\nOnline.dll retrieves the CnC server specified in the hosts file and performs the beaconing request\r\n/aws/newClient.php , sending the victim’s uid and basic system information.\r\nMtps4 (MultiTela Pascal)\r\nModule mtps4 is a backdoor written in Delphi . Its main purpose is to connect to CnC and wait for a\r\nresponding PascalScript to execute. Similar to the previous module, CnC is retrieved from the hosts file.\r\nMtps4 sends a POST request to the server with a hardcoded User-Agent containing uid and command type.\r\nIt currently supports 2 commands: start and reset . If the reset command is responded with ‘ (* SCRIPT\r\nOK *) ’, it will terminate the process.\r\nStart command is a bit more interesting.\r\nExample of an HTTP request with “start” command\r\nAs a reply to this command, it expects to receive a PascalScript code containing a comment ‘ (* SCRIPT OK\r\n* )’.\r\nmtps4 is compiled with https://github.com/remobjects/pascalscript to support PascalScript. Before running, the\r\nscript they create a window that copies the screen and covers the entire desktop to avoid raising suspicion when\r\nperforming malicious tasks on the system.\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 13 of 19\n\nUnfortunately during the investigation, we couldn’t get hold of the actual script from the CnC.\r\nChrolog (ChromeLog)\r\nChrolog is a Google Chrome Password Stealer written in Delphi. Although it is listed as an extension, Chrolog\r\nis an independent tool that extracts user personal data out of the Chrome database and exfiltrates them through\r\nHTTP. The CnC server is also retrieved from the hosts file previously created by instruction.js .\r\n(Cookies, Web Data, Login Data, History, and Local State is standardly located at\r\n%APPDATA%\\\\Local\\\\Google\\\\Chrome\\\\User Data\\\\Default\\\\)\r\nChronodx (Chrome Noder)\r\nchrolog.rar contains NodeJS packages and chronodx.bin aka Chronod2.dll.\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 14 of 19\n\nChronodx dependency (“name”: “chremows” is indeed how it is defined)\r\nThe chronodx extension package can be separated into 2 parts: a loader called Chronod2.dll and a JavaScript\r\nbanking trojan called index_chronodx2.js . First, Chronod2.dll performs an HTTP request\r\n/dsa/chronod/index_chronodx2.js to retrieve index_chronodx2.js . If successful, Chronod2.dll will run\r\nsilently in the background until it detects the Chrome browser opened by the user. When that happens, it will close\r\nthe browser and reopen its own instance of Chrome along with index_chronodx2.js being run from the\r\nnode.exe process.\r\nChronodx in idle mode\r\nChronodx reopens Chrome and executes “node.exe index.js” command Index.js is index_chronodx2.js in this case\r\nIndex_chronodx2.js utilizes puppeteer-core, a NodeJS framework that provides APIs to control Chrome\r\nbrowser, for malicious purposes. Index_chronodx2.js implements many features to intercept popular banking\r\nwebsites in Brazil including\r\nbancobrasil.com.br/aapf\r\nbancodobrasil.com.br/aapf\r\nbb.com.br/aapf\r\nmercadopago.com/…/card_tokens/\r\nmercadopago.com/enter-pass/\r\nmercadolivre.com/enter-pass/\r\nlojaintegrada.com.br/public/login/\r\nmercadobitcoin.com.br\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 15 of 19\n\nUpon visiting any of the above websites, index_chronodx2.js will start collecting the victim’s banking info and\r\nsend it to the attacker through a set of HTTP commands. The CnC server is stored in the hosts file, but when it\r\nis not found in the system, a hardcoded backup CnC will be used instead:\r\nChremows (Chrome WebSocket)\r\nChremows is another extension that uses NodeJS and puppeteer-core, and is similar to the functionality of node.js\r\nmentioned in the Cybereason 2020 report. Chremows targets two platforms Mercado Livre\r\n(mercadolivre.com.br) and Mercado Pago (mercadopago.com.br) both belong to an online marketplace company\r\ncalled Mercado Libre, Inc.\r\nChremows dependency\r\nSharing the same structure of chronodx module, chremows contains a loader, CreateChrome64.dll that\r\ndownloads a JavaScript-based banking trojan called index.js . CreateChrome64.dll will automatically update\r\nindex.js when a newer version is found. Unlike chronodx, chremows executes index.js immediately after\r\ndownload and doesn’t require Google Chrome to be opened. In a separate thread, CreateChrome64.dll loads an\r\nembedded module ModHooksCreateWindow64.dll that Cybereason has analyzed in their 2020 report. Overall,\r\nthis module help increase the capabilities that chremows has on Google Chrome, allowing the attacker to perform\r\n“active” tasks such as sending keypresses/mouse clicks to Chrome, or opening designated pages. Finally,\r\nCreateChrome64.dll copies Chrome’s Local State file to the same location of index.js with the name\r\nlocal.json. Index.js uses local.json to help the attacker identify the victim.\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 16 of 19\n\nHardcoded CnC\r\nIndex.js employs two methods of communicating with the attacker: through WebSocket and through HTTP.\r\nEach method has its own set of C2 servers as shown in the above picture. WebSocket is used to receive commands\r\nand send client-related messages. On the other hand, HTTP is for exfiltrating financial data such as banking\r\ncredentials and account information to the attacker.\r\nList of known Index.js WebSocket commands\r\nIf the user stays connected to the WebSocket C2 server, every six minutes it automatically goes to the targeted\r\nMercado Pago and Mercado Livre pages and performs malicious tasks. During this routine, the attacker loses\r\ndirect control of the browser. The target pages are banking, credit, and merchant pages that require users’ login. If\r\nthe user has not logged out of these pages, the attacker will start to collect data and exfiltrate them through the\r\nfollowing HTTP requests:\r\n/aws/newMercadoCredito.php\r\n/aws/newMercadoPago.php\r\nIf the user is not logged in to those pages but has the password saved in Chrome, after the routine ends, the\r\nattackers will get back their direct control of Chrome and log in manually.\r\nSummary\r\nChaes exploits many websites containing CMS WordPress to serve malicious installers. Among them, there are a\r\nfew notable websites for which we tried our best to notify BR Cert. The malicious installer communicates with\r\nremote servers to download the Python framework and malicious Python scripts which initiate the next stage of\r\nthe infection chain. In the final stage, malicious Google Chrome extensions are downloaded to disk and loaded\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 17 of 19\n\nwithin the Python process. The Google Chrome extensions are able to steal users’ credentials stored in Chrome\r\nand collect users’ banking information from popular banking websites.\r\nIOCs\r\nThe full list of IoCs is available here\r\nNetwork\r\nHTML Scripts\r\nis[.]gd/EnjN1x?V=31\r\nis[.]gd/oYk9ielu?D=30\r\nis[.]gd/Lg5g13?V=29\r\ntiny[.]one/96czm3nk?v=28\r\nis[.]gd/WRxGba?V=27\r\nis[.]gd/3d5eWS?V=26\r\nMSI Download URLs\r\ndragaobrasileiro[.]com.br/wp-content/themes/getcorsfile.php?\r\nchopeecia[.]com.br/D4d0EMeUm7/index.php?install\r\nbodnershapiro[.]com/blog/wp-content/themes/twentyten/p.php?\r\ndmt-sys[.]net/index.php?\r\nup-dmt[.]net/index.php?\r\nsys-dmt[.]net/index.php?\r\nx-demeter[.]com/index.php?\r\nwalmirlima[.]com.br/wp-content/themes/epico/proxy.php?\r\natlas[.]med.br/wp-content/themes/twentysixteen/proxy.php?\r\napoiodesign[.]com/language/overrides/p.php?\r\nCnC Servers\r\n200[.]234.195.91\r\nf84f305c[.]com\r\nbkwot3kuf[.]com\r\ncomercialss[.]com\r\nawsvirtual[.]blogspot.com\r\ncliq-no[.]link\r\n108[.]166.219.43\r\n176[.]123.8.149\r\n176[.]123.3.100\r\n198[.]23.153.130\r\n191[.]252.110.241\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 18 of 19\n\n191[.]252.110.75\r\nSHA256 Hashes\r\nA group of elite researchers who like to stay under the radar.\r\nSource: https://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nhttps://decoded.avast.io/anhho/chasing-chaes-kill-chain/\r\nPage 19 of 19\n\n  https://decoded.avast.io/anhho/chasing-chaes-kill-chain/    \nThe extensions are separated into password-protected archives vs encrypted binaries. The non-compressed \npayloads are PE files that can be run independently while compressed ones add necessary NodeJS packages for\nthe extension to run. Below is the example of chremows63_64 archive contents:  \nAll the binaries with dll_filename argument such as chromeows2.bin are encrypted, including the ones inside\nthe RAR archive. The decryption algorithm is located inside script.js as we mentioned in the previous section.\n   Page 11 of 19",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"ETDA"
	],
	"references": [
		"https://decoded.avast.io/anhho/chasing-chaes-kill-chain/"
	],
	"report_names": [
		"chasing-chaes-kill-chain"
	],
	"threat_actors": [],
	"ts_created_at": 1775434311,
	"ts_updated_at": 1775791305,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/b57552b2713ecde8fa0c3959b9f95150c272de4d.pdf",
		"text": "https://archive.orkl.eu/b57552b2713ecde8fa0c3959b9f95150c272de4d.txt",
		"img": "https://archive.orkl.eu/b57552b2713ecde8fa0c3959b9f95150c272de4d.jpg"
	}
}