Vector35 / Vector35/binaryninja-api

Pointer-Array duality not handled for structure members

Open
#4,256 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Component: Core Core: MLIL Core: Type Propagation Impact: High
Dominant language
C++
Stars
1.3k
Forks
298
Avg merge
5d 5h
Merged PRs (30d)
19

Description

Version and Platform (required):

  • Binary Ninja Version: 3.4.4248-dev, c26685e2
  • OS: macos
  • OS Version: 13.3
  • CPU Architecture: arm64

Data structures

struct __data_var_refs drv_cfg_item_t __packed
{
    char* name;
    int32_t field_4;
    int32_t field_8;
};

struct __data_var_refs drv_cfg_t __packed
{
    char* name;
    struct drv_cfg_item_t* items;
    char field_8;
    char field_9;
    char field_a;
    char field_b;
    char field_c;
    uint8_t field_d;
    char field_e;
    char field_f;
};

What IDA generates

        v10 = v18 - 1;
        v11 = (unsigned __int8)p->field_E;
        v12 = v10 / v11;
        v13 = &p->data[v10 % v11];
        name = v13->name;
        v15 = LOBYTE(v13->field_8);
        v16 = BYTE1(v13->field_8);
        v17 = (&off_E0544)[2 * v15];

and the BN HLIL (see full listing at the bottom)...

000030f74                      uint32_t r3_1 = ((uint32_t)p->field_e);
000030f76                      struct drv_cfg_item_t* items = p->items;
000030f7a                      uint32_t r12_1 = ((r4_5 - 1) / r3_1);
000030f84                      int32_t r4_3 = (((r4_5 - 1) - (r3_1 * r12_1)) * 0xc);
000030f8c                      int32_t r4_4 = *(int32_t*)((char*)items + r4_3);
000030f94                      uint32_t r5_1 = ((uint32_t)*(int8_t*)(((char*)items + r4_3) + 9));

So BN recognizes items to be a structure but fails to recognize items->name

Assembler below

000030f40  void* fetch_config_30f40(int32_t arg1, int32_t arg2)

000030f40  2de9ff41   push    {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr} {var_1c} {var_20_2} {var_24_4} {var_28_4} {var_4} {__saved_r8} {__saved_r7} {__saved_r6} {__saved_r5} {__saved_r4}
000030f44  8c46       mov     r12, r1
000030f46  1046       mov     r0, r2
000030f48  1946       mov     r1, r3
000030f4a  334d       ldr     r5, [pc, #0xcc]  {data_31018}  {FETCH_CONFIG_START}
000030f4c  dff8e080   ldr     r8, [pc, #0xe0]  {data_31030}

000030f50  6c68       ldr     r4, [r5, #4] {drv_cfg_t::items}
000030f52  002c       cmp     r4, #0
000030f54  5bd1       bne     #0x3100e

000030f56  4545       cmp     r5, r8
000030f58  01d3       bcc     #0x30f5e

000030f5a  0020       movs    r0, #0
000030f5c  06e0       b       #0x30f6c

000030f5e  1035       adds    r5, #0x10
000030f60  f6e7       b       #0x30f50

000030f62  0092       str     r2, [sp] {var_28}
000030f64  2d4a       ldr     r2, [pc, #0xb4]  {data_3101c}  {data_108240, "Op.[config]\nname\t%s\ntype\t%d"}
000030f66  d4f768f9   bl      #flight_log_523a

000030f6a  0130       adds    r0, #1

000030f6c  04b0       add     sp, #0x10
000030f6e  bde8f081   pop     {r4, r5, r6, r7, r8, pc} {__saved_r4} {__saved_r5} {__saved_r6} {__saved_r7} {__saved_r8} {var_4}

000030f72  013c       subs    r4, #1
000030f74  ab7b       ldrb    r3, [r5, #0xe] {drv_cfg_t::field_e}
000030f76  d5f804e0   ldr     lr, [r5, #4] {drv_cfg_t::items}
000030f7a  b4fbf3fc   udiv    r12, r4, r3
000030f7e  03fb1c43   mls     r3, r3, r12, r4
000030f82  0c24       movs    r4, #0xc
000030f84  5c43       muls    r4, r3, r4
000030f86  264b       ldr     r3, [pc, #0x98]  {data_31020}
000030f88  0eeb0405   add     r5, lr, r4
000030f8c  5ef80440   ldr     r4, [lr, r4]
000030f90  95f80880   ldrb    r8, [r5, #8]
000030f94  6d7a       ldrb    r5, [r5, #9]
000030f96  53f83830   ldr     r3, [r3, r8, lsl #3]
000030f9a  32b1       cbz     r2, #0x30faa

000030f9c  cde901c5   strd    r12, r5, [sp, #4] {var_24} {var_20}

000030fa0  204a       ldr     r2, [pc, #0x80]  {data_31024}  {data_10825c, "Op.%s\t%s%d %d"}
000030fa2  0094       str     r4, [sp] {var_28_1}
000030fa4  d4f749f9   bl      #flight_log_523a
000030fa8  dfe7       b       #0x30f6a

000030faa  17b1       cbz     r7, #0x30fb2

000030fac  cde90165   strd    r6, r5, [sp, #4] {var_24_1} {var_20_1}
000030fb0  f6e7       b       #0x30fa0

000030fb2  1d4a       ldr     r2, [pc, #0x74]  {data_31028}  {data_10826a, "Op.%s\t%s %d"}
000030fb4  cde90045   strd    r4, r5, [sp] {var_28_2} {var_24_2}
000030fb8  26e0       b       #0x31008

000030fba  0134       adds    r4, #1
000030fbc  95f80ee0   ldrb    lr, [r5, #0xe] {drv_cfg_t::field_e}
000030fc0  0ab1       cbz     r2, #0x30fc6

000030fc2  02fb0efe   mul     lr, r2, lr

000030fc6  a645       cmp     lr, r4
000030fc8  06da       bge     #0x30fd8

000030fca  0136       adds    r6, #1
000030fcc  b742       cmp     r7, r6
000030fce  dbbf       ittet   le
000030fd0  0024       movs    r4, #0
000030fd2  1035       adds    r5, #0x10
000030fd4  0024       movs    r4, #0
000030fd6  2646       mov     r6, r4

000030fd8  0133       adds    r3, #1

000030fda  4545       cmp     r5, r8
000030fdc  bdd2       bcs     #0x30f5a

000030fde  95f90d70   ldrsb   r7, [r5, #0xd] {drv_cfg_t::field_d}
000030fe2  6a7b       ldrb    r2, [r5, #0xd] {drv_cfg_t::field_d}
000030fe4  002f       cmp     r7, #0
000030fe6  b6bf       itet    lt
000030fe8  02f07f07   and     r7, r2, #0x7f
000030fec  0027       movs    r7, #0
000030fee  0022       movs    r2, #0
000030ff0  9c45       cmp     r12, r3
000030ff2  e2d1       bne     #0x30fba

000030ff4  002c       cmp     r4, #0
000030ff6  bcd1       bne     #0x30f72

000030ff8  2b68       ldr     r3, [r5]
000030ffa  2a89       ldrh    r2, [r5, #8] {drv_cfg_t::field_8.w}
000030ffc  002f       cmp     r7, #0
000030ffe  b0d0       beq     #0x30f62

000031000  3244       add     r2, r6
000031002  cde90062   strd    r6, r2, [sp] {var_28_3} {var_24_3}
000031006  094a       ldr     r2, [pc, #0x24]  {data_3102c}  {data_108222, "Op.[config]\nname\t%s%d\ntype\t%…"}

000031008  d4f717f9   bl      #flight_log_523a
00003100c  ade7       b       #0x30f6a

00003100e  0024       movs    r4, #0
000031010  2346       mov     r3, r4  {0x0}
000031012  2646       mov     r6, r4  {0x0}
000031014  e1e7       b       #0x30fda

and full HLIL

000030f40  void* fetch_config_30f40(int32_t arg1, int32_t arg2)

000030f40  {
000030f40      int32_t r3;
000030f40      int32_t var_1c = r3;
000030f40      int32_t r2;
000030f40      int32_t var_20_2 = r2;
000030f40      int32_t var_24_4 = arg2;
000030f40      int32_t var_28_4 = arg1;
000030f4a      struct drv_cfg_t* p = &FETCH_CONFIG_START;
000030f54      void* r0;
000030f54      while (true)
000030f54      {
000030f54          if (p->items != 0)
000030f52          {
00003100e              int32_t r4_5 = 0;
000031010              int32_t r3_3 = 0;
000031012              int32_t r6_1 = 0;
000030fdc              uint32_t v23;
000030fdc              int32_t v25;
000030fdc              while (p < 0x13d3d0)
000030fda              {
000030fde                  v25 = ((int32_t)p->field_d);
000030fe2                  v23 = ((uint32_t)p->field_d);
000030fe4                  bool cond:0_1 = v25 >= 0;
000030fe4                  bool cond:1_1 = v25 < 0;
000030fe8                  if (v25 < 0)
000030fe4                  {
000030fe8                      v25 = (v23 & 0x7f);
000030fe8                  }
000030fec                  if (cond:0_1)
000030fec                  {
000030fec                      v25 = 0;
000030fec                  }
000030fee                  if (cond:1_1)
000030fee                  {
000030fee                      v23 = 0;
000030fee                  }
000030ff2                  if (arg2 == r3_3)
000030ff0                  {
000030ff2                      break;
000030ff2                  }
000030fba                  r4_5 = (r4_5 + 1);
000030fbc                  uint32_t v11 = ((uint32_t)p->field_e);
000030fc0                  if (v23 != 0)
000030fc0                  {
000030fc2                      v11 = (v23 * v11);
000030fc2                  }
000030fc8                  if (v11 < r4_5)
000030fc6                  {
000030fca                      r6_1 = (r6_1 + 1);
000030fd0                      if (v25 <= r6_1)
000030fcc                      {
000030fd0                          r4_5 = 0;
000030fd0                      }
000030fd2                      if (v25 <= r6_1)
000030fcc                      {
000030fd2                          p = &p[1];
000030fd2                      }
000030fd4                      if (v25 > r6_1)
000030fcc                      {
000030fd4                          r4_5 = 0;
000030fd4                      }
000030fd6                      if (v25 <= r6_1)
000030fcc                      {
000030fd6                          r6_1 = r4_5;
000030fd6                      }
000030fcc                  }
000030fd8                  r3_3 = (r3_3 + 1);
000030fd8              }
000030fdc              if (p < 0x13d3d0)
000030fda              {
000030ff6                  void* r0_1;
000030ff6                  if (r4_5 != 0)
000030ff4                  {
000030f74                      uint32_t r3_1 = ((uint32_t)p->field_e);
000030f76                      struct drv_cfg_item_t* items = p->items;
000030f7a                      uint32_t r12_1 = ((r4_5 - 1) / r3_1);
000030f84                      int32_t r4_3 = (((r4_5 - 1) - (r3_1 * r12_1)) * 0xc);
000030f8c                      int32_t r4_4 = *(int32_t*)((char*)items + r4_3);
000030f94                      uint32_t r5_1 = ((uint32_t)*(int8_t*)(((char*)items + r4_3) + 9));
000030f9a                      if (v23 != 0)
000030f9a                      {
000030f9c                          uint32_t var_24 = r12_1;
000030f9c                          uint32_t var_20 = r5_1;
000030f9c                      }
000030faa                      else if (v25 == 0)
000030faa                      {
000030fb4                          int32_t var_28_2 = r4_4;
000030fb4                          uint32_t var_24_2 = r5_1;
000030fb4                      }
000030fac                      else
000030fac                      {
000030fac                          int32_t var_24_1 = r6_1;
000030fac                          uint32_t var_20_1 = r5_1;
000030fac                      }
000030faa                      if ((v23 != 0 || (v23 == 0 && v25 != 0)))
000030faa                      {
000030fa2                          int32_t var_28_1 = r4_4;
000030fa4                          r0_1 = flight_log_523a();
000030fa4                      }
000030ff4                  }
000030ffa                  else
000030ffa                  {
000030ffa                      uint32_t r2_1 = ((uint32_t)p->field_8*(int32_t*)((char*)p + 8));
000030ffe                      if (v25 == 0)
000030ffc                      {
000030f62                          uint32_t var_28 = r2_1;
000030f66                          r0_1 = flight_log_523a();
000030f66                      }
000031002                      else
000031002                      {
000031002                          int32_t var_28_3 = r6_1;
000031002                          int32_t var_24_3 = (r2_1 + r6_1);
000031000                      }
000031000                  }
000030faa                  if (((r4_5 == 0 && v25 != 0) || ((r4_5 != 0 && v23 == 0) && v25 == 0)))
000030faa                  {
000031008                      r0_1 = flight_log_523a();
000031008                  }
000030f6a                  r0 = ((char*)r0_1 + 1);
000030f6a                  break;
000030f6a              }
000030ff6          }
000030f58          else if (p < 0x13d3d0)
000030f56          {
000030f5e              p = &p[1];
000030f60              continue;
000030f60          }
000030f5a          r0 = nullptr;
000030f5c          break;
000030f5c      }
000030f6e      return r0;
000030f6e  }

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 fetch_config_30f40 entry point and compare the supplied ARM assembler with its HLIL listing, focusing on p->items and the later access to the structure member name. Reproduce the case using the drv_cfg_t and drv_cfg_item_t definitions; done means HLIL preserves the structure-member access instead of reducing it to raw pointer arithmetic.

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
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.