Нужно пройти все проверки, чтобы получить флаг.
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!!!!!!!!!!