About
The kungfoo projects aim is to discover and implement the most generic Win32 shellcode that may exist and run in a system independent way, free of hardcoded API addresses and payload specific functionality. The shellcode will be able to perform under any version and release of Windows, without any modification.
The Problem
An example of where shellcode is dependent on a particular version of windows to run is msgtest.asm. Here the code simply displays a message box to the user. To do this we must call the Windows API, MessageBoxA found in user32.dll. To perform this call we must find the address as mapped in our process space of the function. The solution to find this is to call GetProcAddress. In the msgtest example this address along with LoadLibraryA are hardcoded to a specific version of windows. Due to the nature of shellcode, we are not able to link our code dynamically and have the program loader fill in these required exported addresses at load time, because shellcode is not loaded per say it is injected through an injection vector (e.g. Buffer Overflow). This gives us a fundamental problem with Win32 shellcode, if the addresses of GetProcAddress and LoadLibraryA are hardcoded at compile time they may not be mapped at the same addresses on the target host running the code (due to windows version differences) and the shellcode will fail.
The Solution
The solution to our problem requires us to develop a dynamic way to retrieve the two most important addresses, GetProcAddress and LoadLibraryA on the fly in a system independent way. This is achieved by going straight to the source. By scanning the kernels export address table we can calculate the relative virtual addresses of GetProcAddress and LoadLibraryA as found in that system (refer to kungfoo.asm) and proceed to retrieve further API addresses through the use of these two functions (refer to style.asm). This method is limited by how we find the kernels base address in memory. Currently I hardcode it to suit windows release the shellcode will run on. See table below for a list.
| Windows Version |
Kernels Base Address |
| Win95 |
0xBFF70000 |
| Win98 (1st and 2nd editions) |
0xBFF70000 |
| WinME |
0xBFF60000 |
| WinNT (service pack 4 and 5) |
0x77F00000 |
| WinXP |
0x77E60000 |
| Win2K (service pack 1,2 and 3) |
0x77E80000 |
| Win2003 Web Edition |
0x77E40000 |
This method of hardcoding the kernels base address is sufficient if you know which version of Windows you are dealing with. Tools like nmap or rver can report this with a good deal of accuracy.
The Tools
To develop this project a number of tools had to be written first. They each perform a vital task and are all included in the final release.
Name |
Description |
|
Tool to test shellcode by loading in op codes and any required DLL's into the process memory space and executing the shellcode (on the heap). You can then easily attach a debugger and can also output a c character array of the shellcode. |
|
Tool to retrieve a functions address in memory as exported from its library. |
|
Tool to retrieve kernel32's base address as mapped to your process in memory. |
|
Tool to encode some shellcode as to avoid null bytes. |
The Finished Product
The finished shellcode will retrieve the addresses of GetProcAddress and LoadLibraryA and proceed to download a file remotely from the internet and execute it. The shellcode is wrapped in a program called payload which takes two main arguments; the remote URL to download the file from and the version of windows you wish to execute the shellcode on (e.g. Win98, WinNT). It then outputs a file loaded with this shellcode, so you can then apply the injection vector, or test it with the eggtest application.