Unpacking Themida #3

This is where the decompiler becomes slightly less useful and we need to start getting our hands dirty with the disassembly.

So here we are @ 0x10406c5.

Lets take a look 2 instructions down in loc104070e: "cmp dword ptr [ebp+0DE80F35h], 0".
If 0x103ff49 0, then we jump to loc
1040729.
I have no idea whether 0x103ff49 has been modified previously by something somewhere, but I'll assume for now that it's 0 (which is what it seems to be at the moment in the process flow), so we're jumping to loc_1040729.

0x45 is pushed on to the stack and loc_10407D3 is called.
I've had to massage the disassembly a bit to get Hex-Rays to decompile this function nicely, but it does a pretty good job.

  
// sub_10407D4
int __userpurge fill_buf_with_series(int a1)  
{
  unsigned int offset; // ebx@1
  int result; // eax@2
  int count; // [sp+24h] [bp-4h]@1

  offset = 0xF31BF014u;
  count = 0;
  while ( 1 )
  {
    result = count++ + 1;
    if ( count  0x80 )
      break;
    *(_DWORD *)(offset++ + 0xDE81735) = a1++;
  }
  return result;
}

This seems to perform 128 iterations, starting from memory location 0xF31BF014 + 0xDE81735 = 0x1040749, each iterating setting the value of the next memory location to 'val' (the value passed to the function) + 'count' (the number of iterations).

The caller has pushed 0x45 on to the stack so that's our starting value.

Lets go ahead and perform this operation:

  
for i in range(0, 0x80): PatchDword(0x1040749 + i, 0x45 + i)  

We're returning to the next instruction in loc_1040729, so let's try and see what it does.
0x783749a is pushed on to the stack and 0x1040819 is called. Massaging IDA, we get a good disassembly of the function.

And slightly cleaner:

  
void __stdcall sub_1040819(int val)  
{
  _BYTE *p_byte_1040749; // edi@3
  _BYTE *p_buf; // esi@3
  char _CL; // cl@4
  signed int v5; // ebx@4
  signed int _EAX; // eax@4
  _BYTE buf[128]; // [sp+0h] [bp-84h]@2
  int i; // [sp+80h] [bp-4h]@1

  i = 0;
  do
  {
    val = __ROL__(val, 1);
    buf[0] = val;
    ++i;
  }
  while ( i != 0x80 );
  i = 0;
  p_byte_1040749 = byte_1040749;
  p_buf = buf;
  do
  {
    _CL = *p_buf;
    v5 = 500;
    _EAX = 0x785437ABu;
    do
    {
      __asm { rcl     eax, cl }
      _CL = *p_byte_1040749;
      __asm { rcl     eax, cl }
      --v5;
    }
    while ( v5 );
    ++p_byte_1040749;
    ++p_buf;
    ++i;
  }
  while ( i != 0x80 );
}

At least Hex-Rays partially works. It doesn't like the rcl instructions very much but we've got a pretty good picture of what's going on.

Let's dissect it further.

We have a paramter on the stack, 0x783749a, which is our 'val' here. The first 'do ... while' is a transform on val, the result of which is held in buf[0]. The function then performs some sort of a transform using values from our 0x1040749 (which we had set up previously with that incrementing byte series).

sub_1040819() is then called again; this time with a value of 0xa894b25.

I'm not actually sure what the point of sub_1040819() is at this stage to be honest. Need to look into it more...

After sub_1040819() has been run again, we come to this very interesting bit of code:

  
    i = 0x7000u;
    offset = (_BYTE *)loc_10408A5;
    do
    {
      --*offset++;
      --i;
    }
    while ( i );

Interestingly, looking at the assembly, we can see that the location it's modifying is actually part of the same function (the modifications continue past the function too of course).

Let's run the transform:

  
for i in range(0, 0x7000):  
    PatchByte(0x10408a5+i, (Byte(0x10408a5+i) - 1) & 0xff)

Now we've got some more code for next time...