→ DC18: bin500

| No TrackBacks

Binary500 является исполняемым ELF'ом для SPARC V9. Дизассемблированный листинг на первый взгляд похож на смесь IA32 + ESA/390 в синтаксисе AT&T. После знакомства с архитектурой и используемыми соглашениями, все становится на свои места:
Процессор имеет 32 64-х битных регистров общего назначения: global %g0-%g7, out %o0-%o7, local %l0-%l7, in %i0-%i7, 32 регистра FPU и систему быстрых, но простых команд длиной 32 бита каждая. Некоторые регистры имеют особое назначение: %g0 всегда содержит ноль, %o6 также известен как %sp (stack pointer), %i6 - %fp (frame pointer), %o7 содержит адрес текущей инструкции при выполнении вызова подпрограммы и используется для определения адреса возврата. Регистры %o0-%o5 используются для передачи аргументов в процедуры, команда, save сохраняет и меняет mapping регистров в процедуре, и %i0-%i5 будут содержать значения из %o, то есть, переданные аргументы. %o0 содержит возвращаемое значение из процедуры.
Также стоит отметить специфику выполнения циклов: инструкция, следующая за командой условного перехода исполняется всегда. Но если условный переход не был выполнен, ее результат аннулируется.
Можно приступать к разбору.

Так как команды имеют длину всего 4 байта (кроме т.н. синтетических инструкций), а адреса - 8 байт, то одной командой адрес не загрузить, и используются конструкции вида (! обозначает комментарий)
set 0x100000, %l1
sllx %l1, 12, %l1
bset 0xFE0, %l1 ! 100000FE0

Анализ неизвестного кода (тем более на не очень знакомой архитектуре) начинают с рассмотрения функций стандартных библиотек или системных вызовов. У нас таких функций (SUNW_C_GetMechSession, C_CreateObject, C_EncryptInit,..., fopen, fprintf,...) в избытке. Если погуглить по первым двум, то приходим на Symmetric Encryption Example, что почти один-в-один с исследуемой программой. Осталось разобрать, где какие значения лежат в нашем коде. Также пригодится этот заголовочный файл для определения констант.

В функции main практически в самом начале (адрес 100000C5C) видим вычисление адреса 100000FE0 и копирования 8 байт оттуда в стековую переменную. Ее значение становится 0xDEADBEEFBAADF00D. Затем идет вычисление адреса 100000FE8 и копирование оттуда 0x78 байт в стек. Причем адрес приемника вычисляется как sethi %hi(0x3800), %g5 + btog -0x101, %g5. Запомним это.
Далее - формирование параметров для SUNW_C_GetMechSession. Из примера от SUN мы знаем, что должно быть что-то вроде

mechanism.mechanism = CKM_DES_CBC_PAD;
mechanism.pParameter = des_cbc_iv;
mechanism.ulParameterLen = 8;
SUNW_C_GetMechSession(mechanism.mechanism, &hSession);

В листинге видим число 8, видим константу 0x125 = CKM_DES_CBC_PAD. Переименовываем стековые переменные
mechanism.mechanism= 0x7CF
arg_7D7 = 0x7D7
mechanism.ulParameterLen= 0x7DF
Это значит, что arg_7D7 = mechanism.pParameter, а des_cbc_iv = 0xDEADBEEFBAADF00D - что скопировали в самом начале main. SUNW_C_GetMechSession возвращает в %o1 идентификатор hSession.

Пропускаем открытие файла и доходим до вызова C_CreateObject, именно здесь указывается ключ шифрования, как видно из примера от SUN:

CK_ATTRIBUTE template[] = {
{CKA_CLASS, &class, sizeof (class) },
{CKA_KEY_TYPE, &keyType, sizeof (keyType) },
{CKA_TOKEN, &falsevalue, sizeof (falsevalue) },
{CKA_ENCRYPT, &truevalue, sizeof (truevalue) },
{CKA_VALUE, &des_key, sizeof (des_key) } };
C_CreateObject(hSession, template, sizeof (template) / sizeof (CK_ATTRIBUTE), &hKey);

В листинге видим, что значение %o1 вычисляется как sethi %hi(0x3800), %g5 + btog -0x101, %g5. Это значит, что template был сформирован в начале main и находился по адресу 100000FE8 до копирования в стек, и выглядит следующим образом (5 элеметов по 3 quad в каждом):

.quad 0
.quad 0x100101678
.quad 8
.quad 0x100
.quad 0x100101680
.quad 8
.quad 1
.quad 0x100101671
.quad 1
.quad 0x104
.quad 0x100101670
.quad 1
.quad 0x11
.quad 0x100101668
.quad 8

С помощью файла констант можно восстановить исходную структуру:

{ {CKA_CLASS, 0x100101678, 8}, /* value 4 = CKO_SECRET_KEY */
{CKA_KEY_TYPE, 0x100101680, 8}, /* value 0x13 = CKK_DES */
{CKA_TOKEN, 0x100101671, 1}, /* value 0 = FALSE */
{CKA_ENCRYPT, 0x100101670, 1}, /* value 1 = TRUE */
{CKA_VALUE, 0x100101668, 8} } /* value 0xDD73CC7FDD7ECC7F */

Далее идет чтение данных из файла и шифрование в цикле.
Итак, имеем алгоритм, паддинг, ключ и шифротекст, осталось написать процедуру расшифрования. Берем pyDes, пишем скрипт и получаем ответ allthatworkanditsjustDES!?!

No TrackBacks

TrackBack URL: http://smokedchicken.org/m/mt-tb.cgi/34

About this Entry

This page contains a single entry by Павел Збицкий published on May 29, 2010 1:42 PM.

DC18: bin200 & bin300 was the previous entry in this blog.

IDA Entropy Plugin is the next entry in this blog.

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