На вход бинарному файлу был передан флаг. На выходе мы имеем следующий набор чисел:

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_!. Проверю его:

IMG