в любом случае декомпиляция - это разархивирование энергии, времени , сконцетрированной разработчиками в программе.Декомпиляция будет требовать жертвы. Вопрос тока в том, кто будет приносить жертву декомпилятору - пользователь декомпилятора или разработчик декомпилятора. Сказано же в Библии, что дом сильного мона захватить тока после того, как разобрались с хозяином( с ее силой). На сигодня пока.
MrHammer Было бы неплохо, если бы ты приводил цитаты, а то не совсем понятно, на что ты отвечаешь. Например, после слов "А что за фиг с оптимизатором?". А если программа написана на Pascal или другом языке? Или память под структуру выделяется статически? Ещё раз: я не призываю отказаться от использования доп. инфы, но не стоит надеяться лишь на неё. Необходимо использовать такие алгоритмы, которые бы работали как можно лучше во всех условиях. Иначе декомпилятор сможет драться только на ринге, а на улице будет повержен. Какие проблемы?
S_T_A_S заново взглянул на код. комментирую по строчкам, стараясь думать при этом с позиции автоматического декомпилятора. //xor ecx, ecx rECX = 0; Можно заставить анализатор отметить у себя что в регистре rECX или иммедиат или указатель. // mov eax, 00404004 rEAX = *(0x404004); анализатор видит что адрес попадает в секцию данных и автоматом дает ей статус указателя на какую-то переменную. // and [dword eax+8], 0 3 строчка. Декомпилятор видит косвенное обращение по регистру rEAX, отмечает у себя, что это возможно обращение к полю структуры и создает неизвестную структуру struct s1 { byte field_1[8]; dword field_2; }; Поэтому 404004 декомпилятор превращает в указатель на структуру s1. отмечает, что field_2 может быть указателем или иммедиатом. //mov [dword eax+4], 8000000C анализируем число и видит , что в область допустимых адресов не входит, значит, просто константа. // mov [eax], ecx изменяем структуру. // mov [eax+5], cl анализатор обращается к библиотеке идиом, и понимает что это возможно короткая форма модификации константы. // mov [dword eax-4], 004A90A8 анализатор нервничает, много курит и пьет пиво. Обращается к библиотеке идиом компилятора и смотрит, что за гуйню хотел сказать этим данный компилятор. Видит, что компилер возможно в целях оптимизации может взять адрес структурной переменной не с начала( это у меня такое предположение, с мелкософтовским компилером много не разбирался в принципе - MrHammer). // mov [dword eax-4], 004A90A8 меняем структуру. // inc ecx rECX += 1; // add eax, 10 rEAX += 10; // test cl, cl // jnz short 0040353D декомпилятор смекает , что крутится цикл и константа в выражении add eax, 10 может быть размером структуры, а указатель 404004 - массивом структур. В библиотеке идиом компилятора видит что Мелкий циклы вида for ( int i = 0; ; i++ ) может превратить возможно именно такой код. итак: typedef unsigned char byte; typedef unsigned int dword; struct s1 { // указатель на какой-то гуй void* ptr_1; // константа так как rECX равно константа dword field_2; dword flags_1; // тип нужно уточнить ( указатель, константа) dword field_4; }; s1 *404004; void code () { for ( dword i = 0, s1* a = 0x404004; static_cast<byte> i != 0; i++, a++ ) { a->field_4 = 0; a->flags_1 = 0x80000c; a->field_2 = i; a->flags &= 0xffff00ff; a->ptr_1 = 0x4a90a8; } Код улучшится , если будут обращения к полям структуры из других, проверенных мест. }
Ошибочка. поле flags_1 нужно превратить в союз. union { dword flags_1; union { byte u1; // неопределен byte field_1; // выявлено обращение как к константе byte u2[2]; // неопределен }; }; Это станет ясно декомпилятору после того как увидит модификацию этого поля значением счетчика.
Artem Мы говорим о декомпиляции сишных, приплюснутых программ или как? Ведь, например, не попрем же мы на бейсик со своим сишным декомпилятором. Каждому свое место. И еще раз повторяю, я имею в виду декомпиляцию программ , скомпилированных с помощью компиляторов Мелкого и Бормана. Остальные мне как-то фиолетово. Ещё раз: я не призываю отказаться от использования доп. инфы, но не стоит надеяться лишь на неё. Необходимо использовать такие алгоритмы, которые бы работали как можно лучше во всех условиях. Иначе декомпилятор сможет драться только на ринге, а на улице будет повержен Хе-хе-хе. Прикол. Меня, и пнуть собственным кованым нацистким сапогом - просто великолепно!
MrHammer > for - это цикл с предусловием, в оригинеле пост условие. Обращений к полям структуры в остальном коде проги никаких нет - она формируется для системной библиотеки. Этот цикл будет выполнен 0 раз, а не 256, как оригинал: Код (Text): enum { number_of_keys = 0x100 }; static DIOBJECTDATAFORMAT key_data_format[number_of_keys]; unsigned i = 0; do { key_data_format[i].pguid = &GUID_Key; key_data_format[i].dwOfs = i; key_data_format[i].dwType = DIDFT_BUTTON | DIDFT_OPTIONAL; *((char *)&key_data_format[i].dwType+1) = (char)i; // да, я знаю, что нормальные люди так не делают =) key_data_format[i].dwFlags = 0; } while( (char)++i );// number_of_keys
MrHammer Я говорю о декомпиляции машинного кода. И не важно, на чём был исходник - на asm, C, Pascal или Basic. Декомпилятор должен анализировать семантику кода. Ведь, к примеру, цикл он и в Африке цикл. И в приведённом выше коде для определения конструкции do совершенно не зачем обращаться к библиотеке идиом компилятора, потому как ничем другим этот кусок кода просто быть не может (использование goto не в счёт)! А декомпилятор, ориентированный на конкретные компиляторы, гораздо менее интересен как для науки, так и для практических применений.
Artem В принципе, я сам тоже за универсальность декомпилятора. Но конкретизироваться все равно нужно, так как от этого будет страдать качество генерируемого кода. В лучшем случае, как я себе это представляю, в основе нужен абстрактный декомпилятор, а надстройкой над ней будет уже декомпилятор конкретного компилера. Под понятием абстрактного декомпилятора я понимаю энное количество вумных анализаторов, независящих от использованного декомпилера. Возьмем к примеру, асмовые инструкции loop и компания, jcxz. Абстрактный декомпилер нам скажет что типа мужик смотри тутта цикл, а конкретный ему: отвали, данный компилятор при генерации кода эти инструкции не использует. И ставит на уши юзера типа возможно в данном месте анализируемого кода асмовая вставка или асмовый объектный модуль, поэтому умывает руки. S_T_A_S Действительно, код был простой. Но после просмотра исходного кода я тока утвердился в мысли что иду по верному пути. Стремление к генерации кода , максимально похожего на оригинальный, ни к чему. Важна удобочитаемость, возможность дальнейшей поддержки декомпилированного кода. А это обеспечивается заменой всех констант в асмовом коде на символьные имена и конкретизация под определенный компилятор и т.д. Я конкретно ступил с декомпиляцией примера, за этот пинок спасибо, но цикл for универсален , в декомпиляторах нужно стараться использовать именно его. В данном случае это можно представить так: for ( dword i = 0; (static_cast<byte> ++i) != 0; a++ ) { } Кстати, Artem, что ты имеешь ввиду под словом машинный код? Код сгенерированный компилятором или чисто бинарные цифирки, бурлящим потоком низвергающиеся в чрево процессора?
Xmm, однако! Проверка будет перед инициализацией данных, так что точно будет инициализация неправильными данными. Я сказал пачему желателен for, так как в нем можно наглядно указать условие, инициализацию и т.п. Ща вижу, что из правил есть и исключения. Вообщем,стоит мне получше перечитать правила синтаксиса С/С++.
MrHammer Ну и что, что асмовая вставка? Зачем зря тревожить юзера, если возможна нормальная декомпиляция? В моём декомпиляторе на этапе генерации промежуточного кода инструкции loop и jcxz заменяются соответственно на: ecx=ecx-1 if (ecx!=0) jmp label и if (ecx==0) jmp label Т.о., анализатор даже не знает, какие инструкции были первоначально. Да хоть в hex-редакторе от руки написанный!
Artem писал: Ну и что, что асмовая вставка? Зачем зря тревожить юзера, если возможна нормальная декомпиляция? Какой смысл декомпилировать написанный от руки код ( на языке ассемблера)? В оригинальном виде даже попонятней будет. Если тока не ставится вопрос создания клона для друой платформы. Например, перенос консольной игрушки под писюк, например. Но в таких случаях есть более эффективные методики.
MrHammer Естественно, речь идёт о случае, когда нет исходников. Да и C-ый код всё-таки понятней асмовского (кроме случаев, когда используются инструкции, не представимые на ЯВУ).
шобы данный пост не пропал впустую, делаю некоторые выводы из высказываний участвовавших. Как я и предполагал, есть тенденция делать декомпилятор как можно универсальнее, в ущерб качеству воссоздаваемого кода. Есть поговорка кесарю кесарево. Возможно, оно подходит и для данного случая. со своей стороны я, повторяюсь снова, вижу декомпилятор только под определенный компилятор, так как в этом случае можно максимально эффективно генерировать качественный сишный код. Это исходит из того что охотник должен знать повадки зверя лучше самого зверя. Декомпилятору жизненно необходимы всякие внутренние структры использованные компилером при создании кода, его повадки( идиомы) и т.д. также делался акцент на то, что декомпиляция сложна, так как оптимизатор ( главным образом компилеров от Intel, Microsoft и Inprise ) вымывает необходимую информацию. простейший пример предложенный by S_T_A_S продемонстрировал, что этот вопрос действительно нужно ставить в числе главных задач для решения. для решения скорее всего необходимо будет создать формальные правила декомпиляции, которые позволяют воссоздать правильно функционирующий сишный код. некоторые из них я излагал выше, но многое следует еще осмыслить. Искуственный идиот, по моему мнению, не стока необходим при декомпиляции, как это видят некоторые личности. так, время сеанса подходит к концу, в плане продолжить завтра. и главное - декомпиляция реальна.
Artem писал: Естественно, речь идёт о случае, когда нет исходников. Да и C-ый код всё-таки понятней асмовского (кроме случаев, когда используются инструкции, не представимые на ЯВУ). Просто переведенный в псевдоСи асмовый листинг мало чем может прояснить ситуацию. Этта я утверждаю после того как дизассемблировал и декомпилировал некоторые части ТАСМ32. Так как в таком листинге как правило водятся непереводимые национальные поговрки.
Также могу сделать вывод, что ничего не будет делаться, а если и будет, то не будет сделано. И все это чистой воды болтовня и пустая трата времени. Правильно я просек фишку?
captain cobalt а что, задело утверждение по поводу ИИ? Истинная цель данного поста - посеять идеи в умах. Декомпиляция реальна, а кто говорит что это сложно и тускло, то он утомлен нарзаном и и для создания декомпилера ему нужно еще поискать сил. Или сделать взгляд простым.Дорогу осилит идущий.
Очень жаль, но пока не видно общей модели. Гипотезы: 1. Декомпиляция - это компиляция. 2. Декомпиляция сложнее, чем компиляция. 3. Прежде чем разрабатывать декомпиляторы, имеет смысл поиметь опыт разработки компиляторов.