Полный ПИ GPcH (admin@vb-decompiler.org) Хакер, номер #090, стр. 090-082-3 Структура ProcTable SomeTemp String*52 DataConst Long SomeTemp - это просто набор ненужных нам полей, которые я объединил, чтобы немного сэкономить места в статье. Они нам не потребуются, так как для нас важен только адрес DataConst. Теперь логично задать вопрос: а что мы узнали? Только размер пикодовой процедуры и адрес на блок данных? Однако адрес пикодовой процедуры напрямую нигде не прописан, зато мы его можем получить вычитанием из адреса начала структуры ProcDscInfo поля sProcDscInfo.ProcSize. Как видно, пикод идет прямо перед структурой ProcDscInfo. Что ж, теперь, когда мы знаем откуда брать методы (про ивенты я умолчу в связи с ограничением объема статьи), можно приступать к исследованию самого пикода. Как исследовать? Чтобы лучше во всем разбираться, нам потребуется таблица опкодов. Она есть на диске. Заранее предупреждаю, что таблица неполная, так как публичная и имеет кое-какие ошибки, поэтому доверять ей на все 100% не советую, хотя это все-таки лучшее, что можно добыть в инете на данный момент. Таблица представлена в виде: <опкод>tab<размер>tab<название> Опкод может состоять из одного или двух байт. До FBh опкода идут однобайтовые, далее - двухбайтовые. Если ты встретишь, к примеру FEh, то следующий за ним байт относится к опкоду. <размер> в таблице - это число параметров. Теперь посмотрим на пример пикодового блока: 00 00 00 00-00 00 00 00-00 00 00 00-F4 00 2B 6E FF F5 00 00-00 00 F5 00-00 00 00 1B-0C 00 04 70 FF 34 6C 70-FF 1B 0D 00-04 74 FF 34-6C 74 FF F5 00 00 00 00-59 78 FF 0A-0E 00 18 00-3C 32 04 00 74 FF 70 FF-13 00 00 00 Пикод в нашем блоке начинается с F4. Посмотрим по таблице, что же означает этот опкод. Согласно таблице, это - LitI2_Byte, который имеет один байт в параметрах. Запомни раз и навсегда, что Lit - это всегда push. I2 - это двухбайтный integer. Даю небольшую табличку всех возможных значений для упрощения исследования: Типы данных UI1 Byte Bool Boolean I2 Integer I4 Long R4 Single R8 Double Cy Currency Var Variant Str String Так как после F4 идет 0, то логично предположить, что эта команда push 0. Продолжим далее. 2B - это PopTmpLdAd2. Читать следует таким образом: Pop from stack to Temp variable and Load Address to stack. Итак, эта переменная всего лишь резервирует содержимое верхней ячейки стека во временную переменную - нам это не потребуется, так как мы не исполняем код, а декомпилируем. Следующие 2 байта - это та самая временная переменная FF6E. Если число из отрицательного перевести в положительное, то получится 92. Мой декомилятор в этом случае выведет var_92. Если бы число было положительным, то это была бы не локальная, а глобальная переменная. Думаю, теперь все ясно, так что приступим к следующей команде - F5 - LitI4. Понимаем как push следующие 4 байта, то есть push 0. Далее опять идет push 0. Теперь - 1B - LitStr. Этот опкод заносит строку в стек. Не зря я тебе рассказал про адрес на блок данных, именно от него и отсчитываются следующие два байта в параметрах, то есть: |