{
	"id": "b9c536ec-daf2-4389-ad07-65e729fe7c75",
	"created_at": "2026-04-06T00:10:13.716775Z",
	"updated_at": "2026-04-10T03:36:37.074003Z",
	"deleted_at": null,
	"sha1_hash": "07de03e7f9a2c7ecb34b0063cfff43aaab5ef451",
	"title": "Dridex Trojan",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 674548,
	"plain_text": "Dridex Trojan\r\nBy Nidal Fikri\r\nPublished: 2021-11-21 · Archived: 2026-04-05 21:24:38 UTC\r\nDridex in a NutshellPermalink\r\nDridex is a famous banking Trojan which appeared around 2011 and is still very active today. This is because of\r\nits evolution and its complex architecture, which is based on proxy layers to hide the main command and control\r\nservers (C\u0026C). The APT known as TA505 is associated to Dridex, as well as with other malwares such as\r\nTrickBot and Locky ransomware. Dridex is known for its unique anti-analysis techniques which combines API\r\nhashing with VEH (Vectored Exception Handling) manipulation. As a consequence, Dridex is able to effectively\r\nhide its intentions and requires skillful reverse engineers to accurately dissect it. Once installed, Dridex can\r\ndownload additional files to provide more functionality to the Trojan.\r\nTechnical SummaryPermalink\r\n1. Dridex uses API hashing to conceal its imports. It’s using CRC32 hashing, as well as another layer of\r\nXORing with hard-coded key. It’s prasing the loaded DLLs in memory and its export tables. As a\r\nconsequence, Dridex can resolve any imported win APIs then jumps to their addresses.\r\n2. Another layer of complication is done with Vectored Exception Handling manipulation. Dridex inserts a lot\r\nof int 3 and ret instructions everywhere to make the reverse engineering harder. Furthermore, the use\r\nof int 3 triggers a custom exception handler planted by the malware. This malicious handler alters the\r\nexecution flow to effectively jump between APIs.\r\n3. Dridex comes with encrypted strings on its .rdata section. These strings are used as API\r\nparameters/settings for the malicious impact. Therefore, they are must be decrypted to know its intentions.\r\nDridex uses RC4 to do the decryption. The first 40 bytes of every data chunk is the key (stored in a reverse\r\norder) then followed by the encrypted data.\r\n4. Dridex stores its network configuration in plain text on its .data section. Obviously, it establishes\r\nconnection with its C\u0026C for further commands, and also to download additional malware modules. These\r\nmodules extend its functionality. Dridex comes with 4 embedded C\u0026C IP addresses.\r\nTechnical AnalysisPermalink\r\nDefeating Anti-AnalysisPermalink\r\nAPI HashingPermalink\r\nDridex is famous for its anti-analysis techniques which include API hashing. API hashing -in a nutshell- is when a\r\nmalware hashes the names (strings) of its imports, making it harder to know what APIs it will resolve at run-time.\r\nAPI hashing is famous among shellcodes. That’s because a tightly crafted shellcode can’t make use of the OS\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 1 of 12\n\nloader, it’s not a PE file and it must depend on itself to find where DLLs are residing in memory. Once it finds the\r\ntargeted module, it parses its export table to know where it’s providing its exported APIs (the address in memory).\r\nOne way to spot API hashing techniques, is to look for a function which takes constant (random-like data) inputs,\r\nand finding that they are using its return value as a function pointer.\r\nFigure(1): sub_6015C0 will be renamed to be mw_API_Resolver\r\nWe can see that sub_6015C0 matches the description we have just stated. It’s called twice to resolve two\r\nWindows APIs. Also, we can notice that the 1st parameter is the same during the two calls here. This may indicate\r\nthat the 1st parameter is likely to be the hashed DLL name and the 2nd parameter is likely to be the hashed API\r\nname.\r\nWe can label sub_6015C0 as a potential API resolving routine. Now let’s dive into it for more detailed analysis.\r\nWe can see that it’s depending on two more functions: sub_607564 and sub_6067C8 .\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 2 of 12\n\nFigure(2): Using IDA Pro structs.\r\nIn sub_607564 , we find that Dridex is parsing the process PEB structure in order to get the loaded modules- in\r\nthe process address space-. By using the appropriate structs in IDA Pro, the code looks more readable right now.\r\nVariable Name Struct\r\nLdr Pointer to _PEB_LDR_DATA\r\nCurrent_DLL Pointer to _LDR_MODULE (Click the link and search the documentation)\r\nPrev_DLL Pointer to _LDR_MODULE\r\nAs we can see, Dridex is using the Flink pointer to parse the loaded modules (DLLs) as _LDR_MODULE structs.\r\nThe BaseDllName of every loaded module is obtained, and properly converted to the right form for further\r\ncomparison. The BaseDllName is hashed by sub_61D620 and XORed against the 38BA5C7B hard-coded key.\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 3 of 12\n\nFigure(3): Hash comparison; between the function input hash and the obtained name (after hashing and XORing).\r\nWe can determine the type of hashing algorithm using PEiD tool. Using the Krypto ANALyzer plugin, it was able\r\nto identify the hashing algorithm as CRC32 based on the used algorithm constants. After hashing and XORing the\r\nBaseDllName of the loaded module, it’s compared against the target hash. Once there is a match, at 0X60769A ,\r\nthe BaseAddress of the wanted module (DLL) is returned. This address is used later for locating the wanted API\r\nwithin the module’s export table. This address also points to the IMAGE_DOS_HEADER aka MZ header of the\r\nmodule. All that is purely done in the memory without the need of exposing the malware’s imports.\r\nWe proceed to reverse sub_6067C8 . The routine accepts the previously returned DLL BaseAddress as a\r\nparameter along with the second hash. We can make a strong prediction that this function is using those\r\nparameters to return the API address in order to be used by Dridex. As we can see, The malware is parsing the\r\nmodule header in order to locate its export table. The export table of a certain DLL contains the addresses which\r\nits exported APIs are residing in memory.\r\nFigure(4): The offsets are calculated based on the function argurment (DLL ImageAddress)\r\nThe malwares first references the e_lfanew field at offset 0X3C from the beginning of the module. This field\r\ndenotes the offset which the NT Headers begin. From there and by offset 0X78 -i.e. at offset 0X3C + 0X78 =\r\n0X160 from the beginning of the DLL-, the malware can access the Data Directory . The first two fields of this\r\narray is the address of the Export Directory address and its size . We can use PEBear tool to visualize all\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 4 of 12\n\nthese offsets within the PE header. We use the _IMAGE_EXPORT_DIRECTORY struct with the variable\r\nEXPORT_TABLE_Start_Address to make the code more readable.\r\nHence, we can see the malware parsing AddressOfNames , AddressOfNameOrdinals , and AddressOfFunctions\r\nto make a mapping between every exported API’s name and its memory address. If the hashed -and XORed- API\r\nname matches the 2nd argument of the function, its memory address is returned. By using this way, Dridex is able\r\nto effectively hide its needed APIs from security solutions. For more details about how to find an API address in\r\nmemory check this out.\r\nCombining all together from the previous analysis, we now know that Dridex is doing API hashing using CRC32\r\n+ another layer of XORing. We can try to write a script to create a hash table of the famous Windows DLLs and\r\ntheir exports. Generating this table, we can then search into it using the hashes that Dridex uses. As a\r\nconsequence, we can know which API and DLL Dridex is trying to resolve without the need of dynamic code\r\nanalysis.\r\nFortunately, we don’t have to create this script. We can use the amazing hashdb IDA plugin from OALabs. It will\r\nautomate everything for us. We just need to identify the hashing algorithm and the XOR key to make hashdb\r\nready.\r\nFigure(5): Use enums with the 'm' button\r\nThis announces our victory over API hashing anti-analysis, and we can easily use the newly added enums to make\r\nthe malware code more readable right now. For instance, at 0X5F9E47 we find that CreatThread is being\r\nresolved at that particular address.\r\nVectored Exception HandlingPermalink\r\nTo fully understand the intention of this anti-analysis technique, we need to know how Dridex is utilizing API\r\nhashing:\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 5 of 12\n\nFigure(6): This pattern is found hunderds of times in this sample and also in any downloaded module.\r\nThe returned API address from sub_6015C0 (labeled as mw_API_Resolver ) is not used as call instruction\r\noperand. Rather, at sub_607980 , Dridex is registering (adding) a new customized Exception Handler using\r\nRtlAddVectoredExceptionHandler API, which accepts an _EXCEPTION_POINTERS arguemnt. This customized\r\nexception handler will adjust the thread stack and EIP register, in order to alter the process flow to the\r\npreviously resolved API address (via the ret instruction).\r\nAfter calling the mw_API_Resolver function, EAX now contains the address of the resolved API. Dridex then\r\ntraps the debugger or -more accurately- generates an EXCEPTION_BREAKPOINT using int 3 instruction. This\r\nexception is passed to the process exception handlers vector in order to be properly handled. The previously\r\nplanted customized exception handler will be the first to process the exception.\r\nFigure(7): A process context is like a snapshot of its registers and stack.\r\nThis malicious handler will execute and alter the process’ context if and only if the exception is caused by int 3\r\ninstruction -which Dridex exactly wants-. The final process’ context will be altered by these steps:\r\n1. Incrementing EIP by 1 in order to make it point to the ret instruction.\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 6 of 12\n\n2. Mimicking a push EIP+1 instruction, in order to save the address of the instruction after ret on the\r\nstack ( manually building a stack frame).\r\n3. Also mimicking a push EAX instruction, in order to make ESP = Resolved API Address .\r\nSuccessfully achieving these steps, the flow will exactly resume at the ret instruction, pointed by the corrupted\r\nEIP , which will pop the address on top of the stack and jumps to it. This will make the wanted jump to the\r\nresolved API with no call instruction. Furthermore, after executing the resolved API code, the flow resumes at\r\nthe previously saved address of the manually built stack frame (step no. 2). This will make the flow resume at the\r\ninstruction after the ret , successfully returning back to the previous normal flow before the int 3 instruction.\r\nNot to forget, this technique makes the dynamic code analysis harder, because you will deal with hundreds of\r\ndebugger traps everywhere in the code.\r\nMoreover, inserting ret instructions everywhere in the code tricks the disassemblers when trying to identify\r\nfunctions. Some disassemblers use ret instructions to identify the end of the functions. This makes another layer\r\nof complication using this anti-disassembly technique.\r\nTo overcome all this, we need to create a script which parses the code section of the sample, in order to fix those\r\ncomplication. We can create a small IDA Python script to search for the opcodes int 3 and ret , and then\r\npatch them to be call EAX . This means that we are looking for the bytes 0xCCC3 , then we patch them to be\r\n0xFFD0 . The script is below:\r\nimport idautils\r\nimport idaapi\r\nimport ida_search\r\ndef get_text_section ():\r\n for seg in idautils.Segments():\r\n if idc.get_segm_name(seg) == \".text\":\r\n return [idc.get_segm_start(seg), idc.get_segm_end(seg)]\r\ndef search_N_patch(pattern, patch):\r\n search_range = []\r\n search_range = get_text_section()\r\n flag = True\r\n while(flag):\r\n addr = ida_search.find_binary(search_range[0], search_range[1], pattern, 16, ida_search.SEARCH_DOWN)\r\n idc.patch_word(addr,patch)\r\n if (addr == ida_idaapi.BADADDR or addr \u003e= search_range[1]):\r\n flag = False\r\npattern = 'cc c3' # int 3 ret\r\npatch = 0xd0ff # call eax (Little Endian)\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 7 of 12\n\nsearch_N_patch(pattern,patch)\r\nPS: This script only alters the IDA database and not the actual binary. To patch the sample in order to open it in a\r\ndebugger, use the pefile python library instead.\r\nNow, using hashdb as well as our IDA Python script, we have a better chance to understand Dridex functionality.\r\nFirst, we edit the data types of the mw_API_Resolver arguments to be hashdb_strings_crc32 enum instead of\r\nintegers. This in order to make IDA Pro automatically resolve the hashes, Secondly, we use IDA Pro Xrefs to\r\nknow which API is being resolved at any particular location.\r\nStrings DecryptionPermalink\r\nDridex contains a lot of malicious functionality. From simple host profiling up to DLL hijacking, there are a lot to\r\ncover when reversing Dridex. I will not dive deeply into all of its functionality, I will rather focus on the\r\ninteresting parts only. To get the most of its intentions, you need to decrypt all the embedded strings. They are\r\nstored on the .rdata section in chunks. These strings are used as parameters with the resolved APIs to perform\r\ncertain malicious impact.\r\nFigure(8): The key is initialized in the KSA part of the RC4. Check the wiki page.\r\nWe can use the amazing capa tool from Mandiant to find out if it can detect any encryption algorithms.\r\nFortunately, capa was able to identify RC4 is being used at sub_61E5D0 . Also, from capa’s output, we can detect\r\nthe operation: “key modulo its length” at the address 0x61E657 .\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 8 of 12\n\nFigure(9): The first renamed function just copies memory from certain source to defined destination.\r\nFrom here, we can trace the Xrefs to sub_61E5D0 to find out where the key is located and what is the key length.\r\nTaking the last Xref, at sub_607B30 , we can trace back the function arguments to find that the key is loaded from\r\na certain offset at the .rdata section. The key length is 40 bytes and the data to decrypted starts after the key. As\r\na consequence, we can deduce that for every chunk of data, their decryption key is the first 40 bytes then followed\r\nby the encrypted data. Also from other threat intel resources, we can know that Dridex stores the decryption key\r\nbytes in a reverse order.\r\nFigure(10): It's always a good habit to quickly test decryption using CyberChef before developing scripts.\r\nLet’s try to use CyberChef to manually decrypt the data at the address 0X629BC0 . The key starts at 0X629BC0\r\nwith a length of 40 bytes in a reverse order. The encrypted data starts at 0X629BE8 . We can see the fully\r\ndecrypted strings clearly now. The first two words are “Program Manager”. That’s why I didn’t prefer to reverse\r\nall of Dridex functionality. The more important is to find out how the decryption is happening and then you can\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 9 of 12\n\ndecipher any code snippets. From this point, you can try yourself to decrypt every chunk of data and find out how\r\nthey are being used for every malicious impact.\r\nDridex of course tries to connect with its threat actor. It’s a must to find these remote ends in order to block them\r\nand cut out the lines between the malware operators and the infected machines. One way to find out the C\u0026C\r\nservers, is to look for where networking functions are being called. From Xrefs to mw_API_Resolver , we can find\r\nthat there are two important functions which are responsible for networking functionality; sub_623370 and\r\nsub_623820 . At sub_623820 , it seems that it is used for further download activity, because it’s resolving the\r\nInternetReadFile API. Inside sub_623370 , we can see Dridex is resolving InternetConnectW API which\r\naccepts the lpszServerName parameter. This parameter identifies the remote end to where the connection is\r\nhappening.\r\nFigure(11): This chuck of code is a little before the Xref.\r\nTracing the only Xref to sub_623370 , we can spot Dridex parsing a data offset to extract the embedded IPs. This\r\nis at the address 0X5F7232 just a little before the call to sub_623370 .\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 10 of 12\n\nFigure(12): This pattern is repeated starting from (c2_array) to store the whole 4 IPs and their associated ports.\r\nThe network configuration is not encrypted. Starting at offset 0X62B024 . The ports can be converted via simple\r\nhex to decimal conversion. Yet, for the IPs we can use this small Python script to convert them into a human-readable format:\r\nimport socket\r\nimport struct\r\ndef int2ip(addr):\r\n return socket.inet_ntoa(struct.pack(\"!I\", addr))\r\nprint(int2ip(0xC02ED2DC)) # First IP\r\nThe extracted C\u0026C IPs are below:\r\nNo IP Address : Port Number\r\n1 192.46.210.220:443\r\n2 143.244.140.214:808\r\n3 45.77.0.96:6891\r\n4 185.56.219.47:8116\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 11 of 12\n\nConclusionPermalink\r\nThe techniques of Dridex are somehow unique when combined together. We can easily defeat API hashing once\r\nwe know the hashing algorithm and the XOR key. The use of VEH makes the reverse engineering process very\r\npainful and needs urgent patching. Dridex has a lot of capabilities and techniques, I’ve decided to rather focus on\r\ndefeating anti-analysis and strings decryption. From there, you are able to identify any of its intentions.\r\nIoCsPermalink\r\nNo Description Value\r\n1\r\nUnpacked\r\nSample\r\nHash\r\nF9495E968F9A1610C0CF9383053E5B5696ECC85CA3CA2A338C24C7204CC93881\r\n2 1st C2 192.46.210.220:443\r\n3 2nd C2 143.244.140.214:808\r\n4 3rd C2 45.77.0.96:6891\r\n5 4th C2 185.56.219.47:8116\r\n6 Botnet ID 10444\r\nRefrencesPermalink\r\nhttps://www.0ffset.net/reverse-engineering/malware-analysis/dridex-veh-api-obfuscation/\r\nhttps://www.appgate.com/blog/reverse-engineering-dridex-and-automating-ioc-extraction\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nSource: https://cyber-anubis.github.io/malware%20analysis/dridex/\r\nhttps://cyber-anubis.github.io/malware%20analysis/dridex/\r\nPage 12 of 12",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://cyber-anubis.github.io/malware%20analysis/dridex/"
	],
	"report_names": [
		"dridex"
	],
	"threat_actors": [
		{
			"id": "5e6b31a6-80e3-4e7d-8b0a-d94897ce9b59",
			"created_at": "2024-06-19T02:03:08.128175Z",
			"updated_at": "2026-04-10T02:00:03.636663Z",
			"deleted_at": null,
			"main_name": "GOLD TAHOE",
			"aliases": [
				"Cl0P Group Identity",
				"FIN11 ",
				"GRACEFUL SPIDER ",
				"SectorJ04 ",
				"Spandex Tempest ",
				"TA505 "
			],
			"source_name": "Secureworks:GOLD TAHOE",
			"tools": [
				"Clop",
				"Cobalt Strike",
				"FlawedAmmy",
				"Get2",
				"GraceWire",
				"Malichus",
				"SDBbot",
				"ServHelper",
				"TrueBot"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "75d4d6a9-b5d1-4087-a7a0-e4a9587c45f4",
			"created_at": "2022-10-25T15:50:23.5188Z",
			"updated_at": "2026-04-10T02:00:05.26565Z",
			"deleted_at": null,
			"main_name": "TA505",
			"aliases": [
				"TA505",
				"Hive0065",
				"Spandex Tempest",
				"CHIMBORAZO"
			],
			"source_name": "MITRE:TA505",
			"tools": [
				"AdFind",
				"Azorult",
				"FlawedAmmyy",
				"Mimikatz",
				"Dridex",
				"TrickBot",
				"Get2",
				"FlawedGrace",
				"Cobalt Strike",
				"ServHelper",
				"Amadey",
				"SDBbot",
				"PowerSploit"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "99cb4e5b-8071-4f9e-aa1d-45bfbb6197e3",
			"created_at": "2023-01-06T13:46:38.860754Z",
			"updated_at": "2026-04-10T02:00:03.125179Z",
			"deleted_at": null,
			"main_name": "TA505",
			"aliases": [
				"SectorJ04",
				"SectorJ04 Group",
				"ATK103",
				"GRACEFUL SPIDER",
				"GOLD TAHOE",
				"Dudear",
				"G0092",
				"Hive0065",
				"CHIMBORAZO",
				"Spandex Tempest"
			],
			"source_name": "MISPGALAXY:TA505",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "e447d393-c259-46e2-9932-19be2ba67149",
			"created_at": "2022-10-25T16:07:24.28282Z",
			"updated_at": "2026-04-10T02:00:04.921616Z",
			"deleted_at": null,
			"main_name": "TA505",
			"aliases": [
				"ATK 103",
				"Chimborazo",
				"G0092",
				"Gold Evergreen",
				"Gold Tahoe",
				"Graceful Spider",
				"Hive0065",
				"Operation Tovar",
				"Operation Trident Breach",
				"SectorJ04",
				"Spandex Tempest",
				"TA505",
				"TEMP.Warlock"
			],
			"source_name": "ETDA:TA505",
			"tools": [
				"Amadey",
				"AmmyyRAT",
				"AndroMut",
				"Azer",
				"Bart",
				"Bugat v5",
				"CryptFile2",
				"CryptoLocker",
				"CryptoMix",
				"CryptoShield",
				"Dridex",
				"Dudear",
				"EmailStealer",
				"FRIENDSPEAK",
				"Fake Globe",
				"Fareit",
				"FlawedAmmyy",
				"FlawedGrace",
				"FlowerPippi",
				"GOZ",
				"GameOver Zeus",
				"GazGolder",
				"Gelup",
				"Get2",
				"GetandGo",
				"GlobeImposter",
				"Gorhax",
				"GraceWire",
				"Gussdoor",
				"Jaff",
				"Kasidet",
				"Kegotip",
				"Kneber",
				"LOLBAS",
				"LOLBins",
				"Living off the Land",
				"Locky",
				"MINEBRIDGE",
				"MINEBRIDGE RAT",
				"MirrorBlast",
				"Neutrino Bot",
				"Neutrino Exploit Kit",
				"P2P Zeus",
				"Peer-to-Peer Zeus",
				"Philadelphia",
				"Philadephia Ransom",
				"Pony Loader",
				"Rakhni",
				"ReflectiveGnome",
				"Remote Manipulator System",
				"RockLoader",
				"RuRAT",
				"SDBbot",
				"ServHelper",
				"Shifu",
				"Siplog",
				"TeslaGun",
				"TiniMet",
				"TinyMet",
				"Trojan.Zbot",
				"Wsnpoem",
				"Zbot",
				"Zeta",
				"ZeuS",
				"Zeus"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434213,
	"ts_updated_at": 1775792197,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/07de03e7f9a2c7ecb34b0063cfff43aaab5ef451.pdf",
		"text": "https://archive.orkl.eu/07de03e7f9a2c7ecb34b0063cfff43aaab5ef451.txt",
		"img": "https://archive.orkl.eu/07de03e7f9a2c7ecb34b0063cfff43aaab5ef451.jpg"
	}
}