Мое почтение всем. Довольно давно пишу дизассемблер, наконец-то есть что показать. Т.к. справка слишком большая для одного поста, подробнее прочитать о дизассемблере можно здесь http://mika0x65.livejournal.com/6898.html#cutid1 . Здесь же приведу пример использования и ссылку для скачивания: Код (Text): #include <stdio.h> #include <stdlib.h> #include "mediana.h" //Главный заголовочный файл дизассемблера. #define OUT_BUFF_SIZE 0x200 #define IN_BUFF_SIZE 14231285 #define SEEK_TO 0x0 int main(int argc, char **argv) { uint8_t sf_prefixes[MAX_INSTRUCTION_LEN]; //Массив избыточных префиксов. unichar_t buff[OUT_BUFF_SIZE]; //Выходной буфер печати инструкции. struct INSTRUCTION instr; //Выходная инструкция. struct DISASM_INOUT_PARAMS params; //Параметры дизассемблера. uint8_t *base, *ptr, *end; int reallen; unsigned int res; FILE *fp; params.arch = ARCH_ALL; //Включая все архитектуры. params.sf_prefixes = sf_prefixes; //Подключение массива избыточных префиксов. params.mode = DISASSEMBLE_MODE_32; //Режим дизассемблирования. params.options = DISASM_OPTION_APPLY_REL | DISASM_OPTION_OPTIMIZE_DISP; //Все опции. params.base = 0x00401000; //Базовый адрес первой инструкции. base = malloc(IN_BUFF_SIZE); ptr = base; end = ptr + IN_BUFF_SIZE; fp = fopen("asm_com2.bin", "rb"); fseek(fp, SEEK_TO, SEEK_SET); fread(base, IN_BUFF_SIZE, 1, fp); fclose(fp); while(ptr < end) { res = medi_disassemble(ptr, &instr, ¶ms); //Disassemble! if (params.errcode) { printf("%X: fail: %d, len: %d\n", ptr - base, params.errcode, res); if (res == 0) res++; } else { reallen = medi_dump(&instr, buff, OUT_BUFF_SIZE, DUMP_OPTION_IMM_UHEX | DUMP_OPTION_DISP_HEX); //Эта ф-ия будет описана ниже. if (reallen < OUT_BUFF_SIZE) buff[reallen] = 0; else buff[OUT_BUFF_SIZE - 1] = 0; printf("%X: %s\n", ptr - base, buff); } ptr += res; params.base += res; //Высчитываем базовый адрес следующей инструкции. } return 0; } Скачать дизассемблер можно здесь: http://mediana.sf.net . Буду рад предложениям, отчетам об ошибках и откликах в целом .
Mika0x65 Так как дизасм вестма часто используется для создания графа(это базовая задача для которой нужен дизасм), то не плохо былобы сделать двиг.
Clerk Как ты это себе представляешь (в общем)? x64 Завтра вечером. luckysundog Да. В разделе "Немного мыслей о дизассемблировании" немного описано тестирование. Прогонял дизассемблер на этом файле: http://sourceforge.net/projects/mediana/files/tests.bin/asm_com2.bin/download И еще несколько человек тестировали на исполняемых. Думаю, что основные ошибки уже отловлены.
Отлично, жду. Если что, пиши в оффлайн, и когда ты будешь доступен в следующий раз. Примерно раз в сутки я обязательно выхожу в сеть.
Mika0x65 Опишу как работает мой двиг. 1. Граф представляет собой двусвязанный список описателей. Каждый описатель определяет одну инструкцию, либо группу инструкций(опционально, если например в группе инструкций нет ветвлений, то определена длина блока). Описатели связаны ссылками, прямыми и обратными. Для ветвлений также определены ссылки на блоки. Список позволяет перемещать в памяти описатели, заменять их и делать вставки(морфинг), трассировать граф, благодаря обратным ссылкам трассировать граф в обратном направлении. Базовые бве процедуры - парсер, он и дизасмит код и создаёт граф и трассировщик маршрута, который перечисляет все входы в таблице. Обработка релоков и прочие вещи не включены в базовый функционал, а оформляются в виде калбэков, из которых можно формировать цепочки. На вход парсера передаётся адрес разбираемого кода, буфер, флажки и ссылки на калбэки. На выходе получается граф. Буфер расширяемый, так как размер графа заранее не известен. 2. Далее из полученной таблицы(сырая) формируется вторая таблица. В ней элементы перестроены(изза вставок сделанных парсером), удалены ветвления использующие регистр Ecx(Loop, Jcxz etc., точнее в первичной таблице отдельной проедурой). Эта таблица и используется при изменении и сборке кода. Таблица необходима для оптимизатора, который удаляет холостые ветвления(Jmp short $+2, ветвления на ветвления и пр.), перестраивает некоторым образом код. После чего он уже собирается(компилируется). Парсер это минимально необходимый функционал(1).
если уж и кодить граф, то делать это максимально абстрагированно от какого-либо дизассемблерного движка. т.е. как отдельный проект уже. imho
luckysundog Именно. Вам например не нужно будет изучать дизасм для создания графа. Иначе придётся его изучать и писать двиг самостоятельно, что обычно весьма проблемно ибо все нюансы не известны. Обычно отлично от двига создающего граф дизасм не юзается, поэтому двиг должен быть по любому, иначе нафиг никому это не нужно. Разбор структур дизама не проще чем разбор инструкций.
Код (Text): unsigned int medi_disassemble([b]uint8_t *offset[/b], struct INSTRUCTION *instr, struct DISASM_INOUT_PARAMS *inout_params). Чето сыкотно передавать функции указатель на дизассемблируемый код))). Так как вполне возможно, что при декодировании функция вылетит за пределы буфера. Желательно вместо указателя offset принимать функцию-callback для чтения требуемых байтов.
Реально грамотное решение, поддерживаю. Например, в режиме ядра не всегда есть возможность напрямую прочитать байты. К тому же, источников ассемблерного кода может быть сколько угодно, и гораздо удобнее предусмотреть универсальное решение, коль скоро мы пакет разработчика делаем.
и еще, лучше 2 варианта )) хотя для меня пока не решает, но я решил заменить HDE на этот, он развивается, есть 64 бита си изначально одни плюсы для меня )
да ну вас , взяли ту же память в ядре проверили , сколько нужно отдали дизасму ... какие то кастыли мастырите
Мне то нужно тока то , чтобы библиотека учитывала возможность выхода за пределы буфера чтения. 1 вариант решения - callback, скрывает обращение к памяти и более инкапсулирован, чем 2, и позволяет простой заменой callback-функции на другую, дизассемблировать например, код ядра, или процесс на удаленной машине. 2 вариант - более легкий для вызова из ОО-программ.
Обычно сказано сколько байт дизасм читает максимально. Нормально он не должен читать более, чем длина инструкции, иначе например если инструкция в конце страницы, это привидёт к исключению, чего быть не должно.