Deep Analysis of JavaScript Backdoors
0x00 background
Previously, the article JavaScript backdoorof @ san mentioned how to use rundll32.exe to execute a JavaScript code to bounce an Http Shell. Here, I will share with you the article on the analysis of its principles.
Recently, hFireF0X published a detailed investigation of Win32/Poweeliks malware on the reverse engineering Forum kernelmode.info. This malicious software exists in the Windows Registration Table and uses rundll32.exe to execute JavaScript code.
I found it interesting that I was obviously not the only one who found that some JavaScript code could be executed through rundll32.
When we first find that the command line executes JavaScript, we are curious about how it works.
In the following article, we will analyze how JavaScript code is executed and why it is executed when such simple command line code is called:
#!bashrundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";alert(‘foo’);
0x01 Rundll32 Introduction
The use of rundll32.dll has a special document on MSDN. It is often used to call the output function of a DLL file and can be implemented through the following command:
#!bashRUNDLL32.EXE
,
Entrypoint is the output function. Its prototype is as follows:
#!cppvoid CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
Lpszcmdlineis Value.
We will try to see how rundll32.exe can call the RunHTMLApplication function output by mshtml. dll and how the "Javascript" prefix is used to execute actual JavaScript code.
0x02 Rundll32.exe Analysis
A. Parameters
The first thing rundll32.exe does is to use the built-in ParseCommand command to parse the command. This function will find a comma (',', 0x2c) to locate the dll name and a space (', 0x20) to locate the entry point name.
When using our sample command, ParseCommand returns javascript: "\ .. \ mshtml as the DLL name, and returns RunHTMLApplication as the entry point.
0x03 Dll loader
Rundll32.exe will try several methods to load the actual DLL from the original "JavaScript:" \ .. \ mshtml.
The GetFileAttributes ("javascript:" \ .. \ mshtml ") function is used in the first test "). This function will eventually be close to C: \ Windows \ system32 \ mshtml. If this file is not found, the function returns-1.
Next, SearchPath is called to determine the DLL name. This function reads the registry key value HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ SafeProcessSearchMode. Microsoft defines this key value as follows:
When the registry key value of the REG_DWORD type is set to 1, SearchPath first searches for the folder specified in the system path, and then searches for the current working folder. When the registry key value is set to 0, the computer first searches for the current working folder and then searches for the specified folder in the system path. The default value of this registry key is 0.
By default, this registry key value does not exist (in Windows xp, 7, and 8). Therefore, SearchPath first tries to load the file mshtml in the current directory of rundll32.dll, second, the system will try to locate it in the system path.
If all the trials fail, then rundll32.exe will proceed to the next step. GetFileAttribute will be called again to find the manifest file: javascript: "\ .. \ mshtml. manifest for the module.
If all the previous steps fail, rundll32.exe will eventually call Loadlibrary ("javascript:" \ .. \ mshtml ").
LoadLibrary is a simple encapsulation of LdrLoadDLL in ntdll. dll. Internally, LdrLoadDll will add the default extension dll and parse the result string (javascript: "\ .. \ mshtml. dll) as the path. ".." Indicates a new folder: It is parsed into mshtml. dll.
When mshtml. dll has been identified, LdrLoadDll can load the lib library in the system directory.
Rundll32.exe then calls GetProcAddress using the previously extracted entry point name RunHTMLApplication.
At this time, we can find that javascript: prefix looks useless: LoadLibrary ("foobar: \" \ .. \ mshtml ") works well. So why should we add such a prefix?
0x04 protocol processing
Once the entry address has been resolved, rundll32.dll will call the mshtml. dll function! RunHTMLApplication.
Even if not recorded, the actual RunHTMLApplication can be inferred from the call of c: \ windows \ system32 \ mshta.exe (this application is dedicated to starting a. hta file ).
#!cppHRESULT RunHTMLApplication(HINSTANCE hinst,HINSTANCE hPrevInst,LPSTR szCmdLine,int nCmdShow);
This is similar to the expected endpoint address of rundll32.exe:
#!cppvoid CALLBACK EntryPoint(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow);
RunHTMLApplication accepts a window handle rather than a module handle as the first parameter. This parameter is used when mshml registers a window class or creates a window for a class. Passing a value that is inconsistent with the actual instance does not significantly affect user32.
The second parameter is not used at all, so this mismatch is not important.
The last parameter, nCmdShow, is used by the RunHTMLApplication function to display the host window hosting the HTML application. Rundll32 often uses the value SW_SHOWDEFAULT to call the entry point function to indicate that any window that may be opened uses the window default configuration.
In our example, the more interesting parameter is lpszjwline ("; alert ('foo ')).
This obviously causes problems because it is not a valid JavaScript Statement (note the double quotation marks discarded at the end of the statement ). However, it still works because RunHTMLApplication ignores the given parameters and prefers to re-request the original command from the windows API GetCommandLine (encapsulated in a call to the getjavaskline function ).
The complete command contains the executable file and Parameter Name: GetCmdLine extracts parameters by organizing executable specifications.
After that, RunHTMLApplication will call CreateURLMonitor:
This is also where the string "javascript" is needed.
CreateURLMonitor parses the command line to extract the string "javascript" before char ":" (0x3A ".
CreateUrlMoniker crawls the registry key value HKCR \ SOFTWARE \ Classes \ PROTOCOLS \ Handler \. These key values are related to a protocol set and their CLSID.
CreateUrlMoniker will find a suitable protocol processor to process the Javascript protocol (HKCR \ SOFTWARE \ Classes \ PROTOCOLS \ Handler \ javascript ):
CLSID {3050F3B2-98B5-11CF-BB82-00AA00BDCE0B} complies with Microsoft's "Microsoft HTML Javascript Pluggable Protocol" Specification.
This is also why the string "javascript" must be at the beginning of the parameter.
The same mechanism also works when people enter javascript: alert ('alert ') in the IE navigation bar.
Strings located after the ":" separator are interpreted as JavaScript commands by the JavaScript URL moniker:
#!js"\..\mshtml,RunHTMLApplication ";alert(‘foo’);
This is an invalid JavaScript statement with the string "\ .. \ mshtml, RunHTMLApplication" and function (alert) (because double quotation marks will skip all previous steps !).
In the end, RunHTMLApplication will call CHTMLApp: Run, and this JavaScript statement will also be executed:
0x05 security impact
From a security perspective, using rundll32 to execute JavaScript is like executing an HTML application.
In other words, we can use all rights of IE. When the region security is disabled and cross-origin scripting is allowed, we can have the right to read and write client machine files and registries.
With this technique, JavaScript can be executed outside IE, and the script does not have any security concept constraints, such as protection mode \ sandbox.
0x06 conclusion
According to our understanding, this technology bypasses some security products that trust the built-in rundll32 behavior.