Introducing shcode2exe

[Edit: shcode2exe is now part of Remnux]

I've been playing around with Remnux and encountered a problem trying to get one of the tools to run properly. The tool is shellcode2exe, it is used to compile binary shellcode to a file so it can easily be debugged by a debugger.

When I checked out the code, I was surprised to find out how simple it is. Basically, what happens is that the inputted shellcode is added to a barebones assembly file using the incbin assembly instruction. From there, the file is then automatically compiled and linked.

One big problem with the tool is that it needs to use Wine if it needs to run on Linux. I don't want such a huge dependency especially for my own malware analysis lab so I decided to write my own version which have led to the creation of shcode2exe.

shcode2exe

While similar in functionality with the original tool, the biggest improvement I made is that it it does not depend on Wine along with other features as listed below:

  • Can accept a shellcode blob or string (String format \x5e\x31)
  • Can target both 32bit or 64bit Windows architecture.
  • Cross platform. Works on Linux or Windows.
  • No dependency on Wine when running on Linux
  • Tested working with Python v3.3 and above
  • Tested working on Windows 7 (Non SP1) and above

Usage

Here's the help message for the tool:

usage: shcode2exe.py [-h] [-o OUTPUT] [-s] [-a {32,64}] input

Compile a binary shellcode blob into an exe file. Can target both 32bit or 64bit architecture.

positional arguments:
  input                 The input file containing the shellcode.

optional arguments:
  -h, --help            show this help message and exit
  -o OUTPUT, --output OUTPUT
                        Set output exe file.
  -s, --string          Set if input file contains shellcode in string format.
  -a {32,64}, --architecture {32,64}
                        The windows architecture to use

Here's how to load a file with shellcode in the format of a string

$ cat test.txt
\x5e\x31\xc0\xb0\x24\xcd\x80\xb0\x24\xcd\x80\xb0\x58\xbb\xad\xde\xe1\xfe\xb9\x69\x19\x12\x28\xba\x67\x45\x23\x01\xcd\x80
$ ./shcode2exe.py -s -o test-string.exe test.bin

Load a file with shellcode in the format of a blob

$ ./shcode2exe.py -o test-blob.exe test.bin

Use 64 bit architecture for the output (32 bit is the default)

$ ./shcode2exe.py -o test-blob.exe -a 64 test.bin
$ file test-blob.exe
test-blob.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows

Next steps

I decided to reach out to the people behind Remnux to ask if they could consider my tool as a replacement on their platform. It would be great if they would, but it's okay too if they don't, I made it for my own use anyway. (Update 2021-02-07: It's now under review)

For more information about the tool and it's code, go to it's Github page. If you have any comments or suggestions on how to improve it, feel free to tell me via Github issues or dm me at @accidentalrebel.

IOLI Crackme 0x01

I am continuing my reverse engineering review by tackling the IOLI crackmes by @pof. These are beginner friendly challenges that is perfect for newbies or for those who want to review the basics like me. Check out my writeup for 0x00 here.

Getting the password

Of course, the first thing we do is run the program.

ioli-crackme-0x01-01

Just like last time, we opened up the program in IDA and focused on the part of the code that does the comparing of passwords.

ioli-crackme-0x01-02

cmp [ebp+var_4], 149Ah
jz short loc_40137c

This seems easy enough.

Initially I entered 149A as the password but this turned out to be incorrect. The reason for this is because scanf was passed a format of "%d".

mov [esp+18h+Format], offset aD ; "%d"
call _scanf

This means that the input it expects is actually a decimal integer. So converting 149A to decimal results in 5274, which is the correct password.

ioli-crackme-0x01-03

Patching the executables

Patching the executable is actually the same process as my writeup for 0x00.

Passing arguments to functions

Since the crackme was cracked relatively quickly I want to review and highlight how arguments are passed to functions.

The format of the scanf function in C is like so:

int scanf ( const char * format, ... );

Here's an example of how it is used:

int i;
scanf ("%d",&i);

If we look at the 0x01 program we could see how the arguments are passed to the _scanf function by placing the data to send on top of the stack.

lea eax, [ebp+var_4]
mov [esp+18h+var_14], eax
mov [esp+18h+Format], offset aD;  "%d"
call _scanf

lea eax, [ebp+var_4] gets the address of var_4, this is the memory location where scanf would put the inputted data. This is then added to the stack with mov [esp+18h+var_14].

offset aD gets the address of aD which contains the string "%d". This is the format parameter that scanf expects. This is then added to the stack with mov [esp+18h+Format].

With the two parameters added to the stack, it can now be used by the scanf function when call _scanf is executed.

I'm not sure if I was able to explain that properly. At the very least, you should have been able to have a basic idea of how variables are passed to functions. Take note, however, that there are other calling conventions for functions which meants that the passing of arguments can also differ.

On to the next challenge...

This is the second challenge out of 10 in the IOLI series of challenges. So far the challenges are still very easy, which is fine because it's still good for practice. I look forward to the next one.

IOLI Crackme 0x00

I am re-familiarizing myself with reverse engineering again by going through some simple crackme challenges. This one is called the IOLI Crackmes by pof. The goal is to find the correct password and also to patch it so that it can accept any input and still show that it's correct.

Getting the password

Running the program shows a password prompt.

ioli-crackme-0x00-03

Of course, randomly entering passwords is going to be a waste of time so I opened up IDA to look at its code.

I knew that whatever password I enter in the program would be checked against the actual password. This is the part of the program that I should focus on so I scanned the code and found this:

ioli-crackme-0x00-02

mov [esp+38h+Str2], offset Str2; "250382"
mov [esp+38h+Format], eax; 
call _strcmp

And just from these few lines alone I already knew what the password is. IDA Pro was helpful enough to add a comment that offset Str2 equates to 250382. Surely enough, this number was the password.

ioli-crackme-0x00-04

Patching the executable

The next part of the challenge is to patch the executable so that it can accept any input and would still allow us through.

Looking at the graph view, we want the program to always go to the node on the right which has the "Password OK" message.

ioli-crackme-0x00-05

The line that we could change to allow us to do this would be this one:

jz short loc_40138A

The jz can be changed to a jmp command by changing the op code. Opening up the "Patch Bytes" window while the line is highlighted would show us this:

ioli-crackme-0x00-06

74 0E C7 04 24 2E 40 40 00 E8 A8 19 00 00 EB 0C

The opcode related to jz short loc_40138A is the first two btyes 74 0E. 74 is the "Jump short if equal" opcode and 0E is the relative jump distance. Changing 74 to EB converts it to the "Jump" opcode effectively making the line jmp short loc_40138A.

ioli-crackme-0x00-07

After saving, IDA will automatically upgrade the graph. It will now show us that the flow of the program now jumps to the right node directly.

ioli-crackme-0x00-08

All that is left to do is to patch the executable via "Edit > Patch Program > Apply patches to input file..." and run the program. From here, any entered password would automatically get accepted.

ioli-crackme-0x00-09

On to the next challenge...

This is the first out of the 10 challenges from this set. Since this is the first one, it is only natural for it to be very easy. It's still a good refresher for me especially since the last time I did any reversing was from a few years ago. I look forward to the next challenges, I do hope that they would ramp up in difficulty and also teach me new things for me to improve.