{
	"id": "1c5ce7ca-a6e3-4b5c-b9e7-3fac00b760c0",
	"created_at": "2026-04-06T00:18:47.918777Z",
	"updated_at": "2026-04-10T03:21:19.974337Z",
	"deleted_at": null,
	"sha1_hash": "6c988b6799aaffcc4fa411bc2b375c22ae4bc190",
	"title": "Analyzing a Malicious Hangul Word Processor Document from a DPRK Threat Actor Group – 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": 1307610,
	"plain_text": "Analyzing a Malicious Hangul Word Processor Document from a\r\nDPRK Threat Actor Group – One Night in Norfolk\r\nPublished: 2019-02-25 · Archived: 2026-04-05 15:46:41 UTC\r\nA few days ago, ESTsecurity published a post detailing a newly identified malicious Hangul Word Processor\r\n(HWP) document that shared technical characteristics with previously reported malicious activity attributed to\r\nNorth Korean threat actors (an important note: this particular group is not typically associated with or clustered\r\nwith the SWIFT/ATM adversary detailed in other posts on this blog, although this blog avoids using specific\r\nvendor naming classifications where possible).\r\nThe Hangul Office suite is widely used in South Korea; in the West, it’s significantly less common. As a result of\r\nthis, there is limited public documentation regarding how to analyze exploit-laden HWP documents. This blog\r\npost is intended to provide additional documentation from start to finish of the file identified by ESTsecurity. As\r\nsuch, the language used will be somewhat less formal than the content typically posted here.\r\nThe following tools (in a VM) are recommended for analysis:\r\n1) Cerbero Profiler (advanced or standard)\r\n2) Process Hacker\r\n3) Ghostscript\r\n4) Any debugger (I prefer the x96 suite)\r\n5) jmp2it\r\n5) Hangul Office (optional) + a listener (e.g. FakeNet, Inetsim)\r\n6) scdbg (optional)\r\nI purchased my copy of Hangul Office on Amazon a while back. The English language version is typically\r\nvulnerable to the same exploits. Cerbero Profiler has a trial version that will work for this analysis (though it’s a\r\ngreat tool and deserves a purchase).\r\nAs a final note before analysis, two previous posts from other researchers deserve recognition: Jacob Soo’s post\r\npointed me towards Cerbero Profiler (and discusses some important HWP characteristics), and a post from Wayne\r\nLow at Fortinet has some great introductory material for debugging Encapsulated PostScript (EPS).\r\nStep 1: Triage and Analysis of the Document\r\nMD5: f2e936ff1977d123809d167a2a51cdeb\r\nSHA1: 7a86e6bffba91997553ac4cf0baec407bc255212\r\nSHA256: 5d9e5c7b1b71af3c5f058f8521d383dbee88c99ebe8d509ebc8aeb52d4b6267b\r\nA copy of Hangul Word Processor isn’t strictly necessary to analyze the file in question. If we do have a copy and\r\nuse it to open the document, we’ll notice two key events: the document will spawn a copy of Internet Explorer,\r\nand the analysis environment will make a network call to a compromised Korean website. This information is\r\nuseful later on, as it gives some basic guidelines for what to expect when analyzing the document’s payload.\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 1 of 10\n\nOpening the file in Cerbero Profiler will show several of the document’s different streams and objects. For\r\nmalicious HWP files (including the one discussed in Jacob Soo’s 2016 post noted above), there will be malicious\r\nJavaScript present. In this case, we’re instead interested in the contents of one of the streams, BIN0003.eps. The\r\ncontents in these streams are usually zlib compressed, and Cerbero Profiler can apply filters to them to\r\ndecompress them:\r\nIn the “Format” tab, select all of the content of the stream, right click, and hit “filter.”\r\nScroll down to the “unpack” category and select “zlib.” Check the box for “raw” and click “add.”\r\nThen click “Preview” in the bottom right, select all, and copy the “Ascii” contents.\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 2 of 10\n\nThe above images detail the steps for copying and decompressing the contents of the EPS stream. Pasting these\r\ninto a file will reveal a relatively simple EPS script.\r\nStep 2: Analyzing the EPS script\r\nPostScript is a stack-based programming language first conceived by Adobe in the 1980s. The documentation for\r\nthe language is nearly a thousand pages long. I do not recommend reading it. Encapsulated PostScript is a fork of\r\nthis, with restrictions. The documentation for this is significantly shorter, but still probably not necessary. I would\r\nstick with Fortinet’s overview.\r\nThe key concept for an EPS file is that each command is added to the top of a (clearable) “stack” in the order that\r\nit’s typed. Below is the EPS script we copied from Cerbero (pasted into any text editor):\r\nThe decompressed EPS script\r\nEven without truly understanding the EPS language, we can infer what’s likely happening here. At the top, a\r\n(truncated) set of hexadecimal bytes are added to the stack. A series of variables are defined, a transformation is\r\napplied to the bytes, and (presumably) the “exec” function is applied to the results of this transformation. Even\r\nthough we might not know precisely how to interpret this transformation, we can assume that there is a second\r\nlayer to this script. In other programming languages, we might tell the script to Alert, MsgBox, or Print the\r\nexecuted value (instead of executing this value), and EPS is no exception. Substitute the “exec” commands with a\r\nsingle print:\r\nReplace “exec exec” with “print”\r\nWe also need something to actually run the EPS file. Ghostscript supports EPS execution and is a relatively quick\r\ninstall. Ghostscript comes with a GUI/Shell version and a command-line version. For this, we need to use the\r\ncommand-line version, as the shell won’t render all of the data that gets printed and thus we won’t be able to copy\r\nand paste it. Open up a command line prompt and copy the syntax below (noting the inverted slashes on a\r\nWindows system and the parenthesis- these were derived from test dragging files into the Shell version to\r\ndetermine the proper syntax).\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 3 of 10\n\nExecuting an EPS file with Ghostscript\r\nHit enter, and it will print the contents. From there, copy and paste the content of the console into a new text file:\r\nPrinted second-layer EPS script. The boxed brackets represent the boundaries of the hex array to be\r\ncopied into a file for analysis.\r\nAt this stage, we can infer that we likely have executable shellcode: the beginning of the large byte array begins\r\nwith a 0x90 “nop sled.” Copy just the hex array as bytes into a hex editor (such as HxD) and save the file. We can\r\nmove on to the next analysis step.\r\nStep 3: Analyzing Shellcode\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 4 of 10\n\nThe dumped bytes don’t represent a compiled program; rather, they are raw instructions of executable code. There\r\nare two great tools that can help triage and analyze this code:\r\n1) scdbg- Emulates the shellcode and highlights key API calls\r\n2) jmp2it- Executes shellcode in an attachable, debuggable program\r\nBy performing a quick triage with scdbg, we can get a bit of a head start on the shellcode that we’re about to\r\nexamine (note: I had initially redacted the username in some images):\r\nWe can see a handful of API calls, including one that resolves the folder path for the Program Files directory.\r\nHowever, our initial execution of the HWP document indicated that the sample would launch Internet Explorer\r\nand issue a network callout. The API calls above are insufficient to perform those two tasks; hence, we need to\r\ndebug the shellcode to determine what’s “missing” and why that might be.\r\nThe jmp2it tool will execute shellcode beginning at a specified offset (in this case, 0x00 will work as that’s the\r\nstart of the “noop sled”) and can pause it in an infinite loop while we attach a debugger. It provides additional\r\ninstructions for patching this loop and jumping in to the next function.\r\nDebugging the shellcode itself requires a bit of practice. In this sample, immediately after the noop sled, the first\r\nroutine begins decoding additional code (and thus, modified the code):\r\nThe “analyze” button (both before and after any routines that change the code) will help highlight\r\nspecific functions.\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 5 of 10\n\nAs the code is relatively small, single-stepping through is not as daunting as it might be for a larger sample\r\n(though, stepping out of loops that you already understand will certainly save time). One of our questions from the\r\ntriage was identifying additional API calls and next-step functionality. For the former, look for (and\r\ncomment/label) functions that are repeated often:\r\nThe boxed routine on the left returns an API to the EAX register.\r\nUltimately, this shellcode stage will take several actions: it will attempt to open a (non-existent) “thumbs.db” file\r\n(not pictured), and it will launch a suspended copy of Internet Explorer, inject additional code into its memory\r\n(using more resolved API calls) and then create a remote thread in that process to execute this code:\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 6 of 10\n\nWriting code to, and creating a remote thread in, the Internet Explorer process\r\nWe do not want to step into or over the CreateRemoteThread call. Instead, we want to dump the executable\r\nsection of code from the suspended Internet Explorer instance, and repeat the debugging steps.\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 7 of 10\n\nIdentifying an additional set of injected code\r\nRunning this code through scdbg suggests that we’re nearing the end:\r\nNow we see our network traffic endpoint (a compromised website) and a series of API calls directly related to\r\ncommunicating with that location. Debugging this second set of shellcode (with the help of jmp2it) will show a\r\nsimilar pattern: an initial decoding routine, following by the resolution of the API calls needed to carry out the\r\nnext task:\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 8 of 10\n\nAnd finally, these are used to communicate with the endpoint:\r\nUnfortunately, this is where our analysis ends without running the sample and capturing a PCAP (or pulling one\r\ndown from a sandbox). The next call is for the code to read the response from the server and execute it;\r\npresumably, this is an additional layer of shellcode (perhaps containing an embedded payload). Without that code,\r\nwe can’t say for sure what the payload might be; however, some quick pivoting on our initial code can help us\r\nmake an educated assessment:\r\nIt would appear that “our” sample has a code overlap with a previously submitted sample, and this sample\r\ncommunicates with a C2 previously highlighted in a Cisco Talos report.* In that report, Cisco noted (and\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 9 of 10\n\ndocumented) a final payload classified as “NavRAT” delivered using a very similar mechanism and containing the\r\nsame file name from the ESTsecurity report. If we were making an assessment, our best guess would be that we\r\nwould expect the same (or similar) payload here.\r\n* Most likely, somebody took the older shellcode, converted it into an executable for analysis, and uploaded to\r\nVirusTotal.\r\nSource: https://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nhttps://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/\r\nPage 10 of 10",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://norfolkinfosec.com/how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group/"
	],
	"report_names": [
		"how-to-analyzing-a-malicious-hangul-word-processor-document-from-a-dprk-threat-actor-group"
	],
	"threat_actors": [],
	"ts_created_at": 1775434727,
	"ts_updated_at": 1775791279,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/6c988b6799aaffcc4fa411bc2b375c22ae4bc190.pdf",
		"text": "https://archive.orkl.eu/6c988b6799aaffcc4fa411bc2b375c22ae4bc190.txt",
		"img": "https://archive.orkl.eu/6c988b6799aaffcc4fa411bc2b375c22ae4bc190.jpg"
	}
}