{
	"id": "d6c0e19e-4d9b-4245-931d-a1b64c17f9d3",
	"created_at": "2026-04-06T00:19:30.10716Z",
	"updated_at": "2026-04-10T03:21:13.437043Z",
	"deleted_at": null,
	"sha1_hash": "96b6981bc457e1bf778ee1e2f83ac8442058be09",
	"title": "Poweliks - Command Line Confusion - Stormshield",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1235130,
	"plain_text": "Poweliks - Command Line Confusion - Stormshield\r\nBy Stormshield Customer Security Lab\r\nPublished: 2014-08-20 · Archived: 2026-04-05 14:25:29 UTC\r\nRecently, hFireF0X provided a detailed walkthrough on the reverse engineering forum kernelmode.info\r\nabout Win32/Poweliks malware. The particularity of this malware is that it resides in the Windows registry\r\nand uses rundll32.exe to execute JavaScript code.\r\nI found it funny that we can execute some JavaScript through Rundll32 and obviously I was not the only one.\r\nWhen we first saw the command line executing JavaScript, we were wondering how it worked.\r\nIn this blog post, we analyze how and why JavaScript is executed when calling this simple command line:\r\nReminder about Rundll32\r\nRundll32 usage is documented on MSDN; it is used to call an exported function of a DLL file which can be\r\nachieved with the following command line:\r\nRUNDLL32.EXE \u003cdllname\u003e,\u003centrypoint\u003e \u003coptional arguments\u003e\r\nentrypoint is the exported function; its prototype must be:\r\nvoid CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);\r\nThe lpszCmdLine parameter is given the \u003coptional arguments\u003e value specified on the rundll32 command line.\r\nWe will try to figure out how Rundll32 is able to call the function RunHTMLApplication exported by the library\r\nmshtml.dll and how the “javascript:” prefix is used to execute actual JavaScript code.\r\nAnalysis of Rundll32\r\nParameters\r\nOne of the first things done by Rundll32 is to parse the command line in the internal function ParseCommand .\r\nThis function searches for a comma (‘,’, 0x2C) to locate the DLL name and for a space (‘ ‘, 0x20) to locate the\r\nentrypoint name.\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 1 of 9\n\nWhen using our sample command line, ParseCommand returns javascript:\"\\..\\mshtml as the DLL name and\r\nRunHTMLApplication as the entrypoint. In this context, the space after RunHTMLApplication delimits the\r\n‘optional arguments’ part of the rundll32 command line:\r\nDll loader\r\nRundll32 will perform several tries to load the actual DLL from the initial specification\r\njavascript:\"\\..\\mshtml .\r\nThe first test uses the function GetFileAttributes(“javascript:”\\..\\mshtml”) . This function eventually\r\naccesses C:\\Windows\\system32\\mshtml . As this file is not found, the function returns -1.\r\nSearchPath is then invoked to resolve the DLL name. This function reads the registry key\r\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SafeProcessSearchMode . The\r\nMicrosoft definition of this key is:\r\nWhen the value of this REG_DWORD registry value is set to 1, SearchPath first searches the folders that are\r\nspecified in the system path, and then searches the current working folder. When the value of this registry value is\r\nset to 0, the computer first searches the current working folder, and then searches the folders that are specified in\r\nthe system path. The system default value for this registry key is 0.\r\nBy default this registry key doesn’t exist (on Windows XP / 7 / 8) so SearchPath tries to load the file mshtml in\r\nthe current directory of rundll32 (c:\\windows\\system32) prior to trying locating it in the system path.\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 2 of 9\n\nAll these attempts fail and rundll32 moves to the next step. GetFileAttributes is called again searching for the\r\nmanifest for the module: javascript:”\\..\\mshtml.manifest\r\n Since all the previous steps failed, Rundll32 eventually calls LoadLibrary(\"javascript:\"\\..\\mshtml\") .\r\nLoadLibrary is just a thin wrapper around LdrLoadDll located in ntdll.dll . Internally, LdrLoadDll adds\r\nthe default extension .dll and parses the resulting string javascript:”\\..\\mshtml.dll as a path. The token ..\r\ninstructs to go one folder up: it resolves to mshtml.dll (think of foo\\..\\mshtml.dll resolved as mshtml.dll ).\r\nWith mshtml.dll specification, LdrLoadDll is able to load the library in the system directory.\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 3 of 9\n\nRundll32 then calls GetProcAddress with the previously extracted entry point name RunHTMLApplication .\r\nFor the moment, the javascript: prefix seems pretty useless: LoadLibrary(\"foobar:\\\"\\..\\mshtml\") works\r\nfine. So, why prefixing with javascript: ?\r\nProtocols Handler\r\nOnce the entry point address has been resolved, Rundll32 calls the function mshtml.dll!RunHTMLApplication .\r\nEven if not documented, the actual RunHTMLApplication can be inferred from the call made by\r\nc:\\windows\\system32\\mshta.exe (the application dedicated to launch an .hta file):\r\nHRESULT RunHTMLApplication(\r\nHINSTANCE hinst,\r\nHINSTANCE hPrevInst,\r\nLPSTR szCmdLine,\r\nint nCmdShow\r\n);\r\nThis is not far from the function prototype expected for a rundll32 entry point:\r\nvoid CALLBACK EntryPoint(\r\nHWND hwnd,\r\nHINSTANCE hinst,\r\nLPSTR lpszCmdLine,\r\nint nCmdShow\r\n);\r\nRunHTMLApplication receives a handle to a window instead of a handle to a module as the first parameter. This\r\nparameter is used when mshml registers for a window class and creates a window of this new class. Passing a\r\nvalue not corresponding to an actual instance doesn’t seem to disturb user32 very much…\r\nThe second parameter is not used at all, so the mismatch is not important.\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 4 of 9\n\nThe last parameter, nCmdShow , is used by the RunHTMLApplication function to display the window hosting the\r\nHTML application. Rundll32 always calls the entry point function with the value SW_SHOWDEFAULT to instruct any\r\npotential opened window to use window default placement.\r\nThe main parameter of interest would be lpszCmdLine ( \";alert('foo') ) in our case.\r\nThis obviously leads to an issue since this is not a valid JavaScript statement (please note the missing double-quote at the end of the statement). But it works anyway, because RunHTMLApplication ignores the given\r\nparameter and prefers to request again the original command line from the GetCommandLine Windows API\r\n(wrapped in a call to the GetCmdLine function).\r\nThe full command line contains the name of the executable and the parameters: GetCmdLine extracts the\r\nparameters by cleaning up the executable specification:\r\nAfter that, RunHTMLApplication calls CreateUrlMoniker :\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 5 of 9\n\nThis is where the string « javascript: » is essential.\r\nCreateUrlMoniker parses the command line to extract the string before the char “:” (0x3A): “javascript” .\r\nCreateUrlMoniker crawls the registry key HKCR\\SOFTWARE\\Classes\\PROTOCOLS\\Handler\\ . These keys refer to a\r\nset of protocols and their CLSID.\r\nCreateUrlMoniker finds an appropriate protocol handler for the JavaScript protocol\r\n( HKCR\\SOFTWARE\\Classes\\PROTOCOLS\\Handler\\javascript ):\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 6 of 9\n\nThe CLSID {3050F3B2-98B5-11CF-BB82-00AA00BDCE0B} matches «  Microsoft HTML Javascript Pluggable\r\nProtocol  ».\r\nIt is for this reason that the string \" javascript \" is essential in the beginning of the parameters.\r\nThe same mechanism comes into play when one types javascript:alert(‘foo’) ; in the Internet Explorer\r\nnavigation bar:\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 7 of 9\n\nThe remaining of the string located after the ‘:’ separator is interpreted by the JavaScript URL moniker as\r\nJavaScript instructions:\r\n\"\\..\\mshtml,RunHTMLApplication \";alert(‘foo’);\r\nThis is a valid JavaScript with a string \"\\..\\mshtml,RunHTMLApplication \" (hence the double-quotes skipped in\r\nall the previous steps!) and a function ( alert ).\r\nFinally RunHTMLApplication calls CHTMLApp::Run and the JavaScript is executed:\r\nSecurity point\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 8 of 9\n\nFrom a security point of view, executing JavaScript through Rundll32 is like executing an HTML Application.\r\nIn other words, we can have all the power of Internet Explorer—its object model, performance, rendering power\r\nand protocol support—without enforcing the strict security model and user interface of the browser. Zone security\r\nis off, and cross-domain script access is allowed, we have read/write access to the files and system registry on the\r\nclient machine.\r\nWith this trick, JavaScript is executed outside the Internet Explorer process and script is not subject to security\r\nconcept like Protected Mode / Sandbox on Vista and superior.\r\nConclusion\r\nRunHTMLApplication has the perfect prototype to work with Rundll32. Attackers have made great efforts to build\r\na command line using the perfect syntax for passing through all the mechanisms (library loading, command line\r\nparsing, URL syntax correctness, valid JavaScript, etc.) leading to JavaScript execution in an uncontrolled\r\nenvironment.\r\nFrom our understanding, this technique allows bypassing some security products that may trust actions performed\r\nby the built-in rundll32 while specifying the script to run without writing any file on the file system.\r\nThat’s all folks!\r\nSource: https://www.stormshield.com/news/poweliks-command-line-confusion/\r\nhttps://www.stormshield.com/news/poweliks-command-line-confusion/\r\nPage 9 of 9",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://www.stormshield.com/news/poweliks-command-line-confusion/"
	],
	"report_names": [
		"poweliks-command-line-confusion"
	],
	"threat_actors": [],
	"ts_created_at": 1775434770,
	"ts_updated_at": 1775791273,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/96b6981bc457e1bf778ee1e2f83ac8442058be09.pdf",
		"text": "https://archive.orkl.eu/96b6981bc457e1bf778ee1e2f83ac8442058be09.txt",
		"img": "https://archive.orkl.eu/96b6981bc457e1bf778ee1e2f83ac8442058be09.jpg"
	}
}