Rating:

#### TL;DR
to get the flag:
1) Fill buffer username and leak the address of the random password
2) Send the address when asked the size of our password to trick the program into writing a null byte at the beginning of the random password
Now strlen return 0 therefore no byte get checked in the custom_strcmp and we are granted access

### Solution
Here is an aproximation of the source code for the functions we will focus on:

```c
unsigned long custom_strcmp(char *buffer1,char *buffer2,size_t len)
{
unsigned long ret;
size_t size;
char *s2;
char *s1;
unsigned int diff;

if (len == 0) {
ret = 0;
}
else {
diff = 0;
size = len;
s2 = buffer2;
s1 = buffer1;
while (size != 0) {
diff = diff | (int)*s2 - (int)*s1;
size = size + -1;
s2 = s2 + 1;
s1 = s1 + 1;
}
ret = (unsigned long)diff;
}
return ret;
}

long login(void)
{
long rax;
size_t len;
size_t size;
char *buffer;
char username [16];
char *random_string;

printf("USER\n");
*(long *) &username[0] = 0;
*(long *) &username[8] = 0;
random_string = &GLOBAL_RANDOM;
read(0,&username,0x10);
if (strcmp((char *)&username,"admin") == 0) {
printf("PASSWORD\n");
size = 0;
read(0,&size,8);
size = custom_big_to_little_endian_conversion(size);
buffer = (char *)malloc(size + 1);
read(0,buffer,size);
buffer[size] = '\0';
len = strlen(random_string);
if (custom_strcmp(random_string,buffer,len) != 0) {
printf("LOGIN FAIL\n");
exit(1);
}
printf("LOGIN SUCCESS\n");
rax = 1;
}
else {
printf("BAD USER ");
printf("%s", username);
printf("\n");
rax = 0;
}
return rax;
}

int main(void)
{
int possible_attempts;

set_random_string();
printf("HELLO\n");
printf("SERVER sunshine.space.center.local\n");
possible_attempts = 3;
while(possible_attempts > 0) {
if (login())
{
display_flag();
usleep(100000);
return 0;
}
else
{
printf("AGAIN\n");
possible_attempts = possible_attempts + -1;
}
}
printf("LOCKOUT\n");
return 0;
}


}
```
The first thing we noticed was that the username could be used to leak an address. The read is the same length as the buffer, which means that filling it with the 16 bytes there wouldn't be a null byte to terminate our string and printf would give us the next variable too. Which was in our case the pointer to our random string.
Now the true vulnerability resides in the improper strcmp: the author made explicit that len == 0 returned the same value as if the two strings were the same. Now the length is calculated with strlen, which returns the number of bytes before the first null byte, so we have to just have to overwrite the first byte with a \x00.
The only possibility to write a null byte is during the login with the line:`buffer[size] = '\0';`, but this should write it to the heap right?
Well yes, but actually no. There is a big hint with the conversion from big endian to little endian that maybe they are expecting a pointer. Of course it makes no sense, we can not allocate enough memory on the heap to reach our data region, but lets look at what would happen anyway.
We start by executing malloc(0x555555558040). Of course this doesn't work and like with a malloc(0) the function returns 0. Here a good programmer would have checked if they have a pointer, but fortunately for us there is no such control and 'buffer' is hereby set to 0. Now the program tries to write to the address 0, which can not be accessed and returns a -1, but without any checks implemented this doesn't matter.
And what is the next instruction? `*(0 + pointer) = 0;` we can write a null byte on an arbitrary address! We just have to send the address of the random password and we are granted access