深信服的viostor驱动在获取序列号的时候,多了一个IDE处理的代码,位置在+1128处。它会在刚开机加载viostor.sys时机被调用,然后去读取注册表HKLM\\SYSTEM\CurrentControlSet\Services\viostor\Parameters的IDESNCompat,若为1则有此功能,若未0则不会得到正确的磁盘序列号。相关调用栈回溯是:
对DriverEntry逆向,如下处有调用isIDESerialNumber。
NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{NTSTATUS v2; // esichar v3; // alstruct _HW_INITIALIZATION_DATA HwInitializationData; // [esp+8h] [ebp-58h] BYREFchar v6; // [esp+44h] [ebp-1Ch]__int16 v7; // [esp+46h] [ebp-1Ah]char *v8; // [esp+48h] [ebp-18h]__int16 v9; // [esp+4Eh] [ebp-12h]char *v10; // [esp+50h] [ebp-10h]int (__stdcall *v11)(PVOID, int, int); // [esp+54h] [ebp-Ch]char v12[8]; // [esp+58h] [ebp-8h] BYREFqmemcpy(v12, "10011AF4", sizeof(v12));dword_14630 = (int)DriverObject;sub_12252(DriverObject, RegistryPath);byte_1465C = RegistryPath == 0;memset(&HwInitializationData, 0, 0x50u);v7 = 4;v8 = &v12[4];v9 = 4;v10 = v12;HwInitializationData.HwInitializationDataSize = 80;HwInitializationData.DeviceExtensionSize = (ULONG)sub_112A8;HwInitializationData.HwReceivePacket = (PHW_RECEIVE_DEVICE_SRB)sub_1149A;HwInitializationData.HwCancelPacket = (PHW_CANCEL_SRB)CancelPkt_1D70;HwInitializationData.HwRequestTimeoutHandler = (PHW_REQUEST_TIMEOUT_HANDLER)sub_115C4;HwInitializationData.PerRequestExtensionSize = (ULONG)sub_10EC4;v11 = sub_116EC;v6 = 1;*(_DWORD *)&HwInitializationData.BusMasterDMA = 1592;*(_DWORD *)&HwInitializationData.TurnOffSynchronization = 2200;HwInitializationData.HwInterrupt = (PHW_INTERRUPT)5;HwInitializationData.DmaBufferSize = 1;HwInitializationData.NameExtensionArray = (PWCHAR *)16843009;v2 = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, 0);v3 = isIDESerialNumber_1128();
GetIdeFormatSerialNumber是因为DriverEntry里注册了函数sub_11D70而后被调用。调用时机也是发生在刚开机viostor刚载入时。调用时的相关栈回溯如下:
GetIdeFormatSerialNumber的反编译如下:
_BYTE *__stdcall GetIdeFormatSerialNumber(_BYTE *P)
{unsigned int v1; // esi_BYTE *result; // eaxint Length; // eax_BYTE *PoolWithTag; // ediint v5; // eaxint v6; // eaxchar DstBuf; // [esp+Ch] [ebp-Ch] BYREFint v8; // [esp+Dh] [ebp-Bh]unsigned int v9; // [esp+14h] [ebp-4h] BYREFv1 = 0;DstBuf = 0;v8 = 0;v9 = 0;if ( !P )return 0;Length = RtlStringCchLength((int)P, 0x14u, &v9);if ( Length < 0 ){DbgPrint("GetIdeFormatSerialNumber failed in RtlStringCchLength:%x", Length);return 0;}PoolWithTag = ExAllocatePoolWithTag(NonPagedPool, 0x28u, 'SEDI');if ( !PoolWithTag ){DbgPrint("GetIdeFormatSerialNumber ExAllocateWithTage failed.\n");return 0;}memset(PoolWithTag, 0, 0x28u);if ( v9 ){while ( v1 + 1 < v9 ){v5 = RtlStringCchPrintf(&DstBuf, 5, "%2x%2x", (char)P[v1 + 1], (char)P[v1]);if ( v5 < 0 )goto LABEL_16;v6 = sub_1119E(PoolWithTag, 40, &DstBuf);if ( v6 < 0 )goto LABEL_18;v1 += 2;if ( v1 >= v9 )break;}}if ( v1 + 1 == v9 ){v5 = RtlStringCchPrintf(&DstBuf, 5, "%2x", (char)P[v1]);if ( v5 < 0 ){
LABEL_16:DbgPrint("GetIdeFormatSerialNumber failed in RtlStringCbPrintf:%x", v5);}else{BYTE1(v8) = 0;v6 = sub_1119E(PoolWithTag, 40, &DstBuf);if ( v6 >= 0 )goto LABEL_15;
LABEL_18:DbgPrint("GetIdeFormatSerialNumber failed in RtlStringCbCat:%x", v6);}ExFreePoolWithTag(PoolWithTag, 'SEDI');return 0;}
LABEL_15:result = PoolWithTag;PoolWithTag[39] = 0;return result;
}
开源代码里面没有IDE处理代码,只有一种逻辑
初步看GetIdeFormatSerialNumber和isIDESerialNumber都比较简单,基本没有用到全局变量,应该可以直接抄反编译代码。因为我没有编译出xp版本viostor的环境,所以没法做实验了。
通过DeviceIoControl(SMART_RCV_DRIVE_DATA)来查询磁盘序列号。若采用深信服的viostor.sys,则可查询到outputbuffer+0x24处是正确的磁盘序列号文字。