深信服的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; // esi
char v3; // al
struct _HW_INITIALIZATION_DATA HwInitializationData; // [esp+8h] [ebp-58h] BYREF
char 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] BYREF
qmemcpy(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; // eax
int Length; // eax
_BYTE *PoolWithTag; // edi
int v5; // eax
int v6; // eax
char DstBuf; // [esp+Ch] [ebp-Ch] BYREF
int v8; // [esp+Dh] [ebp-Bh]
unsigned int v9; // [esp+14h] [ebp-4h] BYREF
v1 = 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处是正确的磁盘序列号文字。