-1

Given param_1 is the input file bytes, can someone explains what does uVar4 = *(uint *)(param_1 + 3) do? Is it casting param_1 to uint then uVar4 = param_1[3]? Also any clarification about pointer is also good bc my experience with C/Cpp is close to nil (not even mentioning pointers)

uchar * DecryptLZ4(uchar *param_1,ulong param_2,ulong *param_3) //param_1: file bytes, param_2: file size

{
  uchar uVar1;
  uchar *puVar2;
  int iVar3;
  uint uVar4;
  bool bVar5;
  ulong local_28;
  int local_24;
  
  local_24 = __stack_chk_guard;
  local_28 = param_2;
  if (((param_1 != (uchar *)0x0) && (6 < param_2)) && (*param_1 == -8)) { //if param_1[0] == 0xf8..
    uVar1 = param_1[1];
    bVar5 = uVar1 == -0x75; // ..and param_1[1] == 0x8b:
    if (bVar5) { 
      uVar1 = param_1[2];
    } // if param_1[0] = 
    if (((bVar5 && uVar1 == '+') && (param_2 != 7)) && //if param_1[2] == 0x2b and param_2 != 7
       (uVar4 = *(uint *)(param_1 + 3), uVar4 < 0x2000001)) { // THIS LINE
      puVar2 = (uchar *)Allocate((int)GlobalAllocator,(char *)(uVar4 + 1),
                                 (int)
                                 "XANA"
                                 ,&DAT_00000085);
      if (puVar2 != (uchar *)0x0) {
        iVar3 = FUN_00298230(param_1 + 7,puVar2,param_2 - 7,uVar4);
        if (iVar3 < 1) {
          Free((BlockAllocator *)GlobalAllocator,puVar2,(int)(char *)(uVar4 + 1));
          goto LAB_00346faa;
        }
        puVar2[iVar3] = '\0';
        Free((BlockAllocator *)GlobalAllocator,param_1,local_28 + 1);
        param_2 = uVar4;
        param_1 = puVar2;
        local_28 = uVar4;
      }
      if ((0 < (int)uVar4) && (2 < param_2)) {
        while (*param_1 == -8) {
          uVar1 = param_1[1];
          bVar5 = uVar1 != -0x75;
          if (!bVar5) {
            uVar1 = param_1[2];
          }
          if ((bVar5 || uVar1 != '+') ||
             (param_1 = (uchar *)DecryptLZ4(param_1,param_2,&local_28), param_2 = local_28,
             local_28 < 3)) break;
        }
      }
    }
  }
LAB_00346faa:
  if (param_3 != (ulong *)0x0) {
    *param_3 = param_2;
  }
  if (__stack_chk_guard == local_24) {
    return param_1;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

1 Answers1

0

You have to look at the parentheses.

In uVar4 = *(uint *)(param_1 + 3), the addition happens before the conversion to a pointer to uint. param_1 has type uchar *.

So, it is not like uVar4 = param_1[3] because the expression param_1[3] has type uchar. This version would only load one byte, extended to (presumably) 4 bytes to be stored in uVar4. The original would copy (presumably) 4 bytes from the address param_1 + 3 to uVar4.


My answer to

Is it casting param_1 to uint then uVar4 = param_1[3]

would be no for two reasons:

  • param_1 has a fixed type (uchar *), casting it doesn't change its type.
  • If you did something like uint *param_2_ui = (uint *) param_1, then uVar4 = param_2_ui [3], the result would be different.

In C (and C++, though that it is a completely different language) adding to pointers will add to the address by the size of the pointed-to type.

In practice, assuming that sizeof(int) == 4, and given this:

int tmp[2];
int *ptr1 = tmp;

The expression ptr1 + 1 will represent an address 4 greater than ptr1.

Thomas Jager
  • 4,836
  • 2
  • 16
  • 30
  • So for example the file I'm working on with the first 16 bytes: `F8 8B 2B AB 7B 00 00 F0 12 4D 4E 47 A4 7B 00 00` It will take `AB 7B 00 00` and store in uVar4 as uint type? – Minh Nguyen Aug 07 '20 at 12:41
  • Yes, though you have to consider endianness to your processor. You could have the value 0xAB7B0000 or 0x00007BAB. You could even theoretically have some other value, on a weird architecture. This also assumes that `uint` is 4 bytes in size here. This is one of the main reasons why this sort of thing is somewhere between tricky and dangerous. The other is unaligned accesses, which could have no effect, a performance penalty, or raise an exception/cause a crash. – Thomas Jager Aug 07 '20 at 12:48
  • It's little-endian and ARMv8 so result should be 0x00007BAB (`unsigned int` for ARM is 4 bytes). Thank you so much for your thorough answer. – Minh Nguyen Aug 07 '20 at 12:55