Boston Key Party: Unholy
Дан ELF, который используется из Ruby.
require_relative 'unholy'
include UnHoly
python_hi
puts ruby_hi
puts "Programming Skills: PRIMARILY RUBY AND PYTHON BUT I CAN USE ANY TYPE OF GEM TO CONTROL ANY TYPE OF SNAKE"
puts "give me your flag"
flag = gets.chomp!
arr = flag.unpack("V*")
is_key_correct? arr
Никогда не писал на Ruby, но судя по всему он предназначен для проверки корректности флага, который читается из файла. Но файла у нас нет, поэтому будем угадывать, чтобы там могло быть…
Данные, судя по коду в IDA, передаются по 4 символа как int. Внутри они перемешиваются и передаются скрипту на питоне, который запускается и выдает вердикт -- верен флаг или нет.
import struct
e=range
I=len
import sys
F=sys.exit
X=[[0,0,2130567168],[-858993460,-858993460,-858993460],[-858993460,-858993460,-858993460]]
Y =[[383212,38297,8201833],[382494,348234985,3492834886],[3842947,984328,38423942839]]
n=[5034563854941868,252734795015555591,55088063485350767967,-2770438152229037,142904135684288795,-33469734302639376803,-3633507310795117,195138776204250759,-34639402662163370450]
y=[[0,0,0],[0,0,0],[0,0,0]]
A=[0,0,0,0,0,0,0,0,0]
for i in e(I(X)):
for j in e(I(Y[0])):
for k in e(I(Y)):
y[i][j]+=X[i][k]*Y[k][j]
c=0
for r in y:
for x in r:
if x!=n[c]:
print "dang..."
F(47)
c=c+1
print ":)"
Сама проверка на питоне суть просто перемножение матрицы X чисел 3х3 (значит 9 чисел, то есть во флаге должно быть 4х9 = 36 символов, часть из которых известна -- это BKPCTF{.*}) на другую Y и сравнение результата с эталонным.
Реверсим просто -- находим в Wolframalfa обратную матрицу и умножаем на нее эталон.
Получаем числа какие-то. Подставляем на всякий случай в код проверки -- проходят.
Следующим этапом смотрим код в IDA, который перемешивает собственно.
Видно, что числа попарно просто почти xorятся и все. Так как 9 на 2 не делится нацело, у нас есть одно лишнее число для проверки, которое не пойдет в питон, а значит длина флага на 4 символа больше…
int v14[4] = {0x74616877, 0x696F6773, 0x6E6F676E, 0x65726568};
unsigned int f(unsigned int x)
{
return (16 * x ^ (x >> 5)) + x;
}
int i = 0LL;
do
{
int i_2 = 0;
unsigned int loDword = x11[i];
unsigned int hiDword = x11[i+1];
do
{
v11 = i_2 + v14[(i_2 & 3)];
v12 = i_2 + v14[((i_2 >> 11) & 3)];
i_2 -= 0x61C88647;
loDword = (v11 ^ f(hiDword) + loDword;
hiDword = (v12 ^ f(loDword) + hiDword;
}
while ( i_2 != 0xC6EF3720 );
x11[i] = loDword;
x11[i+1] = hiDword;
i += 2LL;
}
while ( i != 10 );
assert(x11[9] == 0x4DE3F9FD);
Элементарными алгебраическими преобразованиями реверсим этот алгоритм и получаем флаг в виде чисел.
Преобразуем его в строку, не забывая про порядок байт :) - получаем флаг!
- Автор: YanTayga
- Комментарии: 0
- Просмотры: 2640