Новый 2013 год и подведение итогов 2012



6 коммент.
Очередной понедельничный пост, на сей раз новогодний. Решил подвести немного итогов года, оглянуться назад и почить на лаврах :-)

Как оно было?

Год выдался весьма плодотворным: было много конференций, узнал много нового, обновил парк ноутбуков и реализовал хрустальную мечту юности (Lenovo X201 Tablet).

В смысле постов - их было столько же, сколько и в предыдущем году. Стало больше гостевых постов, и это радостно: гостевые посты вносят свежую струю в блог, и так я узнаю много нового и интересного (и надеюсь, не только я).

Запущен в тестовом режиме Лунодром "Дебианити". Это совсем мелкие заметки на манжетах, ссылки и прочие наброски, не подходящие под формат записок. Итог моих экспериментов со scriptogr.am и markdown, а так же временное решение проблемы хранения мелких набросков под рукой (ещё один блог заводить не хочется, здесь публиковать рано или ни к чему, а пригодиться могут).

Теперь итоги. Посты были разные, и интересно взглянуть на то, что понравилось из написанного мне, и что - читателям.

Топ5 постов, которые нравятся мне

Есть посты, которые пишутся в формате "чтобы не забылось" - и это почти всё про LaTeX и Gnuplot, которыми я пользуюсь постоянно. Но есть и нечто особенное, что стоит много часов и дней усилий по сбору материала и выпиливанию подробностей. Итак, мой Топ-5 постов за этот год, которые мне нравятся.

Странное рождение и долгая жизнь UNIX

Пост года, во всяком случае для меня, и самый большой перевод с английского на русский. На перевод и утрясание копирайтов с IEEE ушло почти четыре дня, но результат того стоил. Хотя переводчик с меня не очень хороший, смысл, думаю, передать удалось. Пост важен с исторической точки зрения, дабы помнить, с чего всё начиналось.
Статистика: +31 Plus one, 27 Comments, 5977 Views.

Markdown - гаечный ключ для забивания треугольных болтов

После того, как я нашёл применение Markdown в качестве простого и быстрого генератора вложенных списков для LaTeX, он стал частью моего workflow. Но этому предшествовала переписка с iv_vl, которая, надо сказать, направила меня по ложному следу. Пост был написан после того, как я перепробовал массу опенсорсных сноповязалок и прочих велосипедов с квадратными колёсами :-)
Статистика: +24 Plus one, 33 Comments, 2699 Views.

Краткий обзор современных окружений рабочего стола

Несколько неожиданный для меня экспромт Vlsu, ставший отличным постом. Прекрасные иллюстрации, структура и описания, хотя самый первый вариант был вызывающе неполиткорректным :-) Тем не менее, пост более чем стоил усилий, на него потраченных - один из лучших постов этого года, и абсолютный лидер по количеству просмотров. Браво, Vlsu, снимаю шляпу.
Статистика: +25 Plus one, 72 Comments, 13020 Views.

Pomodoro: тайм-менеджмент, который работает

Pomodoro я использую уже больше года, и для меня это было большим прорывом в плане учёта и анализа собственной продуктивности. Позволяет делать больше без стахановских рывков и прочего ненужного героизма. Пост, один из самых подробных за этот год, писался долго и был сильно улучшен усилиями комментаторов.
Статистика: +28 Plus one, 26 Comments, 3991 Views.

Настольный Змей Горыныч

Один из наиболее информативных постов для меня лично - узнал много нового про multihead, хотя это стоило некоторых денег (купленные переходники, хотя и используются время от времени, но tripple-head на ноутбуке не вышел). Пост нравится своей структурированностью, которая стоила немалых усилий. Кроме того, один из немногих постов, почти полностью написанный в Markdown.
Статистика: +22 Plus one, 18 Comments, 2169 Views.



Топ5 постов, которые понравились читателям

Здесь я ориентировался по числу PlusOne и просмотрам. В комментариях можно отвести душу и привести свои списки, но здесь балом правит бездушная статистика.

Вскрытие 9В батарейки: в поисках батареек АААА

Написанный за час и почти не стоивший усилий, пост неожиданно понравился народу на Хабре и собрал больше всех ПлюсАдынов за этот год (почти полсотни). Все деньги, потраченные на его написание, с лихвой отбились кассовыми сборами с рекламы :-)
Статистика: +46 Plus one, 18 Comments, 5041 Views.

Странное рождение и долгая жизнь UNIX

Здесь наши симпатии совпадают - второй пост по плюсадинам. Кривизну перевода сильно выправил тов. Minoru, за что ему большое спасибо.
Статистика: +31 Plus one, 27 Comments, 5977 Views.

Краткий обзор современных окружений рабочего стола

Самый комментируемый и самый посещаемый пост года от Vlsu. Уже растащен на скриншоты, понаставлена куча ссылок и есть по крайней мере два репоста. Как говорится, признание к художнику приходит не тогда, когда его работы в первый раз выставят, а тогда, когда их в первый раз украдут :-)
Статистика: +25 Plus one, 72 Comments, 13020 Views.

Возможности настройки GRUB2 в Linux

Второй пост по числу просмотров в этом году, и не мой, а написанный Yamamaya. Очень подробный и насыщенный деталями, хотя это и было главным объектом критики ведущего. Тем не менее, пост информативный и второй по количеству просмотров за год.
Статистика: +24 Plus one, 29 Comments, 10591 Views.

Как редактировать в Vim без порчи и бибиканья

Снова гостевой пост, на этот раз от Pento, о текстовом редакторе, который пищит и всё портит. Несмотря на краткость и лаконичность, набрал почти 9000 просмотров и часто появляется в поисковых запросах о Vim.
Статистика: +6 Plus one, 38 Comments, 8480 Views.

И ещё немного статистики

Отбирать что-то лучшее всегда непросто, поэтому я приведу Топ5 самых посещаемых, самых комментируемых и собравших больше всех +1 постов, опубликованных в этом году. Ваше слово, товарищ Статистика!

Самые плюсадинистые


Название постаPlus oneCommentsViews
Вскрытие 9В батарейки: в поисках батареек АААА46185041
Странное рождение и долгая жизнь UNIX31275977
Pomodoro: тайм-менеджмент, который работает28263991
Краткий обзор современных окружений рабочего стола257213020
Возможности настройки GRUB2 в Linux242910591
Markdown - гаечный ключ для забивания24332699

 

Самые комментируемые

Название постаPlus oneCommentsViews
Краткий обзор современных окружений рабочего стола257213020
Вычислительный танк заряженный свободой: ThinkPad  15675854
Как редактировать в Vim без порчи и бибиканья6388480
Назад в мезозой к программным динозаврам 19372001
Markdown - гаечный ключ для забивания24332699
Консольный Mplayer: мощь без границ21333371

Самые просматриваемые


Название постаPlus oneCommentsViews
Краткий обзор современных окружений рабочего стола257213020
Возможности настройки GRUB2 в Linux242910591
Как редактировать в Vim без порчи и бибиканья6388480
Навигационные программы для Android6318227
Странное рождение и долгая жизнь UNIX31275977



Глядя в даль...

В следующем году будет... а, впрочем, кто его знает, что там будет. Много черновиков и идей, мало времени, много интересного. Приоткрывая пухлую папку черновиков, можно видеть наброски про латех, гнуплот, программирование на C и Матлаб, не очень много про железо, немного про ядро, пара забойных обзоров и ещё кое-что про Андроид. Ну и что там гостевые авторы понапишут. Кстати, ваши посты тоже тут могут засветиться - гостевые посты принимаются в любое время.


Открывая шампанское...

С новым годом Линукса на Десктопе! Чтоб никогда ничего не падало, чтоб фич было много, а багов - мало. Чтоб была свобода, Столлман, равенство и братство :-)

Ну и уж этот-то год точно станет Годом Линукса на Десктопе :-)
Читать далее

Декомпиляторы, или Что делать, если нужно восстановить исходники из бинарников?



19 коммент.
Проблема восстановления исходного кода из скомпилированных бинарников возникает сравнительно часто и протекает остро, с воем и рыданиями. Здесь нам, до некоторой степени, помогут замечательные программы-декомпиляторы, и в этом посте автор собрал свои скромные попытки выдрать исходники (или хотя бы намёки на них) из скомпилированных из С-шного кода бинарников.


Задача для декомпилятора бинарников, собранных из С кода:
Классический случай: один деятель на факультете написал на правильном ANSI C (и используя библиотеки BLAS и LAPACK) нужные и хорошие алгоритмы, и скомпилировал их в виде MEX-файлов для использования (это С-шный код, который можно вызывать из МАТЛАБ).

Но потом он повздорил с народом, разозлился и свалил в частную контору, унеся все исходники с собой. Документации нет. Копий исходников нет. Есть обрывки личной переписки и намёки в сопровождающих файлах на тип алгоритма. Вариант физического воздействия на автора тупыми тяжёлыми предметами не рассматривается.

Нужно восстановить исходники если и не до компилируемого состояния, то во всяком случае выудить оттуда алгоритмы и ключевые методы, использованные при реализации.


Кратко: суть и сложность проблемы
Декомпилятор (Decompiler) пытается перевести скомпилированный бинарный файл обратно в некое подобие исходного кода. Качество выхлопа зависит от особенностей языка исходника:
  • Для C# или Java есть много декомпиляторов - байткод на java содержит  много информации. Это помогает восстанавливать декомпилятору исходник до состояния, пригодного к повторной компиляции.
  • Совершенно другая история с двоичными файлами, в которых, как правило, отладочной информации нет. Тем не менее, динамически связанные библиотеки функций, как правило, вызываются по имени. Часто, типы параметров библиотечных функций известны, и это может помочь до известных пределов. 
Декомпиляторы пытаются восстановить информацию, которая частично утрачена при компиляции в бинарный файл - в этом и заключается основная сложность.

Если вы думаете, что с помощью декомпилятора вы получите обратно красивый код на С - вы будете сильно разочарованы.  В лучшем случае на выходе будет общая (и довольно грубая) структура программы, в худшем - только имена функций и немного мусора.

Так что ответ на вопрос заголовка поста: "Обхватить голову руками и закричать #$@@@@@!" :-)


Программы для декомпилирования (decompilers) для C/C++
Декомпиляторов для C/C++ немного, и ниже список из наиболее работоспособных. Здесь нет разделения на опенсорс или Linux-only - для такого дела, как вскрытие исходников, можно (и нужно) поступиться своими светлыми идеалами и наступить на горло собственной песне.

Сразу замечу: скорее всего, ни один декомпилятор не выдаст вам сразу компилируемый код. Придётся потратить порядком времени и сил, чтобы это месиво превратить в код, который можно читать (желательно, не только компилятору).


Boomerang
Boomerang это C decompiler с открытыми исходами:
  • поддерживаемые бинарные форматы:  ELF  PE-COFF Mac-OS
  • платформы: Windows/Linux
  • поддерживаемые архитектуры: IA32 MIPS PPC
  • метод работы: поточный, есть жалкий графический интерфейс, лучше использовать CLI.
Весьма продвинутый набор алгоритмов анализа кода, что не удивительно - один из соавтором защитил на этом докторскую диссертацию [Michael James Van Emmerik, Static Single Assignment for Decompilation, Ph.D. thesis, the University of Queensland, Australia. PDF, mirror PDF].

Качество кода, выдаваемого декомпилятором:
  • Структурирование: очень хорошее
  • Переменные: хорошее
  • Типы данных: очень хорошее
Выдаваемое качество кода сильно варьируется: некоторые функции почти идеально восстановлены, хорошо видна структура кода и есть указание типа переменных. В других случаях функции сильно запутаны и их почти невозможно прочитать.

Программа всё ещё в состоянии бета-версии и для больших проектов не подходит. Скачать можно здесь.


RecStudio
Интерактивный декомпилятор RecStudio для С и (отчасти) С++, закрытая разработка:
  • поддерживаемые бинарные форматыELF  PE-COFF AOUT RAW PS-X
  • платформы: Windows/Linux/MacOS
  • поддерживаемые архитектуры: x86 (ia32) x86_64 Mips PowerPC mc68k
  • метод работы: поточный и интерактивный, есть графический интерфейс.
Использует продвинутый набор алгоритмов анализа (partial Single Static Assignment, SSA), хотя до сих пор (и это после 20 лет!) в стадии разработки. Качество кода, выдаваемого декомпилятором:
  • Структурирование: хорошее
  • Переменные: частично
  • Типы данных: частично или никак
Выдаваемое качетсво кода, как правило, хуже, чем у Boomerang, хотя обновлённый RecStudio более подробен.

Программа работает вполне стабильно, есть сборки под Linux. Скачать можно здесь.



dcc - DOS to C decompiler
Поточный декомпилятор Dcc, только ANSI C  и для exe-файлов, с открытым исходным кодом под GPL:
  • поддерживаемые бинарные форматыEXE/COM
  • платформы: Windows
  • поддерживаемые архитектуры: x86
  • метод работы: поточный.
Один из первых декомпиляторов вообще, и только под DOS. Сильная сторона - структурирование кода. Качество кода, выдаваемого декомпилятором:
  • Структурирование: хорошее
  • Переменные: частично
  • Типы данных: частично или никак
Разработка Cristina Cifuentes, которая защитила PhD в Queensland University of Technology  на этом деле [можно полистать, если что - C. Cifuentes, Reverse Compilation Techniques].

Скачать можно отсюда (на сайте университета).



Hex Rays - plugin для IDA Pro
На самом деле Hex Rays не является отдельной программой - это плагин-декомпилятор для IDA Pro. Комбинация продвинутых возможностей IDA Pro (это дизассемблер) и Hex Rays в качестве декомпилятора очень впечатляет, как и аэрокосмическая цена.
По причине закрытости продукта (нет даже демо-версии) и нереальной цены в этом разделе про Hex Rays больше ничего написано не будет.




Ходовые испытания в реальных условиях
Для начала попробуем декомпилировать что-нибудь совсем простенькое и написанное на ANSI C и с использованем библиотеки BLAS для векторых и матричных операций. Бинарный файл можно скачать здесь.



1. Простенький C-шный бинарник + BLAS
Собственно, код на C для перемножения матрицы и вектора (используется CBLAS). Исходник:


#include <stdio.h>
#include <cblas.h>

double m[] = {
  3, 1, 3,
  1, 5, 9,
  2, 6, 5
};

double x[] = {
  -1, -1, 1
};

double y[] = {
  0, 0, 0
};

int main(void)
{
  int i, j;

  for (i=0; i<3; ++i) {
    for (j=0; j<3; ++j) printf("%5.1f", m[i*3+j]);
    putchar('\n');
  }

  cblas_dgemv(CblasRowMajor, CblasNoTrans, 3, 3, 1.0, m, 3, x, 1, 0.0, y, 1);


  for (i=0; i<3; ++i)  printf("%5.1f\n", y[i]);

  return 0;
}

После перемножения выдаст результат на консоль.

Выхлоп Boomerang
У него много ключей и параметров, часть которых не знает даже официальная, скажем так, документация. Тем не менее, для ключа -Td (Use data-flow-based type analysis) мы имеем выхлоп в стиле дзен:

double y;
double m = 3.;

// address: 0x80484e4
int main(int argc, char **argv, char **envp) {
    void *local23;   // r28

    for(;;) {
        proc1();
    }
}

Скажем так, не слишком ободряюще. Ключ  -Tc (Use old constraint-based type analysis) выдаёт больше информации к размышлению:

char y[24];
long long m[9] = { 0x4008000000000000LL, 0x3ff0000000000000LL, 0x4008000000000000LL, 0x3ff0000000000000LL, 0x4014000000000000LL, 0x4022000000000000LL, 0x4000000000000000LL, 0x4018000000000000LL, 0x4014000000000000LL };

// address: 0x80484e4
int main(int argc, char **argv, char **envp) {
    int local10;   // r24
    int local13;   // r28
    int local14;   // r29
    int local15;   // r32
    int local2;   // m[r28 + 72]{60}
    int local3;   // r28{181}
    int local6;   // m[r28 + 72]{119}
    int local7;   // m[r28 + 72]{149}
    int local8;   // m[r28 + 76]{9}
    int local9;   // m[r28 + 76]{49}

    *(int*)(local13 - 4) = local14;
    *(int*)(local13 - 12) = 0;
    local3 = local13 - 84;
    if (*(int*)(local3 + 72) > 2) {
        *(int*)(local3 + 52) = 1;
        *(int*)(local3 + 48) = 0x8049868;
        *(long long*)(local3 + 40) = 0.;
        *(int*)(local3 + 36) = 1;
        *(int*)(local3 + 32) = 0x8049848;
        *(int*)(local3 + 28) = 3;
        *(int*)(local3 + 24) = 0x8049800;
        *(long long*)(local3 + 16) = 1.;
        *(int*)(local3 + 12) = 3;
        *(int*)(local3 + 8) = 3;
        *(int*)(local3 + 4) = 111;
        *(int*)local3 = 101;
        cblas_dgemv();
        local6 = 0;
        for(;;) {
            *(long long*)(local3 + 4) = y[0];
            *(int*)local3 = 0x80486b6;
            proc1();
            local7 = *(int*)(local3 + 72) + 1;
        }
    }
    local8 = 0;
    for(;;) {
        local10 = *(int*)(local3 + 72) + *(int*)(local3 + 72) + *(int*)(local3 + 72);
        local15 = m[local10];
        *(long long*)(local3 + 4) = local15;
        *(int*)local3 = 0x80486b0;
        proc1();
        local9 = *(int*)(local3 + 76) + 1;
    }
} 
 

Подробностей тут больше, и тут выловлен самый главный ключик - cblas_dgemv();    


Выхлоп RecStudio
Намного более обилен и представляет собой следующий поток сознания:


// Generated by Rec Studio 4 - build Oct 20 2012

_init()
{// addr = 0x08048398
    _unknown_ __ebx;                       // r1
    _unknown_ __ebp;                       // r6
    _unknown_ _t2;                         // _t2

    __esp = __esp - 4;
    L1();
    _pop(__ebx);
    if( *((intOrPtr*)(_t2 + 0x1414)) != 0) {
        __gmon_start__();
    }
    frame_dummy();
    __do_global_ctors_aux();
    _pop(__eax);
    return;
}

L080483A4()
{
    _unknown_ _t2;                         // _t2

    _pop(__ebx);
    if( *((intOrPtr*)(_t2 + 0x1414)) != 0) {
        __gmon_start__();
    }
    frame_dummy();
    __do_global_ctors_aux();
    _pop(__eax);
    _pop(__ebx);
    __esp = __ebp;
    _pop(__ebp);
    return;
}

__gmon_start__()
{// addr = 0x080483D8
    goto __imp____gmon_start__;
}

putchar()
{// addr = 0x080483E8
    goto __imp__putchar;
}

__libc_start_main()
{// addr = 0x080483F8
    goto __imp____libc_start_main;
}

cblas_dgemv()
{// addr = 0x08048408
    goto __imp__cblas_dgemv;
}

printf()
{// addr = 0x08048418
    goto __imp__printf;
}

_start(
    signed int __eax,                      // r0
    _unknown_ __edx                        // r3
)
{// addr = 0x08048430
    _unknown_ __ebx;                       // r1
    signed int _t5;                        // _t5
    _unknown_ _t6;                         // _t6
    _unknown_ _t10;                        // _t10

    __edx = __edx;
    _t4 = __eax;
    _pop(__esi);
    __ecx = __esp;
    __esp = __esp & 240;
    _push(__eax);
    _push(__esp);
    _push(__edx);
    _push(__libc_csu_fini);
    _push(__libc_csu_init);
    _push(__ecx);
    _push(_t10);
    _push(main);
    __libc_start_main();
    asm("hlt ");
    0;
    0;
    _push(0);
    _push(_t6);
    __esp = __esp - 4;
    if(completed.5982 != 0) {
    } else {
        _t4 = dtor_idx.5984;
        _t6 = ( &__DTOR_END__ -  &__DTOR_LIST__ >> 2) - 1;
        if(_t4 >= _t6) {
        } else {
            do {
                _t5 = _t4 + 1;
                dtor_idx.5984 = _t5;
                 *((intOrPtr*)(_t5 * 4 +  &__DTOR_LIST__))();
                _t4 = dtor_idx.5984;
            } while(_t4 < _t6);
        }
        completed.5982 = 1;
    }
    __esp = __esp + 4;
    _pop(__ebx);
    _pop(__ebp);
    return;
}

__do_global_dtors_aux(
    _unknown_ __esi                        // r5
)
{// addr = 0x08048460
    _unknown_ __ebx;                       // r1
    _unknown_ __ebp;                       // r6
    _unknown_ _t4;                         // _t4
    signed int _t5;                        // _t5
    signed int _t6;                        // _t6
    _unknown_ _t10;                        // _t10

    if(completed.5982 == 0) {
        _t5 = dtor_idx.5984;
        _t10 = ( &__DTOR_END__ -  &__DTOR_LIST__ >> 2) - 1;
        if(_t5 >= _t10) {
L4:
            completed.5982 = 1;
            return;
        }
        do {
            _t6 = _t5 + 1;
            dtor_idx.5984 = _t6;
             *((intOrPtr*)(_t6 * 4 +  &__DTOR_LIST__))();
            _t5 = dtor_idx.5984;
        } while(_t5 < _t10);
        goto L4;
    }
    return;
}

frame_dummy()
{// addr = 0x080484C0
    _unknown_ __ebp;                       // r6

    __eax = __JCR_LIST__;
    if(__JCR_LIST__ == 0) {
    } else {
        __eax = 0;
        if(__eax != 0) {
             *__esp =  &__JCR_LIST__;
             *__eax();
            return;
        }
    }
    return;
}

main(
    _unknown_ __fp0                        // r28
)
{// addr = 0x080484E4
    signed int _v8;                        // _cfa_fffffff8
    signed int _v12;                       // _cfa_fffffff4
    intOrPtr _v32;                         // _cfa_ffffffe0
    char* _v36;                            // _cfa_ffffffdc
    intOrPtr _v48;                         // _cfa_ffffffd0
    char* _v52;                            // _cfa_ffffffcc
    intOrPtr _v56;                         // _cfa_ffffffc8
    char* _v60;                            // _cfa_ffffffc4
    intOrPtr _v72;                         // _cfa_ffffffb8
    intOrPtr _v76;                         // _cfa_ffffffb4
    intOrPtr _v80;                         // _cfa_ffffffb0
    _unknown_ __ebp;                       // r6

    __fp0 = __fp0;
    __esp = __esp & 240;
    __esp = __esp - 80;
    _v12 = 0;
    while(_v12 <= 2) {
        _v8 = 0;
        while(_v8 <= 2) {
            __fp0 ?_?  *((long long*)((_v12 + __edx + __edx + _v8) * 8 +  &m));
            asm("fstp qword [esp+0x4]");
             *__esp = 134514352;
            printf();
            _v8 = _v8 + 1;
        }
         *__esp = 10;
        putchar();
        _v12 = _v12 + 1;
    }
    _v32 = 1;
    _v36 =  &y;
    asm("fldz ");
    asm("fstp qword [esp+0x28]");
    _v48 = 1;
    _v52 =  &x;
    _v56 = 3;
    _v60 =  &m;
    asm("fld1 ");
    asm("fstp qword [esp+0x10]");
    _v72 = 3;
    _v76 = 3;
    _v80 = 111;
     *__esp = 101;
    cblas_dgemv();
    _v12 = 0;
    while(_v12 <= 2) {
        __fp0 ?_?  *((long long*)(_v12 * 8 +  &y));
        asm("fstp qword [esp+0x4]");
         *__esp = "%5.1f\n";
        printf();
        _v12 = _v12 + 1;
    }
    return 0;
}

__libc_csu_fini()
{// addr = 0x080485F0
    _unknown_ __ebp;                       // r6

    return;
}

__libc_csu_init(
    intOrPtr _a4,                          // _cfa_4
    intOrPtr _a8,                          // _cfa_8
    intOrPtr _a12                          // _cfa_c
)
{// addr = 0x08048600
    intOrPtr _v36;                         // _cfa_ffffffdc
    intOrPtr _v40;                         // _cfa_ffffffd8
    _unknown_ __ebx;                       // r1
    _unknown_ __edi;                       // r4
    signed int __esi;                      // r5
    _unknown_ __ebp;                       // r6
    _unknown_ _t14;                        // _t14
    _unknown_ _t15;                        // _t15
    signed int _t18;                       // _t18

    __i686.get_pc_thunk.bx();
    _t15 = _t14 + 4529;
    __esp = __esp - 28;
    _init();
    _t18 = _t15 + -248 - _t15 + -248 >> 2;
    if(_t18 == 0) {
    } else {
        __esi = 0;
        do {
            _v36 = _a12;
            _v40 = _a8;
             *__esp = _a4;
             *((intOrPtr*)(_t15 + -248 + __esi * 4))();
            __esi = __esi + 1;
        } while(__esi < _t18);
    }
    __esp = __esp + 28;
    return;
}

__i686.get_pc_thunk.bx()
{// addr = 0x0804865A
    return;
}

__do_global_ctors_aux()
{// addr = 0x08048660
    intOrPtr* __ebx;                       // r1
    _unknown_ __ebp;                       // r6

    __eax = __CTOR_LIST__;
    if(__eax == 255) {
    } else {
        __ebx =  &__CTOR_LIST__;
        asm("o16 nop ");
        do {
            __ebx = __ebx - 4;
             *__eax();
            __eax =  *__ebx;
        } while(__eax != 255);
    }
    return;
}

_fini()
{// addr = 0x0804868C
    _unknown_ __ebx;                       // r1
    _unknown_ __ebp;                       // r6
    _unknown_ _t1;                         // _t1

    __esp = __esp - 4;
    L1();
    _pop(__ebx);
    __do_global_dtors_aux(__esi);
    _pop(__ecx);
    return;
}

L08048698()
{
    _unknown_ _t1;                         // _t1

    _pop(__ebx);
    __do_global_dtors_aux(__esi);
    _pop(__ecx);
    _pop(__ebx);
    __esp = __ebp;
    _pop(__ebp);
    return;
}

L08048698()
{
    _unknown_ _t1;                         // _t1

    _pop(__ebx);
    @rec __do_global_dtors_aux@__do_global_dtors_aux@(__esi);
    _pop(__ecx);
    _pop(__ebx);
    __esp = __ebp;
    _pop(__ebp);
    return;
}

// Statistics:
//      74 Register nodes
//      35 Temporaries nodes
//       5 Casts
//     207 Statements
//       2 Labels
//       1 Gotos
//      17 Blocks
//     469 Nodes
//      10 Assembly nodes
//      27 Unknown Types


Total time: 0 seconds.


Структура программы (вначале) в общем несколько лучше, чем у Boomerang, и куда больше подробностей.



2. Бен, ай нид хелп: MEX-файл, написанный на C  + BLAS, исходников которому нет.
Этот пример в посте приводить не стану, так как он длинный, но желающим попробовать своё декомпиляйшн-кунфу такая возможность предоставится:
Некоторые входные данные: это оптимизационный алгоритм для Quadratic Programming типа Branch-and-Bound (почитать тут и здесь). Алгоритм в целом прост и незатейлив, но самая сложная часть в нём - определить lower/upper bound через решение упрощённой оптимизационной задачи, и делать это быстро. Как такое сделать - хороший вопрос, и именно он меня интересует более всего. 

Короче, важен не столько алгоритм, сколько его составные компоненты (стратегия и подпрограммы для lower bound estimation).

Автор этих строк, поковыряв выхлоп RecStudio, нашёл для себя подсказку на строчке 12319:
qps_mq_sub( .....

и особенно на строчке 12088:
getalp( ....
что позволило автору предположить, что для lower/upper bounds  использутеся Liner Programming.  Не слишком много, но по крайней мере понятно, в какую сторону копать.

Если у кого-то вдруг проявится желание потыкать в оный бинарник палочкой, IDA Pro и ещё чем - не стесняйтесь отписываться в комментариях.
Обновление: теперь можно сравнить выдачи Boomerang, RecStudio, и (спасибо, Григорий!) IDA Pro. В самом деле, выдача IDA Pro куда лучше того, что дают остальные, особенно boomerang. Можно выудить (до некоторой степени) структуру программы и даже сообщения об ошибках.


Ссылки
Интересующийся читатель может попробовать полистать вебстраницы автора RecStudio с полезной информацией, сходить на wiki-ресурс по обратной разработке.

Помимо познавательных диссертаций Michael James Van Emmerik (Boomerang) и Cristina Cifuentes [C. Cifuentes, Reverse Compilation Techniques], есть хорошие книжки по теме:
  • "Compilers - Principles, Techniques and Tools", Aho, Sethi, Ullman, 1986 Addison-Wesley Publishing Co.  ISBN 0-201-10088-6.
  • "Advanced Compiler Design & Implementation", Steven Muchnick, 1997 Morgan Kaufmann Publishers, ISBN 1-55860-320-4.
  • "How debuggers work - Algorithms, Data Structures, and Architecture", Jonathan Rosemberg, 1996 John Wiley and Sons, ISBN 0-471-14966-7.

Дело это интересное, но весьма утомительное, хотя может помочь при раскопках очередного legacy-software и сэкономить вам полжизни.
Читать далее

Как оформить исходный код программ в LaTeX без адских страданий



32 коммент.
Иногда в документ LaTeX нужно вставить кусок программного кода или псевдокод, поясняющий алгоритм. В зависимости от языка программирования и целей, подсветка кода в LaTeX достигается подключаемыми пакетами расширений разной степени кривизны и безумия документации.

Пост подвергался чистке и правке после публикации:
Автор заходил править этот пост 16 августа 2013 года.

Читать далее