When we login as level13 we get the following files in our home directory
level13@SnowCrash:~$ ls -l
total 8
-rwsr-sr-x 1 flag13 level13 7303 Aug 30 2015 level13
And when we execute the executable level13 we get :
level13@SnowCrash:~$ ./level13
UID 2013 started us but we we expect 4242
The executable do not take any arguments.
When we disassemble the file we get the following code :
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char * ft_des(char *param_1)
{
char *param_copy;
uint param_len;
char *param_copy_2;
uint param_index;
int num_index;
int i;
int j;
char num_str[] = "0123456";
char p_char;
param_copy = strdup(param_1);
num_index = 0;
param_index = 0;
param_copy_2 = param_copy;
param_len = 0xffffffff;
/* calculate the length of parameter : strlen(param_1) */
do {
if (param_len == 0)
break;
param_len = param_len - 1;
p_char = *param_copy_2;
param_copy_2 = param_copy_2 + 1;
} while(p_char);
do {
/* If param_index == len */
if (~param_len - 1 <= param_index)
return (param_copy);
if (num_index == 6)
num_index = 0;
/* if param_index is a XX number then it's true */
if ((param_index & 1) == 0)
{
if ((param_index & 1) == 0)
{
i = 0;
while (i < num_str[num_index])
{
param_copy[param_index] = param_copy[param_index] + -1;
if (param_copy[param_index] == 0x1f)
param_copy[param_index] = '~';
i = i + 1;
}
}
}
else
{
j = 0;
while (j < num_str[num_index])
{
param_copy[param_index] = param_copy[param_index] + 1;
if (param_copy[param_index] == 0x7f) // 0x7f is the ascii code for Delete
param_copy[param_index] = ' ';
j = j + 1;
}
}
param_index = param_index + 1;
num_index = num_index + 1;
} while( true );
}
void main(void)
{
__uid_t _Var1;
undefined4 uVar2;
_Var1 = getuid();
if (_Var1 != 0x1092) {
_Var1 = getuid();
printf("UID %d started us but we we expect %d\n",_Var1,0x1092);
/* WARNING: Subroutine does not return */
exit(1);
}
uVar2 = ft_des("boe]!ai0FB@.:|L6l@A?>qJ}I");
printf("your token is %s\n",uVar2);
return;
}
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char * ft_des(char *param_1)
{
char cVar1;
char *pcVar2;
uint uVar3;
char *pcVar4;
byte bVar5;
uint local_20;
int local_1c;
int local_18;
int local_14;
bVar5 = 0;
pcVar2 = strdup(param_1);
local_1c = 0;
local_20 = 0;
do {
uVar3 = 0xffffffff;
pcVar4 = pcVar2;
do {
if (uVar3 == 0) break;
uVar3 = uVar3 - 1;
cVar1 = *pcVar4;
pcVar4 = pcVar4 + (uint)bVar5 * -2 + 1;
} while (cVar1 != 0);
if (~uVar3 - 1 <= local_20) {
return pcVar2;
}
if (local_1c == 6) {
local_1c = 0;
}
if ((local_20 & 1) == 0) {
if ((local_20 & 1) == 0) {
local_14 = 0;
while (local_14 < (int)"0123456"[local_1c]) {
pcVar2[local_20] = pcVar2[local_20] + -1;
if (pcVar2[local_20] == 0x1f) {
pcVar2[local_20] = '~';
}
local_14 = local_14 + 1;
}
}
}
else {
local_18 = 0;
while (local_18 < (int)"0123456"[local_1c]) {
pcVar2[local_20] = pcVar2[local_20] + 1;
if (pcVar2[local_20] == 0x7f) {
pcVar2[local_20] = ' ';
}
local_18 = local_18 + 1;
}
}
local_20 = local_20 + 1;
local_1c = local_1c + 1;
} while( true );
}
void main(void)
{
__uid_t _Var1;
undefined4 uVar2;
_Var1 = getuid();
if (_Var1 != 0x1092) {
_Var1 = getuid();
printf("UID %d started us but we we expect %d\n",_Var1,0x1092);
/* WARNING: Subroutine does not return */
exit(1);
}
uVar2 = ft_des("boe]!ai0FB@.:|L6l@A?>qJ}I");
printf("your token is %s\n",uVar2);
return;
}
It seems that the program checks for our UID and if the User ID is not correct it quits the program saying an error message and if the UID is correct then it calls the function ft_des which does some encryption to our given string that we passed as the function parameter and it return us the new encryptes string.
The function ft_des is a rather simple function that
takes an argument
Create a duplicate of the argument
calculate the length of the string
Loop until reached the end of the string
while it is looping for each character it modifies it using simple technics.
To solve this exercice we can simply copy the ft_des and create a C program where we call the ft_des function from our main and print the result.
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char * ft_des(char *param_1)
{
char *param_copy;
uint param_len;
char *param_copy_2;
uint param_index;
int num_index;
int i;
int j;
char num_str[] = "0123456";
char p_char;
param_copy = strdup(param_1);
num_index = 0;
param_index = 0;
param_copy_2 = param_copy;
param_len = 0xffffffff;
/* calculate the length of parameter : strlen(param_1) */
do {
if (param_len == 0)
break;
param_len = param_len - 1;
p_char = *param_copy_2;
param_copy_2 = param_copy_2 + 1;
} while(p_char);
do {
/* If param_index == len */
if (~param_len - 1 <= param_index)
return (param_copy);
if (num_index == 6)
num_index = 0;
/* if param_index is a XX number then it's true */
if ((param_index & 1) == 0)
{
if ((param_index & 1) == 0)
{
i = 0;
while (i < num_str[num_index])
{
param_copy[param_index] = param_copy[param_index] + -1;
if (param_copy[param_index] == 0x1f)
param_copy[param_index] = '~';
i = i + 1;
}
}
}
else
{
j = 0;
while (j < num_str[num_index])
{
param_copy[param_index] = param_copy[param_index] + 1;
if (param_copy[param_index] == 0x7f) // 0x7f is the ascii code for Delete
param_copy[param_index] = ' ';
j = j + 1;
}
}
param_index = param_index + 1;
num_index = num_index + 1;
} while( true );
}
int main(int argc, char const *argv[])
{
printf("Flag : %s\n", ft_des("boe]!ai0FB@.:|L6l@A?>qJ}I"));
return 0;
}
I said it ecrypt the string because the function is called ft_des and is an well known encryption algorithm. But in our case it will rather decrypt because the string boe]!ai0FB@.:|L6l@A?>qJ}I is not the correct fag so it had to be decrypted before we can use it.