From 175d1af3bf850fd0816a730215e028045d82e037 Mon Sep 17 00:00:00 2001 From: Malfurious Date: Sun, 25 Feb 2024 12:53:04 -0500 Subject: Writeup BraekerCTF 2024 / e Signed-off-by: Malfurious --- docs/writeups/2024/BraekerCTF/misc/e.txt | 103 +++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 docs/writeups/2024/BraekerCTF/misc/e.txt (limited to 'docs/writeups/2024/BraekerCTF/misc/e.txt') diff --git a/docs/writeups/2024/BraekerCTF/misc/e.txt b/docs/writeups/2024/BraekerCTF/misc/e.txt new file mode 100644 index 0000000..5b7f455 --- /dev/null +++ b/docs/writeups/2024/BraekerCTF/misc/e.txt @@ -0,0 +1,103 @@ +"Grrrrr". This robot just growls. The other bots tell you that it is angry +because it can't count very high. Can you teach it how? + + + +Overview +-------- +The challenge provides a C++ source file and a netcat port. The program code +appears to be a short series of prompts, which passing all of them will print +the flag. At each stage, our input is taken as a single-precision floating +point number which must pass various rounding error and precision checks. + + + +Level 1 +------- +bool flow_start() { + // Get user input + float a = get_user_input("Number that is equal to two: "); + + // Can't be two + if (a <= 2) + return false; + + // Check if equal to 2 + return (unsigned short)a == 2; +} + +I saw some solutions take advantage of the fact that large numbers would +"overflow" when truncated via the (unsigned short) cast, giving a valid input +like 65538 (0x10002). + +My solution leveraged the floating point truncation (aka: loss of decimal +places): 2.0000002384 + + + +Level 2 +------- +bool round_2() { + float total = 0; + + // Sum these numbers to 0.9 + for (int i = 0; i < 9; i++) + total += 0.1; + + // Add user input + total += get_user_input("Number to add to 0.9 to make 1: "); + + // Check if equal to one + return total == 1.0; +} + +During the for-loop, precision errors accumulate and the total will overshoot +0.9. Less than 0.1 must be given: 0.09999990 + + + +Level 3 +------- +bool level_3() { + float total = 0; + + unsigned int *seed; + vector n_arr; + + // Random seed + seed = (unsigned int *)getauxval(AT_RANDOM); + srand(*seed); + + // Add user input + add_user_input(&n_arr, "Number to add to array to equal zero: "); + + // Add many random integers + for (int i = 0; i < 1024 * (8 + rand() % 1024); i++) + n_arr.push_back((rand() % 1024) + 1); + + // Add user input + add_user_input(&n_arr, "Number to add to array to equal zero: "); + + // Get sum + for (int i = 0; i < n_arr.size(); i++) + total += n_arr[i]; + + // Check if equal to zero + return total == 0; +} + +Many random numbers between [1, 1024] are summed up in this function, and we are +asked for two more, for all of them to sum to zero. Since the range of random +numbers is known (<=1024), we can provide relatively large numbers to squeeze +out the randomness. + +Given the fixed-precision, yet floating decimal point of floats, adding a large +value to a small value can potentially reduce the smaller value to zero as its +exponent and mantissa are adjusted to match the other. + +10000000000000000 +-10000000000000000 + + + +brck{Th3_3pS1l0n_w0rkS_In_M15t3riOuS_W4yS} -- cgit v1.2.3