驱动伪造卷序列号
卷序列号指:
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;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!