High Quality Checks

Category: Rev
Points: 110
Description: After two break-ins to his shell server, kmh got super paranoid about a third! He’s so paranoid that he abandoned the traditional password storage method and came up with this monstrosity! I reckon he used the flag as the password, can you find it?

This challenge was a bitch to work through. Essentially you are given a binary that asks for input. If your input is the flag it says, yep you’ve got the flag. So you have to reverse engineer the “checks” on the input to then get the flag.

Popping the binary into ghidra you will see there is a check function that looks like this:


undefined8 check(byte *param_1)

{
  ulong uVar1;
  undefined8 uVar2;
  
  uVar1 = d((int *)(param_1 + 0xc));
  if (((((((int)uVar1 != 0) && (uVar1 = v(*param_1), (int)uVar1 != 0)) &&
        (uVar2 = u(param_1[0x10],param_1[0x11]), (int)uVar2 != 0)) &&
       ((uVar1 = k(param_1[5]), (int)uVar1 == 0 && (uVar1 = k(param_1[9]), (int)uVar1 == 0)))) &&
      ((uVar1 = w((char *)(param_1 + 1)), (int)uVar1 != 0 &&
       ((uVar1 = b((long)param_1,0x12), (int)uVar1 != 0 &&
        (uVar1 = b((long)param_1,4), (int)uVar1 != 0)))))) &&
     ((uVar2 = z((long)param_1,'l'), (int)uVar2 != 0 && (uVar1 = s((long)param_1), (int)uVar1 != 0))
     )) {
    return 1;
  }
  return 0;
}

It is doing a whole lot of checks with single letter function calls, oh god. So my approach was to reverse each bit of it.

So before the check function it just quickly checks whether your input length is greater than 19 chars if not, it immediately fails. So then we begin the actual checks.

I’m not going to go into too much detail of what each function does but we will see.

First check:
calls d function with 13 14 15 16th chars and checks whether the hex value is 0x30313763, which in ascii is

c710

Second check:
NOTE n function simply bit shifts the given input 1 place to the right

So the check is that it calls the n function with 0xac and then the value of the first character XOR 0x37 equals that value. Therefore doing some math you get the first char needs to be a (big whoop)

a???????????c710???

Third check:
Checks the 16th and 17th char

16th char needs to equal 0xdc bit shifted to the right so n.
17th char calls the o function, which basically if you do some funky maths knowing that the output needs to be 0x35053505 you get the char of 5

a????????????c710n5?

Fourth check:
Checks the sixth char against the o function, which is funky maths again which should ouput 0x660f660f same thing will return f

a????f??????c710n5?

Fifth check:
Same as fourth but with the 10th char

a????f???f??c710n5?

Sixth check:
Checks 2nd 3rd 4th chars (notice the function is called with our input + 1), more funky maths gives us values we need which is ctf

actf?f???f??c710n5?

Seventh check:
From here you can kinda see where we are going. We close 🙂 This one checks the 18th char which if you go along you will see needs to be }

For this I just debugged through IDA and saw what value it wanted at the end rathter than reversing the whole thing

actf?f???f??c710n5}

Eighth check:
Same as seventh but for 5th char to give {

actf{f???f??c710n5}

Ninth Check:
This did a whole lot of shit, again I ignored most of it and used IDA to see what the check was at the end, it was checking the 7th char is u so adding that to my flag

actf{fu??f??c710n5}

At this point I kinda just guessed the flag because it was obvious to me so I didn’t bother reversing the rest and just popped the flag in.

FLAG:

actf{fun_func710n5}