提问者:小点点

IDA/Ghidra反编译代码中的十六进制值翻倍


我有以下一段飞镖代码,它检查输入是否为“ABCDE”,如果输入匹配,则打印正确,并且工作正常。

import 'dart:io';
final List<int> flag = [65, 66, 67, 68, 69];
void main() {
  print("\ngive flag: ");
  List<int> input = stdin.readLineSync(encoding: latin1)!.codeUnits;
  if (input.length != flag.length) {
    print("\nnot flag");
    return;
  }
  for (int i = 0; i < flag.length; i++) {
    if (input[i] != flag[i]) {
      print("\nnot flag");
      return;
    }
  }
  StringBuffer newFlag = new StringBuffer();
  input.forEach((e) {
    newFlag.writeCharCode(e);
  });
  print("correct");
}

我用dart compile aot-snapshot exmaple. dart编译了代码,然后尝试用IDA和Ghidra反编译。但是,反编译后的代码中,原来的十进制值似乎翻了一番。

Ghidra反编译代码:

void flag(void)

{
  long lVar1;
  long extraout_RAX;
  long unaff_R14;
  
  if (&stack0xfffffffffffffff8 < *(undefined **)(ulong *)(unaff_R14 + 0x40) ||
      &stack0xfffffffffffffff8 == *(undefined **)(ulong *)(unaff_R14 + 0x40)) {
    (**(code **)(unaff_R14 + 0x238))();
  }
  lVar1 = Precompiled_Stub__iso_stub_AllocateArrayStub();
  *(undefined8 *)(lVar1 + 0x17) = 0x82;
  *(undefined8 *)(lVar1 + 0x1f) = 0x84;
  *(undefined8 *)(lVar1 + 0x27) = 0x86;
  *(undefined8 *)(lVar1 + 0x2f) = 0x88;
  *(undefined8 *)(lVar1 + 0x37) = 0x8a;
  new__GrowableList._withData();
  *(undefined8 *)(extraout_RAX + 0xf) = 10;
  return;
}

0x82、0x84、0x86、0x88、0x8a十进制为130、132、134、136、138。
dec值是代码中最初值(65、66、67、68、69)的两倍。我不确定为什么会发生这种情况……

我的目标是能够通过. aot文件告诉“ABCDE”是所需的输入。谢谢:)


共1个答案

匿名用户

这是smi编码,它是VM如何在内部表示对象引用的实现细节。

通常,对象引用是指向堆分配对象结构的指针。

然而,为了节省空间和时间,DartVM在内部将小整数(简称Smi)直接表示为特殊格式(标记)的引用,而不是指向堆对象的指针。(在64位VM中,“小”整数实际上是所有可以存储在63位中的整数。)

小整数的表示形式正是向左移动一的整数,又名。乘以二,第0位有一个零。这有一个优点,就是可以直接在标记的值上添加或减去Smis,只要它不溢出。

相反,所有对堆对象的引用都将第0位设置为1。无论如何,访问对象的成员都是通过相对于对象引用进行索引来完成的,因此使用n-1而不是n的偏移量不会花费额外的费用。