DotFix :: Портал разработки и защиты программ
Главная
Программы
Статьи
Разное
Форум
Контакты
Автор: GPcH. Дата публикации: 11.06.2006

Автоматизируем реверсинг


Еще со времен доса системщики привыкли автоматизировать свою работу. Кто-то пишет батники, кто-то забивает задачи в крон, а у кого-то свой софт под это дело. Это порой не раз выручает, что не говори. Но вот что делать реверсерам и кодерам? Об этом и пойдет речь в данной статье.

Введение
Как ты уже понял рассматривать мы будем автоматизацию не простых операций, а реверсерских и кодерских, причем применительно к EXE файлам, так как насчет автоматизации бэкапов и прочей мелкой но рутинной работы многие наверное для себя уже давно определились с инструментами. Речь у нас пойдет о скриптовом языке DotFix Script, входящим в состав протектора DotFix FakeSigner. Прежде чем углубляться в возможности сего языка, поговорим немного о том, что же нужно реверсерам и любителям позащищать свой софт. Средств автоматизации для них не много и все таят какие то сложности по изучению. Порой проще понять стандартный язык программирования вроде бейсика или дельфей и автоматизировать на нем, чем учить чей то корявый скриптовый язык. Здесь все же во многом соглашусь - всегда проще реализовать задачу на первоисточнике. Но вот когда речь идет о работе с PE файлами, тут уже стандартные языки не столь дружелюбны. Простой скрамблер UPX или средство смены имен секций потребует немалых знаний в PE формате файлов, да еще если нет заголовков и прототипов нужных структур и функций - тут вообще беда. И простая по мерам реверсера задача может затянуться на несколько дней. Но не все так плохо, как может показаться. С подобными проблемами сталкивался и автор данного материала и в свое время написал довольно мощный скриптовый движок о котором было написано выше. Данный скриптовый язык позволяет автоматизировать решение практически любых задач по работе с PE файлами. Многие пользователи протектора DotFix FakeSigner даже и не задумываются о том что в его состав входит такое мощное средство автоматизации. Остальные же не изучают по одной простой причине - практически нет готовых примеров, а следовательно и стимулов к изучению. В этой статье я постараюсь исправить это упущение и рассмотреть на конкретных примерах функционал данного языка.

Почему именно DotFix Script
У читателя, продвинутого в области скриптовых движков возникнет вопрос: почему именно DotFix Script, а не к примеру Inq Soft Sign of Mystery или не GPScript? Все дело в том, что данные среды хоть и предназначены для автоматизации задач с использованием скриптов, но специализированных команд для работы с PE файлами в них нет, отсюда они не упрощают, а только усложняют данного рода задачи. Предлагаю поподробнее ознакомиться с предметом разговора. Для этого прежде чем продолжить читать рекомендую установить с диска DotFix FakeSigner, если он еще не установлен, так как без практики весь нижеследующий текст будет мало полезен. Ну что, раз все уже установлено - приступим!

Основные команды языка
Прежде чем что-то писать, необходимо знать матчасть. Это аксиома. С этим спорить не будем, лучше рассмотрим основной набор команд языка. Итак начнем с функций работы со строками как базовых.

CODE NOW!
set <value>, <accumulator>



Первый операнд команды set - числовое или символьное значение, второй - аккумулятор (переменная), в которую будет занесено это значение. По сути команда на понятном человеку языке выглядела бы так: accumulator=value. Соответственно для сложения, вычитания и других операций с числовыми данными используются следующие команды:

CODE NOW!
add <value 1>,<value 2>, <accumulator>
sub <value 1>,<value 2>, <accumulator>
mul <value 1>,<value 2>, <accumulator>
div <value 1>,<value 2>, <accumulator>



Логично предположить, что value 1 и value 2 представляют собой первой и второе число, а accumulator - аккумулятор (переменная) для сохранения результата. Разумный вопрос, а как использовать переменные в value 1 и 2? Легко! Переменную указываем в макросовом виде. Пример: имеем переменную "a", в которой хранится число 10, и переменную "b", в которой хранится число 20, тогда конструкция:

CODE NOW!
add @a@@b@,150,c



выполнится так: "а" приложится к "b" и составит 1020 и к этому числу прибавится 150. В результате в переменной "c" будет 1020+150, то есть 1170. Думаю методика понятна.
Ниже представлю некоторые другие команды для работы со строками, прототипы которых описаны в справке к программе: concat, chrtohex, hextochr, substr, length, createstring, rndbyte, settoclipboard. Имена команд интуитивно понятны и легко запоминаются, потому проблемы думаю не возникнут. Если и возникнут - далее язык будет рассмотрен на примерах. Со строками закончили, пора перейти к командама ввода вывода, предназначенных для общения разрабатываемого нами супер скрипта с пользователем. Весь ввод и вывод производится либо через формы запроса, либо через консоль. Вот основные команды:

CODE NOW!
messagebox <contents>, <message code>, <title>, <accumulator>



По сути аналог одноименной API, только последний параметр - результат возвращаемый функцией - описывающий что за кнопку нажал юзер для контроля результата.

CODE NOW!
inputbox <question>, <accumulator>



Форма запроса данных от пользователя. question - текст вопроса, accumulator - имя переменной, в которую будут занесены введенные пользователем данные.

console.load <text> - грузим консоль с заголовком text
console.unload - выгружаем консоль
console.print <text> - вывести text на консоль
console.get <accumulator> - запросить строку у юзера. Как только он ее введет скрипт продолжит выполнение команд. Логично догадаться, что accumulator переменная будет содержать введенные данные.
console.color <forecolor>, <backcolor> - изменяет палитру, с которой будет выведена строка, командой console.print. Рекомендуется для украшения интерфейса :)
console.attributes <atributes> - меняет атрибуты консоли (сделано лишь для полной реализации консольных команд, а практически можно не юзать)
Для работы с реестром используются команды:
registry.set <key>, <path>, <parameter>, <value>
registry.get <key>, <path>, <parameter>, <accumulator>
пригодятся если скрипт имеет настройки, которые нужно раз установить и больше не вводить.
Если же ini файл ближе, то можно использовать:
ini.set <key>, <subkey>, <value>
ini.get <key>, <subkey>, <accumulator>

Если затребуется приостановить выполнение команд на несколько секунд, рекомендуется использовать команду pause <milliseconds>, для воспроизвения музыки юзать стоит play <wav file>, хоть не xm, но все же сгодится. Для выхода из программы следует использовать exit. Если же ты спец-кодер, то ты будешь счастлив, узнав что в скрипте есть возможность использовать API функции:
loadfunction <function name>, <path to dll>, <param1>, <param2>, <param3>, <accumulator>
Да, параметров только 3, но это максимум, который можно выжать из динамической загрузки, если не считать asm вставки. Как и в любом нормальном языке можно использовать метки и делать на них переходы:
label <title> - создать метку title
goto <label> - перейти на метку label
Напоследок я оставил команды для работы непосрадственно с файлами PE формата и не только. Вот они:
delfile <filename> - удаляет файл с именем filename
copyfile <filename from>, <filename to> - копирует файл filename from в файл filename to
addlog <filename>, <string> - в файл filename добавлется строка string (рекомендуется использовать для ведения логов работы скрипта)
shell <filename> - запускает EXE файл
putcode <offset>, <HEX_Stub> - помещает по смещению offset (записанному в HEX виде) набор байт (также записанных в HEX виде)
getcode <offset>, <length>, <accumulator> считывает в аккумулятор последовательность байт длиной length по смещению offset
getfile <accumulator> - считывает все содержимое файла в аккумулятор
getfilelength <accumulator> - считывает длину файла в аккумулятор
getoem <accumulator> - считывает OEM информацию из DOS заголовка EXE файла
setoem <text> - записывает OEM информацию в dos_header (рекомендуется юзать это поле для каких то своих записей типа "Patched by John Smithon" в обрабатываемых PE файлах, все равно загрузчику винды наплевать на это поле).
getoep <accumulator> - считать точку входа в программу в аккумулятор
setoep <hex string> - изменить точку входа в программе на ту, что записана в HEX виде в hex string
createsection <name>, <size>, accumulator (file offset)>, accumulator (virtual address)> - создает в файле новую секцию с именем name и размером size. При этом смещение секции в PE файле и виртуальный адрес сохраняются в соответствующих аккумуляторах.
setflag <hex string> - ставит флаг hex string на все секции. Полезно поставить флаг возможности записи на все секции чтобы не получить Acces Violation при работе записанного в файл кода
invert <hex string (8 bytes)>, <accumulator> - инвертирует байты (требуется для push’ей, call’ов и других инструкций. Пример: был адрес 00401011, в аккумуляторе после инвертирования будет 11104000. Перед этим числом ставим E8 и получаем относительный jmp, который можно записывать в файл.
getimagebase <accumulator> - получает Image Base
xorcode <offset>, <length>, <accumulator> - xor’им <length> байт по смещению <offset> и заносим код декодера в accumulator
createpath <path> - создаем путь из неограниченного числа каталогов или просто одну папку
Последнее что хотелось бы отметить, что после любой команды в самом конце можно поставить запятую и написать if <variable> = <some text>, где variable - имя переменной, а some text то чему переменная может быть равна (кстати знак "=" не единственный, также можно юзать ">" или "<"). При этом команда выполнится только при равенстве переменной тексту. Вот пример:
messagebox Do you wand to patch program?, 4, Patch, retval
если пользователь нажмет на кнопку Yes:
messagebox You select Yes, 16, Yes, retval1, if retval = 6
если пользователь нажмет на кнопку No:
messagebox You select No, 16, No, retval2, if retval = 7

Теперь когда с языком разобрались попробуем на примерах.

Маскируем EXE файл под Borland C++ 1999
Довольно интересно упаковать EXE файл скажем UPX’ом или ASPack’ом, да чтоб при этом PEiD и другие снифферы думали что это непакованный файл, скомпиленный в борландовом C++. Тут и крэкеры будут смущены немного, и эмулятор команд сглючит в некоторых эмулирующих отладчиках. Короче довольно полезная штука. Теперь определимся с планом работы. Именно с планом, а не алгоритмом. Для начала нам потребуется сформировать сигнатуру - это будут первые байты с OEP нормальной Borland C++ программы, затем выравнивание стэка и очистка регистров, если они менялись этим кодом и переход на оригинальную точку входа. Нашу сигнатуру сформированную по указанному выше плану необходимо вставить в последнюю секцию и поменять EP на нее. Примерный алгоритм реализации этого на DotFIx Script’е представлен на врезке "Профессиональная маскировка". Не правда ли просто?

CODE NOW!
;спросим у юзера, нужно ли патчить
messagebox Do you want to patch this program?, 4, Patch, retval
;если не нужно - выходим
goto exit , if retval = 7
;узнаем EP
getoep oep, va_oep
;узнаем image base
getimagebase imagebase
;объединяем
add @va_oep@,@imagebase@,va_oep
;инвертируем этот адрес
invert @va_oep@, va_oep
;узнаем длину генерируемой сигнатур <сигнатура><прыжок на OEP>
length EB1066623A432B2B484F4F4B90E900000000A100000000C1E002A3000000005290B8@va_oep@FFE0,len
;создаем секцию длиной с длину сигнатуры
createsection cool,@len@,raw,va
;определяем рандомный адрес, чтобы смутить анализаторы, чтобы сигнатура не была статичной
add @va@,@imagebase@,address
;инвертируем этот адрес
invert @address@, address
;вставляем сигну в созданную секцию
putcode @raw@, EB1066623A432B2B484F4F4B90E900000000A1@address@C1E002A3@address@5290B8@va_oep@FFE0,len
;меняем EP на адрес новой секции
setoep @va@
;устанавливаем флаги секций в C0000020
setflag C0000020
;выводим новую точку входа на экран
messagebox New oep: @va@,16
label exit



Как видим, PEiD даже на normal scan’е наивно верит, что это C++




Определяем пикодовость VB проекта
Очень часто реверсеру приходится иметь дело с VB прогами. Кто с такими сталкивался, тот знает, как иногда полезно заранее знать, псевдокод там или нормальный асмовый листинг (да, бейсик умеет и в то и в то компилять). Это бы упростило скорость подбора инструмента для исследования в несколько раз. Раскрою тебе большой секрет - если иметь под рукой DotFix Script задача решается минут за 10. Сомневаешься? Тогда давай напишем с тобой такой скрипт и разберем как он работает:

CODE NOW!
getoep oep, va_oep
getimagebase imagebase
add @va_oep@,@imagebase@,va_oep
add @oep@,1,oep
getcode @oep@, 4, VBHeader
invert @VBHeader@, VBHeader
sub @VBHeader@,@imagebase@,VBHeader
add @VBHeader@,30,VBHeader
getcode @VBHeader@, 4, ProjectInfo
invert @ProjectInfo@, ProjectInfo
sub @ProjectInfo@,@imagebase@,ProjectInfo
add @ProjectInfo@,20,ProjectInfo
getcode @ProjectInfo@, 4, NativeCode
messagebox This program compiled to P-Code,64,VB file sniffer,retval, if NativeCode = 00000000
messagebox This program compiled to Native Code,64,VB file sniffer,retval, if NativeCode > 00000000



Один щелчок мыши и мы уже имеем полное представление о типе команд VB программы. Пора грузить декомпилятор :)




Как видишь скрипт мегапрост. Решить ту же задачу на любом из общепризнанных языков программирования потребовало бы втрое больше времени не говоря уже о том что потребовалось бы позаботиться об открытии файла, встраивании менюшки и т.д. Все эти рутинные операции за нас выполняет скриптовый движок и сам DotFix FakeSigner, нам же остается только объяснить ему что делать с уже открытым файлом. Задача корректно закрыть файл и прочие также будут целиком и полностью ложиться на скрипт. Теперь рассмотрим только что написанный код. Суть его в том, что мы считываем сначала адрес VBHeader структуры, по этому адресу считываем саму структуру, а затем по смещению 30h относительно начала структуры считываем поле ProjectInfo. Оно в свою очередь указывает на соответствующую структуру ProjectInfo. По смещению 20h уже относительно начала ProjectInfo структуры считываем четырех байтное поле NativeCode. Если оно отлично от нуля, то мы имеем Native Code программу, иначе это пикод. Так как Dword поля расположены в EXE файле в формате справа на лево, то мы их все приводим к нормальному отображению командой invert. Затем эти адреса необходимо перевести в Offset, для этого мы отнимаем из них ImageBase. Признаюсь честно - для более корректного перевода надо скорректировать это число по Offset и VA адресам секции, в которой находится адрес, но в VB прогах эти адреса у первой секции обычно всегда равны, поэтому я решил не усложнять скрипт лишним командами.

Пишем простенький криптор
Теперь когда мы немного разобрались с командами скриптового языка я думаю имеет смысл написать что-нибудь гораздо более серьезное, а именно предлагаю написать криптор PE файлов. Он будет криптовать первые 10 байт в EXE файле, начиная от точки входа, а точка входа будет меняться на последнюю секцию. В нее мы запишем декриптор того криптованного участка из 10 байт и соответственно переход на оригинальную точку входа в программу. В простейшем виде скрипт будет выглядеть так:

CODE NOW!
;определяем точку входа
getoep oep, va_oep
;xor’им первые 10 байт точки входа и
;заносим код декриптовщика в переменную ’decoder’
xorcode @va_oep@,10,decoder
;определяем imagebase
getimagebase imagebase
;складываем oep и imagebase
add @va_oep@,@imagebase@,va_oep
;записываем байты в обратном порядке
invert @va_oep@, va_oep
;заносим длину нашего кода в переменную ’len’
length 60@decoder@61B8@va_oep@FFE0,len
;создаем секцию с именем ’cool’ и длиной ’len’
;функция занесет реальный и виртуальный адреса
;в переменные ’raw’ и ’va’.
createsection cool,@len@,raw,va
;вставляем код в exe файл по адресу,
;который содержится в переменной ’raw’
putcode @raw@, 60@decoder@6168@va_oep@E800000000C3C3
;изменим oep на адрес начала нашего кода
;в созданной секции
setoep @va@
;разблокируем возможность записи в секции
setflag C0000020
;выведем на экран сообщение
messagebox New oep: @va@,64



Как видишь, то что пишут на стандартных алгоритмических языках целый день и отлаживают неделю мы в состоянии налабать за полчаса, включая время отладки :) Ладно, это мы отвлеклись. Как же работает скрипт? Все просто! Определяем точку входа и ксорим первые 10 байт, затем копируем декриптор в переменную decoder. Теперь создаем новую секцию и добавляем туда декодер и переход на OEP. Если тебя смутила запись "60@decoder@6168@va_oep@E800000000C3C3", объясняю:
60 - опкод команды ассемблера pushad
61 - опкод команды ассемблера popad
68@va_oep@ - push @va_oep@
E800000000 - push 0
C3 - ret
Этот извратный jmp используется в некоторых протекторах, для неявного jmp’а на адрес. Вот в общем и все, что я хотел тебе рассказать. Думаю немного практики и возможно ты будешь оптимизировать с помощью данного скриптового языка многие свои (и не свои) задачи по обработке PE файлов.

Использование скриптов
Ну вот написал ты скрипты, поставил последнюю команду и первая твоя мысль - а куда это все класть. И ведь правда. О самом главном я таки не сказал. Все скрипты, необходимо сохранять в таком формате: "<имя скрипта>.fix". ".fix" это расширение, "имя скрипта" - имя, которое будет выводиться в программе. Теперь полученный нами скрипт копируем в папку Scripts. Она находится в той папке, в которую ты установил DotFix FakeSigner (если еще не установил - вставляй ту круглую хренотень, что валялась в пакете вместе с журналом в CD привод или открывай http://fakesigner.dotfix.net). Теперь самое время запустить DotFix и выбрать любой EXE файл, затем в списке скриптов выбрать нужный и нажать кнопку Patch - при этом скрипт начнет выполняться. Рекомендую во всех скриптах вначале писать запрос у пользователя, не по ошибке ли он запустил скрипт. Это так сказать правило хорошего тона. Также рекомендуется в скриптах предусматривать бэкап исходного файла и возможность его восстановления в случае ошибки скрипта (рекомендую обратить внимание на команды copyfile и delfile). Также советую предусмотреть консольный интерфейс и возможность сохранения предпочтений юзера в реестр. Только соблюдая эти советы можно написать мощный скрипт.

Пара слов об отладке
Если ты хотя бы раз программировал какую либо софтину, ты наверняка знаешь, что написать что либо безглючное без отладки нельзя. В этом ты абсолютно прав и скриптовый движок DotFix’а содержит довольно мощный анализатор скриптов. Поэтому если ты что-то написал не так, то после того, как твой скрипт выполнится FakeSigner выведет все ошибки, которые были найдены в скрипте и укажет строку в которой закрался баг. Поэтому рекомендую никогда не забывать об этом и помнить что ввод неверной команды всегда будет обнаружен и ты будешь информирован :)

Дебаггер сразу просек все ошибки в скрипте



Хочу компилятор
Разобравшись со скриптовым языком ты наверняка напишешь что-нибудь мощное, новое, продвинутое. Это чтото будет использовать и консоль, и настройки и на полную мощь использовать возможности скриптового языка и движка. Но тут возникнет вопрос: а нельзя ли этот скрипт превратить в нормальный EXE файл, который получает имя PE файла юзерской проги из командной строки или запрашивает при запуске и работает независимо от DotFix’а? Обрадую тебя, над этим вопросом автор уже работает и думаю в одной из ближайших версии DotFix FakeSigner’а появится компилятор скриптов в EXE файл. Так что можешь уже начинать писать свой суперскрипт! А если не хватает команд - писать мне, буду расширять скриптовый язык нужными операторами и командами.

Вместо заключения
Я надеюсь, что прочитанные тобой страницы не пропадут зря и ты наверняка разработаешь какой-нибудь мощный скрипт, автоматизирующий тебе рутинные операции по работе с PE файлами. Кодер автоматизирует процесс после компиляции программы по протекции, реверсер напишет инструменты для анализа и кое кто другой возможно начнет писать полиморф. Поэтому не теряй времени - приступай к изучению примеров. Удачи тебе и безеррорной линковки :)

Сайт программы: http://fakesigner.dotfix.net

За обновлениями сюда :)



http://fakesigner.dotfix.net


Комментарии
отсутствуют

Добавление комментария

Ваше имя (на форуме):

Ваш пароль (на форуме):

Комментарии могут добавлять только пользователи,
зарегистрированные на форуме данного сайта. Если Вы не
зарегистрированы, то сначала зарегистрируйтесь тут

Комментарий:



04.09.2011 Долгожданный релиз VB Decompiler. Масса улучшений декомпиляции Native Code. Значительно расширенна и обновлена справочная система на русском и английском языках.
20.12.2010 DotFix Software поздравляет наших клиентов и посетителей сайта с наступающим Новым Годом и рождеством! Желаем приятно провести праздники и успехов в новом году!
28.11.2010 Выпущена новая версия защиты DotFix NiceProtect. Основные изменения коснулись обфускатора Delphi программ. Теперь имеется полная поддержка Tab и Page контролов на формах, что обеспечивает максимальную совместимость обфускации с Delphi XE программами.
21.10.2010 Обновлен декомпилятор Visual Basic программ до версии 8.1. Декомпиляция P-Code программ становится все более идеальной, также проделана большая работа по улучшению анализа Native Code и .NET приложений.
16.09.2009 Полностью обновлен движок сайта! Теперь все ссылки имеют читаемый понятный вид, разного рода глюки на страницах убраны. И теперь сайт полноценно работает на второй версии нашего движка.
Архив новостей
Яндекс цитирования

Движок сайта: DotFix Engine v0.2
Администрация сайта:
колодки тормозные передние мазда 3