{
	"id": "a14f2295-0596-4371-bc22-2214751d45c4",
	"created_at": "2026-04-06T00:17:22.885568Z",
	"updated_at": "2026-04-10T13:11:34.478108Z",
	"deleted_at": null,
	"sha1_hash": "a370c9e1f5d24dcbd5d1780341cd961d2d444dd8",
	"title": "Dridex Loader Analysis",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1022134,
	"plain_text": "Dridex Loader Analysis\r\nArchived: 2026-04-05 20:47:02 UTC\r\nIntroduction\r\nDridex is an old banking Trojan that appeared in 2014 and is still very active today. This is mainly due to its\r\nevolution and its complex design/architecture based on proxy layers to hide the main command and control\r\n(C\u0026C). This article is a detailed analysis of the Dridex loader found in the wild earlier this year (2021).\r\nThe first part is about anti-debug bypass and string/API recovery and the second part is more focused on the\r\nloader functionality.\r\nAnti-debug - RtlAddVectoredExceptionHandler\r\nAt the beginning of the Dridex loader code, a function is registered using the native API\r\nRtlAddVectoredExceptionHandler to handle all the exceptions raised by the \"int 3\" instructions placed\r\neverywhere in the loader:\r\nint_3\r\nThis instruction is always followed by the \"ret\" instruction, preceded by push instructions and a function that takes\r\ntwo DWORDs. This function is actually a custom \"GetProcAddress\" API and int 3 is a trampoline to execute\r\nthe previously resolved API via the registered exception handler.\r\nThe handler checks if the Exception Code is EXCEPTION_BREAKPOINT and modifies the ESP register in the\r\nPCONTEXT structure accordingly for the next ret instruction to execute the real API:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 1 of 34\n\nPCONTEXT_struct\r\nTo get a better control flow graph and to avoid having your debugger break for each API, a small IDA script can\r\nbe made to find and patch at runtime all the int 3; ret instructions by call eax :\r\nfrom idaapi import get_segm_by_name\r\nfrom idc import patch_byte, add_bpt, set_bpt_cond, BPT_EXEC, load_and_run_plugin\r\nimport ida_search\r\nload_and_run_plugin(\"idapython\", 3)\r\ndef find_all_occurences(start, end, bin_str, flags):\r\n occurences = list()\r\n ea = start\r\n while ea \u003c= end:\r\n occurence = ida_search.find_binary(ea, end, bin_str, 0, flags)\r\n ea = occurence + 1\r\n occurences.append(occurence)\r\n return occurences[0:-1]\r\ndef patch_binary():\r\n segment = get_segm_by_name('.text')\r\n occurences = find_all_occurences(segment.start_ea, segment.end_ea, \"CC C3\", ida_search.SEARCH_DOWN)\r\n datas = [0xFF, 0xD0]\r\n for occurence in occurences:\r\n for i, byte in enumerate(datas):\r\n patch_byte(occurence + i, byte)\r\n return True\r\nAPIs\r\nAs usual, all the API names are obfuscated and as mentioned earlier, addresses are resolved without using the\r\nclassical GetProcAddress. Instead, loaded libraries are parsed and functions names are enumerated from the PE\r\nexport directory header until the CRC32 of the name XORed with a hard-coded key match:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 2 of 34\n\nEnumerates_exports_functions\r\nBefore resolving the API, the loader checks if the module is loaded using the PEB and PEB_LDR_DATA\r\nstructures:\r\nlist_of_loaded_modules\r\nOnce again, it uses a combination of CRC32 and XOR with the same hard-coded key to check the module name.\r\nIf the module is not loaded, it enumerates DLLs in the Windows directory using the\r\nGetSystemWow64DirectoryW and FindFirstFileExW/FindNextFileW APIs and loads it using LdrLoadDLL:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 3 of 34\n\nfind_DLLs\r\nThe following Python script can be used to find which DLL and API are resolved:\r\nimport json\r\nimport zlib\r\nimport sys\r\n# python3 resolve_api_hash.py 0x588AB3EA 0x649746EC\r\n# ntDLL.DLL -\u003e NtProtectVirtualMemory\r\nlib_hash = sys.argv[1]\r\nfunc_hash = sys.argv[2]\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 4 of 34\n\nwith open('exports.json', 'r') as f: # {\"shell32.DLL\": [\"AppCompat_RunDLLW\", \"AssocCreateForClasses\", ....}\r\n apis = json.loads(f.read())\r\nxor_key = 0x38BA5C7B # To change\r\nxor_func_hash = xor_key ^ int(func_hash, 16)\r\nxor_lib_hash = xor_key ^ int(lib_hash, 16)\r\nfor lib, funcs in apis.items():\r\n crc = zlib.crc32(lib.upper().encode('utf-8'))\r\n if crc == xor_lib_hash:\r\n for func in funcs:\r\n crc = zlib.crc32(func.encode('utf-8'))\r\n if crc == xor_func_hash:\r\n print(\"%s -\u003e %s\" % (lib, func))\r\nStrings\r\nStrings are decrypted using a function that takes 3 parameters ( char *output, char *enc_strings, int\r\nstring_index ):\r\ndecrypt_strings\r\nThis function decrypts the enc_strings buffer using the RC4 algorithm with a key located in the first 0x28 bytes\r\n(in reverse order). Then the index selects the strings to return in the output:\r\nSOFTWARE/TrendMicro/Vizor\\x00\\\\VizorUniclientLibrary.DLL\\x00ProductPath\\x00\\x00\r\nThe algorithm can be summed up to the following Python script:\r\nimport sys\r\nfrom Crypto.Cipher import ARC4\r\nfilepath = sys.argv[1]\r\nwith open(filepath, 'rb') as f:\r\n datas = f.read()\r\nrc4_key = datas[0:0x28]\r\nrc4_key = rc4_key[::-1]\r\narc4 = ARC4.new(rc4_key)\r\ndata = arc4.decrypt(datas[0x28:])\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 5 of 34\n\nprint(data)\r\nSystem information\r\nVery early in the code, a function is in charge of gathering information about the infected system. This information\r\nis stored in a global structure and used when needed for other operations. Below are more details on the gathered\r\ninformation:\r\nOperating version\r\nThe build number, the Windows version and the product type are collected through the GetVersionExW function:\r\nGetVersionExW\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 6 of 34\n\nProcess architecture\r\nThe current process architecture is obtained using IsWow64Process:\r\nIsWow64Process\r\nProcess privilege\r\nThe Dridex loader checks his privilege level by comparing the current process token group SID to the local\r\nadministrator SID (S-1-5-32-544). It uses the GetTokenInformation API with TokenGroups as Token\r\nInformation:\r\ngettokeninformation\r\nFinally, Dridex allocates the local administrator SID using AllocateAndInitializeSid and compares it using\r\nEqualSid:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 7 of 34\n\nAllocateAndInitializeSid\r\nUAC level\r\nDridex checks in the registry SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System the values\r\nEnableLUA, ConsentPromptBehaviorAdmin, PromptOnSecureDesktop and attributes a level from 0 to 5\r\nbased on the results:\r\nCheck_UAC\r\nTokenElevation\r\nUsing OpenProcessToken and GetTokenInformation with the parameter TokenElevation, Dridex checks if the\r\ncurrent process has elevated privileges:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 8 of 34\n\nTokenElevation\r\nSessionId\r\nDridex also gets the Terminal Services session ID associated with the current process:\r\nSessionId\r\nProcess Integrity Level\r\nSimilarly, Dridex get the process integrity level using GetTokenInformation with the parameter\r\nTokenIntegrityLevel, then attributes a level from 1 to 7 based on the results:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 9 of 34\n\nProcess Integrity Level\r\nSystem Info\r\nFinally, Dridex calls GetSystemInfo to get information on:\r\nNumber of processors;\r\nPage size;\r\nMinimum application address;\r\nMaximum application address;\r\nAllocation granularity.\r\nGetSystemInfo\r\nFinal information structure\r\nAt the end of the function, we get the following structure:\r\n00000000 info_Struct struc ; (sizeof=0x30, mappedto_36)\r\n00000000 major_plus_minor dd ?\r\n00000004 buildnumber dd ?\r\n00000008 dwMajorVersion db ?\r\n00000009 dwMinorVersion db ?\r\n0000000A ServicePackMajor db ?\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 10 of 34\n\n0000000B x64_x32_bit db ?\r\n0000000C productType dw ?\r\n0000000E dwNumberOfProcessors dw ?\r\n00000010 dwPageSize dd ?\r\n00000014 lpMinimumApplicationAddress dd ?\r\n00000018 lpMaximumApplicationAddress dd ?\r\n0000001C dwAllocationGranularity dd ?\r\n00000020 SessionId dd ?\r\n00000024 UAC_level dd ?\r\n00000028 SID_local_administrator db ?\r\n00000029 TokenElevation db ?\r\n0000002C RID_level dd ?\r\n00000030 info_Struct ends\r\nC\u0026C Requests\r\nThe Dridex loader talks to its C\u0026Cs to download the core module and the node list. The communication is\r\nencrypted using RC4 and the protocol used is HTTPS. Below is a more detailed explanation of how the function\r\ndoes this job. First, it takes a hash in its parameters that will later identify the request type:\r\nMake_CnC_Requests\r\nBy parsing the .data section, it builds a structure with the bot ID and a list of hard-coded IPs:\r\n00000000: ff ff ff ff 01 00 00 00 00 00 00 00 00 00 00 00 ................\r\n00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................\r\n00000020: f3 73 10 57 [7f 27 00 00] 00 7a 01 [03][51 a9 e0 de] .s.W.'...z..Q...\r\n00000030: [3d 0d][3e 4b a8 6a][2e 0f][52 a5 98 7f][3d 0d] d6 ec =.\u003eK.j..R...=...\r\nBot_Id: [7f 27 00 00] -\u003e 10111\r\nIPs (0x03):\r\n[51 a9 e0 de][3d 0d] -\u003e 81.169.224.222:3389\r\n[3e 4b a8 6a][2e 0f] -\u003e 62.75.168.106:3886\r\n[52 a5 98 7f][3d 0d] -\u003e 82.165.152.127:3389\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 11 of 34\n\nGenerate_IPs\r\nThen, it starts building the requests to be sent to the C\u0026Cs in binary format using previously gathered\r\ninformation. The request looks like this:\r\n00000000: [2b][58 58 58 58 58 58 58 58 58 58 5f 63 35 39 31 +XXXXXXXXXX_c591\r\n00000010: 39 35 34 37 30 31 39 31 64 64 66 34 63 30 66 39 95470191ddf4c0f9\r\n00000020: 65 35 34 65 33 33 30 34 36 33 38 36][32 63 33 38 e54e330463862c38\r\n00000030: 61 39 66 30 30 38 64 61 63 39 61 36 63 64 37 39 a9f008dac9a6cd79\r\n00000040: 38 36 66 62 39 66 65 64 66 62 62 32][00 6f][1d b0 86fb9fedfbb2.o..\r\n00000050: f0 11][01 1f 04 11][40] 00 00 [03 3f][49 6e 74 65 6c ......@...?Intel\r\n00000060: ...skip...\r\n00000390: 69 6e 67 20 70 61 74 68 3a 20] 00 00 [07 4e][41 4c ing path: ...NAL\r\n000003a0: ....skip..\r\n00000ae0: 72 3d 43 3a 5c 57 69 6e 64 6f 77 73] r=C:\\Windows\r\nFrom left to right, the fields are the following:\r\nlen(unique_account);\r\nunique_account;\r\nunique_system_hash;\r\nbot_id;\r\nsys_info;\r\ncommand;\r\nprocess_arch;\r\nlen(process_installed);\r\nprocess_installed;\r\nlen(envs);\r\nenvs.\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 12 of 34\n\nThe unique_account field is the concatenation of the Computer Name and the MD5 hash of the following\r\nexpression: md5(computer_name + user_name + \\x00 + \\x00\\x00 + installdate + \\x00\\x00) .\r\nThe unique_system_hash is also an MD5 hash: md5(serial volume + install date + arch + \\x00\\x00) .\r\nThe sys_info field is built using the following code:\r\nsys_info_field\r\nIn this example, [1d b0] (7600) is the Windows build number, [f0] is a bit field that depends on the current\r\nproduct types, process architecture, UAC flag and Administrator rights. [11] indicates the Windows version\r\n((majorversion \u003c\u003c 4 - 0x50) + minorversion) .\r\nThe command field is the command name CRC32 code (e.g. \"bot\" == 0x11041f01) and it is given as a parameter.\r\nThe following commands were found in the loader:\r\n0x11041f01 -\u003e (\"bot\");\r\n0x18F8C844 -\u003e (\"list\");\r\n0x745A17F5 -\u003e (\"mod9\" -\u003e TrendMicro Exclusion vulnerability);\r\n0xD3EF7577 -\u003e (\"dmod5\" -\u003e DllLoaded);\r\n0x69BE7CEE -\u003e (\"dmod6\" -\u003e DllStarted);\r\n0x32DC1DF8 -\u003e (\"dmod11\" -\u003e StartedInHi).\r\nThe process_installed field is extracted from the following registry:\r\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\r\nThe envs field is generated using the GetEnvironmentStringsW API.\r\nBefore sending the request, the payload is encrypted using RC4 (the key comes from the recovered strings) and\r\nprepended by its CRC32 code:\r\nRC4_key\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 13 of 34\n\nThe request is sent in a POST message using the WinINet library (InternetOpenA, InternetConnectW,\r\nHttpOpenRequestW, HttpSendRequestW):\r\nPOST_methods\r\nThe answer is read by calling the InternetReadFile function and if the response code is 200 or 404, the content is\r\ndecrypted using RC4 with the same RC4 key as for encrypting the payload:\r\nrc4_decrypt_rep_content\r\nThe response always starts with a CRC32 code of the content, followed by the content itself, which is RC4-\r\nencrypted with the same key as for sending the command.\r\nBot command\r\nOnce decrypted, the \"bot\" command response reveals an RSA signature (0x80 bytes long) and the Dridex \"core\"\r\nDLL at offset 0x80:\r\n00000000: 921c 0824 eef2 954a a522 5014 0384 e394 ...$...J.\"P.....\r\n00000010: b053 b2ce a5fd aeef 6796 bd1c 5edd 764d .S......g...^.vM\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 14 of 34\n\n00000020: 2c28 ea58 7e40 2132 8389 5259 333b 9d80 ,(.X~@!2..RY3;..\r\n00000030: bcfa 5af5 9eeb 0ac0 22c8 e079 1510 b48e ..Z.....\"..y....\r\n00000040: d53c e43f b9d7 19ea 23a9 8e2e 4f9f 0397 .\u003c.?....#...O...\r\n00000050: c3a5 d586 f1b0 864b 5b2e 03e7 3750 b371 .......K[...7P.q\r\n00000060: 3e42 f62b f1da f555 954e 4bee fae7 823c \u003eB.+...U.NK....\u003c\r\n00000070: 2a7a 812c ba90 cfba bf0a 8965 2a5c 122d *z.,.......e*\\.-\r\n00000080: 4d5a 9000 0300 0000 0400 0000 ffff 0000 MZ..............\r\n00000090: b800 0000 0000 0000 4000 0000 0000 0000 ........@.......\r\n000000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................\r\n000000b0: 0000 0000 0000 0000 0000 0000 8401 0000 ................\r\n000000c0: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468 ........!..L.!Th\r\n000000d0: 6973 2070 726f 6772 616d 2063 616e 6e6f is program canno\r\n000000e0: 7420 6265 2072 756e 2069 6e20 444f 5320 t be run in DOS\r\n000000f0: 6d6f 6465 2e0d 0d0a 2400 0000 0000 0000 mode....$.......\r\n00000100: d006 fb75 9467 9526 9467 9526 9467 9526 ...u.g.\u0026.g.\u0026.g.\u0026\r\n00000110: 9935 4826 2567 9526 21f9 4b26 da66 9526 .5H\u0026%g.\u0026!.K\u0026.f.\u0026\r\n00000120: f289 5926 e667 9526 0f8c 5b26 6a66 9526 ..Y\u0026.g.\u0026..[\u0026jf.\u0026\r\n00000130: ...skip...\r\nThis signature is in the PKCS#1 v1.5 SHA1withRSA format. It can be used to verify the payload content using an\r\nRSA1024 public key found in the decrypted strings from the core DLL:\r\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA9pRumL/WGRvdjoENFuUFZi/f\r\nOB4AaC5yUmFnTYON2qothUQiLagPsXnVNPC/lF30qb/DJbdkWk4i4nbm715TE1np\r\ncmC9Fm4Dh9IPFpaFAuI73R6ywzxsSodkfHqDlS8N0Nf69sOX58bSf96IPKSGY2FV\r\nra3DZaYLeH6S7EwinQIDAQAB\r\nopenssl dgst -sha1 -verify public.pem -signature signature_core 200_rep_content_bot_decoded_mz.bin\r\nVerified OK\r\nNode list command\r\nThe decrypted \"list\" command response is not as easy as the \"bot\" command to understand:\r\n00000000: 4ea7 8684 7e01 2b49 f3df 2efa e02d 9621 N...~.+I.....-.!\r\n00000010: 05e0 6318 e3f7 298a 1d67 e4fa 1349 f7c9 ..c...)..g...I..\r\n00000020: 60b4 06b2 c41c 91a6 4cad 9427 d32e 3775 `.......L..'..7u\r\n00000030: 0f58 bed2 5b92 383a 3b49 8892 0d42 e85b .X..[.8:;I...B.[\r\n00000040: b335 6132 5223 2d3c 4e0e 3b65 0596 f4a6 .5a2R#-\u003cN.;e....\r\n00000050: 4b97 5c79 f4ef 964f 27a9 7654 b67b 65af K.\\y...O'.vT.{e.\r\n00000060: 8f5e 0b02 a61e 521b 1a49 eb19 8af2 c08e .^....R..I......\r\n00000070: 8c37 6e51 cf3c ba62 f249 17ea a816 8c8e .7nQ.\u003c.b.I......\r\n00000080: bd10 3a0d ac9c 7b44 4281 5bda 48e9 05c1 ..:...{DB.[.H...\r\n00000090: b5e4 faeb 8ca2 7554 c375 7803 4b86 c3d5 ......uT.ux.K...\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 15 of 34\n\n000000a0: 3233 3100 7321 c702 213e 953b 6577 011b 231.s!..!\u003e.;ew..\r\n000000b0: 091d 5a91 4b33 6f3e eff2 5ffa 7e38 e389 ..Z.K3o\u003e.._.~8..\r\n000000c0: 4c94 7d02 5077 4143 1c96 e768 9e7e b097 L.}.PwAC...h.~..\r\n000000d0: 2438 1feb 7a46 a694 28f2 cfbb 9a7c f72c $8..zF..(....|.,\r\n000000e0: cfdf b42c b69c 9b4e 97bd 2291 1f1a ec79 ...,...N..\"....y\r\n000000f0: abfe 25fe c13c fefd 131b 0146 40cf 4244 ..%..\u003c.....F@.BD\r\n00000100: d628 00bc f85d f599 5cf2 e27f 58bb c753 .(...]..\\...X..S\r\n00000110: 3be3 2da8 02d1 4ef9 ;.-...N.\r\nThe format is as follows:\r\nCRC32 code of the content (4 Bytes);\r\nSHA1withRSA1024 signature (128 Bytes);\r\nFirst RC4 key (16 Bytes);\r\nContent length, RC4-encrypted (4 Bytes);\r\nSecond RC4 key (16 Bytes);\r\nList content, RC4-encrypted (length Bytes).\r\nThe structure looks like this:\r\n00000000: [4e a7 86 84][7e 01 2b 49 f3 df 2e fa e0 2d 96 21 N...~.+I.....-.!\r\n00000010: 05 e0 63 18 e3 f7 29 8a 1d 67 e4 fa 13 49 f7 c9 ..c...)..g...I..\r\n00000020: 60 b4 06 b2 c4 1c 91 a6 4c ad 94 27 d3 2e 37 75 `.......L..'..7u\r\n00000030: 0f 58 be d2 5b 92 38 3a 3b 49 88 92 0d 42 e8 5b .X..[.8:;I...B.[\r\n00000040: b3 35 61 32 52 23 2d 3c 4e 0e 3b 65 05 96 f4 a6 .5a2R#-\u003cN.;e....\r\n00000050: 4b 97 5c 79 f4 ef 96 4f 27 a9 76 54 b6 7b 65 af K.\\y...O'.vT.{e.\r\n00000060: 8f 5e 0b 02 a6 1e 52 1b 1a 49 eb 19 8a f2 c0 8e .^....R..I......\r\n00000070: 8c 37 6e 51 cf 3c ba 62 f2 49 17 ea a8 16 8c 8e .7nQ.\u003c.b.I......\r\n00000080: bd 10 3a 0d][ac 9c 7b 44 42 81 5b da 48 e9 05 c1 ..:...{DB.[.H...\r\n00000090: b5 e4 fa eb][8c a2 75 54][c3 75 78 03 4b 86 c3 d5 ......uT.ux.K...\r\n000000a0: 32 33 31 00 73 21 c7 02][21 3e 95 3b 65 77 01 1b 231.s!..!\u003e.;ew..\r\n000000b0: 09 1d 5a 91 4b 33 6f 3e ef f2 5f fa 7e 38 e3 89 ..Z.K3o\u003e.._.~8..\r\n000000c0: 4c 94 7d 02 50 77 41 43 1c 96 e7 68 9e 7e b0 97 L.}.PwAC...h.~..\r\n000000d0: 24 38 1f eb 7a 46 a6 94 28 f2 cf bb 9a 7c f7 2c $8..zF..(....|.,\r\n000000e0: cf df b4 2c b6 9c 9b 4e 97 bd 22 91 1f 1a ec 79 ...,...N..\"....y\r\n000000f0: ab fe 25 fe c1 3c fe fd 13 1b 01 46 40 cf 42 44 ..%..\u003c.....F@.BD\r\n00000100: d6 28 00 bc f8 5d f5 99 5c f2 e2 7f 58 bb c7 53 .(...]..\\...X..S\r\n00000110: 3b e3 2d a8 02 d1 4e f9] ;.-...N.\r\nAfter checking that the first 4 bytes are the CRC32 code, it extracts the first RC4 key in 0x84:0x94 just after the\r\nRSA signature (128 bytes). With this key, it can decrypt the next four bytes [8c a2 75 54] to 00 00 00 70 .\r\nThen, the second RC4 key can be extracted (0x98:0xa8) to decrypt the remaining data:\r\ncat 200_rep_content_list_decoded.bin | snip 0xa8: | rc4 h:C37578034B86C3D5323331007321C702 | xxd\r\n00000000: 1f8b 0800 0000 0000 0203 0159 00a6 ff10 ...........Y....\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 16 of 34\n\n00000010: 0000 0054 6bb5 bb4c 01c5 2d91 37aa 01bb ...Tk..L..-.7...\r\n00000020: add4 ced3 01bb 175f 842c 0709 c003 8842 ......._.,.....B\r\n00000030: 01c5 4e52 b1d6 0d73 2d0d c772 01c5 adb7 ..NR...s-..r....\r\n00000040: dad1 01bb ce77 5a31 0d3a bdb3 7eb1 01bb .....wZ1.:..~...\r\n00000050: 5921 a46c 20fb 68a8 d570 0410 83c4 fd94 Y!.l .h..p......\r\n00000060: 01bb c0fa c665 01bb 006b c3f4 5900 0000 .....e...k..Y...\r\nIndeed, the content is gzip-encoded and the first 4 decrypted bytes ( 00 00 00 70 ) are the content size:\r\ncat 200_rep_content_list_decoded.bin | snip 0xa8: | rc4 h:C37578034B86C3D5323331007321C702 | gzip -d | xxd -g 1\r\n00000000: [10][00 00 00 54][6b b5 bb 4c][01 c5][2d 91 37 aa][01 ....Tk..L..-.7..\r\n00000010: bb][ad d4 ce d3][01 bb][17 5f 84 2c][07 09][c0 03 88 ........_.,.....\r\n00000020: 42][01 c5][4e 52 b1 d6][0d 73][2d 0d c7 72][01 c5][ad B..NR...s-..r...\r\n00000030: b7 da d1][01 bb][ce 77 5a 31][0d 3a][bd b3 7e b1][01 ......wZ1.:..~..\r\n00000040: bb][59 21 a4 6c][20 fb][68 a8 d5 70][04 10][83 c4 fd .Y!.l .h..p.....\r\n00000050: 94][01 bb][c0 fa c6 65][01 bb] ......e..\r\nThe first field is a marker (0x10), the second is the node list size and the rest is the list of nodes.\r\nSharing the node list with the core DLL\r\nBecause the decryption is not done in the loader but in the core DLL, it needs a way to share the answer content of\r\nthe list command. This is why the loader uses the Windows registry\r\nSoftware\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s\\shellfolder where %s is a CLISD built\r\nfrom the unique_account hashes with the hard-coded number 0x1c:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 17 of 34\n\nreg_nodes_list_path\r\nThe saved data contains the bot ID ( 7f 27 ], the node list size, the node list and the scheduled tasks URI (details\r\nin the next parts):\r\n00000000: [00 00 00 00][7f 27][18 01][4e a7 86 84 7e 01 2b 49 .....'..N...~.+I\r\n00000010: f3 df 2e fa e0 2d 96 21 05 e0 63 18 e3 f7 29 8a .....-.!..c...).\r\n00000020: 1d 67 e4 fa 13 49 f7 c9 60 b4 06 b2 c4 1c 91 a6 .g...I..`.......\r\n00000030: 4c ad 94 27 d3 2e 37 75 0f 58 be d2 5b 92 38 3a L..'..7u.X..[.8:\r\n00000040: 3b 49 88 92 0d 42 e8 5b b3 35 61 32 52 23 2d 3c ;I...B.[.5a2R#-\u003c\r\n00000050: 4e 0e 3b 65 05 96 f4 a6 4b 97 5c 79 f4 ef 96 4f N.;e....K.\\y...O\r\n00000060: 27 a9 76 54 b6 7b 65 af 8f 5e 0b 02 a6 1e 52 1b '.vT.{e..^....R.\r\n00000070: 1a 49 eb 19 8a f2 c0 8e 8c 37 6e 51 cf 3c ba 62 .I.......7nQ.\u003c.b\r\n00000080: f2 49 17 ea a8 16 8c 8e bd 10 3a 0d ac 9c 7b 44 .I........:...{D\r\n00000090: 42 81 5b da 48 e9 05 c1 b5 e4 fa eb 8c a2 75 54 B.[.H.........uT\r\n000000a0: c3 75 78 03 4b 86 c3 d5 32 33 31 00 73 21 c7 02 .ux.K...231.s!..\r\n000000b0: 21 3e 95 3b 65 77 01 1b 09 1d 5a 91 4b 33 6f 3e !\u003e.;ew....Z.K3o\u003e\r\n000000c0: ef f2 5f fa 7e 38 e3 89 4c 94 7d 02 50 77 41 43 .._.~8..L.}.PwAC\r\n000000d0: 1c 96 e7 68 9e 7e b0 97 24 38 1f eb 7a 46 a6 94 ...h.~..$8..zF..\r\n000000e0: 28 f2 cf bb 9a 7c f7 2c cf df b4 2c b6 9c 9b 4e (....|.,...,...N\r\n000000f0: 97 bd 22 91 1f 1a ec 79 ab fe 25 fe c1 3c fe fd ..\"....y..%..\u003c..\r\n00000100: 13 1b 01 46 40 cf 42 44 d6 28 00 bc f8 5d f5 99 ...F@.BD.(...]..\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 18 of 34\n\n00000110: 5c f2 e2 7f 58 bb c7 53 3b e3 2d a8 02 d1 4e f9] \\...X..S;.-...N.\r\n00000120: [4d 69 63 72 6f 73 6f 66 74 5c 57 69 6e 64 6f 77 Microsoft\\Window\r\n00000130: 73 5c 49 6e 73 74 61 6c 6c 53 65 72 76 69 63 65 s\\InstallService\r\n00000140: 5c 53 6d 61 72 74 52 65 74 72 79 2d 53 2d 31 2d \\SmartRetry-S-1-\r\n00000150: 35 2d 32 31 2d 34 30 37 32 35 37 39 31 36 2d 31 5-21-407257916-1\r\n00000160: 38 33 31 36 35 34 35 30 37 2d 32 36 34 33 30 33 831654507-264303\r\n00000170: 36 33 36 34 2d 31 30 30 31 7c 4d 69 63 72 6f 73 6364-1001|Micros\r\n00000180: 6f 66 74 5c 57 69 6e 64 6f 77 73 5c 57 44 49 5c oft\\Windows\\WDI\\\r\n00000190: 4c 67 77 7a 6f 71 6a] Lgwzoqj\r\nuncrypted_nodes_list_struct\r\nBefore writing the registry value, the original response content of the \"list\" command and its length are encrypted\r\nusing RC4 with two random keys (0x10-byte-long) and the CRC32 code of the content is prepended:\r\n00000000: [ba 3d cc e0][f0 e9 b3 53 b0 46 e0 d2 f2 8e b0 7b .=.....S.F.....{\r\n00000010: fb c2 c8 8d][b2 4b c6][93 30 d0 52 2d 92 66 de da .....K..0.R-.f..\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 19 of 34\n\n00000020: db fd d0 db 18 cc 7b b2][93 ed d6 3b 98 e6 ec 8f ......{....;....\r\n00000030: 84 4d 74 66 48 ab 72 7a f8 08 f2 08 a7 4e 53 3e .MtfH.rz.....NS\u003e\r\n00000040: ce 09 f4 f9 26 93 f2 33 3b 76 db 23 df 91 90 b9 ....\u0026..3;v.#....\r\n00000050: 86 96 f6 3f 5b c1 97 b8 41 32 39 ac 7e 00 94 c0 ...?[...A29.~...\r\n00000060: 0c 35 b7 d7 96 fa b7 57 71 07 63 09 b1 23 e4 72 .5.....Wq.c..#.r\r\n00000070: 6c 5b a3 72 ed 31 e8 f7 62 1e d3 67 06 29 5c aa l[.r.1..b..g.)\\.\r\n00000080: b4 dc 36 18 a8 e4 1f b4 3a e4 5a a0 0b cc aa ba ..6.....:.Z.....\r\n00000090: b3 cc 2c 25 eb cf e5 b4 21 a6 e7 63 64 88 10 1a ..,%....!..cd...\r\n000000a0: c7 44 03 9f bd 87 9e 0c 98 1b 23 5a bc 22 75 4d .D........#Z.\"uM\r\n000000b0: 84 8c 0b d4 c1 8a fb 98 ec bd 60 66 7d 05 89 7f ..........`f}...\r\n000000c0: bf 3b 8c 8f 55 88 5c 59 ed dc bd 53 ee 8f 52 b8 .;..U.\\Y...S..R.\r\n000000d0: 24 9a 34 70 62 87 0a 64 26 83 ff 78 79 2e 2e 25 $.4pb..d\u0026..xy..%\r\n000000e0: e4 8f 3a 75 ad 93 e4 52 21 7f ba 0c b8 25 e7 a7 ..:u...R!....%..\r\n000000f0: f8 7f 31 6b e6 95 72 c5 77 e2 c5 0e 6a 19 98 2a ..1k..r.w...j..*\r\n00000100: 59 01 40 aa 59 d0 cd a3 64 eb d5 00 7d 5e 93 3b Y.@.Y...d...}^.;\r\n00000110: af e1 ad 0c f2 01 b9 c3 dd 45 b9 15 51 f0 33 81 .........E..Q.3.\r\n00000120: 8e 3f 54 41 c5 41 22 96 bf 88 ce 80 e4 ba 97 32 .?TA.A\"........2\r\n00000130: 6d 72 98 7f 24 42 3e b8 63 12 9f 4c 2c b4 73 f8 mr..$B\u003e.c..L,.s.\r\n00000140: 86 58 12 d6 95 d6 59 41 b5 92 c9 0d 23 62 1f 7d .X....YA....#b.}\r\n00000150: 65 c1 a1 b8 1d a8 d5 ad 46 ba 9c 70 5c 9e 40 4d e.......F..p\\.@M\r\n00000160: 21 ab 5b a5 6e 7f 2c d4 5e 8b 38 ef b7 50 6b be !.[.n.,.^.8..Pk.\r\n00000170: 55 4d e0 04 22 6e 15 d2 99 d7 9f fe 0c f5 78 72 UM..\"n........xr\r\n00000180: e3 d5 cf 0b b9 08 bf 10 a7 64 38 d9 e1 0e 9b 57 .........d8....W\r\n00000190: 9b 24 a5 00 c2 ca e3 12 94 35 3c 74 00 49 eb 93 .$.......5\u003ct.I..\r\n000001a0: 41 bf 28 45 1a bf 5d d9 50 87 25 82 d7 1e 17 f6 A.(E..].P.%.....\r\n000001b0: b8 b3 4a 0b 6e 03 e6 76 2e 02 96 12 da a9 70] ..J.n..v......p\r\nFrom left to right, the fields are the following:\r\noriginal content CRC32 code;\r\nfirst random RC4 key;\r\nlength of the original content, RC4-encrypted (with the first RC4 key);\r\nsecond random RC4 key;\r\noriginal content, RC4-encrypted (with the second RC4 key).\r\nAnd finally, it is RC4-encrypted again using the previous generated unique_account hashes with the hard-coded\r\nnumber 0x1c and set using RegSetValueExA:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 20 of 34\n\nRegSetValueExA\r\nThe Dridex core DLL can now access the content.\r\nResponse parsing implementation\r\nBelow are functions that can be used to parse, validate and decrypt the \"list\" and \"bot\" command output:\r\nfrom Crypto.Cipher import ARC4\r\nfrom Crypto.PublicKey import RSA\r\nfrom Crypto.Signature import PKCS1_v1_5\r\nfrom Crypto.Hash import SHA\r\nimport gzip\r\nimport binascii\r\nimport struct\r\ndef validate_decrypt_bot(botcont, rc4k, public_key):\r\n # Check CRC32\r\n crc = binascii.crc32(botcont[4:])\r\n chk = struct.unpack(\"\u003eI\", botcont[:4])[0]\r\n if crc != chk:\r\n print(\"Incorrect CRC32, wrong file ?\")\r\n return None\r\n # Decrypt data\r\n arc4 = ARC4.new(rc4k)\r\n data = arc4.decrypt(botcont[4:])\r\n # Check RSA signature\r\n key = RSA.importKey(public_key)\r\n h = SHA.new(data[0x80:])\r\n verifier = PKCS1_v1_5.new(key)\r\n if not verifier.verify(h, data[:0x80]):\r\n print(\"Incorrect signature, wrong public key?\")\r\n return None\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 21 of 34\n\nreturn data[0x80:]\r\ndef validate_decrypt_list(content, rc4k, public_key):\r\n # Check CRC32\r\n crc = binascii.crc32(content[4:])\r\n chk = struct.unpack(\"\u003eI\", content[:4])[0]\r\n if crc != chk:\r\n print(\"Incorrect CRC32, wrong file?\")\r\n return None\r\n # Decrypt data\r\n arc4 = ARC4.new(rc4k)\r\n data = arc4.decrypt(content[4:])\r\n # Check decrypted CRC32\r\n crc = binascii.crc32(data[4:])\r\n chk = struct.unpack(\"\u003eI\", data[:4])[0]\r\n if crc != chk:\r\n print(\"Incorrect CRC32, wrong key?\")\r\n return None\r\n # Check RSA signature\r\n key = RSA.importKey(public_key)\r\n h = SHA.new(data[0x84:])\r\n verifier = PKCS1_v1_5.new(key)\r\n if not verifier.verify(h, data[0x04:0x84]):\r\n print(\"Incorrect signature, wrong public key?\")\r\n return None\r\n # Decrypt node list length\r\n arc4 = ARC4.new(data[0x84:0x94])\r\n # Decrypt node list\r\n arc4 = ARC4.new(data[0x98:0xA8])\r\n third = arc4.decrypt(data[0xA8:])\r\n list_bot = gzip.decompress(third)\r\n # Parse node list\r\n ret = list()\r\n if list_bot[0] == 0x10:\r\n size = struct.unpack(\"\u003eI\", list_bot[1:5])[0]\r\n if size + 5 == len(list_bot):\r\n for l in range(5, len(list_bot), 6):\r\n j = struct.unpack(\"\u003eBBBBH\", list_bot[l:l+6])\r\n ret.append(\"https://%d.%d.%d.%d:%d/\" % (int(j[0]), int(j[1]), int(j[2]), int(j[3]), int(j[4])))\r\n else:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 22 of 34\n\nprint(\"Length error\")\r\n return None\r\n else:\r\n print(\"Magic error\")\r\n return None\r\n return ret\r\nPersistence and execution of the core DLL\r\nDridex copies a random legitimate program from C:\\Windows\\System32 to a new directory in %AppData%\r\n(randomly named) and the Dridex core DLL is copied to the same folder and renamed to one of the DLLs\r\nimported by the legitimate program. Later on, a scheduled task will run the legitimate binary and one of its DLLs\r\nwill be hijacked by the Dridex core DLL. Below is a more detailed description of how this is done.\r\nDLL hijack\r\nFirst, Dridex scans *.exe files in C:\\Windows\\System32\\ and selects one binary that does not have the property\r\nto AutoElevated. It also enumerates imported DLLs in the binary and checks if the name of one of them matches\r\na CRC32 whitelist:\r\ncheck_import_DLL\r\nBelow are the corresponding DLLs based on the CRC32 whitelist:\r\nACTIVEDS.DLL\r\nAPPWIZ.CPL\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 23 of 34\n\nCREDUI.DLL\r\nD3D10.DLL\r\nD3D10_1.DLL\r\nD3D9.DLL\r\nDPX.DLL\r\nDUI70.DLL\r\nDUSER.DLL\r\nDWMAPI.DLL\r\nDXGI.DLL\r\nDXVA2.DLL\r\nFVEWIZ.DLL\r\nHID.DLL\r\nISCSIDSC.DLL\r\nISCSIUM.DLL\r\nMAGNIFICATION.DLL\r\nMFC42U.DLL\r\nMFPLAT.DLL\r\nMMCBASE.DLL\r\nMSCMS.DLL\r\nMSSWCH.DLL\r\nNDFAPI.DLL\r\nNETPLWIZ.DLL\r\nNEWDEV.DLL\r\nOLEACC.DLL\r\nP2P.DLL\r\nP2PCOLLAB.DLL\r\nQUARTZ.DLL\r\nREAGENT.DLL\r\nSECUR32.DLL\r\nSLC.DLL\r\nSPP.DLL\r\nSQMAPI.DLL\r\nSRCORE.DLL\r\nSRVCLI.DLL\r\nSYSDM.CPL\r\nTAPI32.DLL\r\nUXTHEME.DLL\r\nVERSION.DLL\r\nWER.DLL\r\nWINBRAND.DLL\r\nWINMM.DLL\r\nWINSTA.DLL\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 24 of 34\n\nWMSGAPI.DLL\r\nWTSAPI32.DLL\r\nXMLLITE.DLL\r\nWhen a binary with a matching imported DLL is found, the legitimate DLL export directory content replaces the\r\nmissing one in the core DLL:\r\noriginal_core_DLL\r\nnew_core_DLL_data_dir\r\nnew_core_DLL_export_dir\r\nThe core DLL is copied to a new directory (randomly named) in AppData\\Roaming and the DLL filename is\r\nborrowed from the legitimate one.\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 25 of 34\n\nappdata_roaming_write\r\nThe selected legitimate binary is also copied in the same directory:\r\nls_roaming_dir\r\nEverything is set up for the scheduled task.\r\nTask scheduler\r\nDepending on the process privilege, one or two scheduled tasks are registered. The function which registers the\r\nscheduled task uses a COM object and the task properties are set using the XML format. Important properties are\r\nset dynamically by the following tags:\r\n\u003cauthor\u003e (specifies the author of the task);\r\n\u003cURI\u003e (specifies where the registered task is placed in the task folder hierarchy);\r\n\u003cUserID\u003e (specifies the user identifier required to run those tasks associated with the principal);\r\n\u003cexec\u003e\u003ccommand\u003e (specifies an action that executes a command line operation).\r\nWith administrator privileges, two scheduled tasks are set. In both cases, the task URI is located in a random dir in\r\nC:\\Windows\\System32\\Tasks\\Microsoft\\Windows\\ :\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 26 of 34\n\nget_task_folder\r\necho -en 'tasks' | crc32 | xor h:38BA5C7B | xxd\r\n00000000: 68e2 39ec h.9.\r\necho -en 'microsoft' | crc32 | xor h:38BA5C7B | xxd\r\n00000000: 0523 75f3 .#u.\r\necho -en 'windows' | crc32 | xor h:38BA5C7B | xxd\r\n00000000: db5d d9e0 .]..\r\nThe difference starts with the URI filename. In the first task, the URI takes a legitimate task file and appends the\r\nuser SID (e.g. \u003cURI\u003e\\Microsoft\\Windows\\CloudExperienceHost\\CreateObjectTask-S-1-5-21-407257916-\r\n1831654507-2643036364-1001\u003c/URI\u003e ):\r\ntask_uri_SID\r\nThe \u003cauthor\u003e element is hard-coded \u003cAuthor\u003e$(@%systemroot%\\system32\\wininet.DLL,-16000)\u003c/Author\u003e .\r\nThe \u003cexec\u003e\u003ccommand\u003e is the path to the binary with the hijacked DLL as seen previously in the\r\nAppData\\Roaming dir:\r\n\u003cExec\u003e\u003cCommand\u003eC:\\Users\\YYYYYYYYYYYY\\AppData\\Roaming\\Xsbzewcltzyxfl\\rstrui.exe\u003c/Command\u003e\u003c/Exec\u003e\r\nOn the second scheduled task, the \u003cURI\u003e starts with the randomly selected dir and the filename is built with a\r\npseudo-random algorithm based on the previously seen unique_account hashes. Basically, it generates MD5\r\nhashes and picks only ASCII letters to build a string until it is long enough:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 27 of 34\n\ngenerate_pseudo_random_strings\r\nThe \u003cauthor\u003e element is a field copy from the randomly selected task in the\r\nC:\\Windows\\System32\\Tasks\\Microsoft\\Windows\\ . To get the value, it scans the XML task file until it finds the\r\n\u003cauthor\u003e tags using the traditional CRC32 code methods:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 28 of 34\n\nget_author_tag\r\necho -en 'author' | crc32 | xor h:38BA5C7B | xxd\r\n00000000: 8515 84b3 ....\r\nIn the second task, the \u003cexec\u003e\u003ccommand\u003e is a random dir in C:\\Windows\\System32 that does not exist at that\r\nmoment. It is still unclear what the purpose of this scheduled task is:\r\nrandom_dir_in_sys32\r\nTo register the task, Dridex uses a COM Object by calling CoCreateInstance to create a TaskService instance:\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 29 of 34\n\nITaskService\r\nThe Connect, getfolder, NewTask and RegisterTaskDefinition methods are called to register the task. Both\r\ntasks are launched at the opening session and every 30 minutes:\r\nFirst_task\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 30 of 34\n\nsecund_task\r\nThe full permission is granted to the task file:\r\nGrant_task_URI_Full_permissions\r\nThe differences with normal privileges are the following:\r\n1. The URI path of the created task is in the task root folder;\r\n2. The name is generated from the pseudo-random function.\r\nMutex\r\nBefore and after the scheduled task is registered, the loader checks the presence of a mutex. If the mutex is found,\r\nit means that the core DLL has been successfully started by the scheduled task and the core DLL is already\r\ninjected in the explorer.exe process. Otherwise, it tries to reschedule a task.\r\nmutex_check\r\nThe mutex name is generated using the same technique as the unique_account with a hard-coded number\r\n( md5(computer_name + user_name + \\x00 + \\x02\\x00 + installdate + \\x00\\x00) ) and formatted as a CLSID.\r\nThe following script can be used to check if your computer is infected.\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 31 of 34\n\nFunction Test-IsMutexAvailable {\r\n \u003c#\r\n from: https://www.powershellgallery.com/packages/PSBuildSecrets/1.0.31/Content/Private%5CTest-IsMutexAvailab\r\n .SYNOPSIS\r\n check if current thread is able to acquire an exclusive lock on a system mutex.\r\n .DESCRIPTION\r\n A mutex can be used to serialize applications and prevent multiple instances from being opened at the sa\r\n Wait, up to a timeout (default is 1 millisecond), for the mutex to become available for an exclusive loc\r\n .PARAMETER MutexName\r\n The name of the system mutex.\r\n .EXAMPLE\r\n Test-IsMutexAvailable -MutexName 'Global\\B475815D-EA35-2753-859C-6D042FE3C161'\r\n .NOTES\r\n This is an internal script function and should typically not be called directly.\r\n #\u003e\r\n [CmdletBinding()]\r\n Param (\r\n [Parameter(Mandatory=$true)]\r\n [ValidateLength(1,500)]\r\n [string]$MutexName\r\n )\r\n Try {\r\n Write-Host \"[+] Check to see if mutex $MutexName is available.\"\r\n ## Using this variable allows capture of exceptions from .NET methods. Private scope only changes value\r\n $private:previousErrorActionPreference = $ErrorActionPreference\r\n $ErrorActionPreference = 'Stop'\r\n ## Open the specified named mutex, if it already exists, without acquiring an exclusive lock on it. If t\r\n [Threading.Mutex]$OpenExistingMutex = [Threading.Mutex]::OpenExisting($MutexName)\r\n $IsMutexExist = $true\r\n $OpenExistingMutex.Close()\r\n }\r\n Catch [Threading.WaitHandleCannotBeOpenedException] {\r\n Write-Host \"The named mutex does not exist\"\r\n $IsMutexFree = $true\r\n $IsMutexExist = $false\r\n }\r\n Catch [ObjectDisposedException] {\r\n Write-Host \"Mutex was disposed between opening it and attempting to wait on it\"\r\n $IsMutexFree = $true\r\n $IsMutexExist = $true\r\n }\r\n Catch [UnauthorizedAccessException] {\r\n Write-Host \"The named mutex exists, but the user does not have the security access required to use it\"\r\n $IsMutexFree = $false\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 32 of 34\n\n$IsMutexExist = $true\r\n }\r\n Catch [Threading.AbandonedMutexException] {\r\n Write-Host \"The wait completed because a thread exited without releasing a mutex. This exception is thro\r\n $IsMutexFree = $true\r\n $IsMutexExist = $true\r\n }\r\n Catch {\r\n $IsUnhandledException = $true\r\n Write-Host \"Return $true, to signify that mutex is available, because function was unable to successfull\r\n Write-Verbose \"Unable to check if mutex [$MutexName] is available due to an unhandled exception. Will de\r\n $IsMutexFree = $true\r\n $IsMutexExist = $true\r\n }\r\n $HashObject = @{\r\n MutexName = $MutexName\r\n IsMutexExist = $IsMutexExist\r\n }\r\n $Result += New-Object PSObject -Property $HashObject\r\n return $Result\r\n}\r\n$enc = [system.Text.Encoding]::UTF8\r\n$datas = $enc.GetBytes($env:ComputerName) + $enc.GetBytes($env:UserName) + [byte]0x00 + [byte]0x02 + [byte]0x00\r\n$date = Get-ItemProperty -Path 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\' | select -ExpandProperty In\r\n$x = [BitConverter]::GetBytes($date)\r\n$datas = $datas + $x + [byte]0x00 + [byte]0x00\r\n$md5 = [System.Security.Cryptography.MD5]::Create(\"MD5\")\r\n$md5.TransformFinalBlock($datas, 0, $datas.length)\r\n$hash_txt = ''\r\n$md5.Hash | foreach {\r\n $hash_txt += '{0:X2}' -f $_\r\n}\r\n$hash_guid = [System.guid]::New($hash_txt)\r\n$hash_guid = '{' + $hash_guid + '}'\r\nWrite-Host \"[---------------- Mutex ----------------]\"\r\n$IsMutexExist = Test-IsMutexAvailable -MutexName $hash_guid\r\nWrite-Host $IsMutexExist\r\nOutput on an uncompromised system:\r\n[---------------- Mutex ----------------]\r\n[+] Check to see if mutex {879f371e-fa61-7ba4-a4ab-805bbe55a0c7} is available.\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 33 of 34\n\nThe named mutex does not exist\r\n@{MutexName={879f371e-fa61-7ba4-a4ab-805bbe55a0c7}; IsMutexExist=False}\r\nOutput on a compromised system:\r\n[---------------- Mutex ----------------]\r\n[+] Check to see if mutex {879f371e-fa61-7ba4-a4ab-805bbe55a0c7} is available.\r\n@{MutexName={879f371e-fa61-7ba4-a4ab-805bbe55a0c7}; IsMutexExist=True}\r\nConclusion\r\nDridex loader techniques are common and do not integrate any novel features. The string and API obfuscating\r\nmechanisms are very standard but the anti-debug technique using Vector Exception Handler can be very painful\r\nwithout any sort of bypass, because it is on every API call. The network communication with the C\u0026C combines\r\nHTTPS with RC4. Moreover, the binary format makes it very hard to understand without any sort of reverse\r\nengineering. Finally, the persistence mechanism using the scheduled task is also common, but the use of DLL\r\nhijacking makes it very effective.\r\nIOCs\r\nSample hash\r\nSHA256: 7b38b9c14389d7c57591a3aa4ae8a8f847ff7314f40e9cd2987ee5d4d22e84e9\r\nSHA1: a1a07f9d5801b73214ce5d3675faaeb1e4a70c02\r\nMD5: 509000b87e20c31a8975a035ba8af42c\r\nC\u0026C Server\r\n81.169.224.222:3389\r\n62.75.168.106:3886\r\n82.165.152.127:3389\r\nSource: https://blog.lexfo.fr/dridex-malware.html\r\nhttps://blog.lexfo.fr/dridex-malware.html\r\nPage 34 of 34\n\nMake_CnC_Requests By parsing the .data section, it builds a structure with the bot ID and a list of hard-coded IPs:\n00000000: ff ff ff ff 01 00 00 00 00 00 00 00 00 00 00 00 ................\n00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................\n00000020: f3 73 10 57 [7f 27 00 00] 00 7a 01 [03][51 a9 e0 de] .s.W.'...z..Q...\n00000030: [3d 0d][3e 4b a8 6a][2e 0f][52 a5 98 7f][3d 0d] d6 ec =.\u003eK.j..R...=...\nBot_Id: [7f 27 00 00]-\u003e 10111   \nIPs (0x03):    \n[51 a9 e0 de][3d 0d]-\u003e 81.169.224.222:3389  \n[3e 4b a8 6a][2e 0f]-\u003e 62.75.168.106:3886  \n[52 a5 98 7f][3d 0d]-\u003e 82.165.152.127:3389  \n  Page 11 of 34 \n\nThe saved data contains in the next parts): the bot ID ( 7f 27 ], the node list size, the node list and the scheduled tasks URI (details\n00000000: [00 00 00 00][7f 27][18 01][4e a7 86 84 7e 01 2b 49 .....'..N...~.+I\n00000010: f3 df 2e fa e0 2d 96 21 05 e0 63 18 e3 f7 29 8a .....-.!..c...).\n00000020: 1d 67 e4 fa 13 49 f7 c9 60 b4 06 b2 c4 1c 91 a6 .g...I..`.......\n00000030: 4c ad 94 27 d3 2e 37 75 0f 58 be d2 5b 92 38 3a L..'..7u.X..[.8:\n00000040: 3b 49 88 92 0d 42 e8 5b b3 35 61 32 52 23 2d 3c ;I...B.[.5a2R#-\u003c\n00000050: 4e 0e 3b 65 05 96 f4 a6 4b 97 5c 79 f4 ef 96 4f N.;e....K.\\y...O\n00000060: 27 a9 76 54 b6 7b 65 af 8f 5e 0b 02 a6 1e 52 1b '.vT.{e..^....R.\n00000070: 1a 49 eb 19 8a f2 c0 8e 8c 37 6e 51 cf 3c ba 62 .I.......7nQ.\u003c.b\n00000080: f2 49 17 ea a8 16 8c 8e bd 10 3a 0d ac 9c 7b 44 .I........:...{D\n00000090: 42 81 5b da 48 e9 05 c1 b5 e4 fa eb 8c a2 75 54 B.[.H.........uT\n000000a0: c3 75 78 03 4b 86 c3 d5 32 33 31 00 73 21 c7 02 .ux.K...231.s!..\n000000b0: 21 3e 95 3b 65 77 01 1b 09 1d 5a 91 4b 33 6f 3e !\u003e.;ew....Z.K3o\u003e\n000000c0: ef f2 5f fa 7e 38 e3 89 4c 94 7d 02 50 77 41 43 .._.~8..L.}.PwAC\n000000d0: 1c 96 e7 68 9e 7e b0 97 24 38 1f eb 7a 46 a6 94 ...h.~..$8..zF..\n000000e0: 28 f2 cf bb 9a 7c f7 2c cf df b4 2c b6 9c 9b 4e (....|.,...,...N\n000000f0: 97 bd 22 91 1f 1a ec 79 ab fe 25 fe c1 3c fe fd ..\"....y..%..\u003c..\n00000100: 13 1b 01 46 40 cf 42 44 d6 28 00 bc f8 5d f5 99 ...F@.BD.(...]..\n   Page 18 of 34",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://blog.lexfo.fr/dridex-malware.html"
	],
	"report_names": [
		"dridex-malware.html"
	],
	"threat_actors": [],
	"ts_created_at": 1775434642,
	"ts_updated_at": 1775826694,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/a370c9e1f5d24dcbd5d1780341cd961d2d444dd8.pdf",
		"text": "https://archive.orkl.eu/a370c9e1f5d24dcbd5d1780341cd961d2d444dd8.txt",
		"img": "https://archive.orkl.eu/a370c9e1f5d24dcbd5d1780341cd961d2d444dd8.jpg"
	}
}