0

I am trying to find out which struct storport!RaGetUnitStorageDeviceProperty uses by myself. I know I can use google and find out the correct answer is _RAID_UNIT_EXTENSION. However i want to do it myself on my own manually and learn the logic behind it.

Things so far I tried include setting a breakpoint on the function and then using the dt command which shows the function name as result. I also used IDA to see if I can get any trace of struct but I could not find any trace of _RAID_UNIT_EXTENSION with IDA even though I used storport.pdb as well. How can I find it myself manually? I can clearly see _RAID_UNIT_EXTENSIONusing dt storport!* in the output but there is not any trace of such a name in IDA. I would really appreciate it if someone could help me.

1 Answer 1

1

unless you have a private pdb for storport you wouldn't be able to locate the names and even if you have the private pdb it is mostly a guessing game

i will show a demo using windbg adapt it to the tools of your choice

1)locating function of interest

0: kd> x /v /t /f storport!RaGetUnitStorageDeviceProperty
prv func   fffff801`36f12664  268 <CLR type> storport!RaGetUnitStorageDeviceProperty (void)

since the argument list is void either this functions takes no arguments or the details are missing and is not easily locatable without putting in effort

since this is an x64 the first four arguments are passed via rcx,rdx,r8,r9 in windows lets check if any of them are used inside the function.

if they are going to be accessed they would be saved or used very early in the function dissassemble first 15 lines of the functions

0: kd> u storport!RaGetUnitStorageDeviceProperty l15
storport!RaGetUnitStorageDeviceProperty:
fffff801`36f12664 4055            push    rbp
fffff801`36f12666 53              push    rbx
fffff801`36f12667 56              push    rsi
fffff801`36f12668 57              push    rdi
fffff801`36f12669 4154            push    r12
fffff801`36f1266b 4156            push    r14
fffff801`36f1266d 4157            push    r15
fffff801`36f1266f 488dac2440ffffff lea     rbp,[rsp-0C0h]
fffff801`36f12677 4881ecc0010000  sub     rsp,1C0h
fffff801`36f1267e 488b056b6cffff  mov     rax,qword ptr [storport!_security_cookie (fffff801`36f092f0)]
fffff801`36f12685 4833c4          xor     rax,rsp
fffff801`36f12688 488985b0000000  mov     qword ptr [rbp+0B0h],rax
fffff801`36f1268f 488b7968        mov     rdi,qword ptr [rcx+68h]
fffff801`36f12693 4d8bf0          mov     r14,r8 <<<<<<<<<<<<<<<<<
fffff801`36f12696 4c8bfa          mov     r15,rdx <<<<<<<<<<<<<<<<<
fffff801`36f12699 488bd9          mov     rbx,rcx <<<<<<<<<<<<<<<<<<<<<<<
fffff801`36f1269c 41bc8c010000    mov     r12d,18Ch
fffff801`36f126a2 488d4c2420      lea     rcx,[rsp+20h]
fffff801`36f126a7 458bc4          mov     r8d,r12d
fffff801`36f126aa 33d2            xor     edx,edx
fffff801`36f126ac e88fd2faff      call    storport!memset (fffff801`36ebf940)

as you can notice three arguments are saved the first argument rcx is saved to rbx the second argument rdx is saved to r15 the third argument r8 is saved to r14

disassemble the full function and grep for r9 just in case

0: kd> .shell -ci "uf storport!RaGetUnitStorageDeviceProperty" findstr "r9"
.shell: Process exited

no sign of r9 so this function possibly takes 3 arguments

lets concentrate on rbx which holds the first argument

0: kd> .shell -ci "uf storport!RaGetUnitStorageDeviceProperty" findstr "rbx"
fffff801`36f12666 53              push    rbx
fffff801`36f12699 488bd9          mov     rbx,rcx
fffff801`36f126f3 8b83d00c0000    mov     eax,dword ptr [rbx+0CD0h] <<<<<<<
fffff801`36f126fd 488b8398000000  mov     rax,qword ptr [rbx+98h]
fffff801`36f1270d 488b9390000000  mov     rdx,qword ptr [rbx+90h]
fffff801`36f1274c 6644396372      cmp     word ptr [rbx+72h],r12w
fffff801`36f12773 0fb74370        movzx   eax,word ptr [rbx+70h]
fffff801`36f12777 488b5378        mov     rdx,qword ptr [rbx+78h]
fffff801`36f127c4 5b              pop     rbx
fffff801`36f12819 6644396372      cmp     word ptr [rbx+72h],r12w
fffff801`36f1282e 488b4318        mov     rax,qword ptr [rbx+18h]
fffff801`36f12879 6644396372      cmp     word ptr [rbx+72h],r12w
fffff801`36f12880 0fb77b70        movzx   edi,word ptr [rbx+70h]
fffff801`36f12898 488b5378        mov     rdx,qword ptr [rbx+78h]
.shell: Process exited

this clearly shows rbx is used and is possibly a structure and is possibly a very large structure as a member at offset 0xcd0 is accessed so the possible sizeof structure is greater than 0xcd0

from this stage on you either need to identify each member manually and name them or use google or tools like ida / ghidra to aid you or debug the function and infer the members of the structure

since you already googled and is having a possible candidate lets trial and eliminate or confirm its correctness

confirm if size is greater than the accessed offset

0: kd> ?? sizeof(storport!_RAID_UNIT_EXTENSION)
unsigned int64 0xd40

yes it is greater

check if offset 0xcd0 is correct offset for a member inside this structure

0: kd> .shell -ci "dt -v storport!_RAID_UNIT_EXTENSION " findstr "cd0"
   +0xcd0 BusType          : Enum _STORAGE_BUS_TYPE,  22 total enums
.shell: Process exited

sure it matches lets check the enum

0: kd> dt -v storport!_STORAGE_BUS_TYPE
Enum _STORAGE_BUS_TYPE,  22 total enums
   BusTypeUnknown = 0n0
   BusTypeScsi = 0n1
   BusTypeAtapi = 0n2
   BusTypeAta = 0n3
   BusType1394 = 0n4
   BusTypeSsa = 0n5
   BusTypeFibre = 0n6
   BusTypeUsb = 0n7
   BusTypeRAID = 0n8
   BusTypeiScsi = 0n9
   BusTypeSas = 0n10
   BusTypeSata = 0n11
   BusTypeSd = 0n12
   BusTypeMmc = 0n13
   BusTypeVirtual = 0n14
   BusTypeFileBackedVirtual = 0n15
   BusTypeSpaces = 0n16
   BusTypeNvme = 0n17
   BusTypeSCM = 0n18
   BusTypeUfs = 0n19
   BusTypeMax = 0n20
   BusTypeMaxReserved = 0n127

ok test eax,eax means it is possibly checking BusTypeUnknown

lets check other offsets

+0x018 Adapter : Ptr64 to struct _RAID_ADAPTER_EXTENSION, 178 elements, 0x1740 bytes

all other member access 0x70,72,0x90,0x98 etc fall inside

   +0x068 Identity         : struct _STOR_SCSI_IDENTITY, 7 elements, 0x38 bytes
   +0x0a0 VendorId         : [9] UChar

lets check that structure

0: kd> dt -v storport!_STOR_SCSI_IDENTITY
struct _STOR_SCSI_IDENTITY, 7 elements, 0x38 bytes
   +0x000 InquiryData      : Ptr64 to struct _INQUIRYDATA, 44 elements, 0x68 bytes
   +0x008 SerialNumber     : struct _STRING, 3 elements, 0x10 bytes
   +0x018 Supports1667     : UChar
   +0x019 ZonedDevice      : UChar
   +0x020 DeviceId         : Ptr64 to struct _VPD_IDENTIFICATION_PAGE, 6 elements, 0x4 bytes
   +0x028 AtaDeviceId      : Ptr64 to struct _STOR_ATA_DEVICE_ID, 2 elements, 0x32 bytes
   +0x030 RichDeviceDescription : Ptr64 to struct _STOR_RICH_DEVICE_DESCRIPTION, 5 elements, 0x6c bytes

so your google foo has landed a possibly correct reference to the implementation

opened the storport.sys in ghidra / configured symbol path / searched for the function and de-compiled it selected the PARAMETER 1 and assigned _RAID_UNIT_EXTENSION to it and voila you get a neat output

void RaGetUnitStorageDeviceProperty(_RAID_UNIT_EXTENSION *param_1,void *param_2,uint *param_3)

{
xxxxxxxxxxxxxxxxxxxxxx
  local_1bc = param_1->BusType;
  p_Var5 = (param_1->Identity).RichDeviceDescription;
  if (p_Var5 == (_STOR_RICH_DEVICE_DESCRIPTION *)0x0) {
    p_Var6 = (param_1->Identity).AtaDeviceId;
    if ((p_Var6 == (_STOR_ATA_DEVICE_ID *)0x0) ||
       ((((param_1->Adapter->Miniport).HwInitializationData)->FeatureSupport & 0x40) == 0)) {
      local_1b0 = *(undefined8 *)p_Var4->VendorId;
      uVar3 = *(undefined4 *)p_Var4->ProductRevisionLevel;
      uStack424 = uStack424 & 0xff | *(int *)p_Var4->ProductId << 8;
      uStack420._1_3_ = (undefined3)*(undefined4 *)(p_Var4->ProductId + 4);
      uStack420 = CONCAT31(uStack420._1_3_,(char)((uint)*(int *)p_Var4->ProductId >> 0x18));
      uStack416._1_3_ = (undefined3)*(undefined4 *)(p_Var4->ProductId + 8);
      uStack416 = CONCAT31(uStack416._1_3_,
                           (char)((uint)*(undefined4 *)(p_Var4->ProductId + 4) >> 0x18));
      uStack412._1_3_ = (undefined3)*(undefined4 *)(p_Var4->ProductId + 0xc);
      uStack412 = CONCAT31(uStack412._1_3_,
                           (char)((uint)*(undefined4 *)(p_Var4->ProductId + 8) >> 0x18));
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

opening the file in idafree8 inserted the standard structure _RAxxxxx assigned the parameter to pointer to standard structure and decompiled

idas output

  HIDWORD(v26[3]) = a1->BusType;
  RichDeviceDescription = a1->Identity.RichDeviceDescription;
  if ( RichDeviceDescription )
  {
    if ( RichDeviceDescription->VendorId[0] )
    {
      v15 = *(_OWORD *)RichDeviceDescription->VendorId;
      HIDWORD(v26[1]) = 40;
      *(_OWORD *)&v26[5] = v15;
    }
    v16 = *(_OWORD *)RichDeviceDescription->ModelNumber;
    v26[2] = 0x7A00000039i64;
    v17 = *(_OWORD *)&RichDeviceDescription->ModelNumber[16];
    *(_OWORD *)((char *)&v26[7] + 1) = v16;
    v18 = *(_OWORD *)&RichDeviceDescription->ModelNumber[32];
    *(_OWORD *)((char *)&v26[9] + 1) = v17;
    v19 = *(_OWORD *)&RichDeviceDescription->ModelNumber[48];
    *(_OWORD *)((char *)&v26[11] + 1) = v18;
    v20 = *(_OWORD *)RichDeviceDescription->FirmwareRevision;
    *(_OWORD *)((char *)&v26[13] + 1) = v19;
    *(_OWORD *)((char *)&v26[15] + 2) = v20;
    if ( a1->Identity.SerialNumber.MaximumLength )
      JUMPOUT(0x1C00761D0i64);
    goto LABEL_12;
  }
  AtaDeviceId = a1->Identity.AtaDeviceId;
  if ( AtaDeviceId && (a1->Adapter->Miniport.HwInitializationData->FeatureSupport & 0x40) != 0 )
  {
    v21 = *(_OWORD *)AtaDeviceId->ModelNumber;
    v22 = *(_QWORD *)AtaDeviceId->FirmwareRevision;
    v23 = *(_OWORD *)&AtaDeviceId->ModelNumber[16];
    v26[2] = 0x5100000028i64;
    *(_OWORD *)&v26[5] = v21;
    *(_QWORD *)((char *)&v26[10] + 1) = v22;
    v26[9] = *(_QWORD *)&AtaDeviceId->ModelNumber[32];
    *(_OWORD *)&v26[7] = v23;
    if ( a1->Identity.SerialNumber.MaximumLength )
    {
      Length = a1->Identity.SerialNumber.Length;
      LODWORD(v26[3]) = 90;
      memmove((char *)&v26[11] + 2, a1->Identity.SerialNumber.Buffer);
      v25 = 21;
      if ( (unsigned __int64)(Length + 1) < 0x15 )
        v25 = Length + 1;
      RaidRemoveTrailingBlanks((char *)&v26[11] + 2, v25);
      goto LABEL_8;
    }
2
  • Thank you so much for this wonderful answer. I just have one more question. How should I insert struct in IDA? I am new to reverse engineering. I can't find any structure in IDA with that name. Sep 23, 2022 at 8:46
  • shift+f9 -> add standard structure -> load til or pdb as the case maybe if the standard structure dialog is empty or partial
    – blabb
    Sep 27, 2022 at 11:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.