|Informative Information for the Uninformed|
If the attacker has the convenience of reproducing the operating environment and execution of the target application, or even simply has access to the application's executable, a context-key may be chosen from information known about the address space of the running process. Known locations of static values such as environment variables, global variables and constants such as version strings, help text, or error messages, or even the application's instructions or linked library instructions themselves may be chosen from as contextual keying information.
Profiling the Application
To successfully select a context-key from a running application's memory, the application's memory must first be profiled. By polling the application's address space over a period of time, ranges of memory that change can be eliminated from the potential context-key data pool. The primary requirement of viable data in the process's memory space is that it does not change over time or between subsequent instantiations of the running application. After profiling is complete, the resultant list of memory addresses and static data will be referred to as the application's memory map.
Memory Map Creation
The basic steps to create a comprehensive memory map of a running process are:
Continue the above process until changing data is no longer being eliminated and store the resulting memory map as a map of that instance of the target process. Restart the application and repeat the above process, producing a second memory map for the second instance of the target process. Compare the two memory maps for differences and again eliminate any data that differs. Repeat this process until changing data is no longer being eliminated.
The resulting final memory map for the process must then be analyzed for static data that may be directly relative to the environment of the process and may not be consistent across processes running within different environments such as on different hosts or in different networks. This type of data includes network addresses and ports, host names, operating system "unames", and so forth. This type of data may also include installation paths, user names, and other user-configurable options during installation of the application. This type of data does not include application version strings or other pertinent information which may be directly relative to the properties of the application which contribute to the application being vulnerable and successfully exploited.
Identifying this type of information relative to the application's environment will produce two distinct types of memory map data; one type containing static application context data, and the other type containing environment context data. Both of these types of data can be useful as potential context-key values, however, the former will be more portable amongst targets whereas the latter will only be useful when selecting key values for the actual target process that was actively profiled. If it is undesirable, introducing instantiation of processes being profiled on different network hosts and with different installation configuration options to the memory map generation process outlined above will likely eliminate the latter from the memory map entirely.
Finally, the memory maps can be trimmed of any remaining NULL bytes to reduce their size. The final memory map should consist of records containing memory addresses and the string of static data which can be found in memory at those locations.
Memory Map Creation Methods
Metasploit Framework's msfpescan
One method to create a memory map of viable addresses and values is to use a tool provided by the Metasploit Framework called msfpescan. msfpescan is designed to scan PE formatted executable files and return the requested portion of the .text section of the executable. Data found in the .text section is useful as potential context-key data as the .text section is marked read-only when mapped into a process' address space and is therefore static and will not change. Furthermore, msfpescan predicts where in the executed process' address space these static values will be located, thus providing both the static data values as well as the addresses at which those values can be retrieved.
To illustrate, suppose a memory map for the Windows System service needs to be created for exploitation of the vulnerability described in Microsoft Security Bulletin MS06-040 by an exploit which will employ a context-keyed payload encoder. A common DLL that is linked into the service's executable when compiled can be selected as the target for msfpescan. In this case, ws2help.dll is chosen due to its lack of updates since August 23rd, 2001. Because this particular DLL has remained unchanged for over six years, its instructions provide a particularly consistent cache of potential context-keys for an exploit targeting an application linked against it anytime during the last six years. A scan of the first 1024 bytes of ws2help.dll's executable instructions can be performed by executing the following command:
msfpescan -b 0x0 -A 1024 ws2help.dll
Furthermore, msfpescan has been improved via this research effort to render data directly as a memory map. This improved version is available in the Metasploit Framework as of version 3.1. A scan and dump to memory map of ws2help.dll's executable instructions can be performed by executing the following command:
msfpescan --context-map context ws2help.dll
It is important to note that this method of memory map generation is much less comprehensive than the method previously outlined; however, when targeting a process whose executable is relatively large and links in a large number of libraries, profiling only the instruction portions of the executable and library files involved may provide an adequately-sized memory map for context-key selection.
Metasploit Framework's memdump.exe
The Metasploit Framework also provides another useful tool for the profiling of a running process' memory called memdump.exe. memdump.exe is used to dump the entire memory space of a running process. This tool can be used to provide the polling step of the memory map creation process previously outlined. By producing multiple memory dumps over a period of time, the dumps can be compared to isolate static data.
A tool for profiling a Linux process' address space and creating a memory map is provided by this research effort. The smem-map tool was created as a reference implementation of the process outlined at the beginning of this section. smem-map is a Linux command-line application and relies on the proc filesystem as an interface to the target process' address space.
The first time smem-map is used against a target process, it will populate an initial memory map with all non-null bytes currently found in the process's virtual memory. Subsequent polls of the memory ranges that were initially identified will eliminate data that has changed between the memory map and the most recent poll of the process's memory. If the tool is stopped and restarted and the specified memory map file exists, the file will be reloaded as the memory map to be compared against instead of populating an entirely new memory map. Using this functionality, a memory map can be refined over multiple sessions of the tool as well as multiple instantiations of the target process. A scan of a running process' address space can be performed by executing the following command:
smem-map <PID> output.map
Once a memory map has been created for the target application, the encoder may select any sequential data from any memory address within the memory map which is both large enough to fill the desired key length and also does not produce any disallowed byte values in the encoded payload as defined by restrictions to the attack vector for the vulnerability. The decoder stub should then retrieve the context-key from the same memory address when executed at the target. If the decoder stub is developed so that it may read individual bytes of data from different locations, the encoder may select individual bytes from multiple addresses in the memory map. The encoder must note the memory address or addresses at which the context-key is read from the memory map for inclusion in the decoder stub.
Proof of Concept: Improved Shikata ga Nai
The Shikata ga Nai encoder, included with the Metasploit Framework, implements polymorphic XOR additive feedback encoding against a four byte key. The decoder stub that is prepended to a payload which has been encoded by Shikata ga Nai is generated based on dynamic instruction substitution and dynamic block ordering. The registers used by the decoder stub instructions are also selected dynamically when the decoder stub is constructed.
Improving the original Metasploit implementation of Shikata ga Nai to use contextual keying was fairly trivial. Instead of randomly selecting a four byte key prior to encoding, a key is instead chosen from a supplied memory map. Furthermore, when generating the decoder stub, the original implementation used a "mov reg, val" instruction (0xb8) to move the key value directly from its location in the decoder stub into the register it will use for the XOR operation. The context-key version instead uses a "mov reg, [addr]" instruction (0xa1) to retrieve the context-key from the memory location at [addr] and store it in the same register. The update to the Shikata ga Nai decoder stub was literally as simple as changing one instruction, and providing that instruction with the context-key's location address rather than a static key value directly.
The improved version of Shikata ga Nai described here is provided by this research effort and is available in the Metasploit Framework as of version 3.1. It can be utilized as follows from the Metasploit Framework Console command-line, after the usual exploit and payload commands:
set ENCODER x86/shikata_ga_nai set EnableContextEncoding 1 set ContextInformationFile <application.map> exploit
Case Study: MS04-007 vs. Windows XP SP0
The Metasploit framework currently provides an exploit for the vulnerability described in Microsoft Security Bulletin MS04-007. The vulnerable application in this case is the Microsoft ASN.1 Library.
Before any exploitation using contextual keying can take place, the vulnerable application must be profiled. By opening the affected library from Windows XP Service Pack 0 in a debugger, a list of libraries that it itself includes can be gleaned. By collecting said library DLL files from the target vulnerable system, or an equivalent system in the lab, msfpescan can then be used to create a memory map:
msfpescan --context-map context \ ms04-007-dlls/* cat context/* >> ms04-007.map
After the memory map has been created, it can be provided to Metasploit and Shikata ga Nai to encode the payload that Metasploit will use to exploit the vulnerable system:
use exploit/windows/smb/ms04-007-killbill set PAYLOAD windows/shell_bind_tcp set ENCODER x86/shikata_ga_nai set EnableContextEncoding 1 set ContextInformationFile ms04-007.map exploit