NdH2k11 WaRgam3 – CrackMe 400 (2000pts). Part 1

This challenge was on reverse engineering. The binary is 32bit MZ-PE executable for Windows.


Summary: reverse engineering, crypto

The given file is packed by easy algorithm. It is xored by 0x2d and also has additional anti-reverse trick as jump in the middle of the instructions. It looks like this:

As you can see at the picture above, from VA .00407000 to .0040700C that anti-reverse trick:

push esi // save esi in stack
add esi, 005EB9090 // pseudo command. It is consist of needed bytes
jz .000407005
jnz .000407005 // in any cases we jump to 407005 – in the middle of cmd: add esi, 005EB9090

add esi, 005eb9090 changes to

.00407005: EB05                  jmps     .00040700C // it is jmp into instruction too
.00407007: 74FC                  jz         .000407005
.00407009: 75FA                  jnz       .000407005
.0040700B: E95E64A118       jmp      018E1D46E

jmp         018E1D46E change to

.0040700C: 5E           pop         esi  // get saved before esi  from stack
.0040700D: 64A118000000      mov         eax,fs:[000000018] // it is real command

We can bypass this trick for that we should patch it (just everywhere change bytes):

So, after unpack and patch procedure we have quite comprehensible  C++ compiled sample.
If you have been careful it also would be working and be “hex-raysable” =)
Program has several main functions:

  • Drop driver from itself to “C:\WINDOWS\Temp\ReverMe1.sys”
  • Create and start service “ReverMe1”
  • Make DeviceIoControl request with first command line argument in parameters
  • Get result from service and compare its first 8 bytes with “b1cc4893”

file = (FILE *)open(“C:\\WINDOWS\\Temp\\ReverMe1.sys”, 33537, 448);
if ( (
signed int)file >= 0 )
write(file, &driver_emb, 7808);
strncpy(&buff, argv[1], 0x200u);
hDevice = CreateFileA(“\\\\.\\ReversMe1″, 0xC0000000u, 0, 0, 3u, 0x80u, 0);
DeviceIoControl(hDevice, 0x9C40E003u, &buff, 0x200u, &buff, 0x200u, (LPDWORD)&bytesReturned, 0);
if (
memcmp(&buff, “b1cc4893″, 8u) )
printf(“Sorry noob, just try again ;-)\n”);
printf(“Nice job ! You found me :-)\nValid the hash : %s\n”, &buff);
ret = 0;

If you execute this several times and look to the results, it would be obviously some kind of hash calculation. The fact that hash has a size 16 bytes (32 in text) hints that it is md5 algorithm.
But if you compare md5 of your input string with result from driver it will be different. May it be modified md5?
There are two possible ways (mat be more, but we found two =) ):

  • First method which was proposed by me =)
    Just reverse driver and get answer! I will describe this way in detail in next post.
  • Second method which was proposed by vos:
    Input different data and try to understand what kind of hash is it

Now I describe vos method and in next post you can find detail describing about me one.
For easily do set of inputs-outputs, we should patch unpacked file there (from jnz to jz):

Now we will have hash in output everytime!

I found the interesting set of input-output pairs:

11111 – b59c67bf196a4758191e42f76670ceba
111111 – b59c67bf196a4758191e42f76670ceba

Hm, hashs are same. Let’s try input more “1”

1111111111111111 – b59c67bf196a4758191e42f76670ceba


1111 – b59c67bf196a4758191e42f76670ceba
111 – 63813da8e6d495818746b94d6d9b8382

Op, Hash changed! Could it be hash only from first 4 bytes? Let’s try!

1111HelloWorld – b59c67bf196a4758191e42f76670ceba

It is same! How about md5 form “1111”?

md5(“1111”) = b59c67bf196a4758191e42f76670ceba

Yes, we get it. Program calculates md5 form first 4 input bytes. All what we need is just to bruteforce md5 for 4 symbol string and find one which has first 4 bytes equal  “b1cc4893”

Not so hard isn’t it?

So, key:
Input: OwnM
MD5: b1cc4893de3b7d9401d30f2f5890df12

1 ping

  1. […] It is second part of CrackMe task describing. First one you can find there […]

Leave a Reply

Your email address will not be published.