Uninformed: Informative Information for the Uninformed

Vol 3» 2006.Jan


Next: Conclusion Up: FUTo Previous: The PspCidTable   Contents

FUTo

To demonstrate the weaknesses in the algorithms currently used by rootkit detection software such as Blacklight and Icesword, the authors have created FUTo. FUTo is a new version of the FU rootkit. FUTo has the added ability to manipulate the PspCidTable without using any function calls. It uses DKOM techniques to hide particular objects within the PspCidTable.

There were some design considerations when implementing the new features in FUTo. The first was that, like the ExMapHandleXXX functions, the PspCidTable is not exported by the kernel. In order to overcome this, FUTo automatically detects the PspCidTable by finding the PsLookupProcessByProcessId function and disassembling it looking for the first function call. At the time of this writing, the first function call is always to ExMapHandleToPointer. ExMapHandleToPointer takes the PspCidTable as its first parameter. Using this knowledge, it is fairly straightforward to find the PspCidTable.

PsLookupProcessByProcessId:
mov edi, edi
push ebp
mov ebp, esp
push ebx
push esi
mov eax, large fs:124h
push [ebp+arg_4]
mov esi, eax
dec dword ptr [esi+0D4h]
push PspCidTable
call ExMapHandleToPointer
A more robust method to find the PspCidTable could be written as this algorithm will fail if even simple compiler optimizations are made on the kernel. Opc0de wrote a more robust method to detect non-exported variables like PspCidTable, PspActiveProcessHead, PspLoadedModuleList, etc. Opc0des method does not requires memory scanning like the method currently used in FUTo. Instead Opc0de found that the KdVersionBlock field in the Process Control Region structure pointed to a structure KDDEBUGGER_DATA32[5]. The structure looks like this:

typedef struct _KDDEBUGGER_DATA32 {

    DBGKD_DEBUG_DATA_HEADER32 Header;
    ULONG   KernBase;
    ULONG   BreakpointWithStatus;       // address of breakpoint
    ULONG   SavedContext;
    USHORT  ThCallbackStack;            // offset in thread data
    USHORT  NextCallback;               // saved pointer to next callback frame
    USHORT  FramePointer;               // saved frame pointer
    USHORT  PaeEnabled:1;
    ULONG   KiCallUserMode;             // kernel routine
    ULONG   KeUserCallbackDispatcher;   // address in ntdll

    ULONG   PsLoadedModuleList;
    ULONG   PsActiveProcessHead;
    ULONG   PspCidTable;

    ULONG   ExpSystemResourcesList;
    ULONG   ExpPagedPoolDescriptor;
    ULONG   ExpNumberOfPagedPools;
	
    [...]

    ULONG   KdPrintCircularBuffer;
    ULONG   KdPrintCircularBufferEnd;
    ULONG   KdPrintWritePointer;
    ULONG   KdPrintRolloverCount;

    ULONG   MmLoadedUserImageList;

} KDDEBUGGER_DATA32, *PKDDEBUGGER_DATA32;
As the reader can see the structure contains pointers to many of the commonly needed/used non-exported variables. This is one more robust method to finding the PspCidTable and other variables like it.

The second design consideration was a little more troubling. When FUTo removes an object from the PspCidTable, the HANDLE_ENTRY is replaced with NULLs representing the fact that the process "does not exist." The problem then occurs when the process that is hidden (and has no PspCidTable entries) is closed. When the system tries to close the process, it will index into the PspCidTable and dereference a null object causing a blue screen. The solution to this problem is simple but not elegant. First, FUTo sets up a process notify routine by calling PsSetCreateProcessNotifyRoutine. The callback function will be invoked whenever a process is created, but more importantly it will be called whenever a process is deleted. The callback executes before the hidden process is terminated; therefore, it gets called before the system crashes. When FUTo deletes the indexes that contain objects that point to the rogue process, FUTo will save the value of the HANDLE_ENTRYs and the index for later use. When the process is closed, FUTo will restore the objects before the process is closed allowing the system to dereference valid objects.


Next: Conclusion Up: FUTo Previous: The PspCidTable   Contents