xp的viostor驱动无法获取磁盘序列号的分析

        深信服的viostor驱动在获取序列号的时候,多了一个IDE处理的代码,位置在+1128处。它会在刚开机加载viostor.sys时机被调用,然后去读取注册表HKLM\\SYSTEM\CurrentControlSet\Services\viostor\Parameters的IDESNCompat,若为1则有此功能,若未0则不会得到正确的磁盘序列号。相关调用栈回溯是:

xp的viostor驱动无法获取磁盘序列号的分析_第1张图片

对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刚载入时。调用时的相关栈回溯如下:

xp的viostor驱动无法获取磁盘序列号的分析_第2张图片

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处理代码,只有一种逻辑

xp的viostor驱动无法获取磁盘序列号的分析_第3张图片

初步看GetIdeFormatSerialNumber和isIDESerialNumber都比较简单,基本没有用到全局变量,应该可以直接抄反编译代码。因为我没有编译出xp版本viostor的环境,所以没法做实验了。

通过DeviceIoControl(SMART_RCV_DRIVE_DATA)来查询磁盘序列号。若采用深信服的viostor.sys,则可查询到outputbuffer+0x24处是正确的磁盘序列号文字。

xp的viostor驱动无法获取磁盘序列号的分析_第4张图片

你可能感兴趣的:(qemu)