Vector35 / Vector35/binaryninja-api

Weird stack issue

Open
#5,386 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Component: Core Core: MLIL Impact: Medium
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.0.4958, ddff9339
  • OS: macos
  • OS Version: 14.4
  • CPU Architecture: arm64

Internal binary major dine favor.

IDA Pro code

              recv_cmds = (struct RecvCmd *)djiOs->Malloc(24 * (unsigned int)LOWORD(cmd_list->n_cmds));
              if ( recv_cmds )
              {
                for ( j = 0; LOWORD(cmd_list->n_cmds) > j; ++j )
                {
                  recv_cmd = &recv_cmds[j];
                  recv_cmd_1 = &cmd_list->cmds[j];
                  v8 = recv_cmd_1->field_8;
                  *(_QWORD *)&recv_cmd->field_0 = *(_QWORD *)&recv_cmd_1->field_0;
                  recv_cmd->field_8 = v8;
                  recv_cmd->callback = recv_cmd_1->callback;
                }
                cmd->recv_cmds[ixa].cmds = recv_cmds;
                LOWORD(cmd->recv_cmds[ixa].n_cmds) = cmd_list->n_cmds;
...

BN

00064540                                  struct RecvCmd* recv_cmds = CMD_OSAL->Malloc(size: zx.d(cmd_list->n_cmds.w) * 0x18)
00064550                                  if (recv_cmds == 0)
0006457c                                      DjiLogger_UserLogOutput(level: "linker", fmt: nullptr, "[%s:%d) recv cmd list malloc err…", "DjiCommand_RegRecvCmdHandler", 0x297)
00064550                                  else
00064604                                      for (int32_t j = 0; zx.d(cmd_list->n_cmds.w) s> j; j = j + 1)
000645a8                                          void* x3_16 = &recv_cmds[sx.q(j)]
000645c8                                          void* x0_345 = &cmd_list->cmds[sx.q(j)]
000645d4                                          int64_t x1_56 = *(x0_345 + 8)
000645d8                                          *x3_16 = *x0_345
000645d8                                          *(x3_16 + 8) = x1_56
000645e0                                          *(x3_16 + 0x10) = *(x0_345 + 0x10)
00064614                                      cmd->recv_cmds[sx.q(ix_2)].cmds = recv_cmds
0006463c                                      (&cmd->recv_cmds[0]:8.q)[sx.q(ix_2) * 2].w = cmd_list->n_cmds.w

It's clear that both x3_16 and x0_345 are of type RecvCmd* and we are just copying info between structures.

Assigning the right type to both variables should clear up the code, right? Right?

After typing x3_16 and renaming it to cmd1...

00064604                                      for (int32_t j = 0; zx.d(cmd_list->n_cmds.w) s> j; j = j + 1)
000645a8                                          struct RecvCmd* cmd1 = &recv_cmds[sx.q(j)]
000645c8                                          void* x0_345 = &cmd_list->cmds[sx.q(j)]
000645d4                                          int64_t x0_346 = *x0_345
000645d4                                          int64_t x1_56 = *(x0_345 + 8)
000645d8                                          cmd1->field_0 = x0_346.d
000645d8                                          cmd1->sender = x0_346:4.b
000645d8                                          cmd1->receiver = x0_346:5.b
000645d8                                          cmd1->field_1 = x0_346:6.b
000645d8                                          cmd1->field_2 = x0_346:7.b
000645d8                                          cmd1->field_8 = x1_56
000645e0                                          cmd1->callback = *(x0_345 + 0x10)
00064614                                      cmd->recv_cmds[sx.q(ix_2)].cmds = recv_cmds
0006463c                                      (&cmd->recv_cmds[0]:8.q)[sx.q(ix_2) * 2].w = cmd_list->n_cmds.w

After typing x0_345 and renaming it to cmd2 ...

00064604                                      for (int32_t j = 0; zx.d(cmd_list->n_cmds.w) s> j; j = j + 1)
000645a8                                          struct RecvCmd* cmd1 = &recv_cmds[sx.q(j)]
000645c8                                          struct RecvCmd* cmd2 = &cmd_list->cmds[sx.q(j)]
000645d4                                          int64_t x0_345
000645d4                                          x0_345.d = cmd2->field_0
000645d4                                          x0_345:4.b = cmd2->sender
000645d4                                          x0_345:5.b = cmd2->receiver
000645d4                                          x0_345:6.b = cmd2->field_1
000645d4                                          x0_345:7.b = cmd2->field_2
000645d4                                          int64_t field_8 = cmd2->field_8
000645d8                                          cmd1->field_0 = x0_345.d
000645d8                                          cmd1->sender = x0_345:4.b
000645d8                                          cmd1->receiver = x0_345:5.b
000645d8                                          cmd1->field_1 = x0_345:6.b
000645d8                                          cmd1->field_2 = x0_345:7.b
000645d8                                          cmd1->field_8 = field_8
000645e0                                          cmd1->callback = cmd2->callback
00064614                                      cmd->recv_cmds[sx.q(ix_2)].cmds = recv_cmds
0006463c                                      (&cmd->recv_cmds[0]:8.q)[sx.q(ix_2) * 2].w = cmd_list->n_cmds.w

What's going on here?

Let me know if you want my database!

P.S. IDA is much better with stack management. It will tell me if I type something to a size that the stack layout of the function won't handle, i.e. if my type is larger than what would fit or smaller. BN seems to do none of that.

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.

Research direction

Start with the reported Binary Ninja 4.0.4958 output for DjiCommand_RegRecvCmdHandler and compare the untyped and typed RecvCmd variables against the IDA pseudocode. Reproduce the type assignment and stack-layout behavior on macOS arm64, then determine whether the decompiler output or stack-size validation is incorrect; done means the behavior is explained and a focused regression case or fix is identified.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
reverse-engineering
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.