Нужно пройти все проверки, чтобы получить флаг.

Solution

Анализ main

Перейду к просмотру main:

int32_t main(int32_t argc, char** argv, char** envp)
{
    void* fsbase;
    int64_t rax = *(uint64_t*)((char*)fsbase + 0x28);
    char s[0x408];
    char* var_4f0 = strtok(&s, ",");
    int32_t i = 0;
    __isoc99_scanf("%1024s", &s);
    int32_t var_50c = 0xffffffff;
    char* nptr = strtok(&s, ",");
    int32_t var_4e8[0x34];
    
    do
    {
        char* endptr;
        int32_t rax_5 = strtol(nptr, &endptr, 0xa);
        
        if (*(uint8_t*)endptr)
        {
            puts("You gave me the shit");
            exit(1);
        }
        
        if (rax_5 <= var_50c)
        {
            puts("You gave me unsorted shit");
            exit(1);
        }
        
        var_50c = rax_5;
        int32_t i_2 = i;
        i = i_2 + 1;
        var_4e8[(int64_t)i_2] = rax_5;
        nptr = strtok(nullptr, ",");
        
        if (!nptr)
            break;
    } while (i <= 0x31);
    
    if (i != 50)
    {
        puts("Give me more numbers");
        exit(1);
    }
    
    for (int32_t i_1 = 0; i_1 <= 0x31; i_1 += 1)
    {
        int32_t rax_14 = var_4e8[(int64_t)i_1];
        
        if (sub_400765((&data_6020c0)[(int64_t)rax_14 * 2])
            != strtol((&data_6020c8)[(int64_t)rax_14 * 2], nullptr, 0x10))
        {
            puts("You still trying to drown me in the shit");
            exit(1);
        }
        
        data_602080[(int64_t)i_1] ^= (char)var_4e8[(int64_t)i_1];
    }
    
    puts("fmccZn{R$%!u$-t.~+-~");
    
    if (rax == *(uint64_t*)((char*)fsbase + 0x28))
        return 0;
    
    __stack_chk_fail();
}

Далее я буду показывать уже разобранный код. Вот тут происходит заполнение массива числами, которые передаются через , в порядке возрастания:

do
{
    char* endptr;
    int32_t num = strtol(nptr, &endptr, 10);
    
    if (*(uint8_t*)endptr)
    {
        puts("You gave me the shit");
        exit(1);
    }
    
    if (num <= num_1)
    {
        puts("You gave me unsorted shit");
        exit(1);
    }
    
    num_1 = num;
    int32_t i_2 = i;
    i = i_2 + 1;
    array[(int64_t)i_2] = num;
    nptr = strtok(nullptr, ",");
    
    if (!nptr)
        break;
} while (i <= 49);
root@12e19b324fb7:/rev# ./adooha64.elf
1,2,3
Give me more numbers
root@12e19b324fb7:/rev# ./adooha64.elf
3,2,1
You gave me unsorted shit

Чисел должно быть 50. Сгенерирую последовательность на Python:

print(','.join([f'{i}' for i in range(0, 50)]))
root@12e19b324fb7:/rev# ./adooha64.elf
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49
You still trying to drown me in the shit

Хорошо. Мы дошли до главной проверки:

for (int32_t i_1 = 0; i_1 <= 0x31; i_1 += 1)
{
    int32_t key_pos = array[(int64_t)i_1];
    
    if (sub_400765((&data_6020c0)[(int64_t)key_pos * 2])
        != strtol((&data_6020c8)[(int64_t)key_pos * 2], nullptr, 0x10))
    {
        puts("You still trying to drown me in the shit");
        exit(1);
    }
    
    flag[(int64_t)i_1] ^= (char)array[(int64_t)i_1];
}

Посмотрю, что там за данные. Каждая пара — строка и её контрольная сумма в hex:

char const (* data_6020c0)[0xa] = data_400ae8 {"123456789"}
char const (* data_6020c8)[0x9] = data_400af2 {"CBF43926"}
char const (* data_6020d0)[0x15] = data_400afb {"INByV5qSKB3Cr03y3I7J"}
char const (* data_6020d8)[0x9] = data_400b10 {"0698525B"}
// ...

А вот и сам зашифрованный флаг:

char flag[0x31] = "fmccZn{R$%!u$-t.~+-~\x15\x1aED\x12\x1b\x07\x04\x03\x03]\n\x04[rzqry(kjmqrx}|~"

Анализ sub_400765

Больше всего вопросов вот к этим функциям:

uint64_t sub_400765(void* arg1)
{
    int32_t var_18 = 0;
    int32_t var_c = 0xffffffff;
    
    while (*(uint8_t*)((char*)arg1 + (int64_t)var_18))
    {
        int32_t var_10_2 = sub_4006d6((uint32_t)*(uint8_t*)((char*)arg1 + (int64_t)var_18));
        
        for (int32_t i = 0; i <= 7; i += 1)
        {
            var_c = (var_c ^ var_10_2) >= 0 ? var_c << 1 : (var_c * 2) ^ 0x4c11db7;
            var_10_2 <<= 1;
        }
        
        var_18 += 1;
    }
    
    return sub_4006d6(~var_c);
}

uint64_t sub_4006d6(int32_t arg1) __pure
{
    int32_t rax_5 = (arg1 >> 1 & 0x55555555) | ((arg1 & 0x55555555) * 2);
    int32_t rax_11 = (rax_5 >> 2 & 0x33333333) | (rax_5 & 0x33333333) << 2;
    int32_t rax_18 = (rax_11 >> 4 & 0xf0f0f0f) | (rax_11 & 0xf0f0f0f) << 4;
    return (uint64_t)(rax_18 >> 0x18) | (uint64_t)(rax_18 << 0x18)
        | (uint64_t)((rax_18 & 0xff00) << 8) | ((uint64_t)(rax_18 >> 8) & 0xff00);
}

Загнал их в GPT. Он сказал, что это CRC32. Проверить это легко — первая пара данных "123456789" / "CBF43926" совпадает с известным тест-вектором CRC32.

Решение

Итак, нам нужно пройтись по списку всех пар, вычислить CRC32 от строки и сравнить с результатом. Если совпали — запоминаем индекс этой пары.

import zlib

data = [
    ("123456789", "CBF43926"),
    ("INByV5qSKB3Cr03y3I7J", "0698525B"),
    ("sTNf34DGdqP0yNDy6OoQ", "BD7FA6E5"),
    ("WkCe0SdK7c6Ip4QLugcp", "BB6E2E9D"),
    ("aZunZdPL93fARg6QH6Wv", "1CAE4738"),
    ("bpfHJ0zrxjV3Jf42lKIs", "F6986BDA"),
    ("nFrukjqzbOp7aTEC43z0", "5CE57091"),
    ("jnSAbLutXfbP6jFWoDeP", "7424F3F8"),
    ("rmBEMgQEsFRMn9ZmOUCU", "060F3DCD"),
    ("dXHXv6jW2nEY2sUbydlV", "29F4AA7C"),
    ("zwMe1BZOf7m0LtiPqoIT", "FDB10CE9"),
    ("Y2mWMVmg0f1xTsEkJdyN", "09FEB49A"),
    ("Wm6CW7sMFiwzmHw2M8jX", "28DEB110"),
    ("72rMtCHCb0OEiLX29g7u", "64BC67CC"),
    ("nufOMpIjrKbzPlfKIdaH", "3A121D14"),
    ("UZETiRhSHmuW9AqewUpF", "5CB09F9F"),
    ("mPv97LjnQyfpadvdlfT1", "10B30CED"),
    ("3iw2nqbJxcTaUpVc7Pcr", "72E3F041"),
    ("DyNhcaPhrGU5AP0bxelU", "6382203A"),
    ("VLLRX20lDvHlnWRZoCPr", "3CB5570F"),
    ("8ABoQRMrxzWCVVkeCqjj", "18736753"),
    ("PQ1g928hZva4y2Bz9jKP", "580931E7"),
    ("u7qKDwKr1nzp9OlQn1k7", "E72E8219"),
    ("6sK5UV6CbuY05bSRMYDp", "AF5D411C"),
    ("5JxmuAjMIC2rHRH9Vz5Q", "CC4BF478"),
    ("ftxn19VoKXb1FAtqc7lq", "1AE5F074"),
    ("ZRxnd33O5L0tELG95ckq", "FA929D6B"),
    ("MKmuLtJfPRAcKljyqZQc", "07FF479D"),
    ("DnvFYDAkbCh1Bi0ZPl67", "1EE90516"),
    ("EjOLx6JysuKv6H6Ad5q9", "2A242992"),
    ("FVOflh708Im0u7rQ382f", "C1AF8F61"),
    ("EId9l96ZE7f3MEb95Lqa", "EF2A968C"),
    ("CHa6N7nkwOFTnkJBzoQu", "1DCABB35"),
    ("stOMomJLxwSif1UKl49B", "76A0CE46"),
    ("88NLayQ6iXpu2ldQw4DU", "B9BF0A45"),
    ("7KX0GR05X59eZ8I5N50q", "534A6893"),
    ("1IjDObg2uXpHCxL0VaIf", "D171293C"),
    ("TmAsYZx27UtZYWULwmw3", "A2672F97"),
    ("TRf3C3mdEJjXkiQcUefS", "78AB4784"),
    ("CV7nXcXlRxv0TL4MKGhZ", "ADD8416D"),
    ("DIzQRzLovtrSDxotBQqk", "366D6EEF"),
    ("MsnvgyyNuFSsoIG88GWx", "FF88D119"),
    ("ZoEuWJEzCOboD5om4tML", "7318D1F0"),
    ("MweEIx0UNHRzaZWwd1ay", "F90CF4E6"),
    ("Dj53q82wblbM13RpBwEw", "BE03D81C"),
    ("gl5jDYGBfHSDmAZgx9N0", "9F9F0316"),
    ("1r6pMaezN3vIM3Xx3g80", "AFE06ADC"),
    ("gQJaZ5vGoLN5Ml4PWFsm", "A09DDE18"),
    ("F3GyR3lBC3HrjGGk7Sm6", "1A7FFE8C"),
    ("Mi5ZURtzabIw5ffSGHyP", "EF452CEB"),
    ("MnzZblTTqL6FkOgRAUcJ", "CCDB0995"),
    ("OPOmdglncY9kDIDCEboW", "6523E715"),
    ("6pdOfXq69Asfc9fHwB3j", "209321C4"),
    ("qhbU2EthlUsvV6QvQFh3", "235653F6"),
    ("ngACf3aytfEYdGAd6ZvD", "206A99A0"),
    ("y7b0yp2Ryem9Ron36dY2", "9C1259B9"),
    ("2wDarBw96dnrEIMMm3iB", "E7B46105"),
    ("jnDJaiGwQ5o6taxuPpub", "2858F63D"),
    ("SMgDSCWXoyjBAMBnKl9P", "29D46C3F"),
    ("nO6mWwgqDmMDlyNljL2p", "E4CA39B0"),
    ("AaFMIZr0aXX63QB1vMRL", "1964D7ED"),
    ("wOj9h1stqLqKaYWUb3z0", "4B01A888"),
    ("HmS3iueeSlvxYnBw5SVX", "62A01C0D"),
    ("AdnCs8pj9Srl94vfflzG", "49AFFC7D"),
    ("XTgjGhv0bBIALXnr1QRM", "11CC30B5"),
    ("KA3yUpd6FG2glzwGyaEL", "62A29936"),
    ("glAYk2TQxlSZJId4uW4Y", "86057F10"),
    ("yjMdcdjfqcrTmRxWg0AE", "1BBD6208"),
    ("ovvtCBnOjGZ4BpKQic0n", "AA74C633"),
    ("zPKS8BIcudR1f3yV6Ddb", "29D0FA2E"),
    ("OqngHpL5EwoF1WhFsiEx", "EDC4ABC6"),
    ("8kA2bHLd9zhmWCh7mmDZ", "BE949E83"),
    ("Ls4yqqc5aVxZPuX0x6fe", "6009C018"),
    ("8Er2DPP0EPicOquV1h63", "9883BC12"),
    ("l5THEMUGK6vDJk5ly2t8", "4FE872CC"),
    ("Y7QuD13EmqdzHLBIZTOA", "AD809112"),
    ("ufE0UtYFd0eJnO7ETWXZ", "851F2916"),
    ("2hp441U4E7YGMzmEnuln", "6271E10B"),
    ("wsahlt7GMCN3c5KIscfV", "DE35BB14"),
    ("kDvJUaXtpdmi9efnG9Fy", "BA8A8A4F"),
    ("iEBCe5d3ygoHkDW9HRyy", "6AF94455"),
    ("BivEFH2Z1jcaccF0ShuQ", "8D65EB5D"),
    ("sYdBLMtZiy5O6nGoGvJy", "EBC2477B"),
    ("5qDyFclC9P01lcb5Um0X", "FAE79A1A"),
    ("ZxuTCLsmg88azZ86wX5G", "A311D8AD"),
    ("TRM2al8UZRq80tYwZB7K", "FF3541D1"),
    ("ze649Otz7VfSmjABYZXk", "6F753A3F"),
    ("w0Hsv7wICcxvrcLsjqEq", "59B39E7D"),
    ("KM8AxR5AAnNt53fbSMf2", "2B3090F7"),
    ("3YLgiAO8Wo3mCS0BcA6E", "13013455"),
    ("vBHuCBZX6bTYs7CizcYp", "0657AA6B"),
    ("jvrav2abEzdo3cRuHUMf", "F0873544"),
    ("FY1aIehT1dhqh3YxyaYI", "AB6C469A"),
    ("CFIPhWQgvdC8033Ilq9a", "CB202085"),
    ("hbSDB0p6gKnCpIp6wtbr", "66DFAA6D"),
    ("Xnzoa4rUJvNEuUfpnKC0", "2831F9F9"),
    ("iMSrX1ckykooOIJoS68K", "73323FA1"),
    ("aA68qEjrD2BRyL5kVirM", "C27AF852"),
    ("qIrtvgy2EbDVluvRbbBw", "2208F881"),
    ("IS23Bb1WiRoiziKApWuh", "63DE2515"),
]

def get_checksum(s: str) -> str:
    checksum = zlib.crc32(s.encode('utf-8'))
    return f"{checksum:08X}"

if __name__ == '__main__':
    nums = []

    for i, (s, checksum) in enumerate(data):
        if get_checksum(s) == checksum:
            nums.append(i)

    print(','.join([str(n) for n in nums]), len(nums))

Важный момент: возвращаемый hex всегда должен иметь длину 8 ({checksum:08X}), иначе пропустим значения.

Запущу код, чтобы получить ключ:

cu63:Adooha/ $ python solver.py
0,1,2,4,5,7,8,13,16,17,18,19,20,21,22,25,28,29,30,31,32,34,35,38,39,43,48,50,52,54,57,58,60,63,65,67,70,71,72,73,74,75,76,80,83,89,92,93,95,97 50

Теперь запущу сам бинарь:

root@b082099bbc07:/rev# ./adooha64.elf
0,1,2,4,5,7,8,13,16,17,18,19,20,21,22,25,28,29,30,31,32,34,35,38,39,43,48,50,52,54,57,58,60,63,65,67,70,71,72,73,74,75,76,80,83,89,92,93,95,97
flag_is_443f08b7b63a58fb507675d08d39751a!!!!!!!!!!