• About Me
  • Blog
  • Home

Eric Hokanson

~ E's little space in cyberspace

Eric Hokanson

Tag Archives: ESET CrakMe 2013 Challenge

ESET Challenge Part 4

26 Sunday Jan 2014

Posted by Eric Hokanson in Cyber Security Research, Malware RE

≈ 2 Comments

Tags

ESET ChallengeME 2013, ESET CrakMe 2013 Challenge, Malware Analysis, Malware Reverse Engineering

My continuing adventures in the ESET 2013 CrackMe Challenge

Last time, we discovered that the crack_me_2.zip binary contains two BMP resources, and one of those resources were extracted and dropped into one of my temporary directories.  This “BMP” was actually an executable:

crack_me_2_dotnet_eastereggUpon double-clicking it displays a cute little photo.  We also learned that the executable to the left was not just any executable but a .NET executable and an obfuscated one at that.

crack_me_2_dotnet_decompiled

The strings all appear to be encrypted with some sort of byte array scheme. Classes and functions are all labeled with only the letters A through F in upper and lowercase.

However, even though this executable is obfuscated, we did see an indication that this rabbit bitmap is actually a pipe-server.  The pipe server that our crack_me_2 binary was searching for.  Upon first running the crack_me_2, we didn’t have a pipe-server running so the function returned a -1.  Crack_me_2 then proceeded to create the .tmp

crack_me_2_named_pipefile that resulted in the “Easter Egg” pipe-server .NET file.  Below is the disassembled code confirming our named pipe “Vincent_Vega” server:

easter_egg_pip_server

And the code that creates the pipe:

ester_egg_pipe2

To disassemble a .NET file you may use ILSpy or .NET Reflector.  I used both.  Started with ILSpy to statically study the Easter Egg and Reflector for debugging (dynamic analysis).

Upon re-starting crack_me_2 with this Easter Egg pipe server running, I set a break point on CreateFileW and instead of EAX = -1, EAX = 0x2C so we got a handle to our named pipe.  Now that a pipe server is running, the program skips all the instructions to create its .tmp Easter Egg file and jumps to here:

hamberger_messgae

We see another base 64 encoded string:

base64_royale_with_cheese

With the pipe-server running, the pipe sends the message “Le Big Mac”, and then compares that with our “Royale with Cheese”:

hamburger_message2

In the above screen shot, on the right, you can see the current state of the registers.  EAX contains the string “Le Big Mac”, while ESI holds “Royale with Cheese”.  These two registers are compared.  If they were equal, the Hamburger message box would appear with the message: “Hamburgers.  The cornerstone of any nutritious breakfast.”   The Pulp Fiction theme continues as the hamburger message is another quote delivered by Jules (Played by Samuel L. Jackson) in the film’s diner scene.  Since the messages do not match, no dialog box will be displayed.  However, we can hack the code, change our “Royale with Cheese” to “Le Big Mac” if we wanted to display the message.

Either way, hamburger message or no, when we continue to single-step, the program now takes us to:

loading_malcho_dll

Another set of base64 encoded strings.  They translate to:

base64_malcho_dll

base64_malcho_dll_function

So crack_me_2 is going to attempt to load a MALCHO.DLL that exports a base64 encoded function that gets a password.

It looks as though, once MALCHO.DLL is loaded, crack_me_2 will extract a password from the Easter Egg pipe server.  This password will then be used to in the following:

gets_decrypts_resource_133

The function call at 0x404A71 is going to extract the second BMP resource in crack_me_2’s resource section. The parameter of 0x85 = 133 in base 10 and we see thanks to PE Explorer that the 133 is the second BMP’s resource ID.

crack_me_2_resources_BMPs

All that is missing is the first parameter — the password that this so-called MALCHO.DLL is supposed to retrieve for us.  But where is this dll?  I have to admit that this stymied me for a few days.  I searched up and down the code looking for this MALCHO.DLL.  I even tried googling for it.  No hits for the dll, but there were links to reports that contained the name, Juraj Malcho, head of — you guessed it — ESET’s Virus Laboratory.  Could he be the author???  I was wondering about the dll’s name because I did not see any reference to a Malcho in Pulp Fiction.

After a couple of days searching to no avail, I decided to ask the Reverse Engineering Malware Research group on linkedIn (my thanks to Mr. Mahmoudnia) for some hints.  It turns out that there is no MALCHO.DLL; I have to make my own MALCHO.DLL.  They key is in the .NET Easter Egg binary.

To help me better understand this .NET Easter Egg, I used a tool called DeReactor to deobfuscate this .NET file.

After setting up the named pipe-server, most of the action appears to be here:

deobfuscated_dynamic_routine

deobfuscated_dynamic_routine_part2

The deobfuscated file calls it method_8() in Class_06; its called Method A of Class D in the obfuscated file.  This took me a while to figure out what was going on here.  It turns out that this Easter Egg .Net creates threads that dynamically — and it is one of three routines that does this (the whole chunk of code is below; feel free to scroll past all that).

protected void A([In] List<byte> obj0)
{
Encoding.ASCII.GetString(obj0.ToArray(), 1, obj0.Count - 1);
}

protected void B()
{
string str1 = string.Format(.d(), (object) null, (object) null);
string str2 = string.Format(.E(), (object) null, (object) null);
string str3;
lock (D.A)
str3 = !this.a ? str2 : str1;
this.A.A(str3);
}

private void b()
{
this.A.Add((object) new G((object) OpCodes.Ldc_I4, (object) (this.A & (int) byte.MaxValue), (object) .e()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4, (object) (this.a & (int) byte.MaxValue), (object) .F()));
this.A.Add((object) new G((object) OpCodes.Xor, (object) null, (object) .f()));
}

private void A([In] object obj0)
{
try
{
Thread thread = obj0 as Thread;
if (thread == null)
{
thread = new Thread(new ParameterizedThreadStart(this.A));
thread.IsBackground = true;
thread.Start((object) Thread.CurrentThread);
this.a = this.A(MethodBase.GetCurrentMethod());
this.a.Set();
Thread.Sleep(500);
}
while (!this.A)
{
if (Debugger.IsAttached || Debugger.IsLogging())
this.a();
if (!thread.IsAlive)
this.a();
Thread.Sleep(1000);
}
lock (D.B)
{
if (--this.B != 0)
return;
this.B.WaitOne();
this.A.A.WaitOne();
this.A.Set();
}
}
catch (Exception ex)
{
}
}

private int A([In] MethodBase obj0)
{
byte[] ilAsByteArray = obj0.GetMethodBody().GetILAsByteArray();
int num1 = 0;
foreach (byte num2 in ilAsByteArray)
num1 += (int) num2;
return num1;
}

protected void C()
{
this.A.Add((object) new G((object) OpCodes.Ldarg_1, (object) null, (object) .G()));
this.A.Add((object) new G((object) OpCodes.Ldloc_0, (object) null, (object) .g()));
this.A.Add((object) new G((object) OpCodes.Ldloc_2, (object) null, (object) .H()));
this.A.Add((object) new G((object) OpCodes.Ldarg_0, (object) null, (object) .h()));
this.A.Add((object) new G((object) OpCodes.Nop, (object) null, (object) .I()));
this.A.Add((object) new G((object) OpCodes.Ldloc_2, (object) null, (object) .i()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_1, (object) null, (object) .J()));
this.A.Add((object) new G((object) OpCodes.Add, (object) null, (object) .j()));
this.A.Add((object) new G((object) OpCodes.Stloc_2, (object) null, (object) .K()));
this.A.Add((object) new G((object) OpCodes.Ldlen, (object) null, (object) .k()));
this.A.Add((object) new G((object) OpCodes.Conv_I4, (object) null, (object) .L()));
this.A.Add((object) new G((object) OpCodes.Nop, (object) null, (object) .l()));
this.A.Add((object) new G((object) OpCodes.Ldarg_0, (object) null, (object) .M()));
this.A.Add((object) new G((object) OpCodes.Ldloc_2, (object) null, (object) .m()));
this.A.Add((object) new G((object) OpCodes.Ldelem_U1, (object) null, (object) .N()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_0, (object) null, (object) .n()));
this.A.Add((object) new G((object) OpCodes.Stloc_3, (object) null, (object) .O()));
this.A.Add((object) new G((object) OpCodes.Ldloc_1, (object) null, (object) .o()));
this.A.Add((object) new G((object) OpCodes.Ldloc_0, (object) null, (object) .P()));
this.A.Add((object) new G((object) OpCodes.Sub, (object) null, (object) .p()));
this.A.Add((object) new G((object) OpCodes.Add, (object) null, (object) .Q()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_0, (object) null, (object) .q()));
this.A.Add((object) new G((object) OpCodes.Stloc_0, (object) null, (object) .R()));
this.A.Add((object) new G((object) OpCodes.Stloc_0, (object) null, (object) .r()));
this.A.Add((object) new G((object) OpCodes.Ldloc_0, (object) null, (object) .S()));
this.A.Add((object) new G((object) OpCodes.Ldarg_1, (object) null, (object) .s()));
this.A.Add((object) new G((object) OpCodes.Ldlen, (object) null, (object) .T()));
this.A.Add((object) new G((object) OpCodes.Conv_I4, (object) null, (object) .t()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_1, (object) null, (object) .U()));
this.A.Add((object) new G((object) OpCodes.Sub, (object) null, (object) .u()));
this.A.Add((object) new G((object) OpCodes.Ceq, (object) null, (object) .V()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_0, (object) null, (object) .v()));
this.A.Add((object) new G((object) OpCodes.Ceq, (object) null, (object) .W()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_1, (object) null, (object) .w()));
this.A.Add((object) new G((object) OpCodes.Stloc_3, (object) null, (object) .X()));
this.A.Add((object) new G((object) OpCodes.Stloc_S, (object) 4, (object) .x()));
this.A.Add((object) new G((object) OpCodes.Ldloc_S, (object) 4, (object) .Y()));
this.A.Add((object) new G((object) OpCodes.Clt, (object) null, (object) .y()));
this.A.Add((object) new G((object) OpCodes.Stloc_S, (object) 4, (object) .Z()));
this.A.Add((object) new G((object) OpCodes.Ldloc_S, (object) 4, (object) .z()));
this.A.Add((object) new G((object) OpCodes.Ldelem_U1, (object) null, (object) .aA()));
this.A.Add((object) new G((object) OpCodes.Ceq, (object) null, (object) .aa()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_0, (object) null, (object) .aB()));
this.A.Add((object) new G((object) OpCodes.Ceq, (object) null, (object) .ab()));
this.A.Add((object) new G((object) OpCodes.Nop, (object) null, (object) .aC()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_0, (object) null, (object) .ac()));
this.A.Add((object) new G((object) OpCodes.Stloc_0, (object) null, (object) .aD()));
this.A.Add((object) new G((object) OpCodes.Stloc_1, (object) null, (object) .ad()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_0, (object) null, (object) .aE()));
this.A.Add((object) new G((object) OpCodes.Stloc_2, (object) null, (object) .ae()));
this.A.Add((object) new G((object) OpCodes.Stloc_S, (object) 4, (object) .aF()));
this.A.Add((object) new G((object) OpCodes.Nop, (object) null, (object) .af()));
this.A.Add((object) new G((object) OpCodes.Ldloc_S, (object) 4, (object) .aG()));
this.A.Add((object) new G((object) OpCodes.Nop, (object) null, (object) .ag()));
this.b();
this.A.Add((object) new G((object) OpCodes.Ldloc_0, (object) null, (object) .aH()));
this.A.Add((object) new G((object) OpCodes.Ldc_I4_1, (object) null, (object) .ah()));
}

protected void c()
{
this.A = new DynamicMethod(.aI(), typeof (bool), new Type[2]
{
typeof (byte[]),
typeof (byte[])
}, typeof (D).Module);
ILGenerator ilGenerator = this.A.GetILGenerator();
ilGenerator.DeclareLocal(typeof (int), true);
ilGenerator.DeclareLocal(typeof (int), true);
ilGenerator.DeclareLocal(typeof (int), true);
ilGenerator.DeclareLocal(typeof (bool), true);
ilGenerator.DeclareLocal(typeof (bool), true);
Label label1 = ilGenerator.DefineLabel();
Label label2 = ilGenerator.DefineLabel();
Label label3 = ilGenerator.DefineLabel();
Label label4 = ilGenerator.DefineLabel();
Label label5 = ilGenerator.DefineLabel();
Label label6 = ilGenerator.DefineLabel();
this.A.Add((object) new G((object) OpCodes.Brtrue_S, (object) label2, (object) .ai()));
this.A.Add((object) new G((object) OpCodes.Br_S, (object) label1, (object) .aJ()));
this.A.Add((object) new G((object) label6, (object) null, (object) .aj()));
this.A.Add((object) new G((object) OpCodes.Brtrue_S, (object) label3, (object) .aK()));
this.A.Add((object) new G((object) OpCodes.Br_S, (object) label4, (object) .ak()));
this.A.Add((object) new G((object) label3, (object) null, (object) .aL()));
this.A.Add((object) new G((object) OpCodes.Br_S, (object) label5, (object) .al()));
this.A.Add((object) new G((object) label2, (object) null, (object) .aM()));
this.A.Add((object) new G((object) label5, (object) null, (object) .am()));
this.A.Add((object) new G((object) label1, (object) null, (object) .aN()));
this.A.Add((object) new G((object) OpCodes.Brtrue_S, (object) label6, (object) .an()));
this.A.Add((object) new G((object) OpCodes.Br_S, (object) label4, (object) .aO()));
this.A.Add((object) new G((object) label4, (object) null, (object) .ao()));
this.A.Add((object) new G((object) OpCodes.Ldloc_3, (object) null, (object) .aP()));
this.A.Add((object) new G((object) OpCodes.Xor, (object) null, (object) .ap()));
this.A.Add((object) new G((object) OpCodes.Ret, (object) null, (object) .aQ()));
this.A.Sort();
foreach (G g in this.A)
{
if (g.A is OpCode)
{
if (g.a != null)
{
if (g.a is byte)
ilGenerator.Emit((OpCode) g.A, (byte) g.a);
else if (g.a is int)
{
ilGenerator.Emit((OpCode) g.A, (int) g.a);
}
else
{
if (!(g.a is Label))
throw new Exception(.aq());
ilGenerator.Emit((OpCode) g.A, (Label) g.a);
}
}
else
ilGenerator.Emit((OpCode) g.A);
}
else if (g.A is Label)
ilGenerator.MarkLabel((Label) g.A);
}
this.A = (D.e<bool, byte[], byte[]>) this.A.CreateDelegate(typeof (D.e<bool, byte[], byte[]>));
}

To make analyzing this Easter Egg a challenge, these methods are generating MSIL opcodes on the fly and in a “randomish” order.  Note the this.A.Sort() after all those this.A.Add(…) statements.  To better understand what is going on, we will need to run it in Reflector’s Visual Studio debugger plugin.  But first we will have to deal with:

dotNet_anti_debugging

Its checking if we are running the Easter Egg program in a debugger or if we are running any logging tools, if so the program basically does nothing.  So I used Reflector to edit out that snippet, “re-compile” it and set a break point after the this.A.Sort() routine.  Then I dumped out the IL (Intermediate Language) evaluation stack and here is what I got (I put in the comments):

L_000000000: Nop
L_000000010: Ldc.I4.0
L_000000020: Stloc.0
L_000000030: Ldc.I4,88 	//Load value 88 
L_000000031: Ldc.I4,254 //Load value 254 
L_000000032: Xor  	// Xor: 88 xor 254 = 166
L_000000080: Stloc.1	// store the value 166
L_000000090: Ldc.I4.0
L_0000000A0: Stloc.2
L_0000000B0: br.s label
L_0000000CF: label6
L_0000000D0: Nop
L_0000000E0: Ldarg.0	//Load the byte[] array
L_0000000F0: Ldloc.2 	//Load local2 
L_000000100: Ldelem.U1	//Take one byte from byte[] array with index at 
			//local2
L_000000110: Ldloc.1 	//
L_000000120: Ldloc.0
L_000000130: Sub	//local1 - local2
L_000000140: xor	//(local1 - local2) Xor byte[]
L_000000150: Ldarg.1
L_000000160: Ldloc.0
L_000000170: Ldelem.U1
L_000000180: Ceq
L_0000001A0: Ldc.I4.0
L_0000001B0: Ceq
L_0000001D0: Stloc.S,4
L_0000001F0: Ldloc.S,4
L_000000210: brtrue.s label2
L_000000230: Nop
L_000000240: ldloc.0
L_000000250: ldc.i4.1
L_000000260: Add
L_000000270: Stloc.0
L_000000280: Ldloc.0
L_000000290: Ldarg.1
L_0000002A0: Ldlen
L_0000002B0: Conv.I4
L_0000002C0: Ldc.I4.1
L_0000002D0: Sub
L_0000002E0: Ceq
L_000000300: Ldc.I4.0
L_000000310: Ceq
L_000000330: Stloc.S,4
L_000000350: Ldloc.S,4
L_000000370: brtrue.s label3
L_000000390: Ldc_I4.1
L_0000003A0: Stloc.3
L_0000003B0: Br.s label4
L_0000003CF: label3
L_0000003D0: Nop
L_0000003E0: br.s label5
L_0000003FF: label2
L_000000400: Ldc_I4.0
L_000000410: Stloc.0
L_000000420: Nop
L_000000430: Ldloc.2
L_000000440: Ldc_I4.1
L_000000450: Add
L_000000460: Stloc.2
L_000000470: Ldloc.2
L_000000480: Ldarg.0
L_000000490: Ldlen
L_0000004A0: Conv.I4
L_00000041F: label5
L_00000046F: label
L_0000004B0: Clt
L_0000004D0: Stloc_S,4
L_0000004F0: Ldloc_S,4
L_000000510: brtrue.s label6
L_000000530: Ldc_I4_0
L_000000540: Stloc_3
L_000000550: br.s label4
L_00000056F: label4
L_000000570: ldloc.3
L_000000580: Ret

It looks like this is part of a decryption routine.  In C, it would look something like:

for(int i = 0; i < byteArray.length; i++)
{
    byteArray[i] = (byteArray[i] ^ (166 - i));
}

And what is the byte array? If we examine the original obfuscated start of our routine, we see that there is one byteArray passed in as an argument:

byte_array_screen_shot

and the only byte[] member in Class D contains:

byte_array_contents

which if you run in our psuedo decryption algorithm above, transforms those numbers in the byte array to the ASCII codes that produces the string:

/ download/bmV4dF9maWxl/cGEkJHdk.txt

That looks like a URL. Now this is starting to make sense! In the following:

enumerating_windows_screenshot

My guess is that the above chunk enumerates searching for Internet Explorer and sends the decrypted URL.  If we append our decrypted URL to ESET’s URL:

http://www.joineset.com/download/bmV4dF9maWxl/cGEkJHdk.txt

then click on the link, the site contains:

Jules:You read the bible, Ringo?

So this must be the password that our MALCHO.DLL must retrieve for us to use as the decryption key to the second BMP resource. So now its off to Visual Studio to create a simple MALCHO.DLL:

malcho_dll_code

It simply returns the password as a string.  Also I changed the function name since the base64 encoded name had an equals sign in it.  At first I used the base64 name but the compiler freaked out.  I forgot that you can’t use an ‘=’ in variable names or function names.  The ‘=’ sign is an assignment operator and it confuses the compiler.  So after we load our MALCHO.DLL, we can simply change the function name to getPassord in OllyDbg before we allow the program to call GetProcAddress:

loading_malcho_dll

changing_malcho_function_name

And it loaded!

getPassword_worked

Continuing to step through the program:

gets_decrypts_resource_133

crack_me_2 has now extracted and decrypt the resource 133 BMP and is going to drop it as 2B0.tmp.  I let the Olly run the program to completion and grabbed our new file.  I tried changing the extension to .exe to run it but that did not work.  I tried loading it in PE Explorer but it told me that 2B0 was not a legitimate PE file so I loaded 2B0 into HexWorkshop:

2B0_tmp_is_a_java_class_file

I recognized the magic bytes: CAFEBABE.  This is a java class file.  A java class file called Bible.  And you can see the print statement strings containing the most famous quote in the movie Pulp Fiction:

all_easter_eggs_found

So it seems that we have found all the Easter eggs.  Is that all there is?  I don’t know for sure.  There are still parts of the crack_me_2 code that I have not examined in complete detail.  I did see calls to some registry querying and other registry functions.  Additionally, I found some other anti-debugging checks later in the code, and some of the code doesn’t disassemble correctly; Olly thinks its a bunch of character bytes.  If there is nothing more than why would someone go to all the bother of calling Windows registry functions, add and occlude more code if not to have it do something.  I speak from experience that programmers are generally lazy.  I don’t mean that as a derogatory remark.  Programmers purposely do not add any functionality to a program that will never be used.  Suffice it to say, there may be more to this saga.  After all, I have not tried to put any other Pulp Fiction quotes other than “I did it!” in the second textbox of the starting dialog box.  We could attempt to try all possible Pulp Fiction quotes but there are a lot of them and I could spend the rest of my natural life trying them all.  And since I am lazy I am not going to do that.

Whenever I have some spare time, I will continue to poke around.  If I find anything new, I will post those results here.

ESET Challenge Part 3

18 Saturday Jan 2014

Posted by Eric Hokanson in Malware RE

≈ 2 Comments

Tags

ESET CrakMe 2013 Challenge, Malware Reverse Engineering

My continuing saga tackling the ESET 2013 challenge

In part one and part two, we unpacked and coaxed the ESET CrackMe 1 puzzle into revealing its hidden messages, which led us to a second puzzle called crack_me_2.zip.

crack_me_2.zip is an actual executable because you can see the ‘MZ’ header in a hex editor.  If we examine the sample using the strings command:

crack_me_2_strings

We can see it is packed.  Claims to be UPX but is it?  According to PEiD, it claims “Nothing Found” but there is some overlay.

crack_me_2_peid

Using PEiD’s extra information plug-in, we can examine the EP and the Entropy of the code section.  Entropy is pretty high, indicating that this sample is packed with something.  It turns out, that you can use the same unpacking technique that we did in part one.  However, I needed to use LordPE to rebuild the unpacked and repaired crack_me_2 sample to get it to run.  When the unpacking process was done and we run our unpacked sample we get:

crack_me_diagog_greyedtextbox

Note that the text boxes for Stage 1 and Stage 2 are greyed out.  I can not enter any text in them, nor can I click on any of the “check” buttons.  The only thing I can click on is the red X button in the upper right hand corner of the CrackMe dialog box.

This perplexed me for a while.  I wasn’t sure if I unpacked this sample correctly so I executed the packed crack_me_2.zip and got the same dialog box as above with the inactive text boxes and check buttons.  Perhaps examining the code in OllyDbg will yeild insights into how I might activate the text boxes:

crack_me_2_first_dialog_box_clue

I couldn’t find any sign of how to activate the text boxes but I did find clues as to what to put in the text boxes.  In the above screen shot, you will observe that we should enter the text: “Pigs are filthy animals”.  When we hit the check button, it compares our entry with String2 and if they match, it activates the next text box.

crack_me_2_second_dialogbox_clue

As you can see above, the second text box clue is obsured.  That ASCII string “SSBkaWQgaXQh” looks like a base64 encoding.  We can test this by entering that string in a tool called base64 encoder/decoder (my version is older so it looks different than the one at the link):

crack_me_2_second_textbox_clue

Lucky guess.  I wasn’t sure it was base64 because this encoding did not have the tell tale ‘==’ at the end of the string.  We know what to enter in the text boxes but I still haven’t found any clues as to how to enable these text boxes.

I was still stumped after a few hours.  I decided to try the crack_me_2 sample on my old Windows XP laptop and you know something?  It worked!  The first text box was enabled and I could enter text.  Next I tried the sample on a Windows 7 machine and that, too worked.   Stage 1’s text box was enabled.  I suddenly realized that the difference between those machines and my analysis machine, was that my analysis platform was running inside VMWare.  This sample wouldn’t be VM aware would it and try some anti-VM tricks?  So I found this white paper from SANS on Thwarting VM analysis.  Then I set to searching for OP Codes in Olly that looked for a VM presence.

For example, I thought I would start with a simple anti-VM trick outlined in that SANS paper:

MOV EAX,564D5868 <--"VMXh"
MOV EBX,0
MOV ECX,0A
MOV EDX,5658 <-- "VX"
IN EAX,DX <-- Check for VMWare
CMP EBX,564D5868

I used Olly’s search trying the first MOV instruction.  No hits.  Then I tried the second instruction.  No hits.  It wasn’t until the last instruction, the CMP instruction that I got a hit:

crack_me_2_anti_vm1

By the way, the hexidecimal 0x564D5868 in ASCII is: “VMXh”.  You can see the CMP instruction but not the others.  But you do notice the CHARs VX and VMXh just above the CMP instruction.  It appears that this sample has some anti-disassemble techniques that fool Olly’s ability, in selected parts of the code, to distinguish between data bytes and actual OP codes.  To be sure and avoid the anti-debugging tricks, I activated the Advanced Olly plug in to hide itself from these anti-debugging techniques.

We can highlight these so called data bytes and then right-click, select Analyze, and then Remove Analysis from Selection:

crack_me_2_anti_vm2

By removing Olly’s analysis, the code is revealed and it looks just like one of the tricks mentioned in the SANS white paper.  If we highlight the top instruction and hit F4 (Run to here), then single step past the MOV EAX, 564D5868, we can simply change EAX to something else — like 0.  When we do that:

crack_me_textboxes_work_on_vm

It works!  Well almost.  After entering the correct text we get a “Nope you didn’t” notice.  If you click the OK button, the program just sits there until you hit the red X button and terminate the program.  Argh!  All that work… well, that is the life of a malware analyst.  We will often go after something interesting only to discover that it may lead us astray.  We are going to have to search the code and look for something else of interest.

When you first load crack_me_2 into Olly, it stops at this starting point:

crack_me_2_named_pipe

This program calls CreateFileW and looks for a named pipe called Vincent_Vega.  Since there is no pipe server by that name running, CreateFileW will return a -1.  So I set a break point on CreateFileW and hit F9 to run the program.  When the execution stopped at CreateFileW, I noticed in the stack trace something about a 990.tmp file.crack_me_2_create_990_tmp_file

Looks like this thing will create a .tmp file in my Local Settings\Temp directory.  By the way, each run of crack_me_2 will create a different named .tmp file.  Usually, the names are simple like 2C.tmp, 4C.tmp, etc.  Upon this running, it is calling mine 990.tmp:

crack_me_2_going_to_create_990_tmp_file

This program is going to create a 990.tmp file.  Earlier in the code, I noticed some function calls for getting resources.  If we examine crack_me_2 in PExplorer:

crack_me_2_resources_BMPs

We can see that crack_me_2 has two bitmap resources.  What do you bet that these resources are something MORE than bitmap files?

crack_me_2_going_to_create_990_tmp_file

At 0x404983, we see this function is going to take the resource bitmap ID 0x83 = 131 in decimal, and decrypt it with the key: “T2ggbWFuLEkgc2hvdCBNYXJ2aW4gaW4gdGhlIGZhY2U=”
That looks like base64 encoding:crack_me_2_decryption_key_for_990_tmp

And yes it is!  By the way, I am starting to detect a theme here.  The named pipe is “Vincent Vega” a character played by John Travolta in the film “Pulp Fiction“.  The phrase we put in the Stage 1 text box: “Pigs are filthy animals” is a quote from one of the scenes when Vince asked Jules (played by Samuel L Jackson) if he wanted some bacon.  The key to decrypt our 990.tmp file is another quote from the movie.

If we continue to let this run and let it drop the 990.tmp file, then open it in a hex editor we see that it is supposedly an executable (has an MZ header).  Next, I renamed 990.tmp to 990.exe and double click on it, I discovered that it is a .NET executable because I was told to install .NET Framework 4 in order to run it.  Once that was done:

crack_me_2_dotnet_easteregg

How cute.  Ok, maybe it was a bitmap resource.  However, the picture of a bunny rabbit and a little Easter egg icon in the upper left corner suggests its time to go on an Easter egg hunt.  This .NET file may do more than just display a cute picture.  There is just one small challenge ahead for me: I am pretty weak with reversing .NET executable files in that I have, until today, zero experience.  I am going to have to do some research.

But first, I tried disassembling the Easter egg in IDA Pro and it can handle .NET files, however, it looked gibberish.  No strings to examine and weird function names.  Soon, I discovered that there are open source .NET decompilers like ILSpy.

crack_me_2_dotnet_decompiled

I am not sure how to make heads or tails of the above.  Class names of a, A, b, B, c, etc.  Variable names were not much help either.  However, just by happen chance, I decompiled the class a() and the result is in the left panel above.  This looks like something that sets up a pipe server named Vincent Vega.  My guess is that if we run this .NET Easter egg, it creates the named pipe that our crack_me_2 file was looking for.  The next step, then, is to run this Easter egg and re-run crack_me_2 to see what messages may be passed through this pipe.  I will also need to analyze this Easter egg .NET file further for clues as to where to take my analysis.  I am unsure yet so I have some studying to do.  The challenge continues…

Subscribe

  • Entries (RSS)
  • Comments (RSS)

Archives

  • May 2016
  • May 2015
  • April 2015
  • March 2015
  • September 2014
  • August 2014
  • June 2014
  • May 2014
  • April 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • November 2013

Categories

  • Alan Turing
  • Algorithms
  • Apollo 17
  • C Programming
  • Christmas
  • Computer Programming
  • Computer Science
  • Computer Security
  • Current Events
  • Cyber Security Research
  • Education
  • Freedom of choice
  • Freewill
  • Hacking
  • Holidaze
  • Learning
  • Malware RE
  • Math
  • NASA
  • Pen-testing
  • Philosophy
  • Pi Day
  • procrastination
  • Programming
  • Python
  • Quine programs
  • Quotes
  • Random Stuff
  • Research
  • Reverse Engineering
  • Shopping
  • Smithsonian National Air and Space Museum
  • Software Development
  • Star Wars
  • Success
  • Uncategorized

Meta

  • Register
  • Log in

Blog at WordPress.com.

  • Follow Following
    • Eric Hokanson
    • Join 44 other followers
    • Already have a WordPress.com account? Log in now.
    • Eric Hokanson
    • Customize
    • Follow Following
    • Sign up
    • Log in
    • Report this content
    • View site in Reader
    • Manage subscriptions
    • Collapse this bar
 

Loading Comments...