April 2010 Archives

Histograph... Сервис представляет из себя CGI-программу launch в виде ELF-бинарника. На вход принимает GET-параметры:
action - запрошенное действие, мини-программа на собственном языке в каталоге ./actions
arg - дополнительный параметр для определенных action'ов
in, out - имена входных и выходных файлов.

Флаги хранит в каталоге ./data в виде гистограмм-битмапов.

Соответственно, на каждый запрос подгружается нужная подпрограмма, и интерпретируется-выполняется.
Из полезных подпрограмм set (установить флаг - сгенерировать картинку по флагу), get (получить флаг-картинку), hint (типа подсказка).

Виртуальная машина представляет из себя 16-ти битный процессор с обычными командами типа MOV, PUSH, POP, CALL, RETN,... и необычными - печать значения переменной в консоль, читать / писать символ в файловый поток, system и т.д., всего 28 команд. Каждая команда - байт опкода + 1, 2 или 3 16-ти битных операнда. Зная это, несложно написать простой дизассемблер :)

Изучив подпрограмму get, можно узнать, что если запросить файл, состоящий из 111 и более букв o, можно выполнять произвольные команды, например, так:
launch?action=get&in=myfile&arg=echo 'Content-Type:text/plain\r\n';ls

Изучив hint, можно сделать
launch?action=hint&arg=3255
и получить подсказку в виде

struct registers{unsigned short ip;unsigned short sp;unsigned short bp;} reg;

enum opcodes{SET=0x0,MOV=0x1,ADD=0x2,SUB=0x3,MUL=0x4,
JMP=0x5,JE=0x6,JA=0x7,JB=0x8,CALL=0x9,RET=0xa,DIV=0xb,READ=0x10,WRITE=0x11,
PRINT=0x12,EXEC=0x13,PUSH=0x20,POP=0x21,ENTER=0x22,LEAVE=0x23,GETBP=0x24,PTR=0x25,MOVPTR=0x26,
END=0x30,DUMP=0x40,CONTTYPE=0x41,SHOWSHORT=0x42,GETSHORT=0x43};

Не знаю, как она поможет на этом этапе, когда дизассемблер уже написан.

Осталось 2 вопроса: как туда залить этот файл с oooo, чтобы потом получать список файлов-картинок, и как затем распознавать эти картинки. Вероятно, надо ковырять подпрограмму set. Собственно, проблема с картинками и заставила отступиться от сервиса во время игры.

Дизассемблер, launch, подпрограммы прилагаются.

UPD: Подпрограмма echo позволяет также создавать файлы, если указан параметр out. Таким образом, создать файл с ooo...ooo можно так:
launch?action=echo&out=myfile&arg=oooooo...ooo

UPD2: Генерация картинок, подпрограмма set.
0. Вывод заголовков битмапа в файл и stdout.
1. Вычисляется сумма по символам флага: Sum = flag[i] * (i + 1) mod 256, i =0,31
2. Флаг кодируется с учетом вычисленного значения Sum и таблицы, находящейся по смещению 0x04B3 в set:
index = (flag[i] + Sum) mod 256
flag[i] = table[index]
3. Формирование битмап-картинки.
Картинка представляет из себя изображение размера 500 x 300. По краям гистограммы белые поля, сама гистограмма расположена по x от 26 (0x1A) до 474 (0x1DA) и по y от 22 (0x16) до 278 (0x116).
Заполнение битмапа представляет собой два вложенных цикла по высоте и ширине картинки:
for (i = 0; i < 300; i++)
for (j =0; j < 500; j++)
draw(i,j)

Пиксели, координаты которых не попадают в границы гистограммы, выводятся белым. Оси гистограммы выводятся черным. Если же пиксель не попадает ни на оси, ни на поля, производится вычисление высоты рисуемого столбца гистограммы:
index2 = (j - 26 - 1) / 14
Так как значения j у нас в промежутке от 27 до 474, то index2 принимает значение от 0 до 31, как раз по длине флага.
Далее, вычисляется собственно высота: 278 - flag[index2]. Если полученное значение больше i (текущей отрисовываемой высоты битмапа), то заливаем белым, если равна - рисуем черную окантовку, и рисуем зеленым, если меньше.

Как высчитывать по картинке флаг. Определяем высоту столбца, вычитаем из 278. Получаем значение flag[index2]. Затем находим в таблице table это значение и запоминаем индекс index. Получаем 32 сравнения index = (flag[i] + Sum) mod 256 с двумя неизвестными flag[i] и Sum. Но для так как flag[31] = '=', вычисляем Sum и запросто решаем остальные уравнения.

Сервис сдался. Это было достаточно жестко.

UPD3: PoC - декодер картинок:
test-img : ABCDEFGHIJABCDEFGHIJABCDEFGHIJ1=
0087-4icm-7v79 : VIWW0KCUTYLFJ9TTQH05S0JX7V19WOJ=
Но почему-то не берет encrypted_src/default.

Рассмотрим еще один сервис, по которому никто не добыл ни одного флага. Это сервис svn. Невероятно, но на его анализ и поиск основной уязвимости у меня ушло ДЕСЯТЬ минут, и еще десять на написание эксплойта, который получает флаги с сервиса. В хаскеле я так и не разобрался, поэтому вероятно есть и другие уязвимости. Вероятно все посмотрели, что сервис написан на хаскеле и забили, так сделали и мы, а зря.

Все очень просто, сервис хранит флаги в файлах каталога /home/svn/repo/. Сервис поддерживает следующие команды:
l - получение списка файлов
+<filename> <char> - добавить в файл "+<char>"
-<filename> <char>  - добавить в файл "-<char>"
*<filename> <pos> <char>  - добавить в файл "*<pos> <char>"
<filename> <rev> - получить определенную ревизию файла
<filename> - получить последнюю ревизию файла

Эксплойт состоит в том, что бы сначала послать "l\n", а потом посылать имена файлов полученные на пред. этапе для получения флагов.

Итого:
  • хаскел я так и не знаю
  • команды испугалась незнакомого языка и упустили прекрасную возможность получить флаги.
  • exploit svn.py

В продолжение темы RuCTF2010, хочу рассмотреть еще один уязвимый сервис - CertificateAuthority. Во время игры, флаги с этого сервиса удалось получить только команде SiBears. Сервис CA (certificateauthority.tgz) написан на Java, но это не принципиально. Функционально он представляет собой сервис для выдачи сертификатов и хранения любых сообщений пользователей. Игровые чекеры получали сертификат и оставляли зашифрованное сообщение (флаг).

Предоставленный исходный код содержал функционал не только генерирования сертификата, но и шифрования сообщения, своеобразная подсказка от разработчиков позволила понять в каком формате чекер оставляет сообщения. Почти с первых минут анализа кода стало ясно, что нужно искать уязвимость в криптостойкости применяемого алгоритма. Активный гуглинг на тему дискретного логарифмирования показал, что мы имеем дело со схемой ElGamal. А одним из эффективных алгоритмов дискретного логарифмирования (схема строится на его сложности) является алгоритм Полига-Хеллмана.

Еще гугла, еще кодинга и мы получили PoC (ca.py), но к сожалению игра уже несколько секунд как закончилась, успели только отправить адвайзори без эксплойта. Жаль, что мы взялись за этот сервис так поздно.

Патчинг состоит в использовании достаточно большого простого числа P, на котором генерируется сертификат.

На прошедшем 25 апреля контесте было замечено странное поведение vulnbox'a - глючил tcpdump, а также иногда на консоль валилось что-то типа
BUG: scheduling while atomic: swapper/0/0x10000100

В списке сервисов было нечто под именем GPLv4, которое, к сожалению, мы обнаружили только на следующий день после окончания соревнований: Антон заметил в логе трафика подозрительную UDP-активность - пакеты на произвольные порты, и, что самое забавное, ответы на них от vulnbox.

Как оказалось, это был модуль ядра m.ko, реализующий сетевой фильтр для UDP-трафика. Дизассемблер подсказал, что он принимает команды G (get), P (put), L (list) и хранит флаги в /proc/flags/. UDP-сообщения шифруются инструкцией XOR с ключом 'THINKPAD' первые 8 байт сообщения, следующие 8 байт - XOR с предыдущими 8 байтами этого же сообщения.

Чтобы получить список файлов с флагами, достаточно послать зашифрованную команду 'L', а затем сделать Gfile_name элементам полученного списка файлов.

Также в основной функции-фильтре есть утечка памяти под размер данных UDP-пакета. Вероятно, возможен DOS.

POC прилагается.

В IDA Free 4.9 иногда не хватает поддержки питонового скриптинга. Здесь можно найти патч для SDK от 4.9 - перемапливание имен / ординалов в ida.lib в соответствии с ida.wll из IDA Free. Также можно скачать IDAPython 0.8 для IDA 4.9 и пересобрать. Но варезный SDK 4.9 портит всю малину IDA Free.
Решение - взять python.plw 0.8 и зафиксить в нем импорт. Конечно, IDAPython 0.8 совсем не 1.2, но все же.
Скрипт, конечно же, питоновый, приложен: python49.7z.

About this Archive

This page is an archive of entries from April 2010 listed from newest to oldest.

March 2010 is the previous archive.

May 2010 is the next archive.

Find recent content on the main index or look in the archives to find all content.