Search code examples
creverse-engineeringreverseelf

Complicated variable assignment in C (decompiled ELF)


So I have to get password which "hides" somewhere here

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,__buf,0x17);
                    /* WARNING: Subroutine does not return */
  _exit(unaff_retaddr);
}

I found that vmr contains 0x17 values and vmp only one: 03.

Question:

How cVar1 is created and especially what does mean this (**(code **)(&vfunc + (uint)(byte)(&vmp)[iVar2] * 4))()? Is this line converting vmp value to some number or what else?


Solution

  • It's a call to a function referenced by an indexed function pointer returning something that is then stored into a char variable but:

    • It seems to be obfuscated on purpose ;
    • Some of the variables implied in this expression are visibly declared outside the sample of code we see here.

    But anyway, the expression here says that:

    1. vfunc is probably an array of 32-bits integers acting like pointers towards different callback functions, without being explicitly declared as pointers (probably because of some length & format purposes) ;
    2. vmp is probably an array contains the number of the function to be called for each particular case ;
    3. &vmp returns the address of this array (which is useless if this is really an array, can be necessary if it's an union or something) ;
    4. &vmp[iVar] gets the value of entry indexed by iVar ;
    5. (uint)(byte) then casts this value to a byte first (probably for trimming unnecessary bits) then to an integer. Remark that cast operator precedence (…) comes after the indexing one […] ;
    6. This index is multiplied by * 4 because of 32-bits pointers, which tends to say that vfunc does not point at natively declared pointers, otherwise the pointer arithmetic would have applied ;
    7. The so-obtained pointer is casted to (code **), which is a "pointer to a pointer to some code". code here is probably an alias to a function pointer declared somewhere with typedef ;
    8. This pointer is de-referenced twice to access the function itself: (** …)
    9. This function is called (with no arguments) by appending the final parenthesis …() ;
    10. This result of this function is assigned to cVar1 : cVar1 = …