Vector35 / Vector35/binaryninja-api
Wrong argument passed to function in HLIL vs disassembly
@D0ntPanic is already working on this.
Since Dec 4, 2024.
- 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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.