C 中的复杂变量赋值反编译 ELF

问题描述

所以我必须获得“隐藏”在这里的密码

void __regparm3 entry(undefined4 param_1,void *param_2,size_t param_3,void *param_4,size_t param_5)

{
  char cVar1;
  int iVar2;
  size_t __n;
  void *__buf;
  int unaff_retaddr;
  
  _write((int)prompt,param_2,param_3);
  _read(unaff_retaddr,param_4,param_5);
  iVar2 = 0;
  do {
    cVar1 = (**(code **)(&vfunc + (uint)(byte)(&vmp)[iVar2] * 4))(); //cant understand this
    if (cVar1 != (&vmr)[__n]) {
      _write((int)fail,__buf,__n);
                    /* WARNING: Subroutine does not return */
      _exit(unaff_retaddr);
    }
    iVar2 = __n + 1;
  } while (iVar2 != 0x17);
  _write((int)success,0x17);
                    /* WARNING: Subroutine does not return */
  _exit(unaff_retaddr);
}

我发现 vmr 包含 0x17 个值,而 vmp 只有一个:03。

问题:

cVar1 是如何创建的,特别是这个 (**(code **)(&vfunc + (uint)(byte)(&vmp)[iVar2] * 4))() 是什么意思?此行是将 vmp 值转换为某个数字还是其他什么?

解决方法

这是对索引函数指针引用的函数的调用,返回一些内容然后存储到char变量中,但是:

  • 它似乎是故意混淆的;
  • 此表达式中隐含的一些变量明显是在我们在这里看到的代码示例之外声明的。

但无论如何,这里的表达是:

  1. vfunc 可能是一个 32 位整数数组,就像指向不同回调函数的指针一样,没有明确声明为指针(可能是因为某些长度和格式目的);
  2. vmp 可能是一个数组,包含每个特定情况下要调用的函数的编号;
  3. &vmp 返回这个数组的地址(如果这真的是一个数组,这是没有用的,如果它是一个 union 或其他东西,则可能是必要的);
  4. &vmp[iVar] 获取由 iVar 索引的条目的值;
  5. (uint)(byte) 然后先将此值转换为一个字节(可能是为了修剪不必要的位),然后转换为一个整数。请注意,转换运算符优先级 (…) 出现在索引 […] 之后;
  6. 由于是 32 位指针,因此该索引乘以 * 4,这往往意味着 vfunc 不指向本机声明的指针,否则将应用指针算法;
  7. 如此获得的指针被强制转换为 (code **),这是一个“指向某个代码的指针的指针”。 code 这里可能是用 typedef 声明的函数指针的别名;
  8. 该指针被取消引用两次以访问函数本身:(** …)
  9. 通过附加最后的括号 …() 调用此函数(不带参数);
  10. 这个函数的这个结果被赋值给 cVar1 :cVar1 = …