首页
社区
课程
招聘
[原创]驱动伪造卷序列号
发表于: 2016-8-21 16:12 7565

[原创]驱动伪造卷序列号

2016-8-21 16:12
7565

驱动伪造卷序列号

卷序列号指:

S:\>dir
驱动器 S 中的卷是 RAMDISK
卷的序列号是 FA32-4148

S:\ 的目录

2016-08-21  15:33    <DIR>          TEMP
               0 个文件              0 字节
               1 个目录    396,854,272 可用字节

获取卷序列号:

https://msdn.microsoft.com/zh-cn/library/windows/desktop/aa364993(v=vs.85).aspx

BOOL WINAPI GetVolumeInformation(
  _In_opt_  LPCTSTR lpRootPathName,
  _Out_opt_ LPTSTR  lpVolumeNameBuffer,
  _In_      DWORD   nVolumeNameSize,
  _Out_opt_ LPDWORD lpVolumeSerialNumber,
  _Out_opt_ LPDWORD lpMaximumComponentLength,
  _Out_opt_ LPDWORD lpFileSystemFlags,
  _Out_opt_ LPTSTR  lpFileSystemNameBuffer,
  _In_      DWORD   nFileSystemNameSize
);

IDA -> Kernel32.dll!GetVolumeInformationW()
         NtQueryVolumeInformationFile(FileHandle, &IoStatusBlock, Buf, BufSize, FileFsVolumeInformation)
    -> Ntdll.dll!NtQueryVolumeInformationFile()

.text:7C92D970 _NtQueryVolumeInformationFile@20 proc near
.text:7C92D970                 mov     eax, 0B3h
.text:7C92D975                 mov     edx, 7FFE0300h
.text:7C92D97A                 call    dword ptr [edx]
.text:7C92D97C                 retn    14h
.text:7C92D97C _NtQueryVolumeInformationFile@20 endp

IDA -> Ntoskrnl.exe!NtQueryVolumeInformationFile()
    PIRP pIrp = IoAllocateIrp(v15->StackSize, 1u);
    PIO_STACK_LOCATION IrpSp =
        (PIO_STACK_LOCATION)(pIrp->Tail.Overlay.PacketType - 36);
    IrpSp->MajorFunction = 0xA;    // IRP_MJ_QUERY_VOLUME_INFORMATION

    // IrpSp->Parameters.Create.Options 实际就是(参考 _IO_STACK_LOCATION 定义)
    // IrpSp->Parameters.QueryVolume.FsInformationClass
    IrpSp->Parameters.Create.Options = VolumeInformationClass;
   
然后手写GetVolumeInformation(),内核调试跟一下;
懒人靠运气,笔者发现硬盘某分区躺着个cntfs,来自于NT4源码;
看IRP_MJ_QUERY_VOLUME_INFORMATION的处理函数,最后发现:
Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
也就是卷序列号最终是由文件系统驱动赋值的;
WDK里有FAT32的驱动源码FASTFAT,也是它赋值的;
再测一下win7x64系统,数据结构也兼容;

done! 码如下:
ps1 : 伪造序列号的话,把那个值改掉就行,可以用RtlRandomEx()生成;
ps2 : C语言习惯了,说每句话后面也是分号。。;

#include <ntddk.h>

extern POBJECT_TYPE *IoDriverObjectType;

NTKERNELAPI
NTSTATUS
ObReferenceObjectByName(
                        IN PUNICODE_STRING ObjectName,
                        IN ULONG Attributes,
                        IN PACCESS_STATE PassedAccessState OPTIONAL,
                        IN ACCESS_MASK DesiredAccess OPTIONAL,
                        IN POBJECT_TYPE ObjectType,
                        IN KPROCESSOR_MODE AccessMode,
                        IN OUT PVOID ParseContext OPTIONAL,
                        OUT PVOID *Object
                        );

PDRIVER_DISPATCH g_NTFSQueryVolume;
PDRIVER_DISPATCH g_FATQueryVolume;

NTSTATUS NTFSQueryVolume(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
    NTSTATUS status;
   
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(pIrp);

    if (IrpSp->Parameters.QueryVolume.FsInformationClass == FileFsVolumeInformation)
    {
        PFILE_FS_VOLUME_INFORMATION p =
            (PFILE_FS_VOLUME_INFORMATION)pIrp->AssociatedIrp.SystemBuffer;

        status = g_NTFSQueryVolume(pDeviceObject, pIrp);

        if (NT_SUCCESS(status))
        {
            KdPrint(("NTFS volume : %X\n", p->VolumeSerialNumber));
        }
    }
    else
        status = g_NTFSQueryVolume(pDeviceObject, pIrp);

    return status;
}

NTSTATUS hook_NTFSQueryVolume(PUNICODE_STRING pDrvName, BOOLEAN bHook)
{
    NTSTATUS status;
    PDRIVER_OBJECT realDriverObject;

    status = ObReferenceObjectByName(pDrvName, OBJ_CASE_INSENSITIVE, NULL, 0,
        *IoDriverObjectType, KernelMode, NULL, &realDriverObject);

    if (NT_SUCCESS(status))
    {
        if (bHook)
        {
            g_NTFSQueryVolume = realDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION];
            realDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = NTFSQueryVolume;
        }
        else
        {
            if (g_NTFSQueryVolume)
                realDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = g_NTFSQueryVolume;
        }

        ObDereferenceObject(realDriverObject);
    }

    return status;
}

NTSTATUS FATQueryVolume(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
    NTSTATUS status;

    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(pIrp);

    if (IrpSp->Parameters.QueryVolume.FsInformationClass == FileFsVolumeInformation)
    {
        PFILE_FS_VOLUME_INFORMATION p =
            (PFILE_FS_VOLUME_INFORMATION)pIrp->AssociatedIrp.SystemBuffer;

        status = g_FATQueryVolume(pDeviceObject, pIrp);

        if (NT_SUCCESS(status))
        {
            KdPrint(("FAT volume : %X\n", p->VolumeSerialNumber));
        }
    }
    else
        status = g_FATQueryVolume(pDeviceObject, pIrp);

    return status;
}

NTSTATUS hook_FATQueryVolume(PUNICODE_STRING pDrvName, BOOLEAN bHook)
{
    NTSTATUS status;
    PDRIVER_OBJECT realDriverObject;

    status = ObReferenceObjectByName(pDrvName, OBJ_CASE_INSENSITIVE, NULL, 0,
        *IoDriverObjectType, KernelMode, NULL, &realDriverObject);

    if (NT_SUCCESS(status))
    {
        if (bHook)
        {
            g_FATQueryVolume = realDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION];
            realDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FATQueryVolume;
        }
        else
        {
            if (g_FATQueryVolume)
                realDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = g_FATQueryVolume;
        }

        ObDereferenceObject(realDriverObject);
    }

    return status;
}

NTSTATUS init_volume_driver_hook()
{
    NTSTATUS status;
    UNICODE_STRING drv_name;

    RtlInitUnicodeString(&drv_name, L"\\FileSystem\\Ntfs");
    status = hook_NTFSQueryVolume(&drv_name, TRUE);

    RtlInitUnicodeString(&drv_name, L"\\FileSystem\\Fastfat");
    status = hook_FATQueryVolume(&drv_name, TRUE);

    return status;
}

VOID uninit_volume_driver_hook()
{
    UNICODE_STRING drv_name;

    RtlInitUnicodeString(&drv_name, L"\\FileSystem\\Ntfs");
    hook_NTFSQueryVolume(&drv_name, FALSE);

    RtlInitUnicodeString(&drv_name, L"\\FileSystem\\Fastfat");
    hook_FATQueryVolume(&drv_name, FALSE);
}

VOID Unload(PDRIVER_OBJECT DriverObject)
{
    uninit_volume_driver_hook();
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath)
{
    init_volume_driver_hook();

    DriverObject->DriverUnload = Unload;

    return STATUS_SUCCESS;
}


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (9)
雪    币: 110
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习,楼主其他HOOK 很精彩
2016-8-21 19:42
0
雪    币: 99
活跃值: (110)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
mark。
2016-8-23 17:52
0
雪    币: 221
活跃值: (2326)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
这个驱动做法。64位系统能用?
2017-3-30 15:30
0
雪    币: 719
活跃值: (777)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
5
mark
2017-3-30 17:50
0
雪    币: 12848
活跃值: (9147)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
6
lhglhg 这个驱动做法。64位系统能用?
ntfs和fat的IRP好像PG不管的
2017-3-30 18:16
0
雪    币: 407
活跃值: (1816)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
hzqst ntfs和fat的IRP好像PG不管的
PG是不管这个,之前嫌QQ的txupd.exe太烦,就劫了irp_mj_creat,win8x64正常运行,win10没测
2017-4-3 22:25
0
雪    币: 15
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
WIN7没问题,WIN10会触发PG,不定时蓝屏.
2020-5-8 11:31
0
雪    币: 405
活跃值: (2285)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
hzqst ntfs和fat的IRP好像PG不管的
win10 之后会管。
2020-5-8 14:38
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
感谢分享!
2020-5-8 14:42
0
游客
登录 | 注册 方可回帖
返回
//