{
	"id": "2d79b086-b69b-4fd5-81be-841db93f6d44",
	"created_at": "2026-04-06T00:15:42.094123Z",
	"updated_at": "2026-04-10T13:11:30.224145Z",
	"deleted_at": null,
	"sha1_hash": "30bf6ca1dd72430e1d990ff80c290efee3df30f0",
	"title": "DirtyMoe: Rootkit Driver",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 3629576,
	"plain_text": "DirtyMoe: Rootkit Driver\r\nBy Threat Research TeamThreat Research Team\r\nArchived: 2026-04-05 16:23:43 UTC\r\nAbstract\r\nIn the first post DirtyMoe: Introduction and General Overview of Modularized Malware, we have described one\r\nof the complex and sophisticated malware called DirtyMoe. The main observed roles of the malware are\r\nCryptojacking and DDoS attacks that are still popular. There is no doubt that malware has been released for profit,\r\nand all evidence points to Chinese territory. In most cases, the PurpleFox campaign is used to exploit vulnerable\r\nsystems where the exploit gains the highest privileges and installs the malware via the MSI installer. In short, the\r\ninstaller misuses Windows System Event Notification Service (SENS) for the malware deployment. At the end of\r\nthe deployment, two processes (workers) execute malicious activities received from well-concealed C\u0026C servers.\r\nAs we mentioned in the first post, every good malware must implement a set of protection, anti-forensics, anti-tracking, and anti-debugging techniques. One of the most used techniques for hiding malicious activity is using\r\nrootkits. In general, the main goal of the rootkits is to hide itself and other modules of the hosted malware on the\r\nkernel layer. The rootkits are potent tools but carry a high risk of being detected because the rootkits work in the\r\nkernel-mode, and each critical bug leads to BSoD.\r\nThe primary aim of this next article is to analyze rootkit techniques that DirtyMoe uses. The main part of this\r\nstudy examines the functionality of a DirtyMoe driver, aiming to provide complex information about the driver in\r\nterms of static and dynamic analysis. The key techniques of the DirtyMoe rootkit can be listed as follows: the\r\ndriver can hide itself and other malware activities on kernel and user mode. Moreover, the driver can execute\r\ncommands received from the user-mode under the kernel privileges. Another significant aspect of the driver is an\r\ninjection of an arbitrary DLL file into targeted processes. Last but not least is the driver’s functionality that\r\ncensors the file system content. In the same way, we describe the refined routine that deploys the driver into the\r\nkernel and which anti-forensic method the malware authors used.\r\nAnother essential point of this research is the investigation of the driver’s meta-data, which showed that the driver\r\nis code-signed with the certificates that have been stolen and revoked in the past. However, the certificates are\r\nwidespread in the wild and are misused in other malicious software in the present.\r\nFinally, the last part summarises the rootkit functionally and draws together the key findings of digital certificates,\r\nmaking a link between DirtyMoe and other malicious software. In addition, we discuss the implementation level\r\nand sources of the used rootkit techniques.\r\n1. Sample\r\nThe subject of this research is a sample with SHA-256:\r\nAABA7DB353EB9400E3471EAAA1CF0105F6D1FAB0CE63F1A2665C8BA0E8963A05\r\nThe sample is a windows driver that DirtyMoe drops on the system startup.\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 1 of 19\n\nNote: VirusTotal keeps a record of 44 of 71 AV engines (62 %) which detect the samples as malicious. On the\r\nother hand, the DirtyMoe DLL file is detected by 86 % of registered AVs. Therefore, the detection coverage is\r\nsufficient since the driver is dumped from the DLL file.\r\nBasic Information\r\nFile Type: Portable Executable 64\r\nFile Info: Microsoft Visual C++ 8.0 (Driver)\r\nFile Size: 116.04 KB (118824 bytes)\r\nDigital Signature: Shanghai Yulian Software Technology Co., Ltd. (上海域联软件技术有限公司)\r\nImports\r\nThe driver imports two libraries FltMgr and ntosrnl . Table 1 summarizes the most suspicious methods from\r\nthe driver’s point.\r\nTable 1. Kernel methods imported by the DirtyMoe driver\r\nAt first glance, the driver looks up kernel routine via MmGetSystemRoutineAddress() as a form of obfuscation\r\nsince the string table contains routine names operating with VirtualMemory ; e.g., ZwProtectVirtualMemory() ,\r\nZwReadVirtualMemory() , ZwWriteVirtualMemory() . The kernel-routine ZwQueryInformationProcess() and\r\nstrings such as services.exe , winlogon.exe point out that the rootkit probably works with kernel structures of\r\nthe critical windows processes.\r\n2. DirtyMoe Driver Analysis\r\nThe DirtyMoe driver does not execute any specific malware activities. However, it provides a wide scale of rootkit\r\nand backdoor techniques. The driver has been designed as a service support system for the DirtyMoe service in\r\nthe user-mode.\r\nThe driver can perform actions originally needed with high privileges, such as writing a file into the system folder,\r\nwriting to the system registry, killing an arbitrary process, etc. The malware in the user-mode just sends a defined\r\ncontrol code, and data to the driver and it provides higher privilege actions.\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 2 of 19\n\nFurther, the malware can use the driver to hide some records helping to mask malicious activities. The driver\r\naffects the system registry, and can conceal arbitrary keys. Moreover, the system process services.exe is\r\npatched in its memory, and the driver can exclude arbitrary services from the list of running services. Additionally,\r\nthe driver modifies the kernel structures recording loaded drivers, so the malware can choose which driver is\r\nvisible or not. Therefore, the malware is active, but the system and user cannot list the malware records using\r\nstandard API calls to enumerate the system registry, services, or loaded drivers. The malware can also hide\r\nrequisite files stored in the file system since the driver implements a mechanism of the minifilter. Consequently, if\r\na user requests a record from the file system, the driver catches this request and can affect the query result that is\r\npassed to the user.\r\nThe driver consists of 10 main functionalities as Table 2 illustrates.\r\nTable 2. Main driver functionality\r\nMost of the implemented functionalities are available as public samples on internet forums. The level of\r\nprogramming skills is different for each driver functionality. It seems that the driver author merged the public\r\nsamples in most cases. Therefore, the driver contains a few bugs and unused code. The driver is still in\r\ndevelopment, and we will probably find other versions in the wild.\r\n2.1 Driver Entry\r\nThe Driver Entry is the first routine that is called by the kernel after driver loading. The driver initializes a large\r\nnumber of global variables for the proper operation of the driver. Firstly, the driver detects the OS version and\r\nsetups required offsets for further malicious use. Secondly, the variable for pointing of the driver image is\r\ninitialized. The driver image is used for hiding a driver. The driver also associates the following major functions:\r\n1. IRP_MJ_CREATE , IRP_MJ_CLOSE – no interest action,\r\n2. IRP_MJ_DEVICE_CONTROL – used for driver configuration and control,\r\n3. IRP_MJ_SHUTDOWN – writes malware-defined data into the disk and registry.\r\nThe Driver Entry creates a symbolic link to the driver and tries to associate it with other malicious monitoring or\r\nfiltering callbacks. The first one is a minifilter activated by the FltRegisterFilter() method registering the\r\nFltPostOperation() ; it filters access to the system drives and allows it to hide files and directories.\r\nFurther, the initialization method swaps a major function IRP_MJ_CREATE for \\FileSystem\\Ntfs driver. So, each\r\nAPI call of CreateFile() or a kernel-mode function IoCreateFile() can be monitored and affected by the\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 3 of 19\n\nmalicious MalNtfsCreatCallback() callback.\r\nAnother Driver Entry method sets a callback method using PsSetCreateThreadNotifyRoutine() . The\r\nNotifyRoutine() monitors a kernel process creation, and the malware can inject malicious code into newly\r\ncreated processes/threads.\r\nFinally, the driver tries to restore its configuration from the system registry.\r\n2.2 Start Routine\r\nThe Start Routine is run as a kernel system thread created in the Driver Entry routine. The Start Routine writes the\r\ndriver version into the SYSTEM registry as follows:\r\nKey: HKLM\\SYSTEM\\CurrentControlSet\\Control\\WinApi\\WinDeviceVer\r\nValue: 20161122\r\nIf the following SOFTWARE registry key is present, the driver loads artifacts needed for the process injecting:\r\nHKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\Secure\r\nThe last part of Start Routine loads the rest of the necessary entries from the registry. The complete list of the\r\nsystem registry is documented in Appendix A.\r\n2.3 Device Control\r\nThe device control is a mechanism for controlling a loaded driver. A driver receives the IRP_MJ_DEVICE_CONTROL\r\nI/O control code (IOCTL) if a user-mode thread calls Win32 API DeviceIoControl() ; visit [1] for more\r\ninformation. The user-mode application sends IRP_MJ_DEVICE_CONTROL directly to a specific device driver. The\r\ndriver then performs the corresponding operation. Therefore, malicious user-mode applications can control the\r\ndriver via this mechanism.\r\nThe driver supports approx. 60 control codes. We divided the control codes into 3 basic groups: controlling,\r\ninserting, and setting.\r\nControlling\r\nThere are 9 main control codes invoking driver functionality from the user-mode. The following Table 3\r\nsummarizes controlling IOCTL that can be sent by malware using the Win32 API.\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 4 of 19\n\nTable 3. Controlling IOCTLs\r\nInserting\r\nThere are 11 control codes inserting items into white/blacklists. The following Table 4 summarizes variables and\r\ntheir purpose.\r\nTable 4. White and Black lists\r\nSetting\r\nThe setting control codes store scalar values as a global variable. The following Table 5 summarizes and groups\r\nthese variables and their purpose.\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 5 of 19\n\nTable 5. Global driver variables\r\nThe following Table 6 summarizes variables used for the process injection; see Thread Notification.\r\nTable 6. Injection variables\r\n2.4 Minifilter Driver\r\nThe minifilter driver is registered in the Driver Entry routine using the FltRegisterFilter() method. One of the\r\nmethod arguments defines configuration ( FLT_REGISTRATION ) and callback methods\r\n( FLT_OPERATION_REGISTRATION ). If the QueryDirectory system request is invoked, the malware driver catches\r\nthis request and processes it by its FltPostOperation() .\r\nThe FltPostOperation() method can modify a result of the QueryDirectory operations (IRP). In fact, the\r\nmalware driver can affect (hide, insert, modify) a directory enumeration. So, some applications in the user-mode\r\nmay not see the actual image of the requested directory.\r\nThe driver affects the QueryDirectory results only if a requested process is not present in whitelists. There are two\r\nwhitelists. The first whitelists (Process ID and File names) cause that the QueryDirectory results are not modified\r\nif the process ID or process image file name, requesting the given I/O operation (QueryDirectory), is present in\r\nthe whitelists. It represents malware processes that should have access to the file system without restriction. The\r\nfurther whitelist is called WinDeviceNumber, defining a set of suffixes. The FltPostOperation() iterates each\r\nitem of the QueryDirectory. If the enumerated item name has a suffix defined in the whitelist, the driver removes\r\nthe item from the QueryDirectory results. It ensures that the whitelisted files are not visible for non-malware\r\nprocesses [2]. So, the driver can easily hide an arbitrary directory/file for the user-mode applications, including\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 6 of 19\n\nexplorer.exe . The name of the WinDeviceNumber whitelist is probably derived from malware file names, e.g,\r\nKe145057.xsl , since the suffix is a number; see Appendix B.\r\n2.5 Callback of NTFS Driver\r\nWhen the driver is loaded, the Driver Entry routine modifies the system driver for the NTFS filesystem. The\r\noriginal callback method for the IRP_MJ_CREATE major function is replaced by a malicious callback\r\nMalNtfsCreatCallback() as Figure 1 illustrates. The malicious callback determines what should gain access and\r\nwhat should not.\r\nFigure 1. Rewrite IRP_MJ_CREATE callback of the regular NTFS driver\r\nThe malicious callback is active only if the Minifilter Driver registration has been done and the original callback\r\nhas been replaced. There are whitelists and one blacklist. The whitelists store information about allowed process\r\nimage names, process ID, and allowed files. If the process requesting the disk access is whitelisted, then the\r\nrequested file must also be on the white list. It is double protection. The blacklist is focused on processing image\r\nnames. Therefore, the blacklisted processes are denied access to the file system. Figure 2 demonstrates the\r\nwhitelisting of processes. If a process is on the whitelist, the driver calls the original callback; otherwise, the\r\nrequest ends with access denied.\r\nFigure 2. Grant access to whitelisted processes\r\nIn general, if the malicious callback determines that the requesting process is authorized to access the file system,\r\nthe driver calls the original IRP_MJ_CREATE major function. If not, the driver finishes the request as\r\nSTATUS_ACCESS_DENIED .\r\n2.6 Registry Hiding\r\nThe driver can hide a given registry key. Each manipulation with a registry key is hooked by the kernel method\r\nGetCellRoutine() . The configuration manager assigns a control block for each open registry key. The control\r\nblock ( CM_KEY_CONTROL_BLOCK ) structure keeps all control blocks in a hash table to quickly search for existing\r\ncontrol blocks. The GetCellRoutine() hook method computes a memory address of a requested key. Therefore,\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 7 of 19\n\nif the malware driver takes control over the GetCellRoutine() , the driver can filter which registry keys will be\r\nvisible; more precisely, which keys will be searched in the hash table.\r\nThe malware driver finds an address of the original GetCellRoutine() and replaces it with its own malicious\r\nhook method, MalGetCellRoutine() . The driver uses well-documented implementation [3, 4]. It just goes\r\nthrough kernel structures obtained via the ZwOpenKey() kernel call. Then, the driver looks for\r\nCM_KEY_CONTROL_BLOCK , and its associated HHIVE structured correspond with the requested key. The HHIVE\r\nstructure contains a pointer to the GetCellRoutine() method, which the driver replaces; see Figure 3.\r\nFigure 3. Overwriting GetCellRoutine\r\nThis method’s pitfall is that offsets of looked structure, variable, or method are specific for each windows version\r\nor build. So, the driver must determine on which Windows version the driver runs.\r\nThe MalGetCellRoutine() hook method performs 3 basic operations as follow:\r\n1. The driver calls the original kernel GetCellRoutine() method.\r\n2. Checks whitelists for a requested registry key.\r\n3. Catches or releases the requested registry key according to the whitelist check.\r\nRegistry Key Hiding\r\nThe hiding technique uses a simple principle. The driver iterates across a whole HIVE of a requested key. If the\r\ndriver finds a registry key to hide, it returns the last registry key of the iterated HIVE. When the interaction is at\r\nthe end of the HIVE, the driver does not return the last key since it was returned before, but it just returns NULL,\r\nwhich ends the HIVE searching.\r\nThe consequence of this principle is that if the driver wants to hide more than one key, the driver returns the last\r\nkey of the searched HIVE more times. So, the final results of the registry query can contain duplicate keys.\r\nWhitelisting\r\nThe services.exe and System services are whitelisted by default, and there is no restriction. Whitelisted\r\nprocess image names are also without any registry access restriction.\r\nA decision-making mechanism is more complicated for Windows 10. The driver hides the request key only for\r\nregedit.exe application if the Windows 10 build is 14393 (July 2016) or 15063 (March 2017).\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 8 of 19\n\n2.7 Thread Notification\r\nThe main purpose of the Thread Notification is to inject malicious code into created threads. The driver registers a\r\nthread notification routine via PsSetCreateThreadNotifyRoutine() during the Device Entry initialization. The\r\nroutine registers a callback which is subsequently notified when a new thread is created or deleted. The suspicious\r\ncallback ( PCREATE_THREAD_NOTIFY_ROUTINE ) NotifyRoutine() takes three arguments: ProcessID, ThreadID,\r\nand Create flag. The driver affects only threads in which Create flag is set to TRUE, so only newly created\r\nthreads.\r\nThe whitelisting is focused on two aspects. The first one is an image name, and the second one is command-line\r\narguments of a created thread. The image name is stored in WinDriverMaker1, and arguments are stored as a\r\nchecksum in the WinDriverMaker2 variable. The driver is designed to inject only two processes defined by a\r\nprocess name and two processes defined by command line arguments. There are no whitelists, just 4 global\r\nvariables.\r\n2.7.1 Kernel Method Lookup\r\nThe successful injection of the malicious code requires several kernel methods. The driver does not call these\r\nmethods directly due to detection techniques, and it tries to obfuscate the required method. The driver requires the\r\nfollowing kernel methods: ZwReadVirtualMemory , ZwWriteVirtualMemory , ZwQueryVirtualMemory ,\r\nZwProtectVirtualMemory , NtTestAlert , LdrLoadDll\r\nThe kernel methods are needed for successful thread injection because the driver needs to read/write process data\r\nof an injected thread, including program instruction.\r\nVirtual Memory Method Lookup\r\nThe driver gets the address of the ZwAllocateVirtualMemory() method. As Figure 4 illustrates, all lookup\r\nmethods are consecutively located after ZwAllocateVirtualMemory() method in ntdll.dll .\r\nFigure 4. Code segment of ntdll.dll with VirtualMemory methods\r\nThe driver starts to inspect the code segments from the address of the ZwAllocateVirtualMemory() and looks up\r\nfor instructions representing the constant move to eax (e.g. mov eax, ??h). It identifies the VirtualMemory\r\nmethods; see Table 7 for constants.\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 9 of 19\n\nTable 7. Constants of Virtual Memory methods for Windows 10 (64 bit)\r\nWhen an appropriate constants is found, the final address of a lookup method is calculated as follow:\r\nmethod_address = constant_address - alignment_constant ;\r\nwhere alignment_constant helps to point to the start of the looked-up method.\r\nThe steps to find methods can be summarized as follow:\r\n1. Get the address of ZwAllocateVirtualMemory() , which is not suspected in terms of detection.\r\n2. Each sought method contains a specific constant on a specific address ( constant_address ).\r\n3. If the constant_address is found, another specific offset ( alignment_constant ) is subtracted;\r\nthe alignment_constant is specific for each Windows version.\r\nThe exact implementation of the Virtual Memory Method Lookup method  is shown in Figure 5.\r\nFigure 5. Implementation of the lookup routine searching for the kernel VirtualMemory methods\r\nThe success of this obfuscation depends on the Window version identification. We found one Windows 7 version\r\nwhich returns different methods than the malware wants; namely, ZwCompressKey() , ZwCommitEnlistment() ,\r\nZwCreateNamedPipeFile() , ZwAlpcDeleteSectionView() .\r\nThe alignment_constant is derived from the current Windows version during the driver initialization; see the\r\nDriver Entry routine.\r\nNtTestAlert and LdrLoadDll Lookup\r\nA different approach is used for getting NtTestAlert() and LdrLoadDll() routines. The driver attaches to the\r\nwinlogon.exe process and gets the pointer to the kernel structure PEB_LDR_DATA containing PE header and\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 10 of 19\n\nimports of all processes in the system. If the import table includes a required method, then the driver extracts the\r\nbase address, which is the entry point to the sought routine.\r\n2.7.2 Process Injection\r\nThe aim of the process injection is to load a defined DLL library into a new thread via kernel function\r\nLdrLoadDll() . The process injection is slightly different for x86 and x64 OS versions.\r\nThe x64 OS version abuses the original NtTestAlert() routine, which checks the thread’s APC queue. The APC\r\n(Asynchronous Procedure Call) is a technique to queue a job to be done in the context of a specific thread. It is\r\ncalled periodically. The driver rewrites the instructions of the NtTestAlert() which jumps to the entry point of\r\nthe malicious code.\r\nModification of NtTestAlert Code\r\nThe first step to the process injection is to find free memory for a code cave. The driver finds the free memory\r\nnear the NtTestAlert() routine address. The code cave includes a shellcode as Figure 6. demonstrates.\r\nFigure 6. Malicious payload overwriting the original NtTestAlert() routine\r\nThe shellcode prepares a parameter ( code_cave address) for the malicious code and then jumps into it. The\r\noriginal NtTestAlert() address is moved into rax because the malicious code ends by the return instruction,\r\nand therefore the original NtTestAlert() is invoked. Finally, rdx contains the jump address, where the driver\r\ninjected the malicious code. The next item of the code cave is a path to the DLL file, which shall be loaded into\r\nthe injected process. Other items of the code cave are the original address and original code instructions of the\r\nNtTestAlert() .\r\nThe driver writes the malicious code into the address defined in dll_loading_shellcode . The original\r\ninstructions of NtTestAlert() are rewritten with the instruction which just jumps to the shellcode. It causes that\r\nwhen the NtTestAlert() is called, the shellcode is activated and jumps into the malicious code.\r\nMalicious Code x64\r\nThe malicious code for x64 is simple. Firstly, it recovers the original instruction of the rewritten NtTestAlert()\r\ncode. Secondly, the code invokes the found LdrLoadDll() method and loads appropriate DLL into the address\r\nspace of the injected process. Finally, the code executes the return instruction and jumps back to the original\r\nNtTestAlert() function.\r\nThe x86 OS version abuses the entry point of the injected process directly. The procedure is very similar to the\r\nx64 injection, and the x86 malicious code is also identical to the x64 version. However, the x86 malicious code\r\nneeds to find a 32bit variant of the  LdrLoadDll() method. It uses the similar technique described above\r\n(NtTestAlert and LdrLoadDll Lookup).\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 11 of 19\n\n2.8 Service Hiding\r\nWindows uses the Services Control Manager (SCM) to manage the system services. The executable of SCM is\r\nservices.exe . This program runs at the system startup and performs several functions, such as running, ending,\r\nand interacting with system services. The SCM process also keeps all run services in an undocumented service\r\nrecord ( SERVICE_RECORD ) structure.\r\nThe driver must patch the service record to hide a required service. Firstly, the driver must find the process\r\nservices.exe and attach it to this one via KeStackAttachProcess() . The malware author defined a byte\r\nsequence which the driver looks for in the process memory to find the service record. The services.exe keeps\r\nall run services as a linked list of SERVICE_RECORD [5]. The malware driver iterates this list and unlinks required\r\nservices defined by listServices whitelist; see Table 4.\r\nThe used byte sequence for Windows 2000, XP, Vista, and Windows 7 is as follows: {45 3B E5 74 40 48 8D\r\n0D} . There is another byte sequence {48 83 3D ?? ?? ?? ?? ?? 48 8D 0D} that is never used because it is\r\nbound to the Windows version that the malware driver has never identified; maybe in development.\r\nThe hidden services cannot be detected using PowerShell command Get-Service, Windows Task Manager, Process\r\nExplorer, etc. However, started services are logged via Windows Event Log. Therefore, we can enumerate all\r\nregular services and all logged services. Then, we can create differences to find hidden services.\r\n2.9 Driver Hiding\r\nThe driver is able to hide itself or another malicious driver based on the IOCTL from the user-mode. The Driver\r\nEntry is initiated by a parameter representing a driver object ( DRIVER_OBJECT ) of the loaded driver image. The\r\ndriver object contains an officially undocumented item called a driver section. The LDR_DATA_TABLE_ENTRY kernel\r\nstructure stores information about the loaded driver, such as base/entry point address, image name, image size, etc.\r\nThe driver section points to LDR_DATA_TABLE_ENTRY as a double-linked list representing all loaded drivers in the\r\nsystem.\r\nWhen a user-mode application lists all loaded drivers, the kernel enumerates the double-linked list of the\r\nLDR_DATA_TABLE_ENTRY structure. The malware driver iterates the whole list and unlinks items (drivers) that\r\nshould be hidden. Therefore, the kernel loses pointers to the hidden drivers and cannot enumerate all loaded\r\ndrivers [6].\r\n2.10 Driver Unload\r\nThe Driver Unload function contains suspicious code, but it seems to be never used in this version. The rest of the\r\nunload functionality executes standard procedure to unload the driver from the system.\r\n3. Loading Driver During Boot\r\nThe DirtyMoe service loads the malicious driver. A driver image is not permanently stored on a disk since the\r\nservice always extracts, loads, and deletes the driver images on the service startup. The secondary service aim is to\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 12 of 19\n\neliminate evidence about driver loading and eventually complicate a forensic analysis. The service aspires to\r\ncamouflage registry and disk activity. The DirtyMoe service is registered as follows:\r\nService name: Ms\u003cvolume_id\u003eApp ; e.g., MsE3947328App\r\nRegistry key: HKLM\\SYSTEM\\CurrentControlSet\\services\\\u003cservice_name\u003e\r\nImagePath: %SystemRoot%\\system32\\svchost.exe -k netsvcs\r\nServiceDll: C:\\Windows\\System32\\\u003cservice_name\u003e.dll, ServiceMain\r\nServiceType: SERVICE_WIN32_SHARE_PROCESS\r\nServiceStart: SERVICE_AUTO_START\r\n3.1 Registry Operation\r\nOn startup, the service creates a registry record, describing the malicious driver to load; see following example:\r\nRegistry key: HKLM\\SYSTEM\\CurrentControlSet\\services\\dump_E3947328\r\nImagePath: \\??\\C:\\Windows\\System32\\drivers\\dump_LSI_FC.sys\r\nDisplayName: dump_E3947328\r\nAt first glance, it is evident that ImagePath does not reflect DisplayName , which is the Windows common\r\nnaming convention. Moreover, ImagePath prefixed with dump_ string is used for virtual drivers (loaded only in\r\nmemory) managing the memory dump during the Windows crash. The malware tries to use the virtual driver name\r\nconvention not to be so conspicuous. The principle of the Dump Memory using the virtual drivers is described in\r\n[7, 8].\r\nImagePath values are different from each windows reboot, but it always abuses the name of the system native\r\ndriver; see a few instances collected during windows boot: dump_ACPI.sys , dump_RASPPPOE.sys ,\r\ndump_LSI_FC.sys , dump_USBPRINT.sys , dump_VOLMGR.sys , dump_INTELPPM.sys , dump_PARTMGR.sys\r\n3.2 Driver Loading\r\nWhen the registry entry is ready, the DirtyMoe service dumps the driver into the file defined by ImagePath .\r\nThen, the service loads the driver via ZwLoadDriver() .\r\n3.3 Evidence Cleanup\r\nWhen the driver is loaded either successfully or unsuccessfully, the DirtyMoe service starts to mask various\r\nmalicious components to protect the whole malware hierarchy.\r\nThe DirtyMoe service removes the registry key representing the loaded driver; see Registry Operation. Further,\r\nthe loaded driver hides the malware services, as the Service Hiding section describes. Registry entries related to\r\nthe driver are removed via the API call. Therefore, a forensics track can be found in the SYSTEM registry HIVE,\r\nlocated in %SystemRoot%\\system32\\config\\SYSTEM . The API call just removes a relevant HIVE pointer, but\r\nunreferenced data is still present in the HIVE stored on the disk. Hence, we can read removed registry entries via\r\nRegistryExplorer.\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 13 of 19\n\nThe loaded driver also removes the dumped ( dump_ prefix) driver file. We were not able to restore this file via\r\ntools enabling recovery of deleted files, but it was extracted directly from the service DLL file.\r\nCapturing driver image and register keys\r\nThe malware service is responsible for the driver loading and cleans up of loading evidence. We put a breakpoint\r\ninto the nt!IopLoadDriver() kernel method, which is reached if a process wants to load a driver into the system.\r\nWe waited for the wanted driver, and then we listed all the system processes. The corresponding service\r\n( svchost.exe ) has a call stack that contains the kernel call for driver loading, but the corresponding service has\r\nbeen killed by EIP registry modifying. The process (service) was killed, and the whole Windows ended in BSoD.\r\nWindows made a crash dump, so the file system caches have been flushed, and the malicious service did not finish\r\nthe cleanup in time. Therefore, we were able to mount a volume and read all wanted data.\r\n3.4 Forensic Traces\r\nAlthough the DirtyMoe service takes great pains to cover up the malicious activities, there are a few aspects that\r\nhelp identify the malware.\r\nThe DirtyMoe service and loaded driver itself are hidden; however, the Windows Event Log system records\r\ninformation about started services. Therefore, we can get additional information such as ProcessID and ThreadID\r\nof all services, including the hidden services.\r\nWinDbg connected to the Windows kernel can display all loaded modules using the lm command. The module\r\nlist can uncover non-virtual drivers with prefix dump_ and identify the malicious drivers.\r\nOffline connected volume can provide the DLL library of the services and other supporting files, which are\r\nunfortunately encrypted and obfuscated with VMProtect. Finally, the offline SYSTEM registry stores records of\r\nthe DirtyMoe service.\r\n4. Certificates\r\nWindows Vista and later versions of Windows require that loaded drivers must be code-signed. The digital code-signature should verify the identity and integrity of the driver vendor [9]. However, Windows does not check the\r\ncurrent status of all certificates signing a Windows driver. So, if one of the certificates in the path is expired or\r\nrevoked, the driver is still loaded into the system. We will not discuss why Windows loads drivers with invalid\r\ncertificates since this topic is really wide. The backward compatibility but also a potential impact on the kernel\r\nimplementation play a role.\r\nDirtyMoe drivers are signed with three certificates as follow:\r\nBeijing Kate Zhanhong Technology Co.,Ltd.\r\nValid From: 28-Nov-2013 (2:00:00)\r\nValid To: 29-Nov-2014 (1:59:59)\r\nSN: 3C5883BD1DBCD582AD41C8778E4F56D9\r\nThumbprint: 02A8DC8B4AEAD80E77B333D61E35B40FBBB010A0\r\nRevocation Status: Revoked on 22-May-2014 (9:28:59)\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 14 of 19\n\nBeijing Founder Apabi Technology Limited\r\nValid From: 22-May-2018 (2:00:00)\r\nValid To: 29-May-2019 (14:00:00)\r\nSN: 06B7AA2C37C0876CCB0378D895D71041\r\nThumbprint: 8564928AA4FBC4BBECF65B402503B2BE3DC60D4D\r\nRevocation Status: Revoked on 22-May-2018 (2:00:01)\r\nShanghai Yulian Software Technology Co., Ltd. (上海域联软件技术有限公司)\r\nValid From: 23-Mar-2011 (2:00:00)\r\nValid To: 23-Mar-2012 (1:59:59)\r\nSN: 5F78149EB4F75EB17404A8143AAEAED7\r\nThumbprint: 31E5380E1E0E1DD841F0C1741B38556B252E6231\r\nRevocation Status: Revoked on 18-Apr-2011 (10:42:04)\r\nThe certificates have been revoked by their certification authorities, and they are registered as stolen, leaked,\r\nmisuse, etc. [10]. Although all certificates have been revoked in the past, Windows loads these drivers\r\nsuccessfully because the root certificate authorities are marked as trusted.\r\n5. Summarization and Discussion\r\nWe summarize the main functionality of the DirtyMoe driver. We discuss the quality of the driver implementation,\r\nanti-forensic mechanisms, and stolen certificates for successful driver loading.\r\n5.1 Main Functionality\r\nAuthorization\r\nThe driver is controlled via IOCTL codes which are sent by malware processes in the user-mode. However, the\r\ndriver implements the authorization instrument, which verifies that the IOCTLs are sent by authenticated\r\nprocesses. Therefore, not all processes can communicate with the driver.\r\nAffecting the Filesystem\r\nIf a rootkit is in the kernel, it can do “anything”. The DirtyMoe driver registers itself in the filter manager and\r\nbegins to influence the results of filesystem I/O operations; in fact, it begins to filter the content of the filesystem.\r\nFurthermore, the driver replaces the NtfsCreatCallback() callback function of the NTFS driver, so the driver\r\ncan determine who should gain access and what should not get to the filesystem.\r\nThread Monitoring and Code injection\r\nThe DirtyMoe driver enrolls a malicious routine which is invoked if the system creates a new thread. The\r\nmalicious routine abuses the APC kernel mechanism to execute the malicious code. It loads arbitrary DLL into the\r\nnew thread. \r\nRegistry Hiding\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 15 of 19\n\nThis technique abuses the kernel hook method that indexes registry keys in HIVE. The code execution of the hook\r\nmethod is redirected to the malicious routine so that the driver can control the indexing of registry keys. Actually,\r\nthe driver can select which keys will be indexed or not.\r\nService and Driver Hiding\r\nPatching of specific kernel structures causes that certain API functions do not enumerate all system services or\r\nloaded drivers. Windows services and drivers are stored as a double-linked list in the kernel. The driver corrupts\r\nthe kernel structures so that malicious services and drivers are unlinked from these structures. Consequently, if the\r\nkernel iterates these structures for the purpose of enumeration, the malicious items are skipped.\r\n5.2 Anti-Forensic Technique\r\nAs we mentioned above, the driver is able to hide itself. But before driver loading, the DirtyMoe service must\r\nregister the driver in the registry and dump the driver into the file. When the driver is loaded, the DirtyMoe service\r\ndeletes all registry entries related to the driver loading. The driver deletes its own file from the file system through\r\nthe kernel-mode. Therefore, the driver is loaded in the memory, but its file is gone.\r\nThe DirtyMoe service removes the registry entries via standard API calls. We can restore this data from the\r\nphysical storage since the API calls only remove the pointer from HIVE. The dumped driver file is never\r\nphysically stored on the disk drive because its size is too small and is present only in cache memory. Accordingly,\r\nthe file is removed from the cache before cache flushing to the disk, so we cannot restore the file from the physical\r\ndisk.\r\n5.3 Discussion\r\nThe whole driver serves as an all-in-one super rootkit package. Any malware can register itself in the driver if\r\nknowing the authorization code. After successful registration, the malware can use a wide range of driver\r\nfunctionality. Hypothetically, the authorization code is hardcoded, and the driver’s name can be derived so we can\r\ncommunicate with the driver and stop it.\r\nThe system loads the driver via the DirtyMoe service within a few seconds. Moreover, the driver file is never\r\npresent in the file system physically, only in the cache. The driver is loaded via the API call, and the DirtyMoe\r\nservice keeps a handler of the driver file, so the file manipulation with the driver file is limited. However, the\r\ndriver removes its own file using kernel-call. Therefore, the driver file is removed from the file system cache, and\r\nthe driver handler is still relevant, with the difference that the driver file does not exist, including its forensic\r\ntraces.\r\nThe DirtyMoe malware is written using Delphi in most cases. Naturally, the driver is coded in native C. The code\r\nstyle of the driver and the rest of the malware is very different. We analyzed that most of the driver functionalities\r\nare downloaded from internet forums as public samples. Each implementation part of the driver is also written in a\r\ndifferent style. The malware authors have merged individual rootkit functionality into one kit. They also merged\r\nknown bugs, so the driver shows a few significant symptoms of driver presence in the system. The authors needed\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 16 of 19\n\nto adapt the functionality of the public samples to their purpose, but that has been done in a very dilettante way. It\r\nseems that the malware authors are familiar only with Delphi.\r\nFinally, the code-signature certificates that are used have been revoked in the middle of their validity period.\r\nHowever, the certificates are still widely used for code signing, so the private keys of the certificates have\r\nprobably been stolen or leaked. In addition, the stolen certificates have been signed by the certification authority\r\nwhich Microsoft trusts, so the certificates signed in this way can be successfully loaded into the system despite\r\ntheir revocation. Moreover, the trend in the use of certificates is growing, and predictions show that it will\r\ncontinue to grow in the future. We will analyze the problems of the code-signature certificates in the future post.\r\n6. Conclusion\r\nDirtyMoe driver is an advanced piece of rootkit that DirtyMoe uses to effectively hide malicious activity on host\r\nsystems. This research was undertaken to inspect the rootkit functionally of the DirtyMoe driver and evaluate the\r\nimpact on infected systems. This study set out to investigate and present the analysis of the DirtyMoe driver,\r\nnamely its functionality, the ability to conceal, deployment, and code-signature.\r\nThe research has shown that the driver provides key functionalities to hide malicious processes, services, and\r\nregistry keys. Another dangerous action of the driver is the injection of malicious code into newly created\r\nprocesses. Moreover, the driver also implements the minifilter, which monitors and affects I/O operations on the\r\nfile system. Therefore, the content of the file system is filtered, and appropriate files/directories can be hidden for\r\nusers. An implication of this finding is that malware itself and its artifacts are hidden even for AVs. More\r\nimportantly, the driver implements another anti-forensic technique which removes the driver’s evidence from disk\r\nand registry immediately after driver loading. However, a few traces can be found on the victim’s machines.\r\nThis study has provided the first comprehensive review of the driver that protects and serves each malware service\r\nand process of the DirtyMoe malware. The scope of this study was limited in terms of driver functionality.\r\nHowever, further experimental investigations are needed to hunt out and investigate other samples that have been\r\nsigned by the revoked certificates. Because of this, the malware author can be traced and identified using thus\r\nabused certificates.\r\nIoCs\r\nSamples (SHA-256)\r\n550F8D092AFCD1D08AC63D9BEE9E7400E5C174B9C64D551A2AD19AD19C0126B1\r\nAABA7DB353EB9400E3471EAAA1CF0105F6D1FAB0CE63F1A2665C8BA0E8963A05\r\nB3B5FFF57040C801A4392DA2AF83F4BF6200C575AA4A64AB9A135B58AA516080\r\nCB95EF8809A89056968B669E038BA84F708DF26ADD18CE4F5F31A5C9338188F9\r\nEB29EDD6211836E6D1877A1658E648BEB749091CE7D459DBD82DC57C84BC52B1\r\nAppendix A\r\nRegistry entries used in the Start Routine\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDeviceAddress\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDeviceNumber\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 17 of 19\n\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDeviceId\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDeviceName\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDeviceNameB\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDeviceNameOnly\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverMaker1\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverMaker1_2\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverMaker2\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverMaker2_2\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDevicePathA\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDevicePathB\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverPath1\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverPath1_2\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverPath2\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverPath2_2\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDeviceDataA\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDeviceDataB\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverDataA\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverDataA_2\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverDataB\r\n\\\\Registry\\\\Machine\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinApi\\\\WinDriverDataB_2\r\nAppendix B\r\nExample of registry entries configuring the driver\r\nKey: ControlSet001\\Control\\WinApi\r\nValue: WinDeviceAddress\r\nData: Ms312B9050App ;   \r\nValue: WinDeviceNumber\r\nData:\r\n\\WINDOWS\\AppPatch\\Ke601169.xsl;\r\n\\WINDOWS\\AppPatch\\Ke237043.xsl;\r\n\\WINDOWS\\AppPatch\\Ke311799.xsl;\r\n\\WINDOWS\\AppPatch\\Ke119163.xsl;\r\n\\WINDOWS\\AppPatch\\Ke531580.xsl;\r\n\\WINDOWS\\AppPatch\\Ke856583.xsl;\r\n\\WINDOWS\\AppPatch\\Ke999860.xsl;\r\n\\WINDOWS\\AppPatch\\Ke410472.xsl;\r\n\\WINDOWS\\AppPatch\\Ke673389.xsl;\r\n\\WINDOWS\\AppPatch\\Ke687417.xsl;\r\n\\WINDOWS\\AppPatch\\Ke689468.xsl;\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 18 of 19\n\n\\WINDOWS\\AppPatch\\Ac312B9050.sdb;\r\n\\WINDOWS\\System32\\Ms312B9050App.dll;\r\nValue: WinDeviceName\r\nData:\r\nC:\\WINDOWS\\AppPatch\\Ac312B9050.sdb;\r\nC:\\WINDOWS\\System32\\Ms312B9050App.dll;\r\nValue: WinDeviceId\r\nData: dump_FDC.sys ;\r\nA group of elite researchers who like to stay under the radar.\r\nSources\r\nSource: https://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nhttps://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/\r\nPage 19 of 19\n\nprocess image A decision-making names are also mechanism without any is more registry access complicated for restriction. Windows 10. The driver hides the request key only for\nregedit.exe application if the Windows 10 build is 14393 (July 2016) or 15063 (March 2017).\n   Page 8 of 19",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://decoded.avast.io/martinchlumecky/dirtymoe-rootkit-driver/"
	],
	"report_names": [
		"dirtymoe-rootkit-driver"
	],
	"threat_actors": [],
	"ts_created_at": 1775434542,
	"ts_updated_at": 1775826690,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/30bf6ca1dd72430e1d990ff80c290efee3df30f0.pdf",
		"text": "https://archive.orkl.eu/30bf6ca1dd72430e1d990ff80c290efee3df30f0.txt",
		"img": "https://archive.orkl.eu/30bf6ca1dd72430e1d990ff80c290efee3df30f0.jpg"
	}
}