Exetools

Exetools (https://forum.exetools.com/index.php)
-   General Discussion (https://forum.exetools.com/forumdisplay.php?f=2)
-   -   WinCE dll unpacking (https://forum.exetools.com/showthread.php?t=18602)

leader 01-15-2018 22:49

WinCE dll unpacking
 
Hi,

I have a packed dll for WinCE and I wan't to analyse it.
Unfortunately I can not identify what protector is used.
It seems that the dll is unpack himself in the memory during runtime.
There is only 5 functions who does the unpacking/decompressing, so I decide to make a static unpacker for it.

I have a problem to analyse 2 short functions, and I don't know how to handle them:

Quote:

int __fastcall nullsub_1(int a1, int a2)
{
int (__fastcall *v2)(int, int); // r10

return v2(a1, a2);
}
Quote:

int __fastcall sub_10009F7E(int a1, int a2)
{
int (__fastcall *v2)(int, int); // r11

return v2(a1, a2);
}
Both functions are similar, and just calls another functions from memory with the arguments passed. The problem is that the functions pointer is never set, so I don't know what fucntions will be called. (v2 (r10 and r11) never assigned in the dll)

Maybe somebody can give me some tips how to handle this calls?

Regards,
leader

leader 01-20-2018 02:14

Hi,

I have a problem with the analyze one function.
I think this function make the decompression of the code in the memory.
It has many integer overflow checks and it will be overflow in short time:

Code:

char *__fastcall sub_9F92(char *a1, int a2, _BYTE *a3, _DWORD *a4)
{
  char *v4; // r7
  unsigned int v5; // r5
  int v6; // r4
  char *result; // r0
  char v8; // r3
  unsigned __int8 v9; // cf
  int i; // r1
  int v11; // r1
  unsigned __int8 v12; // cf
  unsigned __int8 v13; // cf
  int v14; // r4
  unsigned int v15; // r1
  unsigned __int8 v16; // cf
  int v17; // r3
  signed int v18; // r1
  int v19; // r5
  int v20; // r5
  unsigned __int8 v21; // cf
  unsigned __int8 v22; // cf
  unsigned __int8 v23; // cf
  int v24; // r4
  unsigned __int8 v25; // cf
  int v26; // r1
  unsigned __int8 v27; // cf
  int v28; // r3
  _BYTE *v29; // [sp+0h] [bp-1Ch]
  _DWORD *v30; // [sp+4h] [bp-18h]

  v29 = a3;
  v30 = a4;
  v4 = &a1[a2];
  v5 = -1;
  v6 = 0x80000000;
  while ( 1 )
  {
    v9 = __CFADD__(v6, v6);
    v6 *= 2;
    if ( !v6 )
      return a1 + 1;
    if ( !v9 )
    {
      for ( i = 1; ; i = v11 + v12 + v11 )
      {
        v13 = __CFADD__(v6, v6);
        v14 = 2 * v6;
        if ( !v14 )
          return a1 + 1;
        v15 = i + v13 + i;
        v16 = __CFADD__(v14, v14);
        v6 = 2 * v14;
        if ( !v6 )
          return a1 + 1;
        if ( v16 )
          break;
        v11 = v15 - 1;
        v12 = __CFADD__(v6, v6);
        v6 *= 2;
        if ( !v6 )
          return a1 + 1;
      }
      v9 = v15 >= 3;
      v17 = v15 - 3;
      v18 = 0;
      if ( v9 )
      {
        v19 = (unsigned __int8)*a1++;
        v20 = ~(v19 | (v17 << 8));
        if ( !v20 )
        {
          result = (char *)(a1 - v4);
          *v30 = a3 - v29;
          return result;
        }
        v9 = v20 & 1;
        v5 = v20 >> 1;
        if ( !v9 )
        {
LABEL_21:
          v18 = 1;
          v22 = __CFADD__(v6, v6);
          v6 *= 2;
          if ( !v6 )
            return a1 + 1;
          if ( !v22 )
          {
            while ( 1 )
            {
              v23 = __CFADD__(v6, v6);
              v24 = 2 * v6;
              if ( !v24 )
                break;
              v18 += v23 + v18;
              v25 = __CFADD__(v24, v24);
              v6 = 2 * v24;
              if ( !v6 )
                break;
              if ( v25 )
              {
                v26 = v18 + 4;
                goto LABEL_30;
              }
            }
            return a1 + 1;
          }
        }
      }
      else
      {
        v21 = __CFADD__(v6, v6);
        v6 *= 2;
        if ( !v6 )
          return a1 + 1;
        if ( !v21 )
          goto LABEL_21;
      }
      v27 = __CFADD__(v6, v6);
      v6 *= 2;
      if ( !v6 )
        return a1 + 1;
      v26 = v18 + v27 + v18 + 2;
LABEL_30:
      if ( v5 < 0xFFFFFB00 )
        ++v26;
      v28 = (unsigned __int8)*a3;
      do
      {
        *a3 = a3[v5];
        ++a3;
        --v26;
      }
      while ( v26 );
      continue;
    }
    v8 = *a1++;
    *a3++ = v8;
  }
}

The function arguments are:
- a1 => compressed code buffer
- a2 => length of compressed code buffer
- a3 => To this address will be decompressed the the code
- a4 => I think it will store the lengh of decompressed code (not sure)

__CFADD__ check if the sum of 2 integers is overflow or not. Tipically used to check the sum of the same integer.
There is another overflow check by multiply the integer with 2 (For example v6 *= 2)

As you see the inital value of integer v6 is 0x80000000, so it produce very fast overflow and the function will return without decompressing the code.

I try to reproduce this ARM code on X86 but without success. I spent many time on it, but I can not understand the purpose of this overflow checks and how the decompression made.

I would be very pleased with all your useful ideas.

Thanks,
leader

leader 01-20-2018 05:16

I just identified that the function above is NRV2E decription rutine.
It is used in UPX, so I think this windows ce dll is compressed with a modified UPX.

I made a little program to decompress code section using UCL library, now I need to rebuild import library.... :)


All times are GMT +8. The time now is 09:49.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2026, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX