Исходный код бинарного файла:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void toLowerCase(char* str) {
for (size_t i = 0; str[i]; i++) {
str[i] = tolower((unsigned char)str[i]);
}
}
void algorithm(char* input, char digit, char* output) {
size_t length = strlen(input);
for (size_t i = 0; i < length; i += 2) {
int hexValue;
sscanf(&input[i], "%2x", &hexValue);
hexValue ^= (digit - '0');
sprintf(&output[i], "%02x", hexValue);
}
}
int main() {
char input[64];
char output[64];
const char digit = '4';
const char* predefinedString = "630c5b3c9a313fdc9a3a1e7625be6f04bee0d380"; // уже заксоренная строка
printf("Введите строку в шестнадцатеричном формате: ");
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = '\0';
toLowerCase(input);
memset(output, 0, sizeof(output));
algorithm(input, digit, output);
if (strcmp(output, predefinedString) == 0) {
printf("ptech2024{%s}\n", input);
} else {
printf("Упс, не то...\n");
}
return 0;
}
Для ревёрса откроем бинарный файл в программе Ghidra:
В списке функций увидим “main”, посмотрим её содержание:
Заметим, что флага в явном виде здесь нет, но мы видим, что он формируется из ввода пользователя т.к внутренняя часть флага это переменная local_98, а она, в сою очередь, получается через функцию fgets, которая считывает символы до тех пор, пока не встретится символ “/n” - новая строка
Также, заметим функцию “algorithm” в которую передаётся большая строка и какое то число, если навести на него, то можно увидеть его в ASCII
Теперь, посмотрим функцию “algorithm”. Проанализировав её, можно понять, что это XOR, в частности, стоит посмотреть на строку:
local_24 = local_24 ^ (int)param_2 - 0x30U;
Также, можно заметить, что XOR выполняется не над всей строкой разом, а над каждым символом отдельно, это можно понять по циклу:
for (local_20 = 0; local_20 < local_18; local_20 = local_20 + 2) {
__isoc99_sscanf(param_1 + local_20, &DAT_00102008, &local_24);
local_24 = local_24 ^ (int)param_2 - 0x30U;
sprintf((char *)(param_3 + local_20), "%02x", (ulong)local_24);
}
Зная все эти данные, напишем программу, которая восстановит нам исходную строку:
def reverse_algorithm(input_str, digit):
output = ""
for i in range(0, len(input_str), 2):
hex_value = int(input_str[i:i+2], 16)
hex_value ^= int(digit)
output += f"{hex_value:02x}"
return output
encoded_str = "630c5b3c9a313fdc9a3a1e7625be6f04bee0d380"
digit = '4'
decoded_str = reverse_algorithm(encoded_str, digit)
print(f"Decoded: {decoded_str}")
Результат работы программы:
Decoded: 67085f389e353bd89e3e1a7221ba6b00bae4d784
Для проверки на валидность, скормим программе эту строку:
Получаем заветный флаг!