• About Me
  • Blog
  • Home

Eric Hokanson

~ E's little space in cyberspace

Eric Hokanson

Category Archives: Cyber Security Research

ESET CrackMe 2013 Challenge Solved!

18 Tuesday Feb 2014

Posted by Eric Hokanson in Cyber Security Research, Malware RE

≈ Leave a comment

Tags

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

my continuing adventures in reversing the eset 2013 crackme challenge…

In my last post, we found all the Easter eggs and set off looking for the solution to unlock this puzzle.  This is a challenge from an anti-malware company, so there should a “malicious-like” component to this puzzle and started examining other threads that were spawned before the WinMain function that displays the textboxes began.  We did find an interesting path, a path that led us to the process injection of Window’s userinit.exe.  That was our “malicious-like” behavior and when we traced the code to the CreateRemoteThread call:

Call_to_createRemoteThread

And stepped over that call (F8), we could observe our CrackMe code launching the newly injected userinit process:

userinit_in_task_mgruserinit_in_procmon

Unfortunately, the process goes immediately into a suspended state, which prevents OllyDbg from attaching to it.  After several failed attempts of trying to find a solution, I posed the question to the community for some help.  My thanks to the many members Reverse Engineering and Malware Group on LinkedIn for their suggestions.  The solution that worked was submitted by Mr. Mahmoudnia — he found another person’s solution to this ESET challenge.  The solution is rather clever.  Before we hit the second call to WriteProcessMemory:

before_2nd_call_to_WriteProcessMemory_0x403E70

Which is going to write the code at location 0x403E70 into userinit’s process space at 0xA0000.  We want to go to 0x403E70 and change the function prologue from “PUSH EBP” and “MOV EBP, ESP” to the opcode “EB FE”:

at_0x403E70

In Olly, right-click on the “PUSH EBP” instruction, select binary, then edit and uncheck the “keep size” box; now you can change the opcode to the value “EB FE”:

at_0x403E70_changed_to_EBFE

The opcode “EB FE” creates an infinite jump to the start of this function, i.e. to address 0x403E70.  Now we can step over the “WriteProcessMemoryCall” and proceed to step to the “CreateRemoteThread” call.  Now hit F8 to step over CreateRemoteThread and stay at location 0x4063B6:

step_over_call_to_CreateRemoteThread

Next, open a second OllyDbg instance, go to File -> Attach and scroll down the list of process until you find userinit.exe and click the “Attach” button:

attaching_to_userinit

Once attached and in the CPU window hit CTL-G and go to address 0xA0000 and change the “EB FE” back to the “PUSH EBP” and “MOV EBP, ESP” function prologue and set a break point.  This may take several attempts.  What consistently worked for me was to go to the theads window (the blue T button) and check to see if my thread was suspended.  If it was, I right clicked on the thread and selected “Resume”, then I hit F9 (Run).  If the RE gods are smiling upon us, we will hit the BP:

attached_to_userinit_goto_A0000

To see what the above routine does, I am going to single-step through this code line-by-line:

in_0xA0000_after_keygen_func

A little ways down, there is a call to a function at 0xA02F0.  I stepped inside that function and determined that this was some kind of key generation function.  Observe that ESI was set to the ASCII string “472631FB”.  Continuing on:

in_0xA0000_setting_up_Http_wget_over_port_1F90=8080

In the above chunk of code, we are making a call to a function in wininet.dll,  I used DLL Export Viewer to resolve the symbol name.  This is setting up a http network connection to localhost on port (highlighted as 0x1F90 in the stack window) 8080.  In my last post, we observed a wget POST call posting an index.php.  Continuing on, we can observe that this section of code is setting up all the parameters for an HttpOpenRequest call:

in_0xA0000_setting_up_HttpOpenRequest_index_php

Again, I fired up FakeNet and stepped over the call:

in_0xA0000_sends_index_php_over_port_8080

The wget POST with index.php is supposed to receive data but as you can clearly see, we don’t because EAX is set to 0.  The next instruction will test EAX and since it is 0, we will jump all the way down to 0xA0296.  At that location, there is code to terminate our thread.  I don’t want to end just yet.  There is an awful lot of code real estate that we are skipping and I want to see what it does.  So, I changed EAX from 0 to 1 so that the JE instruction is NOT taken in order to see what happens next:

in_0xA0000_compare_to_jules

In the above screen shot, we can see that what ever we were supposed to receive from our first wget POST is supposed to decrypt to the value of “Jules” — one of the main character’s (played by Samuel L. Jackson) in the movie “Pulp Fiction”.  So our Pulp Fiction theme continues.  Since we did not receive any data, the zero flag is not set and we make that long jump to 0xA0296 again.  So I set the ZF to 1 so the JNZ instruction is not taken.  Continuing on:

in_0xA0000_second_call_with_index_php

The code continues to set up a second HttpOpenRequest call.  This time instead of passing just index.php as one of the parameters, I thought I would change it to “index.php?key=280877F8”  This was the key that was generated in our first wget POST call.  I don’t know why I thought to try this, I was just curious and assumed that since we were getting a key, that there would be a second decryption routine.  Maybe I could coax the code to decrypted what ever is going to happen next…

in_0xA0000_second_call_index_php2

So we make the second wget POST call and and continue on to what I believe to be is a decryption routine…

in_0xA0000_decrypted_message_thats_all_congrats

Interesting!  We did get a message: “That’s all. Congratulations!”  We must be getting close to solving this thing.  So if we continue to single-step our way through this routine, eventually we wend our way to a USER32.MessageBox call:

in_0xA0000_call_to_final_messagebox

Let’s step over that call and see what message we get…

I_cracked_it_the_movie_is_over

W00t w00t — we did it!

This was a very fun RE challenge.  My thanks to ESET for creating such a fun puzzle and a special thanks to Mr. Mahmoudnia and others in the Reverse Engineering and Malware Research group on LinkedIn for their help and suggestions during the times I got stuck.  I learned some new tricks like that “EB FE” trick to attach to a suspended process.  I’ll have to remember that one if I ever encounter such a sneaky maneuver by malware in the future.

ESET Challenge Part 5

02 Sunday Feb 2014

Posted by Eric Hokanson in Cyber Security Research, Malware RE

≈ 1 Comment

Tags

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

In my last post we found all the Easter Eggs.  Each egg was another quote from the movie Pulp Fiction and when we found the most famous quote from the film:

all_easter_eggs_found

we knew we found all the eggs.

At the end of our hunt, I wondered if there might be more to this challenge.  There was a lot more code that I haven’t even analyzed yet and some of the code appeared obfuscated to hide its functionality.  And this is a crack me puzzle after all.  When we first discovered what to put in each stage box:

crack_me_textboxes_work_on_vm

we were alerted that we did not “do it.”  Since this challenge has an ongoing Pulp Fiction theme, and the Stage 2 text is not a quote from the movie, this may indicate that another Pulp Fiction quote might unlock the puzzle.  But which quote is the correct quote?  There are lots of memorable quotes from the film so a brute force approach is not likely practical.  Where to begin next?

After some thinking, I realized that the CrackMe text box above didn’t appear until the start (WinMain) function ran.  But, as we have seen in my previous posts, there is a lot of activity that happens before the start function runs.  There were several threads that ran before the main function.  I decided to put a break point on CreateThread and examine the corresponding call stack.  After setting the break point and hitting F9 to run, we encountered our first break:

first_BP_CreateThread

in the call stack window we can see the thread function starts at 0x404A60.  If we go to that address and put a break point there, we will be able to examine what that piece of code does.  But before I do that, I hit F9 (run) again to catch the next CreateThread call:

second_BP_CreateThread

this thread’s function starts at 0x404680.  If we go to that location:

threadfunct_404860_obfuscated

huh!  Olly is confused and is having a hard time analyzing this code; it thinks these are data bytes.  If we highlight all these data bytes to the nearest RETN instruction (at 0x404B1E), then right-click –> Analyze –> During next analysis, treat selection as –> Commands:

threadfunct_40486_revealed1

threadfunct_40486_revealed2

threadfunct_40486_revealed3

we can start to see that this is the part that sets up the named pipe server that we already analyzed in ESET CrackMe Challenge Part 3.  We can let this thread go; we already know what it does.

Lets return to the thread function from our CreateThread break at 0x405A60.

threadfunct_405A60_sleeps_until_textboxes_enabled

When this tread spawns, the process enters a sleep loop until the CrackMe text boxes are enabled and ready for input.  When that happens, the process sends us to a function at 0x405CD0.  So I put a break point at that function, let the program run (F9) and waited for a break to step into 0x405CD0.  Its a pretty big function but eventually we get to another CreateThread call:

threadfunct_405A6_takes_us_another_CreateThread_at_405D52

CreateThread_405D52_with_threadfunc_405CC0

this new thread has a function at 0x405CC0.  We set a break point at this new thread function to see what that does:

threadfunc_405CC0

it takes us to 0x405B10:

func_405B10

This is a huge function but the most interesting stuff happens here:

threadfunc_045CC0_with_textbox_proc_change

First, this function calls LoadLibrary and loads a number of user32.dll functions.  But as you can see in the Registers window, the function are not names but addresses (e.g., user32.7E41D60F).  This makes it harder for us to understand what is going on.  How can we resolve these address location calls in user32.dll to their actual function names?  There is a tool called DLL Export Viewer and it will load all of the Windows/System32 DLL’s mapping the addresses to function names.  I sorted on addresses and searched for what was being called at 0x405C7A and at 0x405C83:

DLL_Export_Viewer

In the example above, the CALL ESI is really a call to user32.7E41D60F, which is between the two addresses highlighted in the screen shot above.  So this call must be a call to a SetWindowLong function.  I did the same for the FindWindowsEx call that came before the SetWindowLong call.  After painstakingly stepping through this function and re-labeling all the user32.dll functions, I finally stumbled upon a key piece as illustrated in the following snippet of code:

Screen Shot 2014-02-01 at 5.54.04 PM

what this is doing is finding our CrackMe text box and setting the Stage 2 textbox to include this new procedure.  This means that the Stage 2 textbox will have two routines to check the input.  One will check for the “I did it!”, which will give us the “Nope. You didn’t!” dialog box, and the other checks for some other text — the correct text presumably.  We will need to set a break point at this new textbox procedure which is at:

new_textbox_proc_at_405F50

0x405F50

new_text_boxfunct_BP

Actually, through trial and error, I discovered that if we place a BP at 0x405F50, the CrackMe text boxes don’t finish rendering yet, and when you click on the CrackMe box, it breaks the program at 0x405F50.  I discovered that if we place a BP further down, say at 0x406023, the text box is fully rendered, and we can input text in the Stage 2 box, which will cause us to break at 0x406023.  If we do that, and place in any text other than the “I did it!”, we can trace this part of the code to try and figure out what the real message should be:

second_text_box_I_put_anything_to_hit_BP_at_406023

checks_my_imput_in_second_textbox_and_what_is_04041D0

We see that at 0x406023, ECX contains my bogus input and then a call is made to 0x4041D0.  What does that do?  If we go to 0x4041D0:

4041D0_is_obfuscated

Ack — we see that Olly hasn’t disassembled this piece correctly; it is fooled into believing that these are just data bytes.  So if we highlight all these data bytes until we get to the next RETN instruction (to 0x40429A), then right-click on the highlighted section, select Analysis –> During next analysis, treat selected as –> Commands:

4041D0_deobfuscated1

4041D0_deobfuscated2

The above two screen shots show the entire routine as supposedly correct commands.  This routine is rather complicated but my gut tells me that this is some kind of encryption routine.  I am rather lazy, so instead of analyzing the above mess, I am going to try and find an easier way by observing the behavior of stepping over this routine and see what the program does.  Back to our current breaking point:

comparing_my_imput_to_some_value_at_4227EC

when we return from the 0x4041D0 encryption routine, we note that some data at 0x4227EC is being loaded into a pointer to a data segment.  It looks like the program will compare that data with my encrypted input of “sfsf”.  If we follow 0x4227EC in the dump window (highlighted in grey in the bottom left window), we can see that this data looks encrypted.  Naturally, my input is not going to match whatever is in 0x4227EC:

comparison_not_same_back_to_new_textbox_proc

hence, the program will sit here waiting for the correct input from the Stage 2 textbox.  If we let the program resume (F9), we should be able to enter some other text into Stage 2.  It is likely that the encryption routine is symmetric since that is computationally cheaper than an asymmetric scheme.  To test my theory, I entered the word “cat” and hit the check button.  When we broke again, I stepped over the encryption routine and observed the encrypted result of “cat”.  I copied this encrypted “cat”, then resumed the program again (F9) and pasted the encrypted version of cat into the Stage 2 textbox and hit the check button to return to our current break point.  When I stepped over the encrypted routine again, I got back the word “cat”; this confirms my hunch.  So, we should be able to apply the same trick to the data at 0x4227EC.  Copy and paste that encrypted data into the Stage 2 textbox and let the program run again:

cut_and_paste_value_at_4227EC

cut_and_past_value_in_second_textbox

And…

Zed's_dead_baby1

Did you see it?  In the stack window??

Zed's_dead_baby2

“Zed’s dead, baby” — not only another quote from Pulp Fiction (uttered by Bruce Willis’ character Butch), but this must be the correct quote to unlock this puzzle!

After entering the correct input, it looks like the code will now take us to:

with_correct_input_we_goto_4060C0

0x4060C0:

base64_decoder_for_userinit

0x4060C0, like the previous thread routine, is loading a number of functions but this time from kernel32.dll; and like the previous thread, it is using address locations and not the names of the functions from kernel32.dll to hide the true functionality.  So again, I used the DLL Export Viewer tool to resolve the names.  We eventually come to an interesting part of the routine as observed in the above screen shot.  Another base64 encoded string.  The string is sent to the base64 decoder function and I already decoded it as noted above: it looks like this routine is going to do something with userinit.exe.  This must be the “malware” part of the CrackMe puzzle.  No legitimate program has any business hooking into userinit.exe; this is typical malware behavior.

Userinit, according to Microsoft, “Specifies the programs that Winlogon runs when a user logs on. By default, Winlogon runs Userinit.exe, which runs logon scripts, reestablishes network connections, and then starts Explorer.exe, the Windows user interface.”  Let us see what CrackMe intends to do with userinit:

allocating_new_memory_in_userinit_at_0x90000

at 0x406348, we see that in EAX, new memory was allocated in userinit.exe’s process space at address 0x90000.  This is writing some sort of data, I presume.  Then…

allocating_new_memory_in_userinit_at_0x0A0000

at 0x406380, more memory is allocated in userinit.exe’s process space at location 0xA0000.  Continuing a little further…

Call_to_createRemoteThread

we observe a call to CreateRemoteThread with EAX = 0xA0000.  So what was written at 0xA0000 must be code because CreateRemoteThread creates a thread that runs in the virtual address space of another process.

Before stepping over the CreateRemoteThread, I fired up FakeNet and ProcMon tools to capture any events that might happen:

after_stepping_over_CreateRemoteThread_a_post_index_php

this new process used wget to post an index.php on port 8080 localhost.  That is interesting, but here is where my trail (or thread) goes cold.  When I look for this process, I can not find it.  I don’t see this new process spawned by CreateRemoteThread listed in the active processes in OllyDbg even though it is clearly running somewhere:

crack_me_launches_userinit_and_is_running

There is a PID of 2276 but I don’t even see it in Process Explorer or the task manager.  This leaves me somewhat stumped as to how I can attach to this new process.  If I can find it, and attach, then I might be able to figure out what to do next.  I invite the community to share any hints or tips as to how I might attempt to locate this process.  I am so close to solving this thing — I can feel it.  I would expect that the patched userinit is supposed to generate my next dialog box after entering the correct quote, “Zed’s dead, baby” in the Stage 2 textbox.  But it must be missing a key piece to finish the job.  What was sent to localhost?

index_php_post

it looks like there is a key of some kind.  My guess is index.php must somehow use the code injected into userinit.exe at 0xA0000 to decrypt the data at 0x90000 (???) but I won’t know this for sure until I figure out how to find and attach to the process spawned at 0xA0000.

I will keep playing with it to see if I can figure it out.  If I come up with anything new, I will be sure to post those results here.  Stay tuned…

EDIT TO ADD February 18, 2014:  After several debug sessions, I did manage to find the userinit process in Windows Task Manager and Sysinternal’s Process Explorer.

userinit_in_task_mgruserinit_in_procmon

However, I still can not locate the userinit thread in OllyDbg to attach to it.  The problem seems to be that when the thread is spawned, it immediately goes into a suspended state, which would explain why I can’t find it in Olly’s active process window.  Hmmmmmm….  I will keep trying…

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.

A Malware Analyst’s Bookshelf

02 Thursday Jan 2014

Posted by Eric Hokanson in Computer Security, Cyber Security Research, Malware RE

≈ 2 Comments

Tags

Gary McGraw, Greg Hoglund, Malware, Malware Analysis, Malware Analysis Sources, Microsoft Windows, OllyDbg, Reverse Engineering, Static program analysis

I am often asked by those wishing to pursue a career as a malware analysit, what references are useful in learning, or the continued learning of the art and craft of malware analysis?  Here is a list of resources that I find useful:

1.  The Art of Computer Virus Research and Defense by Peter Szor (TAOCVRD).  This is the book that introduced me to malware research.  It could use some updating, but sadly, the author recently passed away.  On the other hand, with the popularity of Android malware, what is old is new again.  Many Android malware samples are doing what the old Windows malware used to do in the early days.

TAOCVRD covers different malware types, and the armoring, self-protection strategies they employ, the common detection techniques, and the last chapter is a useful guide in setting up your own malware analysis lab.  Again, a bit outdated because many of the tools we use today were not widely available back when this book was originally published.  However, many of the analysis techniques are still relevant today.

2.  Practical Malware Analysis by Michael Sikorski and Andrew Honig (PMA).  An introductory tour of malware analysis and reverse engineering techniques.  The hands-on labs reinforce the skills covered in each chapter.  Each lab has a set of  “malware” like samples (download from the book’s website).  Introductory chapters cover x86 assembly and the common instructions you will encounter, as well as how to use common tools, such as OllyDbg, and IDA Pro.

3.  One of the most powerful tool for static analysis, that I mentioned in (2), is IDA Pro.  But it has a steep learning curve.  The IDA Pro Book by Chris Eagle is about the only practical users guide available.  Whenever I need to learn something new in IDA, or how to write a plugin, I consult this book.

4.  Exploiting Software: How to Break Code by Greg Hoglund and Gary McGraw.  This book shows the common software programming errors and exploitation patterns.  Usually, I will start looking for these patterns in the malware samples I am analyzing to help guide my investigations; knowing these patterns can reveal what the malware may be targeting.

5.  Reversing: Secrets of Reverse Engineering by Eldad Eilam.  This too is a little outdated, but it is the best introduction into the art of RE that I have found so far.  It covers the common tools used, the basics of assembly and x86 architecture, basic Windows internals, and even has a chapter on reversing malware.

This list is by no means exhaustive.  I am sure I am overlooking other good sources and would be happy to hear what other analysts routinely consult.  I am always looking to expand my library.

related articles
  • How To Get Started with Malware Analysis.
  • An Overview of Becoming a Malware Analyst.

Holy 1984 Batman!

01 Sunday Dec 2013

Posted by Eric Hokanson in Computer Security, Cyber Security Research, Hacking

≈ Leave a comment

Tags

George Orwell, Hacking, TV

I warned that hooking everything up to Internet was a bad idea years ago.  Your TV can now watch you!  Too bad you can’t break for commercial every 10 minutes like your TV does.  Here is another article on the subject.

This is what people can do with the new smart TV you are buying for Christmas.  I shudder to think what can be done to medical devices that talk over wireless networks.  I am not sure what can be done about the problem.  People love the convenience of controlling their home’s thermostat or security system remotely, from the Internet.  And the bad guys love the ease of convenience, too.  The “Internet of things” security is a hot growing research area so we will be reading a lot more about the problem.

to publish or not to publish

Often, I am confronted by people about publishing vulnerabilities.  “Why would you bring this to the attention of the hackers?”, they would say.  The truth is, if someone like me can find the problem, then any reasonably intelligent and curious person can also find the problem.  It is very likely, that there are others who are aware of the vulnerabilities and this would include the hacker community.  More of our appliances contain computer chips that run light-weight versions of the Linux operating system and open source software.  Anybody can get access to the source code, and all code contain bugs and vulnerabilities.  It doesn’t matter who wrote the software, or how smart they are, mistakes get made, and others will find those mistakes and exploit them if they can.

Other scientific professions have suffered from similar dilemmas.  Physicists working on the Manhattan project, for example, often had to come to terms with the prospects of advancing human knowledge and having that knowledge lead to human destruction.  Wasn’t there a story somewhere about Buddhist priest who once said: “The good news is: all humans possess the keys to heaven.  The bad news: that same keys also opens the gates of hell.”?

I believe it is better to publish the technical vulnerabilities; to be aware of them so that many bright minds can come together and fix the problems.  And it helps alert the defenders to look out for them.  I remember watching the “Super Friends” as a kid.  On one episode, Robin was complaining about the inherent dangers of scientific discoveries and how easy it can be for people like Lex Luthor to use them for evil.  Batman replied: “… Technology is neither good or evil.  It is the mind behind it that determines its use.”

And they say Batman has no real super powers.  He has a super intellect.  I know.  It’s not as sexy as having a chest you can bounce bullets off of.  Or a new smart TV that you can hook directly up to the Internet.

Why our Government will Never Solve the Cyber Security Problem

25 Monday Nov 2013

Posted by Eric Hokanson in Cyber Security Research

≈ 1 Comment

Tags

Computer security, Cyber Security, Government Funded Research, Information security, Intrusion detection system

One only needs to look at the healthcare.gov debacle as an example.  Software development of this scale needs agility; fast iterations to get all the ideas, both good and bad, on paper.  Everything form the user experience to how data will be stored, accessed, and verified must be hammered out on paper before coding begins.  But agility, as I can tell you from my own experience, rarely happens when a government (or any large, bureaucratic) entity is involved.  From the reports I have read, these poor developers did not get the go ahead to implement until March or April.  With an October deadline, that leaves very little time for rigorous testing of any software solution.  I am not defending the developers, they made missteps too, including not having the in-house capability to handle such a colossal technical task.  There is a lot of blame to go around.

Success is rarely determined by the quality of your ideas. But it is frequently determined by the quality of your execution.

Atwood (Coding Horror), Jeff (2012-07-04). Effective Programming: More Than Writing Code (p. 45). Hyperink – Guide to Effective Programming. Kindle Edition.

It has been my personal experience that if you give a great idea to a mediocre group of people, they will mess it up.  On the other hand, give a mediocre idea to a great team and they will not only make it happen — they will make it better.

Secondly, cyber security is hard problem.  Let me illustrate with a simple analogy: Think of cyber defense as a sphere of Swiss cheese, and this ball of cheese is as big and ever expanding as our universe.  The holes, also infinite, are all the possible vulnerabilities of the system.  There is a very small subset of holes (vulnerabilities) we know about and we can “fix” or plug them (actually, this is not always possible.  There are vulnerabilities that we do know of but no practical fix exists… yet).  We cannot possibly plug every hole.  Attackers only need to find one good hole, or maybe a small handful of holes, to compromise a system.  The defenders have to be vigilant everywhere all the time; its an asymmetric problem.  And I haven’t even addressed the case where an attacker, like a mouse, worms its way in making a new hole.

Now, I know what you must be thinking: “Ok smart guy.  What’s the answer?”  Frankly, I am not sure there is one or will ever be one.  Lots of very smart people in academia, government, and industry, have been working this problem since the beginning of this whole Internet phenomenon.  And all we have to show for it is a handful of anti-virus (AV) and intrusion detection systems (IDS).  Some products are more effective than others but they don’t catch everything.  Attackers still persist.  Becoming more sophisticated, more determined.

So, lots of bright people have tackled, are still tackling this problem, and still no solution.  There may never be a solution.  Does that mean we should curl up into a fetal position, sucking our thumbs while crying, “mommy”?  No!  This is what makes research so exciting.  How to turn the attacker’s asymmetric advantage against them?  There are many interesting research ideas proposed.  However, one thing is certain: we will never solve these problems if our government keeps acting they way it has been lately.

Governments will always play a huge part in solving big problems.  They set public policy and are uniquely able to provide the resources to make sure solutions reach everyone who needs them.  They also fund basic research, which is a crucial component of the innovation that improves life for everyone.”

Bill Gates

If congress seriously wants to “win the war on cyber-terrorism”, or prevent a “cyber-9-11” event, they must quit their sequestration/shutdown shenanigans.  There are organizations active in researching ways to defend our critical infrastructures but they are hamstrung by congress’ actions — er make that in-action.  It is hard to do your job when your representatives aren’t doing their jobs.

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...