Vector35 / binaryninja-api

Public API, examples, documentation and issues for Binary Ninja
https://binary.ninja/
MIT License
897 stars 200 forks source link

Missing lifting for ARMv7 `vcvt, vabs, vcmpe, vmrs` #3975

Open blue-devil opened 1 year ago

blue-devil commented 1 year ago

Hello,

What is the feature you'd like to have? Binary ninja cannot detect/parse doubles in HLIL/PseudoC view if the binary is an ARM binary

Additional Information:

I want to report a decompilation incapability. I have realized this while solving a challenge from r0. Mirror download link

In this situation we have a 32 bit ARM binary. Anyone can run binary in Raspbian.

This binary has been initializing some doubles. Then uses them. I have realized that Binary Ninja HLIL and Pseudo C views cannot decompile the doubles in exact values:

Disassembly:

00008624  e13f8fe2   adr     r3, data_89b0
00008628  d020c3e1   ldrd    r2, r3, [r3]  {data_89b0}  {0x400921cac083126f}
0000862c  f4214be1   strd    r2, r3, [r11,  #-0x14] {var_18}
00008630  0e3d8fe2   adr     r3, data_89b8

Pseudo C

00008628      int32_t r2;
00008628      int32_t r3;
00008628      r3 = HIGHW(0x400921cac083126f);
00008628      r2 = LOWW(0x400921cac083126f);

Let's cross check this binary in IDA Pro:

Disassembly:

.text:00008624 ADR     R3, dword_89B0
.text:00008628 LDRD    R2, R3, [R3]
.text:0000862C STRD    R2, R3, [R11,#f1]
.text:00008630 ADR     R3, dword_89B8

Pseudo C

  double v20; // [sp+68h] [bp-1Ch]
  double v21; // [sp+70h] [bp-14h]
  int i; // [sp+7Ch] [bp-8h]

  v21 = 3.1415;
  v20 = 6.283;

BTW, I have extracted the pseudo c code and recompiled as x86, then check it through Binary Ninja:

Pseudo C

00001243      double var_58 = ((double)((long double)3.1415000000000002));
00001263      double var_48 = ((double)((long double)9.9000000000000004));
.
.
.
snip code
.
.
.
((long double)((double)((long double)6.2830000000000004)))

Final words

Binary Ninja have problems detecting/parsing doubles if the binary is an ARM binary, but can decompile/detect doubles if the binary is x86 binary

plafosse commented 1 year ago

The linked binary doesn't exist. Could you please provide a fresh link?

blue-devil commented 1 year ago

Hello @plafosse , I have updated the link: Updated link Alternative link

plafosse commented 1 year ago

Thanks for the update. The root cause of this issue is the lifting lack of support for the following armv7 instructions:

vcvt, vabs, vcmpe, vmrs

I'm going to move this to the Arm repository, for it to be dealt with. If you were so inclined this architecture is open source and you could implement the instructions yourself :)

xusheng6 commented 1 year ago

The relevant code in HLIL:

main:
   0 @ 00008628  int32_t r2
   1 @ 00008628  int32_t r3
   2 @ 00008628  r3:r2 = 0x400921cac083126f
   3 @ 0000862c  double var_18 = r3:r2
   4 @ 00008634  int32_t r2_1
   5 @ 00008634  int32_t r3_1
   6 @ 00008634  r3_1:r2_1 = 0x401921cac083126f
   7 @ 00008650  int32_t r2_2
   8 @ 00008650  int32_t r3_2
   9 @ 00008650  r3_2:r2_2 = 0x4023cccccccccccd
  10 @ 00008654  int64_t var_30 = r3_2:r2_2

I think the real problem is we do not support setting the type of sth like r3:r2. Otherwise, we should have displayed it correctly. @plafosse

xusheng6 commented 1 year ago

The binary uploaded to GH:

548774e79cb74a656e8c75dc82cfa7fc.zip

xusheng6 commented 1 year ago

There are a couple of ways to approach this:

  1. Setting UIDF on the variable var_18. However, we cannot set a floating point UIDF for now.
  2. Somehow generate a synthetic variable for that r3:r2.