Нужно найти флаг из 10 чисел.

ELF PE

Solution

Закину бинарь в бинжу, чтобы начался его анализ, а сам в это время посмотрю строки в файле с помощью strings:

UWVS
t$,U
^L[^_]
Correct!
Wrong!
;*2$"$
GCC: (GNU) 6.1.1 20160802
GCC: (GNU) 6.3.1 20170109

Чего-то очень интересного нет. Но Correct! и Wrong! стоит проверить) Они находятся прямо в функции main. Не всегда все так очевидно.

int32_t main(int32_t argc, char** argv, char** envp)
    void* const __return_addr_1 = __return_addr
    int32_t* var_10 = &argc
    void s
    __builtin_memset(&s, c: 0, n: 0x28)
    mapM_(int_read, 0xa, &s)
    mapM_(int_print, 0xa, &s)
    putchar(c: 0xa)
    
    if (int_foldl1(xor, 0xa, &s) != 0 || int_foldl(and, 1, 0xa, &s) == 0)
        puts(str: "Wrong!")
    else
        puts(str: "Correct!")
    
    return 0

Выглядит не очень понятно. Поэтому попробую запустить его:

root@af1dc1924b47:/rev# ./crackme1
12
22
33
11
11
11
11
11
11
11
12 22 33 11 11 11 11 11 11 11
Wrong!

Значит бинарь считывает 10 чисел с клавиатуры, а далее проверяет их корректность в int_fold1.

int_foldl1:

int32_t int_foldl1(int32_t* func, int32_t count, int32_t* key)

    return int_foldl(func, pos: 0, len: count, key)

int_foldl:

int32_t int_foldl(int32_t* func, int32_t pos, int32_t len, int32_t* key)
    if (len == 0)
        return pos
    
    return int_foldl(func, pos: func(pos, *key), len: len - 1, key: &key[1])

Давайте разберем. Функция int_foldl1 является вызывающей для int_foldl, которая задает pos в 0. Условие проверки мы видели.

В качестве проверки у нас используются логические функции xor и and.

xor:

int32_t xor(int32_t arg1, int32_t arg2) __pure
{
    return (arg1 ^ arg2);
}

and:

int32_t and(int32_t arg1, int32_t arg2) __pure
{
    if ((arg1 != 0 && arg2 != 0))
        return 1;
    
    return 0;
}

В отладчике я сидеть не хочу, поэтому накидаю код на python:

def xor_test(nums: int):
    key = 0
    for n in nums:
        key ^= n
    print(key)
    return key


def and_test(nums: int):
    key = 1
    for n in nums:
        if key != 0 and n != 0:
            key = 1
        else:
            key = 0
    return key


nums = []
if xor_test(nums) != 0 or and_test(nums) == 0:
    print('Wrong')
else:
    print('Correct')

Теперь нужно подобрать правильный список из 10 чисел, чтобы у нас выполнилось условие проверки. В целом, это не должно быть сложно. Так как чисел у нас 10, то мы легко может пройти проверку xor - нужно передавать пары одинаковых чисел. Для прохождения проверки AND нам нужно, чтобы у нас не было 0. Это тоже легко. Сильно голову ломать не буду, подставлю 10 единиц:

cu63:crackme1/ $ python test.py                                                                                   
1
0
Correct

Проверю на оригинальном бинаре:

IMG

Это строка и является флагом.