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);




Элементарными алгебраическими преобразованиями реверсим этот алгоритм и получаем флаг в виде чисел.

Преобразуем его в строку, не забывая про порядок байт :) - получаем флаг!скачать dle 10.5фильмы бесплатно

  • Автор: YanTayga
  • Комментарии: 0
  • Просмотры: 2430

Добавить комментарий

Вы не авторизованы и вам запрещено писать комментарии. Для расширенных возможностей зарегистрируйтесь!