You won't find the solution to the challenge here. That is against root-me.org rules. We are simply looking at a ghidra analysis of the executable.
The previous test on Ghidra impressed me, and so I decided to test it on another simple crackme challenge from root-me.org
In this case the executable is MIPS ELF:
$ file ch27.bin ch27.bin: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, strippedLets see if Ghidra can handle it:
And it has no problem with this. In fact, the decompiler may make this crackme challenge kind of a boring exercise - IF the code is correct. Let's try!
size_t sVar1; int local_58; char local_54 [4]; char local_50; char local_4f; char local_4e; char local_4d; char local_43; char local_42; undefined4 local_c; puts("crack-me for Root-me by s4r"); puts("Enter password please"); fgets(local_54,0x40,stdin); // read up to 0x40 characters from // user entry (including 0) // note that local_54 is technically // only has space for 4 characters sVar1 = strlen(local_54); // how many chars actually got entered *(undefined *)((int)&local_58 + sVar1 + 3) = 0;// terminate string at // local_58+strlen+3 with 0 sVar1 = strlen(local_54); if (sVar1 == 0x13) { // the password has to be 0x13 = 19 chars long local_58 = 8; // initialize local_58 to 8 while (local_58 < 0x11) { // just a for loop from 8 to 16 if (local_54[local_58] != 'i') { // local_54[8] to local_54[16] have to be 'i' FUN_00400814(); return 0; } local_58 = local_58 + 1; // just a for loop from 8 to 16 } if (local_42 == 's') { // local_54[18] if (local_43 == 'p') { // local_54[17] if (local_4d == 'm') { // local_54[7] if ((local_54[2] == 'n') && (local_4e == 'n')) { // local_54[2] and local_54[6] if (local_54[0] == 'c') { // local_54[0] if (local_54[1] == 'a') { // local_54[1] if (local_54[3] == 't') { // local_54[3] if (local_50 == 'r') { // local_54[4] if (local_4f == 'u') { // local_54[5] FUN_004007c0(); return local_c; }I left out all the else statement, because they all go to the same function, which fails the password check.
Lets look at the local variables
char local_54 [4]; char local_50; char local_4f; char local_4e; char local_4d; char local_43; char local_42; The stack grows downward here, and the naming of the variables is a bit unfortunate, because they are named by how far down in the stack they are. Here a bit of the disassembly window:
Stack[-0x4]:4 local_4 Stack[-0x8]:4 local_8 Stack[-0xc]:4 local_c Stack[-0x10]:4 local_10Stack[-0x42]:1 local_42Stack[-0x43]:1 local_43Stack[-0x4c]:1 local_4cStack[-0x4d]:1 local_4dStack[-0x4e]:1 local_4eStack[-0x4f]:1 local_4fStack[-0x50]:1 local_50Stack[-0x51]:1 local_51Stack[-0x52]:1 local_52Stack[-0x53]:1 local_53Stack[-0x54]:1 local_54Stack[-0x58]:4 local_58Stack[-0x60]:4 local_60So local_53 means 0x53 down from the stack pointer. This is important, because it implies that
fgets(local_54,0x40,stdin);allows us to overwrite the other local variables. Hence,
char local_54 [4]; //local_54[0..3] char local_50; //local_54[4] char local_4f; //local_54[5] char local_4e; //local_54[6] char local_4d; //local_54[7] char local_4c; //local_54[8] char local_4b; //local_54[9] char local_4a; //local_54[10] char local_49; //local_54[11] char local_48; //local_54[12] char local_47; //local_54[13] char local_46; //local_54[14] char local_45; //local_54[15] char local_44; //local_54[16] char local_43; //local_54[17] char local_42; //local_54[18] undefined4 local_c;//local_54[19] extra space for 0 terminationand now the password is easy to deduce. local_54[8] to local_54[16] have to be 'i's and the other characters are specified in the if statements.
The decompiler made this very very easy in deed. I rarely look at MIPS assembly code and this would have been very tedious to solve for me without the pseudocode.