Boston Key Party: Unholy
- 7-03-2016, 23:07
- 2617
Статьи / Обратная разработка (Reverse Engineering)
Дан ELF, который используется из Ruby.
Никогда не писал на Ruby, но судя по всему он предназначен для проверки корректности флага, который читается из файла. Но файла у нас нет, поэтому будем угадывать, чтобы там могло быть…
Данные, судя по коду в IDA, передаются по 4 символа как int. Внутри они перемешиваются и передаются скрипту на питоне, который запускается и выдает вердикт -- верен флаг или нет.
Сама проверка на питоне суть просто перемножение матрицы X чисел 3х3 (значит 9 чисел, то есть во флаге должно быть 4х9 = 36 символов, часть из которых известна -- это BKPCTF{.*}) на другую Y и сравнение результата с эталонным.
Реверсим просто -- находим в Wolframalfa обратную матрицу и умножаем на нее эталон.
Получаем числа какие-то. Подставляем на всякий случай в код проверки -- проходят.
Следующим этапом смотрим код в IDA, который перемешивает собственно.
Видно, что числа попарно просто почти xorятся и все. Так как 9 на 2 не делится нацело, у нас есть одно лишнее число для проверки, которое не пойдет в питон, а значит длина флага на 4 символа больше…
Элементарными алгебраическими преобразованиями реверсим этот алгоритм и получаем флаг в виде чисел.
Преобразуем его в строку, не забывая про порядок байт :) - получаем флаг!
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);
Элементарными алгебраическими преобразованиями реверсим этот алгоритм и получаем флаг в виде чисел.
Преобразуем его в строку, не забывая про порядок байт :) - получаем флаг!
Комментарии (0)