Malware Reverse Engineering - TryHackMe

Basic Malware RE - “This room aims towards helping everyone learn about the basics of “Malware Reverse Engineering” This is a TryHackMe box. To access this you must sign up to https://tryhackme.com/.

URL: Basic Malware RE

Difficulty: Medium

Author: w4tchd0g

“These challenges are aimed towards learning about the “Static Analysis” technique used to analyze the malware. The main aim for this room is not to use any types of debuggers neither the executable’s/programs should be run on any platform. You are required to answer all the questions without even using the debugger and even not executing the executable’s/programs.”

Strings1.exe

“This executable prints an MD5 Hash on the screen when executed. Can you grab the exact flag? Note: You don’t need to run the executable!”

Running this code shows us this file is a PE32 executable (GUI) Intel 80386, for MS Windows.

┌─[[email protected]]─[~/TryHackMe/MalwareRE]
└──╼ $file strings1.exe_ 
strings1.exe_: PE32 executable (GUI) Intel 80386, for MS Windows

Let us investigate the binary more. Have a look at the functions.

I will be using a tool called Ghidra, you can install the program here:

Ghidra - software reverse engineering (SRE) suite of tools

Go ahead and run Ghidra with ./ghidraRun in the base directory of the Ghidra files.

Create a new project and import the binary provided by the challenge (strings1.exe_):

Open Ghidra

As the screenshot above shows, we can view all the functions. We have:

entry
FUN_00402300
md5_hash
memcpy
memset
sprintf

Let us investigate the first function “entry”.

entry

The decompiled code (on the right) shows a variable called lpText with an md5_hash function and a string. This is a challenge question:

What is the flag of which that MD5 gets generated?

I double click on the string to take us where it is defined, and we can see the original flag there:

flag1.1

flag1.2

Strings 2

We are told that the MD5 Hash is printed on the screen when executed, but we don’t want to run the executable.

Let us open this up in Ghidra and analyse the file to find the flag again.

Here is a list of functions in our new file:

symbol tree

I go to entry again and this is what I see:

entry function

Here is the decompiled C code:

undefined4 entry(void)

{
  char local_2c;
  undefined local_2b;
  undefined local_2a;
  undefined local_29;
  undefined local_28;
  undefined local_27;
  undefined local_26;
  undefined local_25;
  undefined local_24;
  undefined local_23;
  undefined local_22;
  undefined local_21;
  undefined local_20;
  undefined local_1f;
  undefined local_1e;
  undefined local_1d;
  undefined local_1c;
  undefined local_1b;
  undefined local_1a;
  undefined local_19;
  undefined local_18;
  undefined local_17;
  undefined local_16;
  undefined local_15;
  undefined local_14;
  undefined local_13;
  undefined local_12;
  undefined local_11;
  undefined local_10;
  undefined local_f;
  undefined local_e;
  undefined local_d;
  undefined local_c;
  undefined local_b;
  undefined local_a;
  undefined local_9;
  char *local_8;
  
  local_2c = 'F';
  local_2b = 0x4c;
  local_2a = 0x41;
  local_29 = 0x47;
  local_28 = 0x7b;
  local_27 = 0x53;
  local_26 = 0x54;
  local_25 = 0x41;
  local_24 = 0x43;
  local_23 = 0x4b;
  local_22 = 0x2d;
  local_21 = 0x53;
  local_20 = 0x54;
  local_1f = 0x52;
  local_1e = 0x49;
  local_1d = 0x4e;
  local_1c = 0x47;
  local_1b = 0x53;
  local_1a = 0x2d;
  local_19 = 0x41;
  local_18 = 0x52;
  local_17 = 0x45;
  local_16 = 0x2d;
  local_15 = 0x42;
  local_14 = 0x45;
  local_13 = 0x53;
  local_12 = 0x54;
  local_11 = 0x2d;
  local_10 = 0x53;
  local_f = 0x54;
  local_e = 0x52;
  local_d = 0x49;
  local_c = 0x4e;
  local_b = 0x47;
  local_a = 0x53;
  local_9 = 0x7d;
  local_8 = md5_hash(&local_2c);
  MessageBoxA((HWND)0x0,local_8,"We\'ve been compromised!",0x30);
  ExitProcess(0);
  return 0;
}

Some things to note: There is a char assigned at the start, most of the following variables are undefined and the rest of the local_* assignments look like hex values.

For example, let us take local_10, 0x53 would convert to the ascii value “S”.

Look at the main window - we can see how each variable is assigned to the stack. Let’s start with the char “f” and move up the variables (according to the way it is stacked).

Use this as a reference if you want to manually work out the ascii values:

ascii conversion

I created my own script to do it for me :) Copy all the hex assignments into a file called char.

Then make a script to convert all the hex values to ascii characters.

chars file:

chars

Script:

script and flag

And we get our flag.

Here is a pastebin to the script I created (Python3). You can install this with wget as the raw pastebin.

Script Pastebin

Strings 3

Open up the binary and look at the functions:

functions string 3

Here is the main window and the C code for “entry”:

entry function

Here is the decompiled code:

undefined4 entry(void)

{
  char local_4a4;
  undefined local_4a3 [1027];
  char *local_a0;
  MD5 local_9c [144];
  HRSRC local_c;
  undefined4 local_8;
  
  MD5(local_9c);
  local_4a4 = '\0';
  memset(local_4a3,0,0x3ff);
  local_8 = 0;
  local_c = FindResourceA((HMODULE)0x0,"rc.rc",(LPCSTR)0x6);
  local_8 = 0x110;
  LoadStringA((HINSTANCE)0x0,0x110,&local_4a4,0x3ff);
  local_a0 = digestString(local_9c,&local_4a4);
  MessageBoxA((HWND)0x0,local_a0,"We\'ve been compromised!",0x30);
  ExitProcess(0);
  return 0;
}

A couple of things that caught my eye were FindResourceA and LoadStringA.

Take a closer look at the function “LoadStringA”:

Load String A

We can see there is a string of what it actually loads - our flag.

Written on June 26, 2020