This source shows how to deal with kernel functions from the Ring0.
Example, RestoreShadow.C
Driver and full VS project inside attachment.Code:#include <ntddk.h> #include "RestoreShadow.h" #include "dbghelp.h" #include "LDasm.h" NTKERNELAPI NTSTATUS KeAddSystemServiceTable( IN PULONG_PTR Base, IN PULONG Count OPTIONAL, IN ULONG Limit, IN PUCHAR Number, IN ULONG Index ); typedef struct _KSERVICE_TABLE_DESCRIPTOR { PULONG_PTR Base; PULONG Count; ULONG Limit; PUCHAR Number; } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { struct { ULONG TimeDateStamp; }; struct { PVOID LoadedImports; }; }; struct _ACTIVATION_CONTEXT * EntryPointActivationContext; PVOID PatchInformation; }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow = NULL; PVOID pWin32kBase = NULL; //=========================================== NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString); NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp); NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp); VOID DriverUnload(PDRIVER_OBJECT pDriverObj); #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) #pragma alloc_text(PAGE, DispatchCreate) #pragma alloc_text(PAGE, DispatchClose) #pragma alloc_text(PAGE, DriverUnload) #endif // ALLOC_PRAGMA ////////////////////////////////////////////////////////////////////////// VOID GetWin32kBase(PDRIVER_OBJECT pDriverObj); VOID GetSSDTShadowBase(); NTSTATUS RestoreShadow(); ULONG RVAToRaw(PVOID lpBase,ULONG VirtualAddress); //========================================== NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING ustrLinkName; UNICODE_STRING ustrDevName; PDEVICE_OBJECT pDevObj; dprintf("DriverEntry: %S\n", pRegistryString->Buffer); // Create dispatch points for device control, create, close. pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; pDriverObj->DriverUnload = DriverUnload; // RtlInitUnicodeString(&ustrDevName, DEVICE_NAME); status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj); dprintf("Device Name %S", ustrDevName.Buffer); if (!NT_SUCCESS(status)) { dprintf("IoCreateDevice = 0x%x\n", status); return status; } RtlInitUnicodeString(&ustrLinkName, LINK_NAME); status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); if (!NT_SUCCESS(status)) { dprintf("IoCreateSymbolicLink = 0x%x\n", status); IoDeleteDevice(pDevObj); return status; } dprintf("SymbolicLink:%S", ustrLinkName.Buffer); GetWin32kBase(pDriverObj); GetSSDTShadowBase(); dprintf("Win32k Base : 0x%X",pWin32kBase); dprintf("KeServiceDescriptorTableShadow : 0x%X", KeServiceDescriptorTableShadow); return STATUS_SUCCESS; } VOID DriverUnload(PDRIVER_OBJECT pDriverObj) { UNICODE_STRING strLink; RtlInitUnicodeString(&strLink, LINK_NAME); // // Delete the symbolic link // IoDeleteSymbolicLink(&strLink); // // Delete the device object // IoDeleteDevice(pDriverObj->DeviceObject); dprintf("Unloaded\n"); } NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) { RestoreShadow(); pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; dprintf("IRP_MJ_CREATE\n"); IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; dprintf("IRP_MJ_CLOSE\n"); IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID GetSSDTShadowBase() { UCHAR *cPtr; UCHAR *pOpcode; ULONG Length; for (cPtr = (PUCHAR)KeAddSystemServiceTable; cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE; cPtr += Length) { Length = SizeOfCode(cPtr, &pOpcode); if (!Length) break; if ( *(PUSHORT)cPtr == 0x888D ) { KeServiceDescriptorTableShadow = (PKSERVICE_TABLE_DESCRIPTOR)(*(ULONG *)((ULONG)pOpcode + 2)); break; } } } VOID GetWin32kBase(PDRIVER_OBJECT pDriverObj) { PLIST_ENTRY pList = NULL; PLDR_DATA_TABLE_ENTRY Ldr = NULL; pList = ( (PLIST_ENTRY)pDriverObj->DriverSection )->Flink; do { Ldr = CONTAINING_RECORD( pList, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (Ldr->EntryPoint && Ldr->FullDllName.Buffer) { if ( !_wcsicmp(Ldr->FullDllName.Buffer, L"\\systemroot\\system32\\win32k.sys") ) { //Compare module name pWin32kBase = Ldr->DllBase;//Save the module base address break; } } pList = pList->Flink; } while ( pList != ((LIST_ENTRY*)pDriverObj->DriverSection)->Flink ); } NTSTATUS RestoreShadow() { NTSTATUS status; HANDLE hFile; //File handle OBJECT_ATTRIBUTES ObjAttr; UNICODE_STRING ustrWin32k; IO_STATUS_BLOCK ioStatus; ULONG ulShadowRaw = 0; ULONG ulShadowBase = 0; PVOID PoolArea = NULL; FILE_POSITION_INFORMATION fpi; LARGE_INTEGER Offset; ULONG OrigAddress = 0; ULONG CurAddress = 0; ULONG i = 0; ULONG ulCount = 0; PULONG pAddr; if ( pWin32kBase == NULL || KeServiceDescriptorTableShadow == NULL) { dprintf("Error."); return STATUS_UNSUCCESSFUL; } //Index? ulCount = KeServiceDescriptorTableShadow[1].Limit; dprintf("Count Of Shadow : %d\n", ulCount ); ulShadowBase = *(ULONG*)&KeServiceDescriptorTableShadow[1].Base;//Get the base address dprintf("ulShadowBase = 0x%X\n",ulShadowBase); ulShadowRaw = ulShadowBase - (ULONG)pWin32kBase; //ulShadowRaw = RVAToRaw(pWin32kBase,ulShadowBase); dprintf("ulShadowRaw = 0x%X\n",ulShadowRaw); RtlInitUnicodeString(&ustrWin32k, L"\\SystemRoot\\System32\\win32k.sys"); PoolArea = ExAllocatePool( PagedPool, sizeof(ULONG) * ulCount ); if (!PoolArea) { dprintf("PoolArea is null\n"); return STATUS_UNSUCCESSFUL; } RtlZeroMemory(&ObjAttr, sizeof(ObjAttr) ); InitializeObjectAttributes( &ObjAttr, &ustrWin32k, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); //Open win32K.SYS status = IoCreateFile( &hFile, FILE_READ_ATTRIBUTES, &ObjAttr, &ioStatus, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 0, NULL, 0, 0, NULL, IO_NO_PARAMETER_CHECKING); if ( !NT_SUCCESS(status) ) { dprintf("IoCreateFile Error : 0x%X", status); goto __exit; } //Set the file offset Offset.LowPart = ulShadowRaw; Offset.HighPart = 0; //Read data status = ZwReadFile ( hFile, NULL, NULL, NULL, &ioStatus, PoolArea, ulCount*sizeof(ULONG), &Offset, NULL); if ( !NT_SUCCESS(status) ) { dprintf("ZwReadFile Error : 0x%X"); goto __exit; } //Change the pointer type pAddr = (PULONG)PoolArea; //Comparing the original address for (i=0;i<ulCount;i++) { OrigAddress = *pAddr; //Point to the original address CurAddress = KeServiceDescriptorTableShadow[1].Base[i]; //Read the current address if ( OrigAddress != CurAddress ) { dprintf("ID:%-3d.OrigAddr : 0x%X CurAddr : 0x%X---Hooked!\n",i,OrigAddress,CurAddress); } else { dprintf("ID:%-3d.OrigAddr : 0x%X.CurAddr : 0x%X\n",i,OrigAddress,CurAddress); } pAddr++;//increase counter, Pointer to the next function } __exit: if (PoolArea) { ExFreePool(PoolArea); } if (hFile) { //close handle ZwClose(hFile); } return status; }
P.S. I don't know how the author of this stuff.
Please register or login to download attachments.