{
	"id": "6c4e36b0-345b-494c-af45-7cef8123c51e",
	"created_at": "2026-04-06T00:19:06.54359Z",
	"updated_at": "2026-04-10T03:21:59.065665Z",
	"deleted_at": null,
	"sha1_hash": "25f142d6166eb7a729fdb65b7df641f9a839ce3f",
	"title": "Inside the Kronos malware - part 1 | Malwarebytes Labs",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 803590,
	"plain_text": "Inside the Kronos malware - part 1 | Malwarebytes Labs\r\nBy Malwarebytes Labs\r\nPublished: 2017-08-17 · Archived: 2026-04-05 15:49:54 UTC\r\nRecently, a researcher nicknamed MalwareTech famous from stopping the WannaCry ransomware got arrested for\r\nhis alleged contribution to creating the Kronos banking malware. We are still not having a clear picture whether\r\nthe allegations are true or not – but let’s have a look at Kronos itself.\r\nBackground\r\nThis malware has been first advertised on the black market since around June 2014, by an individual nicknamed\r\nVinnyK, writing in Russian:\r\nSource: https://twitter.com/x0rz/status/893191612662153216\r\nThe full text of the advertisement, translated into English, has been included in the IBM’s Security Intelligence\r\narticle.\r\nWe found Kronos being spread by various exploit kits, i.e. Sundown (more information here). The malware is\r\nbeing distributed up to now – some of the recent samples have been captured about a month ago, dropped from\r\nRig EK.\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 1 of 18\n\nNowadays, Kronos is often used for the purpose of downloading other malware. One of the campaigns using\r\nKronos as a downloader was described by Proofpoint.\r\nAnalyzed samples\r\nSamples from 2014:\r\n01901882c4c01625fd2eeecdd7e6745a  – first observed sample of Kronos (thanks to Kevin Beaumont)\r\nf085395253a40ce8ca077228c2322010 – sample from the Lexsi article\r\na81ba5f3c22e80c25763fe428c52c758 – Kronos (final payload)\r\n6c64c708ebe14c9675813bf38bc071cf – injlib-client.dll (module of Kronos)\r\nSample #1 (from 2016)\r\n2452089b4a9d889f94843430a35fa34f – packed\r\n9818958e65a0a71e29a2f5e7ffa650ca – Kronos (final payload) \u003c- main focus of this analysis\r\nSample #2 (from 2017):\r\nde9ab737905e09b69b28dc0999d08894 – packed\r\n4f5006835669d72c6ce121e66b3034d7 – loader (second stage)\r\nb8986fe9e40f613804aee29b34896707 – Kronos (final payload)\r\ncb7e33e5ede49301e7cd9218addd5c29 – DLL module\r\nBehavioral analysis\r\nAfter being run, Kronos installs itself in a new folder (%APPDATA%/Microsoft/[machine-specific GUID]):\r\nThe dropped sample has a hidden attribute.\r\nPersistence is achieved with the help of a simple Run key:\r\nAt the beginning of the execution, the malware modifies the Firefox profile, overwriting user.js with the following\r\ncontent:\r\nuser_pref(\"network.cookie.cookieBehavior\", 0); user_pref(\"privacy.clearOnShutdown.cookies\", false); u\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 2 of 18\n\nThe new settings are supposed to give to the malware more control over the browser’s behavior and downgrade\r\nthe security settings. Then, the malware injects itself into svchost, and continues running from there. We can find it\r\nlistening on local sockets.\r\nIt is worth noting, that Kronos deploys a simple userland rootkit, that hides the infected process from the\r\nmonitoring tools. So, the process running the main module may not be visible. The rootkit is, however, not\r\nimplemented in a very reliable way, and the effect of hiding does not always work.\r\nWhenever some browser is deployed. Kronos injects its module there and connects with the main module, that\r\nruns inside the svchost process. Looking at the TCP connections established by the particular processes (i.e. using\r\nProcessExplorer), we can see that a browser is paired with the infected svchost:\r\nThis trick is often used by banking trojans for the purpose of stealing data from the browser. The module injected\r\nin the browser hooks the used API and steals the data. After that, it sends this data to the main module that process\r\nit further, and reports to the CnC.\r\nNetwork communication\r\nThe analyzed sample was connecting to CnCs at two addresses:\r\nhttp://springalove.at:80/noix/connect.php http://springahate.at:80/noix/connect.php\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 3 of 18\n\nAt the time of analysis, each CnC was dead (sinkholed), but still, we could spot some patterns typical for this\r\nmalware family.\r\nFirst, the malware sends a beacon that is 74 bytes long:\r\nThen, follows another chunk of data:\r\nIn both cases, we can see that the requests are obfuscated by XOR with a random character. This is how the\r\nbeacon looks after being XOR-decoded:\r\nWe can see that all the requests start from the same header, including the GUID specific to the infected machine.\r\nDetailed research about decrypting Kronos communication has been already described here.\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 4 of 18\n\nInside\r\nInteresting strings\r\nLike most malware, Kronos is distributed packed by various packers/crypters. After unpacking the first layer, we\r\nget the malicious payload. We can easily identify Kronos by the typical strings used:\r\nThere are more strings that are typical for this particular malware:\r\nThose strings are hashes used to dynamically load particular imported functions. Malware authors use this method\r\nto obfuscate used API functions, and by this way, hide the real mission of their tool. Instead of loading function\r\nusing its explicit name, they enumerate all imports in a particular DLL, calculate hashes of their names, and if the\r\nhash matches the hardcoded one, they load that function.\r\nAlthough the approach is common, the implementation seen in Kronos is not typical. Most malware stores hashes\r\nin the form of DWORDs, while Kronos stores them as strings.\r\nInside the early samples of Kronos, we can find a path to the debug symbols, revealing the structure of directories\r\non the machine where the code was built. The following path was extracted from one of the Kronos samples\r\nobserved in wild (01901882c4c01625fd2eeecdd7e6745a):\r\nC:UsersRootDesktopkronosVJF1BinariesReleaseVJF.1.pdb\r\nThe PDB path can be also found in the DLL (6c64c708ebe14c9675813bf38bc071cf) that belongs to the release of\r\nKronos from 2014:\r\nC:UsersRootDownloadsKronos2VJF1Botinjlibbininjlib-client-Releaseinjlib-client.pdb\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 5 of 18\n\nThis module, injlib-client.dll, is the part injected into browsers. In the newer version of Kronos, analogical DLL\r\ncan be found, however, the PDB path is removed.\r\nInjection into svchost\r\nThe main module of Kronos injects itself into svchost (version from 2014 injects into explorer instead). In order to\r\nachieve this initial injection, the malware uses a known technique, involving the following steps:\r\n1. creates the svchost process as suspended\r\n2. maps its sections into its own address space\r\n3. modifies the sections, adding its own code and patching the entry point in order to redirect the execution\r\nthere\r\n4. resumes the suspended process, letting the injected code execute\r\nBelow, you can see the memory inside the infected svchost (in early versions, the injection was targeting\r\nexplorer). The malware is added in a new, virtual section – in the given example, mapped as 0x70000:\r\nThis is how the patched entry point of svchost looks like – as we can see, execution is redirected to the address\r\nthat lies inside the added section (injected malware):\r\nThe execution of the injected PE file starts in a different function now – at RVA 0x11AB0:\r\n– while the original Entry Point of the malware was at RVA 0x12F22:\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 6 of 18\n\nThe malware defends itself from the analysis, and in the case of the VM or debugger being detected, the sample\r\nwill crash soon after the injection.\r\nRunning sample from new Entry Point\r\nThe main operations of the malware starts inside the injected module. This is how the new Entry Point looks like:\r\nThe main function is responsible for loading all the imports and then deploying the malicious actions.\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 7 of 18\n\nIf you are an analyst trying to run Kronos from that point of the execution, below you will find some tips.\r\nThe first block of the function is responsible for filling the import table of the injected module. If we want to run\r\nthe sample from that point, rather than following it when it is injected, there are some important things to notice.\r\nFirst of all, the loader is supposed to fill some variables inside the injected executable, i.e. the variable\r\nmodule_base. Other functions will refer to this, so, if it does not contain the valid value, the sample will crash.\r\nAlso, the functions filling the imports expects that the section .rdata (containing the chunks to be filled), is set as\r\nwritable. It will be set as writable in the case when the sample is injected because then, the full PE is mapped in a\r\nmemory region with RWX (read-write-execute) access rights. However, in the normal case – when the sample is\r\nrun from the disk – it is not. That’s why, in order to pass this stage, we need to change the access rights to the\r\nsection manually.\r\nAnother option is to run Kronos sample starting from the next block of the main function. This also leads to\r\nsuccessful execution, because in case if the sample is run from the disk rather than injected, imports are filled by\r\nwindows loader and doing it manually is just redundant.\r\nThe last issue to bypass is the defensive check, described below.\r\nDefensive tricks\r\nThe malware deploys defense by making several environment checks. The checks are pretty standard – searching\r\nblacklisted processes, modules etc. The particular series of checks are called from inside one function, and results\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 8 of 18\n\nare stored as flags set in a dedicated variable:\r\nIf the debugger/VM is detected, the variable has a non-zero value. Further, the positive result of this check is used\r\nto make the malware crash, interrupting the analysis.\r\nThe crash is implemented by taking an execution path inappropriate to the architecture where the sample was\r\ndeployed. The malware is a 32 bit PE file, but it has a bit different execution paths, depending if it is deployed on\r\n32 or 64-bit system. First, the malware fingerprints the system and sets the flag indicating the architecture:\r\nDWORD is_system64_bit() { DWORD flag = 0; __asm { xor eax,\r\nThis trick uses observations about typical values of CS registry on different versions of Windows\r\n(more information\r\nThat’s why the sample crashes on the next occasion when the architecture-specific path of execution should be\r\ntaken.\r\nFor example, if the sample is deployed on 64-bit machine, under Wow64, the syscall can be performed by using\r\nthe address pointed by FS:[0xC0\u003e. But if the malware runs on a 32-bit machine, the value pointed by FS:[0xC0]\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 9 of 18\n\nwill be NULL, thus, calling it crashes the sample.\r\nThis way of interrupting analysis is smart – sample does not exit immediately after the VM/debugger is detected,\r\nand it makes it harder to find out what was the reason of the crash.\r\nUsing raw syscalls\r\nAs mentioned in the previous paragraph, Kronos uses raw syscalls. Syscall basically means an interface that\r\nallows calling some function implemented by kernel from the user mode. Applications usually use them via API\r\nexported by system DLLs (detailed explanation you can find i.e. on EvilSocket’s blog).\r\nThose API calls can be easily tapped by monitoring tools. That’s why, some malware, for the sake of being\r\nstealthier reads the syscalls numbers from the appropriate DLLs, and calls them by it’s own code, without using\r\nthe DLL as a proxy. This trick has been used i.e. by Floki bot.\r\nLet’s have a look how is it implemented in Kronos. First, it fetches appropriate numbers of the syscalls from the\r\nsystem DLLs. As mentioned before, functions are identified by hashes of their names (full mapping hash-to-function you can find in Lexsi report).\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 10 of 18\n\nFor example:\r\nB6F6X4A8R5D3A7C6 -\u003e NtQuerySystemInformation\r\nThe numbers of syscalls are stored in variables, xored with a constant. Fragment of the code responsible for\r\nextracting raw syscalls from the DLL:\r\nIn order to use them further, for every used syscall Kronos implements its own wrapper function with an\r\nappropriate number of parameters. You can see an example below:\r\nThe EAX registry contains the number of the syscall. In the given example, it represents the following function:\r\n00000105 -\u003e NtQuerySystemInformation\r\nKronos uses raw syscalls to call the functions that are related to injections to other processes because they usually\r\ntrigger alerts. Functions that are called by this way are listed below:\r\nNtAllocateVirtualMemory NtCreateFile NtCreateSection NtGetContextThread NtOpenProcess NtProtectVirtua\r\nIt matches the black market advertisement, stating: “The Trojan uses an undetected injection method” (source).\r\nRootkit and the hooking engine\r\nOne of the features that malware provides is a userland rootkit. Kronos hooks API of the processes so that they\r\nwill not be able to notice its presence. The hooking is done by a specially crafted block of the shellcode, that is\r\nimplanted in each accessible running process.\r\nFirst, Kronos prepares the block of shellcode to be implanted. It fills all the necessary data: addresses of functions\r\nthat are going to be used, and the data specific to the malware installation, that is intended to be hidden.\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 11 of 18\n\nThen, it searches through the running processes and tries to make injection wherever it is possible. Interestingly,\r\nexplorer.exe and chrome.exe are omitted:\r\nThe shellcode is deployed in a new thread within the infected process:\r\nBelow you can see the shellocode inside the memory of the infected process:\r\nWhen it runs, it hooks the following functions in the address space of the infected process:\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 12 of 18\n\nZwCreateFile NtOpenFile ZwQueryDirectoryFile NtEnumerateValueKey RtlGetNativeSystemInformation NtSetV\r\nThe interesting thing about this part of Kronos is its similarity with a hooking engine described by MalwareTech\r\non his blog in January 2015. Later, he complained in his tweet, that cybercriminals stolen and adopted his code.\r\nLooking at the hooking engine of Kronos we can see a big overlap, that made us suspect that this part of Kronos\r\ncould be indeed based on his ideas. However, it turned out that this technique was described much earlier (i.e.\r\nhere, //thanks to  @xorsthings for the link ), and both authors learned it from other sources rather than inventing\r\nit.\r\nLet’s have a look at the technique itself. During hooking, one may experience concurrency issues. If a half-overwritten function will start to be used by another thread, the application will crash. To avoid this, it is best to\r\ninstall a hook by a single assembly instruction. MalwareTech’s engine used for this purpose an instruction lock\r\ncmpxch8b. Similar implementation can be found in Kronos.\r\nThe hooking function used by Kronos takes two parameters – the address of the function to be hooked, and the\r\naddress of function used as a proxy. This is the fragment of the implanted shellcode where the hooking function is\r\nbeing called:\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 13 of 18\n\nFirst, the hooking function searches the suitable place in the code of the attacked function, where the hook can be\r\ninstalled:\r\nThe above code is an equivalent of the following:\r\nhttps://github.com/MalwareTech/BasicHook/blob/master/BasicHook/hook.cpp#L103\r\nThen, it installs the hook:\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 14 of 18\n\nAs we can see, the used method of  installing hook is almost identical to:\r\nhttps://github.com/MalwareTech/BasicHook/blob/master/BasicHook/hook.cpp#L77\r\nBelow you can see an example of Kronos hooking a function ZwResumeThread in the memory of the attacked\r\nprocess. Instruction lock cmpxch8b is indeed used to overwrite the function’s beginning:\r\nAfter the hook installation, whenever the infected process calls the hooked function, the execution is redirected to\r\nthe proxy code inside the malicious module:\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 15 of 18\n\nThe hooking engine used in Kronos is overall more sophisticated. First of all, even the fact that it is a shellcode\r\nnot a PE file makes a difficulty level of implementing it higher. The author must have taken care of filling all the\r\nfunctions addresses by his own. But also, the author of Kronos shown some more experience in predicting possible\r\nreal-life scenarios. For example, he took additional care for checking if the code was not already hooked (i.e. by\r\nother Trojans or monitoring tools):\r\nAttacking browsers\r\nThe malware injects into a browser an additional module (injlib-client.dll). Below we can see an\r\nexample of the DLL injected into Firefox address space:\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 16 of 18\n\nThe malware starts the injected module with the help of the injected shellcode:\r\nWe can see some API redirections added by the malware. Some of the functions imported by the attacked browser\r\nare hooked so that all the data that passes through them is tapped by the Kronos module.\r\nThe data that is being grabbed using the hooked browser API is then sent to the main module, that is coordinating\r\nmalware’s work and reporting to the CnC server.\r\nConclusion\r\nAn overall look at the tricks used by Kronos shows that the author has a prior knowledge in implementing\r\nmalware solutions. The code is well obfuscated, and also uses various tricks that requires understanding of some\r\nlow-level workings of the operating system. The author not only used interesting tricks, but also connected them\r\ntogether in a logical and fitting way. The level of precision lead us to the hypothesis, that Kronos is the work of a\r\nmature developer, rather than an experimenting youngster.\r\nMalwarebytes users are protected against the Kronos malware.\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 17 of 18\n\nAppendix\r\n“Overview of the Kronos banking malware rootkit” by Lexsi\r\nDecrypting the configuration\r\nSee also:\r\n/blog/cybercrime/2017/08/inside-kronos-malware-p2/\r\nThis was a guest post written by Hasherezade, an independent researcher and programmer with a strong interest\r\nin InfoSec. She loves going in details about malware and sharing threat information with the community. Check\r\nher out on Twitter @hasherezade and her personal blog: https://hshrzd.wordpress.com.\r\nSource: https://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nhttps://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/\r\nPage 18 of 18\n\ntaken. For example, if the sample is deployed on 64-bit machine, under Wow64, the syscall can be performed by using\nthe address pointed by FS:[0xC0\u003e. But if the malware runs on a 32-bit machine, the value pointed by FS:[0xC0]\n   Page 9 of 18",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA",
		"Malpedia"
	],
	"references": [
		"https://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/"
	],
	"report_names": [
		"inside-kronos-malware"
	],
	"threat_actors": [],
	"ts_created_at": 1775434746,
	"ts_updated_at": 1775791319,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/25f142d6166eb7a729fdb65b7df641f9a839ce3f.pdf",
		"text": "https://archive.orkl.eu/25f142d6166eb7a729fdb65b7df641f9a839ce3f.txt",
		"img": "https://archive.orkl.eu/25f142d6166eb7a729fdb65b7df641f9a839ce3f.jpg"
	}
}