A Simple Go Crackme (+ Manual UPX unpacking)

REFAIM
5 min readApr 5, 2023

--

Intro

As the name of this challenge suggests, we are going to reverse a program that has been written with GOLANG. This program has been packed with UPX, and there are different ways to unpack this — I am going to represent 3 different ways in this article, and afterward, we will continue to solve the challenge.

Whoever wants to do this alone before can download the challenge from: https://forum.tuts4you.com/topic/41404-a-simple-go-crackme

Detecting the packer

Looking at detect it easy shows that this file is 64-bit, packed with UPX 3.95

Unpacking process

So as I said there are different ways of unpacking this program, but I will represent 3 ways:

Using UPX (Not cool)

can be downloaded from here: https://github.com/upx/upx/releases

Hardware breakpoints on pushed registers

many packers before they start the unpacking routine, they push the values of the registers into the stack so they will save the state of the program. many use pushad/pushfd instructions and once the unpacking routine is finished they are using popad/popfd to load the registers/flags back — Those instructions are available at 32bit programs only (Thanks for @agentjones) . In this specific program (64 bit), each flag is pushed using a simple push instruction. if we look at x64dbg we will see this at the entry point:

We can click f8 to move one instruction forward and then set hardware access breakpoint on the qword that has been pushed to the stack:

Running the program using f9 will trigger the breakpoint:

we can see a jmp instruction at 0x5930a1, we can enter using f7 and we got the OEP (Original Entry Point)

Finding OEP using ida

Opening the program using IDA, we can see the dynamic API loading using LoadLibraryA and GetProcAddress, and afterwards we see a jump to the instruction 0x453a60, setting there hardware breakpoint will lead us to the same OEP:

Fixing IAT (Only if done manually)

So we found our OEP, and now we want to dump the file, we can use Scylla for this:

Clicking on Scylla icon will open Scylla. Clicking on IAT Autosearch and then imports will try to find automatically the IAT and load the imports:

Dump the file using the dump option and save it.

But trying to run this file will receive an error message:

If we open the file using pe-bear we will see that actually the IAT is corrupted:

So we are going to need to fix it, return to x64dbg to our OEP, right-click on the dissassembler > search for > all user modules > intermodular calls

This will show us the calls to different library functions

Clicking on one of them, for example, the first one, and then viewing its location at dump:

we can find the actual IAT and by selecting the dump we can see that its size is f8 bytes starting from 0x55f000:

so let us return to our Scylla window and update the VA (Virtual address) of the IAT (Import address table) and its size by cliking get imports we will get the following window:

Select the fix dump and select our previously dumped file, now it should work:

Solving the challenge

Finally to solve the crack, open this at IDA:

IDA successfully extracts the functions name of the GOLANG program, lets open its main (Usually main program in go is named: main_main):

in this function, we can see the call to bufio__ptr_reader_readbytes which probably receives the input from the user, and later we can see runtime_memequal comparing our input with a 7-length dword:

lets double click the dword_4c8ec4, select 7 bytes from there, and clicking A will convert the dword to a string:

And then we will receive our flag: ‘@flag{}’:

Summary

this program was really easy to crack, also UPX has a built-in option to unpack the program, but I wanted to show in this post how we can do this manually and how to fix the IAT. This will help in the next challenges to come with more difficult packers. I will really appreciate any corrections!

--

--

REFAIM
REFAIM

No responses yet