Solution
И снова не понятно, что за файл. В diec его:
Info:
File name: /spbctf_rev/cosy/cosy
Size: 16384
File type: ELF64
String: ELF(AMD64)
Extension: so
Operation system: Debian Linux(ABI: 3.2.0)
Architecture: AMD64
Mode: 64-bit
Type: DYN
Endianness: LE
Анализ main
Пойду смотреть main.
int32_t main(int32_t argc, char** argv, char** envp)
{
puts("Give me the key: ");
char buf[0x100];
fgets(&buf, 0xff, stdin);
int32_t rax = strlen(&buf);
buf[(uint64_t)(rax - 1)] = 0;
if (strlen(&buf) != 0x16)
{
puts("Incorrect length");
exit(0xffffffff);
/* no return */
}
int64_t var_138;
__builtin_memset(&var_138, 0, 0x16);
int32_t var_198;
__builtin_memcpy(&var_198,
"\x11\x0c\x00\x00\xbb\x25\x00\x00\xae\x00\x00\x00\x09\x27\x00\x00\xb7\x0c\x00\x00\xe9\x26\x00"
"00\xf4\x16\x00\x00\xce\x22\x00\x00\x0b\x18\x00\x00\x02\x27\x00\x00\x1e\x11\x00\x00\xc8\x1e\x"
"00\x00\xc2\x04\x00\x00\xd4\x21\x00\x00\xb7\x0c\x00\x00\x2a\x22\x00\x00\x0b\x18\x00\x00\x35\x"
"26\x00\x00\x87\x13\x00\x00\xef\x24\x00\x00\xc2\x04\x00\x00\x33\x1f\x00\x00",
0x58);
int32_t var_c = 0;
while (true)
{
if (rax - 1 <= var_c)
{
puts("Correct!");
exit(0);
/* no return */
}
int32_t rax_9 = toRad(buf[(int64_t)var_c]);
if (rax_9 < 0)
{
puts("Internal error");
exit(0xffffffff);
/* no return */
}
int32_t temp0_1;
int32_t temp1_1;
temp0_1 = HIGHD((int64_t)var_c);
temp1_1 = LOWD((int64_t)var_c);
uint32_t rdx_3 = temp0_1 >> 0x1f;
if (modify(rax_9, ((temp1_1 + rdx_3) & 1) - rdx_3) != (&var_198)[(int64_t)var_c])
break;
var_c += 1;
}
puts("Wrong input");
exit(0xffffffff);
/* no return */
}
Слишком много букаф. Ну да ладно. Флаг у нас имеет длину 22.
Анализ toRad
Мда. Переводим символ в число. Пон)
uint64_t toRad(char arg1)
{
if (arg1 > '`' && arg1 <= 'z')
return (uint64_t)((int32_t)arg1 - 'a');
if (arg1 > '/' && arg1 <= '9')
return (uint64_t)((int32_t)arg1 - '\x16');
if (arg1 == '{')
return '$';
if (arg1 == '}')
return '%';
if (arg1 != '_')
return 4294967295;
return '&';
}
Анализ modify
Опять немного математики.
uint64_t modify(int32_t arg1, int32_t arg2)
{
double zmm0 = 3.141 * (double)arg1 / 180.0;
if (!arg2)
return (uint64_t)(int32_t)(sin(zmm0) * 10000.0);
if (arg2 != 1)
return 0;
return (uint64_t)(int32_t)(cos(zmm0) * 10000.0);
}
Написание декодера
Разбирать многое то и не нужно. Каждый символ ключа преобразуется вот в такие значения:
mem2[0] = 0xc11;
mem2[1] = 0x25bb;
mem2[2] = 0xae;
mem2[3] = 0x2709;
mem2[4] = 0xcb7;
mem2[5] = 0x26e9;
mem2[6] = 0x16f4;
mem2[7] = 0x22ce;
mem2[8] = 0x180b;
mem2[9] = 0x2702;
mem2[10] = 0x111e;
mem2[11] = 0x1ec8;
mem2[12] = 0x4c2;
mem2[13] = 0x21d4;
mem2[14] = 0xcb7;
mem2[15] = 0x222a;
mem2[16] = 0x180b;
mem2[17] = 0x2635;
mem2[18] = 0x1387;
mem2[19] = 0x24ef;
mem2[20] = 0x4c2;
mem2[21] = 0x1f33;
Есть 2 возможных логичных решения:
- повторить код и брутить значения;
- написать обратные функции;
Первый вариант проще, поэтому его и сделаю. Меньше шансов ошибиться. Да и можно закинуть код в гпт и попросить его навоять такое же. Мы же тут реверсом занимаемся, а не разработкой. Еще предложите переменные адекватно называть, психи…
import math
def toRad(arg1: str) -> int:
c = arg1
if '`' < c <= 'z': # 'a'..'z'
return ord(c) - ord('a')
if '/' < c <= '9': # '0'..'9'
return ord(c) - 0x16 # '\x16' == 22
if c == '{':
return ord('$') # '$' == 36
if c == '}':
return ord('%') # '%' == 37
if c == '_':
return ord('&') # '&' == 38
return 0xFFFFFFFF # 4294967295 (uint32_t -1)
def modify(arg1: int, arg2: int) -> int:
zmm0 = 3.141 * float(arg1) / 180.0
if arg2 == 0:
val = math.sin(zmm0) * 10000.0
return int(val) & 0xFFFFFFFF
elif arg2 == 1:
val = math.cos(zmm0) * 10000.0
return int(val) & 0xFFFFFFFF
else:
return 0
if __name__ == '__main__':
mem2 = [0] * 22
mem2[0] = 0xc11
mem2[1] = 0x25bb
mem2[2] = 0xae
mem2[3] = 0x2709
mem2[4] = 0xcb7
mem2[5] = 0x26e9
mem2[6] = 0x16f4
mem2[7] = 0x22ce
mem2[8] = 0x180b
mem2[9] = 0x2702
mem2[10] = 0x111e
mem2[11] = 0x1ec8
mem2[12] = 0x4c2
mem2[13] = 0x21d4
mem2[14] = 0xcb7
mem2[15] = 0x222a
mem2[16] = 0x180b
mem2[17] = 0x2635
mem2[18] = 0x1387
mem2[19] = 0x24ef
mem2[20] = 0x4c2
mem2[21] = 0x1f33
for i, target in enumerate(mem2):
for c in "abcdefghijklmnopqrstuvwxyz_{}0123456789":
n = toRad(c)
n = modify(n, i % 2)
if n == target:
print(c, end='')
break
print('\n')
Запущу код:
root@2972fc48b804:/rev# python3 solver.py
spbctf{1_d0_h4t3_m4th}
Проверю в оригинальном бинаре:
root@2972fc48b804:/rev# ./cosy
Give me the key:
spbctf{1_d0_h4t3_m4th}
Correct!