diff options
-rw-r--r-- | docs/forensics/image_convolution.txt | 2 | ||||
-rw-r--r-- | docs/re/arch_x86.txt | 60 | ||||
-rw-r--r-- | docs/re/rep_prefix.txt | 18 | ||||
-rw-r--r-- | docs/re/test_v_cmp.txt | 17 | ||||
-rw-r--r-- | docs/writeups/2024/BraekerCTF/misc/e.txt | 103 | ||||
-rw-r--r-- | docs/writeups/2024/BraekerCTF/misc/eye_doctor.png | bin | 0 -> 53001 bytes | |||
-rw-r--r-- | scores.txt | 1 |
7 files changed, 166 insertions, 35 deletions
diff --git a/docs/forensics/image_convolution.txt b/docs/forensics/image_convolution.txt new file mode 100644 index 0000000..419389b --- /dev/null +++ b/docs/forensics/image_convolution.txt @@ -0,0 +1,2 @@ +https://medium.com/analytics-vidhya/image-convolution-from-scratch-d99bf639c32a +https://docs.gimp.org/2.6/en/plug-in-convmatrix.html diff --git a/docs/re/arch_x86.txt b/docs/re/arch_x86.txt index 5d526b2..85cf22f 100644 --- a/docs/re/arch_x86.txt +++ b/docs/re/arch_x86.txt @@ -105,3 +105,63 @@ The function return value is stored in the a register. Stack pointer register: rsp Base pointer register: rbp Return value in: rax + + + +Specific Callouts +============================================================ + +TEST vs. CMP +------------ +CMP subtracts operands and sets internal flags. Among these, it sets the +zero flag if the difference is zero (operands are equal). + +TEST sets the zero flag (ZF) when the result of the AND operation is zero. If +the two operands are equal, their bitwise AND is zero only when the operands +themselves are zero. TEST also sets the sign flag (SF) when the most +significant bit is set in the result, and the parity flag (PF) when the number +of set bits is even. + +JE (alias of JZ) tests the zero flag and jumps if it is set. This creates the +following equivalencies: + +test eax, eax +je <somewhere> ----> if (eax == 0) {} + +cmp eax, ebx +je <somewhere> ----> if (eax == ebx) {} + + +REP prefix +---------- +The "rep" prefix on a string instruction repeats that string instruction for CX +block loads. + +e.g. STOS is "Store String" +It will store the value in AX at the address in RDI +(technically, STOSB, STOSW, STOD, and STOSQ use AL, AX, EAX, and RAX respectively) +If RCX = 0x20, RDI = some buffer, and RAX = 0, + +`rep stosq` is equivalent to: + +``` +buf_ptr = buf +for(i = 0x20; i != 0; i--) + *buf_ptr = 0; + buf_ptr++; +``` + + +LOOP instruction +---------------- +#from stack overflow: +#https://stackoverflow.com/questions/46881279/how-exactly-does-the-x86-loop-instruction-work + +LOOP is exactly like `dec ecx / jnz`, except it doesn't set flags. + +It's like the bottom of a `do {} while (--ecx != 0);` loop in C. If execution +enters the loop with ecx=0, wrap-around means the loop will run 2**32 times +(2**64 times in 64-bit mode). + +Unlike `rep movsb/stosb/etc`, it doesn't check for ecx=0 before decrementing, +only after. diff --git a/docs/re/rep_prefix.txt b/docs/re/rep_prefix.txt deleted file mode 100644 index 23e0cec..0000000 --- a/docs/re/rep_prefix.txt +++ /dev/null @@ -1,18 +0,0 @@ -The "rep" prefix on a string instruction repeats that string instruction for CX block loads. -e.g. -STOS is "Store String" -It will store the value in AX at the address in RDI -(technically, STOSB, STOSW, STOD, and STOSQ use AL, AX, EAX, and RAX respectively) -If RCX = 0x20, RDI = some buffer, and RAX = 0, - -`rep stosq` - -is equivalent to: - -``` -buf_ptr = buf -for(i = 0x20; i != 0; i--) - *buf_ptr = 0; - buf_ptr++; -``` - diff --git a/docs/re/test_v_cmp.txt b/docs/re/test_v_cmp.txt deleted file mode 100644 index c98424f..0000000 --- a/docs/re/test_v_cmp.txt +++ /dev/null @@ -1,17 +0,0 @@ -CMP subtracts operands and sets internal flags. Among these, it sets the -zero flag if the difference is zero (operands are equal). - -TEST sets the zero flag (ZF) when the result of the AND operation is zero. If -the two operands are equal, their bitwise AND is zero only when the operands -themselves are zero. TEST also sets the sign flag (SF) when the most -significant bit is set in the result, and the parity flag (PF) when the number -of set bits is even. - -JE (alias of JZ) tests the zero flag and jumps if it is set. This creates the -following equivalencies: - -test eax, eax -je <somewhere> ----> if (eax == 0) {} - -cmp eax, ebx -je <somewhere> ----> if (eax == ebx) {} 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<float> 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} diff --git a/docs/writeups/2024/BraekerCTF/misc/eye_doctor.png b/docs/writeups/2024/BraekerCTF/misc/eye_doctor.png Binary files differnew file mode 100644 index 0000000..58e27d3 --- /dev/null +++ b/docs/writeups/2024/BraekerCTF/misc/eye_doctor.png @@ -28,3 +28,4 @@ RITSEC CTF 2023 3472 72 /712 (717) BITSCTF 2024 1040 93 /921 lactf 2024 1347 447 /1074 +BraekerCTF 606 75 /487 (1361) |