My Road to Digital Forensics Excellence

vOR – Rotate velocity

Posted by Paul Bobby on July 8, 2009

Still working on the previous mentioned crackme. Wrestling with the following code and reproduction in Python (my preferred language for keygens).

   1:  .text:004010D1                 mov     eax, 12345678h
   2:  .text:004010D6                 xor     edx, edx
   3:  .text:004010D8 loc_4010D8:
   4:  .text:004010D8                 mov     dl, [esi]
   5:  .text:004010DA                 xor     eax, edx
   6:  .text:004010DC                 rol     eax, 5
   7:  .text:004010DF                 inc     esi
   8:  .text:004010E0                 test    edx, edx
   9:  .text:004010E2                 jnz     short loc_4010D8

This routine takes the inputted userid, and XORs each character in the userid with the hex string 0x12345678 and rotates the results to the left, 5 times.

My dilemma? Analyzing the instruction “ROL EAX, 5”.

According to every x86 assembly manual I can find, ROL (and yes I know the difference between ROL and RCL – carry flag), is a simple instruction that takes the contents of a register, drops the left most bit, and shoves it on to the right hand side. Yep, everything takes one step to the left – and the bit that drops off comes in on the right. Sounds simple enough….

Python has limited bitwise manipulation support – however a module called BitVector was written, and I tested the  rotate left functionality for the module (found here). It works in the way I think ROL should work – but does NOT match what the x86 processor generates. Ugh.

  • mov eax, 0x12345608
  • rol eax, 5
  • EAX = 0x468AC102

Using the BitVector module:

  • test = BitVector.BitVector (intVal=0x12345608)
  • test << 5
  • print hex(int(test)) produces 0x68AC112

Close, but no cigar

What’s happening? Let’s look at the python/how-the-manual-explains-it approach first.

   1:  0x12345608 10010001101000101011000001000
   2:  0x468ac11  00100011010001010110000010001
   3:  0x8d15822  01000110100010101100000100010
   4:  0x11a2b044 10001101000101011000001000100
   5:  0x3456089  00011010001010110000010001001
   6:  0x68ac112  00110100010101100000100010010

Line 1, in hex and as a binary string, followed by five ROL EAX, 1 equivalent instructions (yes ROL EAX,5 is the same at ROL EAX,1 executed 5 times)

Now let’s look at how the code really executes when stepping through using Ollydbg.

   1:      EAX  = 0x12345608 =  10010001101000101011000001000
   2:  ROL EAX,1= 0x2468AC10 =  100100011010001010110000010000
   3:  ROL EAX,1= 0x48D15820 =  1001000110100010101100000100000
   4:  ROL EAX,1= 0x91A2B040 =  10010001101000101011000001000000
   5:  ROL EAX,1= 0x23456081 =  100011010001010110000010000001
   6:  ROL EAX,1= 0x468AC102 =  1000110100010101100000100000010

Each new value in EAX looks similar to lines 2-6 in the first example. But there’s obviously more than just dropping the most significant bit and sticking it on the right.

1. If the MSB is 0, just drop and rotate as normal

2. If the MSB is 1, append 1 zero for each zero in the bitstring until you get to the next 1

3. When the next 1 is reached, drop the MSB 1 and subsequent 0s, move all bits to the left, so that the next 1 becomes the MSB, and append 1 to the bitstring.

Now this I can simulate in python using a straightforward list. Look for this code in the upcoming solution to the linked crackme.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: