The crackme is written in Go, so with my IDA Free without plugins and Lumina, it is quite difficult to understand the code generated by the Go compiler. Anyway, it’s a nice little game that simulates a store: you can buy or sell things, and the goal is to “buy” a flag when you’ve collected enough money. The only problem is that you don’t have enough items to sell to get it, so you need to find a way to cheat the game.
After going through the confusing code of calling functions from the standard library and trying to understand the logic, I eventually found the point where the actual purchase of things occurs. If you discard all unnecessary details, you will get something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | printf("Choose an option: "); scanf("%d", &choiceIdx); if (choiceIdx < 3) { exit(0); } printf("How many do you want to buy: "); scanf("%d", &howMuchToBuy); if (howMuchToBuy <= inventory[choiceIdx].count) { if (wallet < inventory[choiceIdx].price) { printf("Not enough money\n"); } else { inventory[choiceIdx].count -= howMuchToBuy; wallet -= howMuchToBuy * inventory[choiceIdx].price; userInventory[choiceIdx].count += howMuchToBuy; } } |
The problem with this code is that it does not validate the user-supplied howMuchToBuy
value, so no one is stopping you from asking to buy a negative amount of things. Magically, the quantity of the selected item in the store will increase, including the money you have in your wallet.
Here’s a step-by-step solution:
1 2 3 4 5 6 7 | Choose an option: 1 How many do you want to buy? -10 You have 190 coins Choose an option: 2 How many do you want to buy? 1 Flag is: [112 105 99 111 67 84 70 123 98 52 100 95 98 114 111 103 114 97 109 109 101 114 95 57 99 49 49 56 98 98 102 125] |
Now, given that the flag is an array of numbers (each of which is an ASCII character), we need to convert it to a string, like this:
1 2 3 4 5 6 7 | $ tail -c +2 flag.txt | head -c -2 | awk ' BEGIN {FS=" ";} { for (i=1; i<=NF; i++) { printf("%c", $i) } }' |