На вход бинарному файлу был передан флаг. На выходе мы имеем следующий набор чисел:
497 1207 1273 871 476 884 1615 475 2233 231 505 1919 190 2755 231 561
Solution
Перейду к статическому анализу:
int32_t main(int32_t argc, char** argv, char** envp)
{
void* const __return_addr_1 = __return_addr;
int32_t* var_c = &argc;
void* gsbase;
int32_t ecx = *(uint32_t*)((char*)gsbase + 0x14);
int32_t result;
if (argc > 1)
{
srandom(time(nullptr));
int32_t len;
void* eax_4 = Tr4NsF0rm(argv[1], &len);
for (int32_t i = 0; i < len; i += 1)
printf("%d ", *(uint32_t*)((char*)eax_4 + (i << 2)));
puts(&data_804887d);
result = 0;
}
else
{
puts("Give me a string");
result = 1;
}
if (ecx == *(uint32_t*)((char*)gsbase + 0x14))
return result;
__stack_chk_fail();
/* no return */
}
По коду видно, что ключ передается в качестве аргумента командной строки. Далее он передается в функцию Tr4NsF0rm. Веселье происходит в ней. Перейдем к ее разбору (тут уже подразобранный вариант):
int32_t* Tr4NsF0rm(char* key, int32_t* len) {
size_t res_len = strlen(key);
int32_t* result = calloc((res_len * 2), 4);
*(uint32_t*)len = (res_len * 2);
int32_t i = 0;
int32_t j = 0;
while (i < res_len)
{
int32_t prime_1;
int32_t prime_2;
do
{
prime_1 = primes[(random() % 10)];
prime_2 = primes[(random() % 10)];
} while (prime_1 == prime_2);
result[j] = (((int32_t)key[i]) * prime_1);
result[(j + 1)] = (((int32_t)key[i]) * prime_2);
i += 1;
j += 2;
}
return result;
}
Теперь все встало на свои места. Каждый символ ключа кодируется двумя числами. При этом каждое их этих чисел - это ascii-код символа, умноженный на рандомное число из вот этого списка простых чисел:
int32_t primes[0xa] =
{
[0x0] = 2
[0x1] = 3
[0x2] = 5
[0x3] = 7
[0x4] = 11
[0x5] = 13
[0x6] = 17
[0x7] = 19
[0x8] = 23
[0x9] = 29
}
Значит для решения нам нужно искать общий делитель для пары чисел. Для этого можно использовать алгоритм Евклида:
def gcd(a, b):
while b:
a, b = b, a % b
return a
Код решения будет следующим:
def gcd(a: int, b: int) -> int:
while b:
a, b = b, a % b
return a
if __name__ == "__main__":
crypted = [497, 1207, 1273, 871, 476, 884, 1615, 475, 2233, 231, 505, 1919, 190, 2755, 231, 561]
for i in range(0, len(crypted), 2):
print(chr(gcd(crypted[i], crypted[i+1])), end='')
print('')
Искомый флаг - GCD_Me_!. Проверю его:
