Дизассемблер своими руками GPcH (www.dotfix.net) Хакер, номер #078, стр. 078-114-3 // это инструкция call? Call : boolean; // это инструкция jmp? Jmp : boolean; // адрес относительный или абсолютный? RelTarget : boolean; // сам адрес Target : pointer; // указатель на данные в коде PTarget : pointer; // указатель на указатель на данные PPTarget : TPPointer; // размер данных в байтах (1/2/4) TargetSize : integer; // может ли размер опкода быть расширенным? Enlargeable : boolean; // адрес начала инструкции This : pointer; // адрес следующей инструкции Next : pointer; end; Также нам будет интересна еще одна функция, особенностью которой является способность дизассемблировать не одну инструкцию, а всю функцию целиком, автоматически находя ее конец по команде retn. Вот ее прототип: function ParseFunction (func: pointer; var disAsm: string) : TFunctionInfo; overload; Тут все аналогично предыдущей функции, только в данном случае код будет дизассемблироваться не по одной машинной команде, а целиком. При этом компонент попытается сам определить ссылки на API и прочие данные, что, несомненно, огромный плюс. Структура, возвращаемая данной функцией, на порядок больше предыдущей. В ней куча разных членов: размер дизассемблированного кода, данные об ошибках (в том числе в виде строки), о переходах (jmp и call) и т.п. Есть и еще одна функция — третья, о которой упоминаний совсем мало: function ParseFunctionEx (func: pointer; var disAsm: string, exceptAddr: Pointer; maxLines: Integer; autoDelimiters: Boolean); Насколько я понял, она не возвращает структуры, зато дизасмит весь код нужной нам функции и кладет его в переменную disAsm. exceptAddr — это адрес конца дизассемблируемой функции (указывать необязательно), maxLines — число дизассемблируемых строк (если 0, то все), autoDelimiters — точно не могу сказать, но ориентировочно это флаг, завершать ли функцию первым ret'ом или нет. [кодим] Теперь, когда мы разобрались, как управлять компонентом, можно начинать писать дизассемблер. Открывай Delphi, создавай новый проект, добавляй в раздел uses наш madDisAsm и помещай на форму пару Edit'ов, Memo и два CommandButton'а. В результате этих несложных манипуляций у тебя должно получиться нечто похожее на интерфейс проги (см. рисунок). В первое текстовое поле мы будем вводить имя открываемого для дизассемблирования файла, а во второе — адрес кода. Так как дизассемблер понимает только pointer'ы (указатели) на код, нам нужна функция, которая будет открывать EXE-файл, считывать по указанному смещению код в некоторый буфер и возвращать на него pointer. Ну раз нужна, напишем: function TfrmMain.GetCode(strFileName: string; strOffset: string): pointer; var hFile: integer; read_bytes: cardinal; EP_code: array[1..64000] of byte; begin //открываем файл hFile:=CreateFile(pchar(strFileName), GENERIC_READ, FILE_SHARE_READ + FILE_SHARE_WRITE, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //если файл открыт успешно if hFile<>-1 then begin //устанавливаем файловый указатель на начало дизассемблируемого кода SetFilePointer(hFile,StrToInt(strOffset),NIL,FILE_BEGIN); |