Not sure if it is appropriate to report here but it is possible to completely bypass the license checking on babyrev_level8_teaching1
due to the first byte of the EXPECTED_RESULT
variable being \x00
.
PoC
The following works with any string 12 chars or less, just as long as some data is consumed via the unix socket.
$ ./babyrev_level8_teaching1 & echo abcdefghijkl | socat -t 2 ./knfjs -
[1] 236570
###
### Welcome to ./babyrev_level8_teaching1!
###
This license verifier software will allow you to read the flag.
However, before you can do so, you must verify that you are licensed to read flag files!
This program consumes a license key over some communication channel that you must figure out.
You must also figure out (by reverse engineering this program) what that license key is.
Providing the correct license key will net you the flag!
Ready to receive your license key!
This challenge takes input by reading it from a unix socket.
You will need to understand what a unix socket is in Linux,
and how to interact with one.
The name of the unix socket that this specific challenge will listen on is "knfjs".
The challenge has now read in the data it needs, after skipping some bytes
to make things a bit more complicated! Specifically, it skipped 12 bytes.
The data it read in (and that will now be mutated and checked) was:
0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
This challenge is now mangling your input using the "xor" mangler with key `0x090361`.
This mangled your input, resulting in:
03 03 61 09 03 61 09 03 61 09 03 61 09 03 61 09
This challenge is now mangling your input using the "sort" mangler.
This mangled your input, resulting in:
03 03 03 03 03 03 09 09 09 09 09 61 61 61 61 61
This challenge is now mangling your input using the "xor" mangler with key `0x03`.
This mangled your input, resulting in:
00 00 00 00 00 00 0a 0a 0a 0a 0a 62 62 62 62 62
The mangling is done! The resulting bytes will be used for the final comparison
For reference, the resulting data is:
00 00 00 00 00 00 0a 0a 0a 0a 0a 62 62 62 62 62
To verify that you input the correct license key, the program will compare this
against the following expected result:
00 0b 09 10 1a 63 69 68 6d 73 72 70 77 76 75 7b
If those byte sequences match, you will get the flag! Let's see...
Checking the received license key!
Correct! Here is your flag:
Cause
In the custom cmp
function, there is a logical flaw since the detection of null bytes is used to control the code path taken, however, if the EXPECTED_RESULT
variable has a null byte in it then as long as the previous bytes matched, the check will pass even though the rest of the license
is incorrect. In the case of babyrev_level8_teaching1
you can bypass the check altogether since the null byte is in the very first position.
This might be clearer looking at the following code:
long long cmp(char *a, char *b, unsigned __int64 n){
int i;
for (i = 0; i < n; i++){
if (a[i] != b[i])
return (unsigned int)(a[i] - b[i]);
if (!a[i] || !b[i]) // if we get here and a[0] is \x00, we win
break;
}
// success
return 0;
}
Fix
Since null bytes have a special semantic purpose in the cmp
function, they should be avoided in the EXPECTED_RESULT
variable for all binaries that use this function.