{
	"id": "f6bc0def-17b3-4242-84fa-fbb5cd34ce3d",
	"created_at": "2026-04-10T03:21:51.442353Z",
	"updated_at": "2026-04-10T03:22:19.365128Z",
	"deleted_at": null,
	"sha1_hash": "9e20f513aa3b746b84f0f8fc55d2da185af58040",
	"title": ".Sys Payload and Registry Hunting – One Night in Norfolk",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1479760,
	"plain_text": ".Sys Payload and Registry Hunting – One Night in Norfolk\r\nPublished: 2021-02-01 · Archived: 2026-04-10 02:42:45 UTC\r\nIn an earlier post, this blog examined malware from a DPRK-affiliated campaign targeting security researchers.\r\nSince the initial public post about this activity from Google, multiple vendors have corroborated and\r\nsupplemented the technical details in this attack.\r\nWhereas the previous post examined a DLL file delivered via social engineering and VisualStudio, this post\r\nexamines the inner-workings of a malicious .sys file likely delivered through a watering hole. In addition to\r\nreverse engineering, this post offers possible threat hunting avenues for identifying data associated with this file\r\nhidden in the registry of a compromised system.\r\nFor those purely interested in the hunting portion of this post (the malware reads, and likely executes, data from\r\nthe registry), click here to skip ahead. As a disclaimer, the hunt workflow proposed is merely hypothetical, and\r\nshould not be considered any sort of official security guidance.\r\n(2/1 Update, Stage 2 can be found here)\r\nTechnical Analysis\r\nFilename: helpsvc.sys\r\nMD5: ae17ce1eb59dd82f38efb9666f279044\r\nSHA1: 3b3acb4a55ba8e2da36223ae59ed420f856b0aaf\r\nSHA256: a4fb20b15efd72f983f0fb3325c0352d8a266a69bb5f6ca2eba0556c3e00bd15\r\nExamining this file in IDA reveals that this file is a DLL likely intended to run as a service, given one of its\r\nexports (ServiceMain) and several of its imports (RegisterServiceCtrlHandlerW, SetServiceStatus). There are a\r\nfew routes available for debugging a file like this- ultimately, I settled on the following steps:\r\n1) Edit the first two bytes of ServiceMain to EB FE, creating a loop that allows us to attack, resume, and debug it\r\n2) Modify a previous service-installing PowerShell script from a different DPRK adversary\r\n3) Run PSExec with system-level permissions\r\n4) Use PSExec to run x64dbg, giving it the permissions needed to step into the running service and begin\r\ndebugging\r\nThe PowerShell script was selected for simplicity; in short, previous research showed that it can be used to install\r\na DLL as a service. This current task requires that a DLL be installed as a service. Thus, it did the job of handling\r\nthe appropriate registry modifications.\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 1 of 9\n\nModified script to install the driver. Note that the .cfg and .dat files are not needed. For simplicity,\r\nduring this analysis I created dummy files in their place to save time rather than removing them\r\naltogether, as they do not affect the script’s overall execution.\r\nThis PowerShell script will start a new copy of svchost, which in turn runs this new service. The PowerShell script\r\nwill also indicate that it is waiting for the service to start; this is expected, as several key routines within the\r\nmalware occur before the ServiceStatus is set.\r\nBy stepping into the svchost process, resuming this process, and selecting the correct running thread, we can place\r\na breakpoint on the infinite loop and re-patch the malware to the original instructions.\r\nDouble click the RIP to reach the infinite loop and set a breakpoint.\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 2 of 9\n\nRight click -\u003e Binary -\u003e Edit\r\nOnce this patch is in place, the malware will resume its expected behavior. First, the malware steps into a function\r\nand begins placing data in memory in a similar fashion as the previously analyzed DLL. In this instance, the\r\nmalware decrypts three values:\r\n– SubVersion\r\n– Description\r\n– Software\\Microsoft\\Windows\\CurrentVersion\\KernelConfig\r\nThis third value is a registry entry. The malware attempts to open this value under HKLM; however, this value\r\ndoes not exist, and the malware does not create it. This strongly suggests another mechanism, such as code\r\nlaunched via browser exploit or another dropper, places this data in the registry.\r\nIf the malware does open this key, it attempts to read data within values named SubVersion and Description (the\r\ntwo other decrypted strings). For the purposes of continuing the analysis, I created this registry key and these two\r\nentries, with dummy values in each location. The values chosen were random, which led to some trial and error to\r\ndetermine their possible purpose.\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 3 of 9\n\nThe RegQueryValue call takes in a handle (78) to a previously opened key and reads the data stored\r\nfrom this key into memory.\r\nAfter some attempts, it seemed that anything longer than four bytes in the SubVersion entry led to an error during\r\nthe malware’s execution. Specifically, the malware returned 0xEA and gracefully terminated. In addition, the\r\nmalware seemed to hit an exception when tested with exactly four bytes. I picked a random two-byte value to\r\nallow it to proceed.\r\nFor the Description entry, I used human-readable sentences and words to make them easier to track.\r\nContents of the Description key created to allow the malware to proceed.\r\nAfter reading the Description value, it begins transforming this data through a loop; however, the number of\r\nrepetitions of the loop is not dependent on the length of the Description data. Instead, the malware uses a value\r\nthat appears to be [10 in hex, 16 in decimal] fewer than the value stored in the SubVersion registry key. In\r\naddition, the malware truncates 16 hex characters off of the start of the data being transformed.\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 4 of 9\n\nData transformation\r\nAfter this transformation, the malware steps into a function that checks for the presence of a PE header (MZ) and\r\nallocates memory. This function also contains a call to a dynamic API resolution routine similar to the previously\r\nexamined DLL associated with this campaign; unfortunately, neither of these routines could be properly examined\r\nduring this analysis (likely due to the lack of a proper expected payload or other similar factors).\r\nFollowing these function calls, the malware starts the service.\r\nSecond Stage Payload\r\nAfter publication, an analyst who wished to remain anonymous pointed me to a copy of the missing registry data. I\r\nleft the previous writing intact, as the analytic method may prove useful to future readers. Below contains some\r\nbrief technical analysis of the payload decrypted from the registry.\r\nName: KernelConfig Registry data (approx. 2mb)\r\nMD5 7904d5ee5700c126432a0b4dab2776c9\r\nSHA1 79bd808e03ed03821b6d72dd8246995eb893de70\r\nSHA256 7c4ea495f9145bd9bdc3f9f084053a63a76061992ce16254f68e88147323a8ef\r\nThis file can be given a .reg extension, which will import the data into the device’s registry. With this data in\r\nplace, the malware properly continues its routine and decrypts and runs an executable payload.\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 5 of 9\n\nUnlike the DLL analyzed in a previous post that functioned as a downloader, this file has a wide range of\r\nadditional features. This second-stage file begins by dynamically resolving a very large list of APIs from Windows\r\nlibraries such as kernel32, advapi, ntdll, userenv, and others. The malware then:\r\n– Performs a startup check\r\n– Communicates with the C2 server (using the OpenSSL library)\r\n– Uses a Case-Switch workflow to carry out commands\r\nThe startup check (and other routines within the malware) use the same in-memory decoding routine to decrypt\r\nhidden strings containing important values for the malware’s execution. In this case, the malware can use this\r\nroutine to decode three C2 servers for communication. In addition, it can write to and read data from the a key\r\nlocated at HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\DriverConfig.\r\nAfter this, the malware will contact a C2 server. The decoded C2s for this sample are:\r\nhxxp: // www.colasprint[.]com/_vti_log/upload.asp\r\nhxxps: // www.dronerc[.]it/forum/uploads/index.php\r\nhxxps: // www.fabioluciani[.]com/es/include/include.asp\r\nC2 Workflow\r\nThe malware supports a wide range of commands and actions. Some of the highlights are:\r\n– Writing files to the disk and executing them\r\n– Collecting network adapter information\r\n– Enumerating running processes and there start times\r\n– Collecting drive and file info\r\n– Enumerating items in a directory\r\n– Creating a process\r\n– Terminating a process\r\n– Performing a screen capture\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 6 of 9\n\nScreen capture code\r\nBased on these commands, the tool is likely used to conduct reconnaissance and potentially to triage a device\r\nbefore taking further steps in the environment.\r\nHunting Possibilities\r\nWhen looking for malware like this on a device or across a network, an initial instinct might be to search for\r\nknown malicious registry key values. At the time of this writing, the only known registry entries for this malware\r\nare the ones described above at KernelConfig; however, the attackers could easily change this (or could have\r\ndeployed malware that uses different values against targets that have yet to identify the infection).\r\nFrom a defensive perspective, however, two things work in our favor:\r\n– Registry key values are usually small\r\n– Code needed to execute a malicious workflow is usually larger than a registry key\r\nGiven these two facts, one option is to examine the registry for any uncharacteristically large values. As this\r\npost will shortly show, this is merely a starting point for hunting; however, it’s an effective one.\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 7 of 9\n\nAs an experiment, I pulled malware samples from previous (unrelated) adversary activity. An uncompressed\r\nmeterpreter shell took up just under 1 kb (1,000 bytes). A compressed version took up approximately 300 bytes. I\r\nconsider these to be a reasonable estimate for the lower-bounds of an executable payload size that an attacker\r\nwould use.\r\nI then modified an open-source PowerShell script to enumerate the every key and value in the CurrentVersion\r\nlocation of HKLM. In a real scenario, I would likely try this against the entire registry.\r\nGet-ChildItem -Recurse registry::hklm\\software\\microsoft\\windows\\currentversion\\ | foreach-object {\r\n$path = $_.PSPath\r\n$_.Property | foreach-object {\r\n$name = $_\r\n$data = get-itemproperty -literalpath $path -name $name |\r\n select -expand $name\r\n $dl = $data.length\r\n#[pscustomobject]@{value=$name; data=$data; key=$path}\r\nadd-content -path \"c:\\users\\[user]\\desktop\\dump2.txt\" -value \"$path¿$name¿$dl\"\r\n}\r\n}\r\nThis produces a CSV file of approximately 194,000 values (I used the upside down question mark as a delimiter\r\nand edited out excess commas and quotation marks) with the key path, key name, and length of the data. In theory,\r\nsorting these by the largest keys should show outliers. I used the following Python code:\r\nimport csv\r\nimport re\r\nkeys = []\r\nwith open(\"c:\\\\users\\\\[user]\\\\desktop\\\\dump.txt\", encoding=\"utf-8\") as csvfile:\r\n reader = csv.reader(csvfile, delimiter=\",\")\r\n for line in reader:\r\n if int(line[2]) \u003e 199:\r\n demo_value = re.sub(\".*?hklm\",\"hklm\",line[0])\r\n else:\r\n demo_value = line[0]\r\n keyadd = []\r\n keyadd.append(int(line[2]))\r\n keyadd.append(str(line[1]))\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 8 of 9\n\nkeyadd.append(demo_value)\r\n keys.append(keyadd)\r\n #print(len(keys))\r\n keys.sort(reverse=True)\r\n for item in keys:\r\n print(item\r\nOut of 194,000 entries within the CurrentVersion section of the HKLM hive:\r\n– A 100KB payload such as the one analyzed in the previous post would easily top the list\r\n– A 1KB uncompressed meterpreter shell would also top the list\r\n– A 300 byte compressed meterpreter shell would be harder to identify, ranking right around the top 100\r\nAs mentioned above, this is just a starting point. Additions to this workflow, such as generating the last modified\r\ntime of the registry key, would likely greatly improve this workflow. Parsing the data for character entropy would\r\nalso likely improve the accuracy. Even without these two changes, however, a malicious payload stored in a\r\nregistry value would easily rank in the top 99% of values.\r\nUpdate 2/1/2021: Analysis of the proper, adversary-intended KernelConfig value shows that the registry data is\r\napproximately 2mb. Registry data of this size would likely rank at the top of any registry dump in this proposed\r\nworkflow.\r\nSource: https://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nhttps://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/\r\nPage 9 of 9",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://norfolkinfosec.com/dprk-targeting-researchers-ii-sys-payload-and-registry-hunting/"
	],
	"report_names": [
		"dprk-targeting-researchers-ii-sys-payload-and-registry-hunting"
	],
	"threat_actors": [],
	"ts_created_at": 1775791311,
	"ts_updated_at": 1775791339,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/9e20f513aa3b746b84f0f8fc55d2da185af58040.pdf",
		"text": "https://archive.orkl.eu/9e20f513aa3b746b84f0f8fc55d2da185af58040.txt",
		"img": "https://archive.orkl.eu/9e20f513aa3b746b84f0f8fc55d2da185af58040.jpg"
	}
}