Vector35 / Vector35/binaryninja-api

Wrong argument passed to function in HLIL vs disassembly

Open
#5,609 4 comments 0 reactions 1 assignee View on GitHub

@D0ntPanic is already working on this.

Since Dec 4, 2024.

State: Awaiting Triage
Dominant language
C++
Stars
1.3k
Forks
298
Avg merge
5d 5h
Merged PRs (30d)
19

Description

Version and Platform (required):

  • Binary Ninja Version: 4.1.5474-dev, f6ba0af7
  • OS: macos
  • OS Version: 14.5
  • CPU Architecture: arm64

Internal binary major dine favor.

In DjiStreamChannelUsbBulk_AddPort...

For the call to UsbBulkInit IDA shows

    v17 = (usb->UsbBulkInit)(v15, v16, &s_channelUsbBulkPortContent + 144 * i + 2);

whereas BN shows

000a434c              int64_t usbBulkInfo
000a434c              uint64_t err_1 = usb->UsbBulkInit(usbBulkInfo, usbBulkHandle: nullptr)

The first argument is a 12-byte structure that's passed on the stack

struct T_DjiHalUsbBulkInfo __packed
{
    bool isUsbHost;
    short unsigned int pid;
    short unsigned int vid;
    struct __packed
    {
        short unsigned int interfaceNum;
        short unsigned int endPointIn;
        short unsigned int endPointOut;
    } channelInfo;
};

Looking at the IDA stack layout (clicking on v15 points at var_40) shows that there's indeed 12 bytes of space available (var_40 + var_38.

-0000000000000044 var_44          DCW ?
-0000000000000042                 DCB ? ; undefined
-0000000000000041 var_41          DCB ?
-0000000000000040 var_40          DCQ ?
-0000000000000038 var_38          DCD ?
-0000000000000034                 DCB ? ; undefined
-0000000000000033                 DCB ? ; undefined
-0000000000000032                 DCB ? ; undefined
-0000000000000031                 DCB ? ; undefined
-0000000000000030 var_30          DCQ ?
-0000000000000028 var_28          DCQ ?
-0000000000000020 osal            DCQ ?
-0000000000000018 usb             DCQ ?
-0000000000000010                 DCB ? ; undefined
-000000000000000F                 DCB ? ; undefined
-000000000000000E                 DCB ? ; undefined
-000000000000000D                 DCB ? ; undefined
-000000000000000C var_C           DCD ?
-0000000000000008 var_8           DCD ?
-0000000000000004 var_4           DCD ?
+0000000000000000
+0000000000000000 ; end of stack variables

I don't know why IDA insists on passing 3 arguments to UsbBulkInit, I asked their support and will update this ticket when I have the answer. Still, BN insists that the function takes usbBulkInfo as its first argument, or 8 bytes passed in register x29.

I tried typing var_40 as T_DjiHalUsbBulkInfo, per the signature of UsbBulkInit. This changed BN output like so but didn't change the argument passed to UsbBulkInit.

000a42ec              bulk_info.isUsbHost = arg1
000a42f4              bulk_info.pid = arg2
000a42fc              bulk_info.vid = arg3
000a4304              bulk_info.channelInfo.interfaceNum = arg4
000a430c              bulk_info.channelInfo.endPointIn = arg5
000a4314              bulk_info.channelInfo.endPointOut = arg6
000a434c              int64_t usbBulkInfo
000a434c              uint64_t err_1 = usb->UsbBulkInit(usbBulkInfo, usbBulkHandle: nullptr)

Dropping down to MLIL showed register x29 as argument

  73 @ 000a434c  err_1 = x3_2(usbBulkInfo: __saved_x29, usbBulkHandle: nullptr)

Corresponding disassembly shows register x29 being used to set things up but x0 points to bulk_info, as it should.

000a4344  a01b40f9   ldr     x0, [x29, #0x30 {bulk_info.isUsbHost.q}]  {0x0}
000a4348  a13b40b9   ldr     w1, [x29, #0x38 {bulk_info.channelInfo.endPointIn.d}]  {0x0}
000a434c  60003fd6   blr     x3

Does this mean that HLIL is wrong?


Setup

000a42e8  a0bf4039   ldrb    w0, [x29, #0x2f {var_41}]
000a42ec  a0c30039   strb    w0, [x29, #0x30 {bulk_info.isUsbHost}]
000a42f0  a05b4079   ldrh    w0, [x29, #0x2c {var_44}]
000a42f4  a0670079   strh    w0, [x29, #0x32 {bulk_info.pid}]
000a42f8  a0574079   ldrh    w0, [x29, #0x2a {var_46}]
000a42fc  a06b0079   strh    w0, [x29, #0x34 {bulk_info.vid}]
000a4300  a0534079   ldrh    w0, [x29, #0x28 {var_48}]
000a4304  a06f0079   strh    w0, [x29, #0x36 {bulk_info.channelInfo.interfaceNum}]
000a4308  a04f4079   ldrh    w0, [x29, #0x26 {var_4a}]
000a430c  a0730079   strh    w0, [x29, #0x38 {bulk_info.channelInfo.endPointIn}]
000a4310  a04b4079   ldrh    w0, [x29, #0x24 {var_4c}]
000a4314  a0770079   strh    w0, [x29, #0x3a {bulk_info.channelInfo.endPointOut}]
000a4318  a02f40f9   ldr     x0, [x29, #0x58 {var_18}]
000a431c  030040f9   ldr     x3, [x0 {T_DjiHalUsbBulkHandler::UsbBulkInit}]
000a4320  a16f80b9   ldrsw   x1, [x29, #0x6c {i}]
000a4324  e00301aa   mov     x0, x1
000a4328  00f07dd3   lsl     x0, x0, #0x3
000a432c  0000018b   add     x0, x0, x1
000a4330  00ec7cd3   lsl     x0, x0, #0x4
000a4334  610f00d0   adrp    x1, 0x292000
000a4338  21e03391   add     x1, x1, #0xcf8  {s_channelUsbBulkPortContent}
000a433c  0000018b   add     x0, x0, x1
000a4340  02080091   add     x2, x0, #0x2
000a4344  a01b40f9   ldr     x0, [x29, #0x30 {bulk_info.isUsbHost.q}]  {0x0}
000a4348  a13b40b9   ldr     w1, [x29, #0x38 {bulk_info.channelInfo.endPointIn.d}]  {0x0}
000a434c  60003fd6   blr     x3

IDA listing

__int64 __fastcall DjiStreamChannelUsbBulk_AddPort(
        char a1,
        __int16 a2,
        __int16 a3,
        unsigned __int16 a4,
        __int16 a5,
        __int16 a6,
        _QWORD *a7)
{
  __int64 v15; // [xsp+30h] [xbp+30h]
  unsigned int v16; // [xsp+38h] [xbp+38h]
  __int64 v17; // [xsp+40h] [xbp+40h]
  __int64 v18; // [xsp+40h] [xbp+40h]
  _BYTE *v19; // [xsp+48h] [xbp+48h]
  T_DjiOsalHandler *osal; // [xsp+50h] [xbp+50h]
  T_DjiHalUsbBulkHandler *usb; // [xsp+58h] [xbp+58h]
  int k; // [xsp+64h] [xbp+64h]
  int j; // [xsp+68h] [xbp+68h]
  int i; // [xsp+6Ch] [xbp+6Ch]

  usb = DjiPlatform_GetHalUsbBulkHandler();
  osal = DjiPlatform_GetOsalHandler();
  BYTE1(v15) = 0;
  v19 = osal->Malloc(1LL);
  if ( v19 )
  {
    for ( i = 0; i <= 4 && *(&s_channelUsbBulkPortContent + 144 * i) == 1; ++i )
      ;
    if ( i > 0 )
    {
      for ( j = 0; j < i; ++j )
      {
        if ( a2 == *(&s_channelUsbBulkPortContent + 72 * j + 5)
          && a3 == *(&s_channelUsbBulkPortContent + 72 * j + 6)
          && a4 == *(&s_channelUsbBulkPortContent + 72 * j + 7)
          && a5 == *(&s_channelUsbBulkPortContent + 72 * j + 8)
          && a6 == *(&s_channelUsbBulkPortContent + 72 * j + 9) )
        {
          *a7 = *(&s_channelUsbBulkPortContent + 144 * j + 2);
          ++*(&s_channelUsbBulkPortContent + 144 * j + 1);
          DjiLogger_Output(
            "channel",
            3,
            "[%s:%d) Usb bulk port has inited, interfaceNum:%d.",
            "DjiStreamChannelUsbBulk_AddPort",
            457LL,
            a4);
          return 0LL;
        }
      }
    }
    LOBYTE(v15) = a1;
    WORD1(v15) = a2;
    WORD2(v15) = a3;
    HIWORD(v15) = a4;
    LOWORD(v16) = a5;
    HIWORD(v16) = a6;
    v17 = (usb->UsbBulkInit)(v15, v16, &s_channelUsbBulkPortContent + 144 * i + 2);
    if ( v17 )
    {
      DjiLogger_Output(
        "channel",
        0,
        "[%s:%d) Init usb bulk channel failed, ret:%08X.",
        "DjiStreamChannelUsbBulk_AddPort",
        473LL,
        v17);
      return v17;
    }
    else
    {
      *(&s_channelUsbBulkPortContent + 72 * i + 5) = a2;
      *(&s_channelUsbBulkPortContent + 72 * i + 6) = a3;
      *(&s_channelUsbBulkPortContent + 72 * i + 7) = a4;
      *(&s_channelUsbBulkPortContent + 72 * i + 8) = a5;
      *(&s_channelUsbBulkPortContent + 72 * i + 9) = a6;
      for ( k = 0; k <= 9; ++k )
      {
        *(&s_channelUsbBulkPortContent + 72 * i + 5 * k + 22) = 0;
        *(&s_channelUsbBulkPortContent + 144 * i + 10 * k + 46) = 0LL;
      }
      *(&s_channelUsbBulkPortContent + 36 * i + 7) = 0;
      *(&s_channelUsbBulkPortContent + 144 * i + 20) = osal->Malloc(0x80000LL);
      if ( *(&s_channelUsbBulkPortContent + 144 * i + 20) )
      {
        *v19 = i;
        v18 = osal->TaskCreate(
                "bulk_recv_task",
                DjiStreamChannelUsbBulk_RecvDataThread,
                2048LL,
                v19,
                (&s_channelUsbBulkPortContent + 144 * i + 36));
        if ( v18 )
        {
          DjiLogger_Output(
            "channel",
            0,
            "[%s:%d) Create usb bulk recv task failed, ret:%08X.",
            "DjiStreamChannelUsbBulk_AddPort",
            501LL,
            v18);
          return v18;
        }
        else
        {
          *(&s_channelUsbBulkPortContent + 144 * i) = 1;
          ++*(&s_channelUsbBulkPortContent + 144 * i + 1);
          *a7 = *(&s_channelUsbBulkPortContent + 144 * i + 2);
          return 0LL;
        }
      }
      else
      {
        DjiLogger_Output(
          "channel",
          0,
          "[%s:%d) Malloc failed, ret:%08X.",
          "DjiStreamChannelUsbBulk_AddPort",
          491LL,
          0LL);
        return 226LL;
      }
    }
  }
  else
  {
    DjiLogger_Output("channel", 0, "[%s:%d) Malloc error", "DjiStreamChannelUsbBulk_AddPort", 438LL);
    return 226LL;
  }
}

BN HLIL

000a4000  uint64_t DjiStreamChannelUsbBulk_AddPort(char arg1, int16_t arg2, int16_t arg3, int16_t arg4, int16_t arg5, int16_t arg6, int64_t* arg7)

000a4024      struct T_DjiHalUsbBulkHandler* usb = DjiPlatform_GetHalUsbBulkHandler()
000a402c      struct T_DjiOsalHandler* osal = DjiPlatform_GetOsalHandler()
000a4034      int64_t var_28 = 0
000a4038      struct T_DjiHalUsbBulkInfo bulk_info
000a4038      bulk_info.isUsbHost = 0
000a4038      bulk_info.pid = 0
000a4038      bulk_info.vid = 0
000a4038      bulk_info.channelInfo.interfaceNum = 0
000a403c      bulk_info.channelInfo.endPointIn = 0
000a403c      bulk_info.channelInfo.endPointOut = 0
000a404c      void* arg = osal->Malloc(size: 1)
000a405c      uint64_t err
000a4000      
000a405c      if (arg == 0)
000a4088          DjiLogger_Output(tag: "channel", level: 0, fmt: "[%s:%d) Malloc error", "DjiStreamChannelUsbBulk_AddPort", 0x1b6)
000a408c          err = 0xe2
000a405c      else
000a40e4          int32_t i
000a4094          
000a40e4          for (i = 0; i s<= 4; i += 1)
000a40cc              if (zx.d(*(&s_channelUsbBulkPortContent + sx.q(i) * 0x90) ^ 1) != 0)
000a40cc                  break
000a4094          
000a40f8          int32_t i_1
000a4094          
000a40f8          if (i s> 0)
000a42e4              for (i_1 = 0; i_1 s< i; i_1 += 1)
000a4134                  if (zx.d(arg2) == zx.d(*(sx.q(i_1) * 0x90 + &data_292d02)) && zx.d(arg3) == zx.d(*(sx.q(i_1) * 0x90 + 0x292d04)) && zx.d(arg4) == zx.d(*(sx.q(i_1) * 0x90 + 0x292d06)) && zx.d(arg5) == zx.d(*(sx.q(i_1) * 0x90 + 0x292d08)) && zx.d(arg6) == zx.d(*(sx.q(i_1) * 0x90 + 0x292d0a)))
000a4204                      break
000a40fc              
000a42e4              if (i_1 s< i)
000a4230                  *arg7 = *(sx.q(i_1) * 0x90 + 0x292cfa)
000a428c                  *(sx.q(i_1) * 0x90 + 0x292cf9) += 1
000a42c0                  DjiLogger_Output(tag: "channel", level: 3, fmt: "[%s:%d) Usb bulk port has inited…", "DjiStreamChannelUsbBulk_AddPort", 0x1c9, zx.q(arg4))
000a42c4                  err = 0
000a4094          
000a42e4          if (i s<= 0 || i_1 s>= i)
000a42ec              bulk_info.isUsbHost = arg1
000a42f4              bulk_info.pid = arg2
000a42fc              bulk_info.vid = arg3
000a4304              bulk_info.channelInfo.interfaceNum = arg4
000a430c              bulk_info.channelInfo.endPointIn = arg5
000a4314              bulk_info.channelInfo.endPointOut = arg6
000a434c              int64_t usbBulkInfo
000a434c              uint64_t err_1 = usb->UsbBulkInit(usbBulkInfo, usbBulkHandle: nullptr)
000a42ec              
000a435c              if (err_1 != 0)
000a438c                  DjiLogger_Output(tag: "channel", level: 0, fmt: "[%s:%d) Init usb bulk channel fa…", "DjiStreamChannelUsbBulk_AddPort", 0x1d9, err_1)
000a4390                  err = err_1
000a435c              else
000a43c0                  *(sx.q(i) * 0x90 + &data_292d02) = arg2
000a43ec                  *(sx.q(i) * 0x90 + 0x292d04) = arg3
000a4418                  *(sx.q(i) * 0x90 + 0x292d06) = arg4
000a4444                  *(sx.q(i) * 0x90 + 0x292d08) = arg5
000a4470                  *(sx.q(i) * 0x90 + 0x292d0a) = arg6
000a43a0                  
000a4518                  for (int32_t i_2 = 0; i_2 s<= 9; i_2 += 1)
000a44bc                      *(sx.q(i_2) * 0xa + sx.q(i) * 0x90 + 0x292d24) = 0
000a4500                      *(sx.q(i_2) * 0xa + sx.q(i) * 0x90 + 0x292d26) = 0
000a43a0                  
000a4540                  *(sx.q(i) * 0x90 + 0x292d14) = 0
000a457c                  *(sx.q(i) * 0x90 + 0x292d0c) = osal->Malloc(size: 0x80000)
000a43a0                  
000a45ac                  if (*(sx.q(i) * 0x90 + 0x292d0c) == 0)
000a45dc                      DjiLogger_Output(tag: "channel", level: 0, fmt: "[%s:%d) Malloc failed, ret:%08X.", "DjiStreamChannelUsbBulk_AddPort", 0x1eb, err_1)
000a45e0                      err = 0xe2
000a45ac                  else
000a45f4                      *arg = i.b
000a4644                      uint64_t err_2 = osal->TaskCreate(name: "bulk_recv_task", taskFunc: DjiStreamChannelUsbBulk_RecvDataThread, stackSize: 0x800, arg, task: sx.q(i) * 0x90 + 0x292d1c)
000a45f4                      
000a4654                      if (err_2 == 0)
000a46b4                          *(&s_channelUsbBulkPortContent + sx.q(i) * 0x90) = 1
000a4710                          *(sx.q(i) * 0x90 + 0x292cf9) += 1
000a473c                          *arg7 = *(sx.q(i) * 0x90 + 0x292cfa)
000a4740                          err = 0
000a4654                      else
000a4684                          DjiLogger_Output(tag: "channel", level: 0, fmt: "[%s:%d) Create usb bulk recv tas…", "DjiStreamChannelUsbBulk_AddPort", 0x1f5, err_2)
000a4688                          err = err_2
000a4000      
000a4748      return err

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.