{
	"id": "cc782052-0b30-4a8b-9cfe-d1179423c6be",
	"created_at": "2026-04-06T00:17:14.283979Z",
	"updated_at": "2026-04-10T03:37:32.809413Z",
	"deleted_at": null,
	"sha1_hash": "8306228f6c967a0a3d2ae148a937bb3e26546622",
	"title": "How to defeat the Russian Dukes: A step-by-step analysis of MiniDuke used by APT29/Cozy Bear – CYBER GEEKS",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 11109068,
	"plain_text": "How to defeat the Russian Dukes: A step-by-step analysis of MiniDuke\r\nused by APT29/Cozy Bear – CYBER GEEKS\r\nPublished: 2021-09-29 · Archived: 2026-04-05 22:29:44 UTC\r\nSummary\r\nAPT29/Cozy Bear is a Russian actor that has been associated with Russia’s Foreign Intelligence Service (SVR). The US\r\ngovernment has blamed this actor for the SolarWinds supply chain compromise operation, as described at\r\nhttps://media.defense.gov/2021/Apr/15/2002621240/-1/-1/0/CSA_SVR_TARGETS_US_ALLIES_UOO13234021.PDF/CSA_SVR_TARGETS_US_ALL\r\nMiniDuke is a backdoor written in pure assembly that was previously documented by ESET at\r\nhttps://www.welivesecurity.com/wp-content/uploads/2019/10/ESET_Operation_Ghost_Dukes.pdf and Kaspersky at\r\nhttps://securelist.com/miniduke-is-back-nemesis-gemina-and-the-botgen-studio/64107/, however, this sample is the most\r\nrecent one (June 2019) that we’re aware of and hasn’t been documented before. This malware is pretty obfuscated (control-flow flattening) and implements multiple methods of data exfiltration, such as using POST and PUT HTTP methods in the\r\ncase of sending data to the C2 server or using a named pipe in the case of no Internet connectivity. The backdoor implements\r\n37 different functions that can be visualized below (some of these are similar/identical and were skipped):\r\nAnalyst: @GeeksCyber\r\nTechnical analysis\r\nSHA256: 6057b19975818ff4487ee62d5341834c53ab80a507949a52422ab37c7c46b7a1\r\nThe malware uses the SetUnhandledExceptionFilter function in order to set the exception filter function to a particular\r\nfunction:\r\nFigure 1\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 1 of 23\n\nThe process retrieves the content of the STARTUPINFO structure by calling the GetStartupInfoA routine, as shown below:\r\nFigure 2\r\nA new thread is created by the malicious file using the CreateThread API:\r\nFigure 3\r\nThread activity – sub_4036D0\r\nAs mentioned by ESET at https://www.welivesecurity.com/wp-content/uploads/2019/10/ESET_Operation_Ghost_Dukes.pdf, the backdoor has added a lot of obfuscation that consists of\r\ncontrol-flow flattening (every function is split in a switch/case, and a lot of computation that is useless for the main\r\nexecution flow is added):\r\nFigure 4\r\nFigure 5 presents an example of an instruction that jumps to a place where a lot of useless computation occurs. We’ve added\r\nNOP operations in place of the jump and patched the binary:\r\nFigure 5\r\nThe binary forces the system not to display the Windows Error Reporting dialog (0x2 =\r\nSEM_NOGPFAULTERRORBOX):\r\nFigure 6\r\nThe kernel32.dll, advapi32.dll and winninet.dll DLLs are loaded into the address space using the LoadLibraryA routine:\r\nFigure 7\r\nThe functions that will be used during the execution are located using a hashing mechanism. Basically, for each function\r\nname from a DLL, the malware computes a 4-byte value that is compared with a hard-coded one:\r\nFigure 8\r\nThe following APIs belong to the targeted list: GetProcAddress, GetLongPathNameA, GetLastError,\r\nCreateProcessWithLogonW, CryptAcquireContextW, CryptGenRandom, InternetOpenA, InternetConnectA,\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 2 of 23\n\nInternetSetOptionA, HttpOpenRequestA, HttpSendRequestA, HttpQueryInfoA, InternetReadFile, InternetCloseHandle,\r\nHttpAddRequestHeadersA. The hashing function is displayed below:\r\nFigure 9\r\nThe CryptAcquireContextW API is utilized to get a handle to a key container within a CSP (cryptographic service provider).\r\nThe function call is presented in figure 10 (0x1 = PROV_RSA_FULL, 0xF0000040 = CRYPT_VERIFYCONTEXT |\r\nCRYPT_SILENT):\r\nFigure 10\r\nAllocateAndInitializeSid is used to allocate and initialize a SID with one subauthority:\r\nFigure 11\r\nThe file creates a new ACL using the SetEntriesInAclA routine (0x2 = SET_ACCESS):\r\nFigure 12\r\nA new security descriptor is initialized by the malicious process (0x1 = SECURITY_DESCRIPTOR_REVISION):\r\nFigure 13\r\nThe malware sets information in a DACL (discretionary access control list) using the SetSecurityDescriptorDacl API:\r\nFigure 14\r\nThe following relevant strings are written into memory and will be used later on:\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 3 of 23\n\nFigure 15\r\nCryptGenRandom is utilized to generate 16 random bytes. The first 15 bytes are encoded using the Base64 algorithm:\r\nFigure 16\r\nThe binary writes the file signature of JPEG in the JFIF format into the memory. These bytes will be used in data\r\nexfiltration, as we’ll describe in the following paragraphs:\r\nFigure 17\r\nThe process creates the “Software\\Microsoft\\ApplicationManager” registry key using the RegCreateKeyA API (0x80000001\r\n= HKEY_CURRENT_USER):\r\nFigure 18\r\nA new value called “AppID” is created under the above registry key. This value is computed using the output of a\r\nGetTickCount function call:\r\nFigure 19\r\nThere are 2 more calls to the GetTickCount routine (it retrieves the number of milliseconds that elapsed since the system\r\nwas started):\r\nFigure 20\r\nOne of the outputs from above is transformed and written into a buffer, along with the “AppID” value. This buffer will be\r\nencrypted using a custom algorithm that also includes the XOR operator:\r\nFigure 21\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 4 of 23\n\nThe encryption algorithm and the result of the above operation are highlighted in figure 22:\r\nFigure 22\r\nThe backdoor initializes the use of the WinINet functions using the InternetOpenA API with a particular user agent:\r\nFigure 23\r\nThe proxy is set to 10.1.1.1:8080 using the InternetSetOptionA function (0x26 = INTERNET_OPTION_PROXY):\r\nFigure 24\r\nThe connect time-out value for connection requests is set to 11 seconds (0x2 =\r\nINTERNET_OPTION_CONNECT_TIMEOUT):\r\nFigure 25\r\nThe receive time-out value for connection requests is set to 11 seconds (0x6 =\r\nINTERNET_OPTION_RECEIVE_TIMEOUT):\r\nFigure 26\r\nThe send time-out value for connection requests is set to 11 seconds (0x5 = INTERNET_OPTION_SEND_TIMEOUT):\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 5 of 23\n\nFigure 27\r\nInternetConnnectA is utilized to open an HTTP session with the C2 server salesappliances[.]com (0x3 =\r\nINTERNET_SERVICE_HTTP):\r\nFigure 28\r\nThe malware implements 3 different cases for exfiltrating the buffer that was encrypted earlier (or outputs from backdoor\r\nfunctions), depending on the availability of Internet connectivity.\r\nCase 1 (no Internet availability)\r\nWaitNamedPipeA is used to wait until 11 seconds have elapsed or an instance of the “\\\\pipe\\DefPipe” pipe is available for\r\nconnection (this pipe is supposed to be utilized between this machine and another machine that has an Internet connection):\r\nFigure 29\r\nThe process opens the specified pipe using the CreateFileA routine (0xC0000000 = GENERIC_READ |\r\nGENERIC_WRITE, 0x3 = OPEN_EXISTING):\r\nFigure 30\r\nSetNamedPipeHandleState is utilized to set the read mode and the blocking mode of the pipe mentioned above (0x2 =\r\nPIPE_READMODE_MESSAGE, 0x0 = PIPE_WAIT):\r\nFigure 31\r\nThe binary writes the encrypted buffer to the specified pipe using the TransactNamedPipe API:\r\nFigure 32\r\nCase 2 (Data exfiltration using PUT method)\r\nA new HTTP request handle is created by the file (0x80400100 = INTERNET_FLAG_RELOAD |\r\nINTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_PRAGMA_NOCACHE):\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 6 of 23\n\nFigure 33\r\nThe Referer header is added to the HTTP request handle using HttpAddRequestHeadersA (0x20000000 =\r\nHTTP_ADDREQ_FLAG_ADD):\r\nFigure 34\r\nThe Accept-Language header is added to the HTTP request handle using HttpAddRequestHeadersA (0x20000000 =\r\nHTTP_ADDREQ_FLAG_ADD):\r\nFigure 35\r\nThe Accept-Encoding header is added to the HTTP request handle using HttpAddRequestHeadersA (0x20000000 =\r\nHTTP_ADDREQ_FLAG_ADD):\r\nFigure 36\r\nThe process exfiltrates the encrypted buffer to the C2 server by calling the HttpSendRequestA routine, as shown below:\r\nFigure 37\r\nCase 3 (Data exfiltration using POST method)\r\nA new HTTP request handle is created by the file (0x80400100 = INTERNET_FLAG_RELOAD |\r\nINTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_PRAGMA_NOCACHE):\r\nFigure 38\r\nThe Referer header is added to the HTTP request handle using HttpAddRequestHeadersA (0x20000000 =\r\nHTTP_ADDREQ_FLAG_ADD):\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 7 of 23\n\nFigure 39\r\nThe Accept-Language header is added to the HTTP request handle using HttpAddRequestHeadersA (0x20000000 =\r\nHTTP_ADDREQ_FLAG_ADD):\r\nFigure 40\r\nThe Accept-Encoding header is added to the HTTP request handle using HttpAddRequestHeadersA (0x20000000 =\r\nHTTP_ADDREQ_FLAG_ADD):\r\nFigure 41\r\nThe encrypted buffer is added to a fake JPEG image (note the file signature in the network traffic) and transmitted to the C2\r\nserver without raising any suspicion:\r\nFigure 42\r\nHttpOpenRequestA is utilized to create a new HTTP request handle. The HTTP method is set to GET ( 0x80480100 =\r\nINTERNET_FLAG_RELOAD | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_COOKIES |\r\nINTERNET_FLAG_PRAGMA_NOCACHE):\r\nFigure 43\r\nThe file generates 256 random bytes via a function call to CryptGenRandom (the result will be Base64-encoded, and a small\r\npart of the output is used as a parameter in the Referer header):\r\nFigure 44\r\nThe Referer, Accept-Language and Accept-Encoding headers are set as described before. The encrypted buffer that was\r\nexfiltrated using one of the 3 methods is Base64-encoded:\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 8 of 23\n\nFigure 45\r\nThe Cookie header is set to a string that is obtained from the above using some transformations, and the request is sent to the\r\nC2 server, as shown in figure 46.\r\nFigure 46\r\nHere is the network request captured by FakeNet:\r\nFigure 47\r\nIt’s important to mention that the backdoor also performs a “cleaning” operation by freeing the memory in order to hide\r\npossible IOCs that could be extracted from it:\r\nFigure 48\r\nThe status code returned by the server is extracted and compared with 200 (0x20000013 =\r\nHTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE):\r\nFigure 49\r\nThe malicious binary retrieves the size of the resource using the HttpQueryInfoA API (0x20000005 =\r\nHTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_CONTENT_LENGTH):\r\nFigure 50\r\nThere is a function call to InternetReadFile, which is utilized to read data received from the C2 server:\r\nFigure 51\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 9 of 23\n\nThe response from the C2 server is parsed, and the byte at position 0x1c (28 in decimal) is extracted. There is also a\r\n“checksum” of the 5th-8th bytes that is computed, and the result should match the first 4 bytes. We will describe each case\r\ndepending on that particular byte.\r\nByte = 0x11 – read the content of a file specified by the C2 server and compute the MD5 hash of it\r\nThe path of the %TEMP% directory is extracted using GetTempPathA:\r\nFigure 52\r\nThe path of the %TEMP% directory is converted to its long form by calling the GetLongPathNameA routine, as highlighted\r\nbelow:\r\nFigure 53\r\nGetCurrentDirectoryA is utilized to extract the current directory for the current process:\r\nFigure 54\r\nThe response from the C2 server is supposed to contain a file name, which is opened via a CreateFileA function call\r\n(0x80000000 = GENERIC_READ, 0x1 = FILE_SHARE_READ, 0x3 = OPEN_EXISTING, 0x80 =\r\nFILE_ATTRIBUTE_NORMAL):\r\nFigure 55\r\nThe malware creates an unnamed file mapping object using the CreateFileMappingA API (0x8 = PAGE_WRITECOPY):\r\nFigure 56\r\nThe malicious binary maps the newly created file mapping into the address space of the calling process, as shown in the next\r\npictures (0x1 = FILE_MAP_COPY):\r\nFigure 57\r\nFigure 58\r\nThe MD5 hashing algorithm is implemented by the malware (note the variables from below), which is used to perform\r\nhashing of the file content extracted above:\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 10 of 23\n\nFigure 59\r\nFigure 60\r\nThe resulting buffer that will be exfiltrated is similar to the one from figure 21, however, it also contains the MD5 hash\r\nvalue and the file name. The encryption algorithm is the same presented in figure 22 (this is valid for all cases, and we will\r\nnot repeat it every time):\r\nFigure 61\r\nByte = 0x12 – create and populate a new file\r\nThe backdoor creates a new file specified by the C2 server in the network traffic (0x40000000 = GENERIC_WRITE, 0x1\r\n= FILE_SHARE_READ, 0x1 = CREATE_NEW, 0x80 = FILE_ATTRIBUTE_NORMAL):\r\nFigure 62\r\nThe newly created file is populated with content provided by the C2 server as well:\r\nFigure 63\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 11 of 23\n\nThe final buffer that will be exfiltrated contains the file name:\r\nFigure 64\r\nByte = 0x13 (same execution flow as 0x11)\r\nByte = 0x14 – write specific bytes into memory depending on the C2 server response\r\nDepending on 2 bytes received from the C2 server, the binary writes 0x100, 0x200, 0x400, 0x800, 0x1000 or 0x2000 into\r\nmemory. The first 3 cases are highlighted in figure 65:\r\nFigure 65\r\nThe buffer that will be exfiltrated contains a 4-byte value computed from a GetTickCount function call, the “AppID” value\r\nand a marker value (0x81 in this case):\r\nFigure 66\r\nByte = 0x15 – listen on port 8080 and record all connections that are established on this port\r\nA new thread is created using the CreateThread routine:\r\nFigure 67\r\nThe process creates a new socket using the socket API. The inet_addr function is utilized to convert a string containing an IP\r\ndotted-decimal address into a proper address for the IN_ADDR structure, as shown below:\r\nFigure 68\r\nThere is a mistake done by the malware developers because they’ve called the inet_addr routine with the C2 server as the\r\nparameter (and not an IP as above). This function call returns INADDR_NONE (0xFFFFFFFF):\r\nFigure 69\r\nThe binary associates the local address with the socket created before using the bind API:\r\nFigure 70\r\nThe listen function is used to place the socket in a listening state for incoming connections:\r\nFigure 71\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 12 of 23\n\nThe malware was supposed to connect to the C2 server using the connect API, however, due to the implementation mistake,\r\nthis function call fails:\r\nFigure 72\r\nFor the sake of the analysis, we’ve emulated an external connection from a remote IP to the local host on port 8080. The\r\ngetpeername API is utilized to extract the address of the peer to which the socket is connected:\r\nFigure 73\r\nThe inet_ntoa routine is the opposite of inet_addr and it’s used to convert an IP from a hex form into an ASCII string\r\n(dotted-decimal format):\r\nFigure 74\r\ngetsockname is utilized to retrieve the local name for the socket:\r\nFigure 75\r\ninet_ntoa is used again to convert the IP address from hex to dotted-decimal format, as highlighted in figure 76:\r\nFigure 76\r\nThe final buffer that will be exfiltrated contains some details about the network connection (source and destination IPs/ports)\r\nand the string “listen”:\r\nFigure 77\r\nIt’s important to mention that because of the bug, only this behavior is expected, however, there are other execution flows as\r\nwell. For example, if no connection is established, the malware only copies the string “idle” in the buffer. If the connection\r\nto the C2 server is successful, then the string “connect” would have been copied into the final buffer. Finally, if the\r\nconnection is successful and the process accepts another connection on port 8080, the string “accept” is copied into the\r\nbuffer as well.\r\nByte = 0x16 – create a named pipe and wait for connections\r\nThe file creates a new named pipe using the CreateNamedPipeA routine (0x40040003 = FILE_FLAG_OVERLAPPED |\r\nWRITE_DAC | PIPE_ACCESS_DUPLEX, 0x6 = PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE):\r\nFigure 78\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 13 of 23\n\nA new unnamed event object is created by the backdoor:\r\nFigure 79\r\nThe binary enables the pipe to wait for connections from client processes, as displayed below:\r\nFigure 80\r\nWhether the C2 server specifies the “off” parameter in the network traffic, the malware calls the DisconnectNamedPipe API:\r\nFigure 81\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0x20 – extract timestamps for a file mentioned by the C2 server\r\nThe FindFirstFileA routine is utilized to locate a file specified by the C2 server in the network traffic:\r\nFigure 82\r\nThe malicious process converts the file time to system time format using FileTimeToSystemTime:\r\nFigure 83\r\nThe GetTimeFormatA API is utilized to convert the time from above to a time string (0x800 =\r\nLOCALE_SYSTEM_DEFAULT, 0x80000000 = LOCALE_NOUSEROVERRIDE):\r\nFigure 84\r\nThe GetDateFormatA API is utilized to convert the date from above to a date string (0x800 =\r\nLOCALE_SYSTEM_DEFAULT, 0x80000000 = LOCALE_NOUSEROVERRIDE):\r\nFigure 85\r\nThe final buffer that will be exfiltrated contains the file name, file creation date and time, and the length of the file content:\r\nFigure 86\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 14 of 23\n\nIf any error occurs during an operation such as creating a file, opening a file, and so in all studied cases, the malware formats\r\nthe error message using FormatMessageA and copies it to the final buffer (0x1000 =\r\nFORMAT_MESSAGE_FROM_SYSTEM, 0x2 = ERROR_FILE_NOT_FOUND):\r\nFigure 87\r\nByte = 0x21 – move a file to a new file\r\nThe response from the C2 server contains 2 file names. The process moves the first file to the second one by calling the\r\nMoveFileA API:\r\nFigure 88\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0x22 – copy a file to a new file\r\nThe response from the C2 server contains 2 file names. The malware copies the first file to the second one by calling the\r\nCopyFileA API:\r\nFigure 89\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0x23 – delete a file\r\nThe response from the C2 server contains a file name. The binary deletes the file using the DeleteFileA function:\r\nFigure 90\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0x24 – retrieve the current directory for the process\r\nGetCurrentDirectoryA is used to extract the current directory for the process:\r\nFigure 91\r\nThe final buffer that will be exfiltrated contains the path extracted above:\r\nFigure 92\r\nByte = 0x25 – create a directory\r\nThe response from the C2 server contains a directory name. The backdoor creates the new directory using the\r\nCreateDirectoryA routine:\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 15 of 23\n\nFigure 93\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0x26 – delete a directory\r\nThe response from the C2 server contains a directory name. The binary deletes the directory using the\r\nRemoveDirectoryA routine:\r\nFigure 94\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0x27 – change the current directory for the process\r\nThe response from the C2 server contains a directory name. The process changes the current directory for the process to this\r\ndirectory:\r\nFigure 95\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0x28 – set the current directory for the process to the %TEMP% folder\r\nGetTempPathA is utilized to retrieve the path of the %TEMP% directory:\r\nFigure 96\r\nThe file changes the current directory for the process using the SetCurrentDirectoryA API:\r\nFigure 97\r\nByte = 0x29 – retrieve the valid drives on the system and their type\r\nThe valid drives on the system are extracted by calling the GetLogicalDriveStringsA function:\r\nFigure 98\r\nThe backdoor extracts the type of the drive using the GetDriveTypeA API, as displayed in figure 99.\r\nFigure 99\r\nThe final buffer that will be exfiltrated contains the drives name and a string that categorizes their type:\r\nFigure 100\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 16 of 23\n\nThe following strings are hard-coded and indicate the type of drives: unk (DRIVE_UNKNOWN), nrt\r\n(DRIVE_NO_ROOT_DIR), rmv (DRIVE_REMOVABLE), fix (DRIVE_FIXED), net (DRIVE_REMOTE), cdr\r\n(DRIVE_CDROM), ram (DRIVE_RAMDISK) and und (most likely UNDEFINED).\r\nByte = 0x2A – retrieve the computer Uptime and encrypt the value\r\nThe malware calls the GetTickCount function and stores the result in a separate buffer:\r\nFigure 101\r\nThe 4-byte value extracted above is encrypted using a custom algorithm:\r\nFigure 102\r\nThe final buffer that will be exfiltrated contains the result of the above encryption:\r\nFigure 103\r\nByte = 0x30 – retrieve the path of an executable that corresponds to a particular process ID\r\nThe response from the C2 server contains a string with a process ID. The atoi function is used to convert the string to a\r\nnumber:\r\nFigure 104\r\nThe malicious binary opens the local process object that corresponds to the process ID using the OpenProcess routine\r\n(0x1F0FFF = PROCESS_ALL_ACCESS):\r\nFigure 105\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 17 of 23\n\nEnumProcessModules is utilized to enumerate the modules of the targeted process:\r\nFigure 106\r\nGetModuleFileNameExA is used to retrieve the path of the file that contains a specific module. This is an interesting way to\r\nfind out the path to the executable that corresponds to the targeted process ID:\r\nFigure 107\r\nThe final buffer that will be exfiltrated contains the address of the module from above and the path to the executable:\r\nFigure 108\r\nByte = 0x31 – kill a process\r\nThe response from the C2 server contains a string with a process ID. The backdoor opens the local process object that\r\ncorresponds to the process ID using the OpenProcess routine (0x1= PROCESS_TERMINATE):\r\nFigure 109\r\nThe binary kills the targeted process using TerminateProcess, as described in figure 110:\r\nFigure 110\r\nThe final buffer that will be exfiltrated contains the string “term” (which probably refers to terminate) and the process ID:\r\nFigure 111\r\nByte = 0x32 – create a new process\r\nThe response from the C2 server contains a process name. The malware creates this process by calling the CreateProcessA\r\nAPI:\r\nFigure 112\r\nThe final buffer that will be exfiltrated contains the ID of the process created earlier:\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 18 of 23\n\nFigure 113\r\nByte = 0x33 – create a new process in the security context of the credentials received from the C2 server\r\nThe response from the C2 server contains the following data: user, password, Windows domain, and process name. Two\r\nanonymous pipes are created using the CreatePipe API:\r\nFigure 114\r\nFigure 115\r\nGetCurrentDirectoryW is utilized to retrieve the current directory for the process:\r\nFigure 116\r\nThe binary creates a new process that runs in the context of the credentials extracted from the network traffic via a\r\nCreateProcessWithLogonW function call:\r\nFigure 117\r\nThe executable extracts a handle for each module in the process created above by calling the EnumProcessModules routine:\r\nFigure 118\r\nThere is a call to GetModuleFileNameExA that extracts the path of the file containing the above module:\r\nFigure 119\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 108.\r\nByte = 0x34 (same execution flow as 0x33)\r\nByte = 0x40 – retrieve the current process ID, the path of the executable, the hostname, the username, and the default locale\r\nGetModuleFileNameA is utilized to extract the path of the executable of the current process:\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 19 of 23\n\nFigure 120\r\nThe malware retrieves the NetBIOS name of the local computer and the user name by calling the GetComputerNameA and\r\nGetUserNameA functions, respectively:\r\nFigure 121\r\nFigure 122\r\nThe current process ID is extracted using the GetCurrentProcessId routine:\r\nFigure 123\r\nGetLocaleInfoA is utilized to retrieve information about the default locale for the user or process (0x400 =\r\nLOCALE_USER_DEFAULT):\r\nFigure 124\r\nThe final buffer that will be exfiltrated contains the current process ID, the path of the executable, the hostname, the\r\nusername, the “AppID” value, the C2 server, the HTTP method used during network communications, the pipe name\r\nmentioned in Case1 of Data Exfiltration, and the user’s language (English – United States):\r\nFigure 125\r\nByte = 0x41 – retrieve the current process ID, the path of the executable, the hostname, the username, and the default locale\r\nGetModuleFileNameA is utilized to extract the path of the executable of the current process:\r\nFigure 126\r\nThe GetComputerNameA and GetUserNameA APIs are used to retrieve the hostname and the username associated with the\r\ncurrent thread:\r\nFigure 127\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 20 of 23\n\nFigure 128\r\nGetCurrentProcessId is utilized to extract the ID of the current process:\r\nFigure 129\r\nThe default locale for the user or process is extracted using GetLocaleInfoA (0x400 = LOCALE_USER_DEFAULT):\r\nFigure 130\r\nThe final buffer that will be exfiltrated contains the current process ID, the path of the executable, the hostname, the\r\nusername, and the user’s language (English – United States):\r\nFigure 131\r\nByte = 0x48 – retrieve the hostname and username\r\nThe malware extracts the username and hostname as before:\r\nFigure 132\r\nFigure 133\r\nThe final buffer that will be exfiltrated contains the hostname and username, as highlighted in figure 134:\r\nFigure 134\r\nByte = 0x49 – exfiltrate the C2 domain name and port number\r\nThe final buffer that will be exfiltrated contains the C2 server and the port number:\r\nFigure 135\r\nByte = 0x85 – close open handles\r\nThere is only a FindClose function call regarding this case. The buffer that will be exfiltrated is similar to the one presented\r\nin figure 66.\r\nByte = 0x8B – close open handles\r\nThis is also a “cleaning” case because the backdoor calls the CloseHandle API a few times. The buffer that will be\r\nexfiltrated is similar to the one presented in figure 66.\r\nByte = 0x98 calculate the MD5 hash of the empty string\r\nThe process computes the MD5 hash of the empty string and saves the result to the buffer that will be exfiltrated:\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 21 of 23\n\nFigure 136\r\nByte = 0xC4 – close open handles\r\nNo notable activity regarding this case. The buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0xC7 – close open handles and unmap a mapped view of a file\r\nThe binary performs 2 function calls to CloseHandle and a call to UnmapViewOfFile. The buffer that will be exfiltrated is\r\nsimilar to the one presented in figure 66.\r\nByte = 0xCA – close open handles\r\nNo notable activity regarding this case. The buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0xE1 – resume a suspended thread and copy data from a pipe\r\nThe malicious process resumes a thread that was previously suspended using the ResumeThread routine:\r\nFigure 137\r\nPeekNamedPipe is utilized to copy data from a named or anonymous pipe into a buffer without removing it from the pipe:\r\nFigure 138\r\nWhether more data is available in the pipe, the malware reads it using the ReadFile API:\r\nFigure 139\r\nThe buffer that will be exfiltrated contains the data received from the pipe:\r\nFigure 140\r\nByte = 0xE2 – copy data from a pipe\r\nThe executable copies data from a named or anonymous pipe into a buffer via a PeekNamedPipe function call:\r\nFigure 141\r\nThe ReadFile function is utilized to read more data from the pipe if it’s available:\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 22 of 23\n\nFigure 142\r\nThe buffer that will be exfiltrated contains the data received from the pipe:\r\nFigure 143\r\nByte = 0xE3 – kill a process\r\nThe backdoor kills a specific process, whose handle is read from memory:\r\nFigure 144\r\nThe buffer that will be exfiltrated is similar to the one presented in figure 66.\r\nByte = 0xFE – close open handles\r\nThe binary performs a function call to CloseHandle and closesocket. The buffer that will be exfiltrated is similar to the one\r\npresented in figure 66.\r\nByte = 0xFF – copy a string that probably represents the exit of the program\r\nThe malware copies the string “Exiting…” to the final buffer that will be exfiltrated:\r\nFigure 145\r\nReferences\r\nMSDN: https://docs.microsoft.com/en-us/windows/win32/api/\r\nVirusTotal:\r\nhttps://www.virustotal.com/gui/file/6057b19975818ff4487ee62d5341834c53ab80a507949a52422ab37c7c46b7a1\r\nFakenet: https://github.com/fireeye/flare-fakenet-ng\r\nMalwareBazaar:\r\nhttps://bazaar.abuse.ch/sample/6057b19975818ff4487ee62d5341834c53ab80a507949a52422ab37c7c46b7a1/\r\nESET: https://www.welivesecurity.com/wp-content/uploads/2019/10/ESET_Operation_Ghost_Dukes.pdf\r\nKaspersky: https://securelist.com/miniduke-is-back-nemesis-gemina-and-the-botgen-studio/64107/\r\nCybersecurity Advisory:\r\nhttps://media.defense.gov/2021/Apr/15/2002621240/-1/-1/0/CSA_SVR_TARGETS_US_ALLIES_UOO13234021.PDF/CSA_SVR_TARGETS_US_ALL\r\nINDICATORS OF COMPROMISE\r\nC2 server: salesappliances[.]com\r\nSHA256: 6057b19975818ff4487ee62d5341834c53ab80a507949a52422ab37c7c46b7a1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111\r\nSafari/537.36 (prone to False Positives)\r\nNamed Pipe: \\\\pipe\\DefPipe\r\nSource: https://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nhttps://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/\r\nPage 23 of 23",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://cybergeeks.tech/how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear/"
	],
	"report_names": [
		"how-to-defeat-the-russian-dukes-a-step-by-step-analysis-of-miniduke-used-by-apt29-cozy-bear"
	],
	"threat_actors": [
		{
			"id": "5b748f86-ac32-4715-be9f-6cf25ae48a4e",
			"created_at": "2024-06-04T02:03:07.956135Z",
			"updated_at": "2026-04-10T02:00:03.689959Z",
			"deleted_at": null,
			"main_name": "IRON HEMLOCK",
			"aliases": [
				"APT29 ",
				"ATK7 ",
				"Blue Kitsune ",
				"Cozy Bear ",
				"The Dukes",
				"UNC2452 ",
				"YTTRIUM "
			],
			"source_name": "Secureworks:IRON HEMLOCK",
			"tools": [
				"CosmicDuke",
				"CozyCar",
				"CozyDuke",
				"DiefenDuke",
				"FatDuke",
				"HAMMERTOSS",
				"LiteDuke",
				"MiniDuke",
				"OnionDuke",
				"PolyglotDuke",
				"RegDuke",
				"RegDuke Loader",
				"SeaDuke",
				"Sliver"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "a241a1ca-2bc9-450b-a07b-aae747ee2710",
			"created_at": "2024-06-19T02:03:08.150052Z",
			"updated_at": "2026-04-10T02:00:03.737173Z",
			"deleted_at": null,
			"main_name": "IRON RITUAL",
			"aliases": [
				"APT29",
				"Blue Dev 5 ",
				"BlueBravo ",
				"Cloaked Ursa ",
				"CozyLarch ",
				"Dark Halo ",
				"Midnight Blizzard ",
				"NOBELIUM ",
				"StellarParticle ",
				"UNC2452 "
			],
			"source_name": "Secureworks:IRON RITUAL",
			"tools": [
				"Brute Ratel C4",
				"Cobalt Strike",
				"EnvyScout",
				"GoldFinder",
				"GoldMax",
				"NativeZone",
				"RAINDROP",
				"SUNBURST",
				"Sibot",
				"TEARDROP",
				"VaporRage"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "46b3c0fc-fa0c-4d63-a38a-b33a524561fb",
			"created_at": "2023-01-06T13:46:38.393409Z",
			"updated_at": "2026-04-10T02:00:02.955738Z",
			"deleted_at": null,
			"main_name": "APT29",
			"aliases": [
				"Cloaked Ursa",
				"TA421",
				"Blue Kitsune",
				"BlueBravo",
				"IRON HEMLOCK",
				"G0016",
				"Nobelium",
				"Group 100",
				"YTTRIUM",
				"Grizzly Steppe",
				"ATK7",
				"ITG11",
				"COZY BEAR",
				"The Dukes",
				"Minidionis",
				"UAC-0029",
				"SeaDuke"
			],
			"source_name": "MISPGALAXY:APT29",
			"tools": [
				"SNOWYAMBER",
				"HALFRIG",
				"QUARTERRIG"
			],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "20d3a08a-3b97-4b2f-90b8-92a89089a57a",
			"created_at": "2022-10-25T15:50:23.548494Z",
			"updated_at": "2026-04-10T02:00:05.292748Z",
			"deleted_at": null,
			"main_name": "APT29",
			"aliases": [
				"APT29",
				"IRON RITUAL",
				"IRON HEMLOCK",
				"NobleBaron",
				"Dark Halo",
				"NOBELIUM",
				"UNC2452",
				"YTTRIUM",
				"The Dukes",
				"Cozy Bear",
				"CozyDuke",
				"SolarStorm",
				"Blue Kitsune",
				"UNC3524",
				"Midnight Blizzard"
			],
			"source_name": "MITRE:APT29",
			"tools": [
				"PinchDuke",
				"ROADTools",
				"WellMail",
				"CozyCar",
				"Mimikatz",
				"Tasklist",
				"OnionDuke",
				"FatDuke",
				"POSHSPY",
				"EnvyScout",
				"SoreFang",
				"GeminiDuke",
				"reGeorg",
				"GoldMax",
				"FoggyWeb",
				"SDelete",
				"PolyglotDuke",
				"AADInternals",
				"MiniDuke",
				"SeaDuke",
				"Sibot",
				"RegDuke",
				"CloudDuke",
				"GoldFinder",
				"AdFind",
				"PsExec",
				"NativeZone",
				"Systeminfo",
				"ipconfig",
				"Impacket",
				"Cobalt Strike",
				"PowerDuke",
				"QUIETEXIT",
				"HAMMERTOSS",
				"BoomBox",
				"CosmicDuke",
				"WellMess",
				"VaporRage",
				"LiteDuke"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "f27790ff-4ee0-40a5-9c84-2b523a9d3270",
			"created_at": "2022-10-25T16:07:23.341684Z",
			"updated_at": "2026-04-10T02:00:04.549917Z",
			"deleted_at": null,
			"main_name": "APT 29",
			"aliases": [
				"APT 29",
				"ATK 7",
				"Blue Dev 5",
				"BlueBravo",
				"Cloaked Ursa",
				"CloudLook",
				"Cozy Bear",
				"Dark Halo",
				"Earth Koshchei",
				"G0016",
				"Grizzly Steppe",
				"Group 100",
				"ITG11",
				"Iron Hemlock",
				"Iron Ritual",
				"Midnight Blizzard",
				"Minidionis",
				"Nobelium",
				"NobleBaron",
				"Operation Ghost",
				"Operation Office monkeys",
				"Operation StellarParticle",
				"SilverFish",
				"Solar Phoenix",
				"SolarStorm",
				"StellarParticle",
				"TEMP.Monkeys",
				"The Dukes",
				"UNC2452",
				"UNC3524",
				"Yttrium"
			],
			"source_name": "ETDA:APT 29",
			"tools": [
				"7-Zip",
				"ATI-Agent",
				"AdFind",
				"Agentemis",
				"AtNow",
				"BEATDROP",
				"BotgenStudios",
				"CEELOADER",
				"Cloud Duke",
				"CloudDuke",
				"CloudLook",
				"Cobalt Strike",
				"CobaltStrike",
				"CosmicDuke",
				"Cozer",
				"CozyBear",
				"CozyCar",
				"CozyDuke",
				"Danfuan",
				"EnvyScout",
				"EuroAPT",
				"FatDuke",
				"FoggyWeb",
				"GeminiDuke",
				"Geppei",
				"GoldFinder",
				"GoldMax",
				"GraphDrop",
				"GraphicalNeutrino",
				"GraphicalProton",
				"HAMMERTOSS",
				"HammerDuke",
				"LOLBAS",
				"LOLBins",
				"LiteDuke",
				"Living off the Land",
				"MagicWeb",
				"Mimikatz",
				"MiniDionis",
				"MiniDuke",
				"NemesisGemina",
				"NetDuke",
				"OnionDuke",
				"POSHSPY",
				"PinchDuke",
				"PolyglotDuke",
				"PowerDuke",
				"QUIETEXIT",
				"ROOTSAW",
				"RegDuke",
				"Rubeus",
				"SNOWYAMBER",
				"SPICYBEAT",
				"SUNSHUTTLE",
				"SeaDaddy",
				"SeaDask",
				"SeaDesk",
				"SeaDuke",
				"Sharp-SMBExec",
				"SharpView",
				"Sibot",
				"Solorigate",
				"SoreFang",
				"TinyBaron",
				"WINELOADER",
				"WellMail",
				"WellMess",
				"cobeacon",
				"elf.wellmess",
				"reGeorg",
				"tDiscoverer"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434634,
	"ts_updated_at": 1775792252,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/8306228f6c967a0a3d2ae148a937bb3e26546622.pdf",
		"text": "https://archive.orkl.eu/8306228f6c967a0a3d2ae148a937bb3e26546622.txt",
		"img": "https://archive.orkl.eu/8306228f6c967a0a3d2ae148a937bb3e26546622.jpg"
	}
}