Crackme - Golang Reversing
Crackme is an easy reverse engineering challenge from YASCON 2020, in this blog we’ll be discussing the intended way to solve the challenge.
Introduction
We’re given a windows PE executable binary, non-stripped and on execution, it just asks “Dead or Alive?“. It’s the typical crackme chall and is pretty much static reverse engineering so we’ll be using Ghidra to solve this challenge.
After analyzing the binary, we can start looking for the main function. Usually, Go binaries are huge and a lot of functions are embedded in binary by the compiler. C compiled programs would import the library they use and could be seen in the import section. But in Go, the functions used are actually compiled in the binary itself, and only a few libraries were imported, in my case kernel32
and winmm
. So after a little digging, we could find the main function named main.main
.
Looking into the main function we find the Fprint()
to the few strings we see when executing the binary,
Then it takes STDIN using the fmt.Fscan()
function and perform strings.genSplit()
. Split
function splits a string into all substrings separated by the given separator and returns a slice that contains these substrings. So basically it creates an array of characters from the user-input and remaining comparisons are performed in the array, element by element.
It then continues to find the length of the input string and checks if it is greater than 10 characters. If not it displays the error message and exits the program, and on giving input with greater than 10 characters we get a different error message. So the flag is probably 10 chars or larger.
It then starts a huge if comparison with the elements of the array and a hardcoded characters, and if any comparison returns false
it prints out an error message and exits the program. So the objective here is to trace the characters which are being compared, from the array to the hardcoded elements.
Reading the disassembly, it looks like the comparisons are happening with an index value added to the base index value, except for the ‘Y’ comparison.
That is,
1 | if(string(array[0+1]) == "C") && each other comparisons { |
It continues to perform the comparisons for the rest of the elements in the array with the added index value ‘1’. And on arranging the characters to which is compared in the right order of user input, we get the flag.
YASCON{W3lc0me_t0_gO_r3v3rs1nG}
source code: main.go