|
|||||||||||||||||||||||||||||||||||||||||
Автор: 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, если он еще не установлен, так как без практики весь нижеследующий текст будет мало полезен. Ну что, раз все уже установлено - приступим! Основные команды языка Прежде чем что-то писать, необходимо знать матчасть. Это аксиома. С этим спорить не будем, лучше рассмотрим основной набор команд языка. Итак начнем с функций работы со строками как базовых.
Первый операнд команды set - числовое или символьное значение, второй - аккумулятор (переменная), в которую будет занесено это значение. По сути команда на понятном человеку языке выглядела бы так: accumulator=value. Соответственно для сложения, вычитания и других операций с числовыми данными используются следующие команды:
Логично предположить, что value 1 и value 2 представляют собой первой и второе число, а accumulator - аккумулятор (переменная) для сохранения результата. Разумный вопрос, а как использовать переменные в value 1 и 2? Легко! Переменную указываем в макросовом виде. Пример: имеем переменную "a", в которой хранится число 10, и переменную "b", в которой хранится число 20, тогда конструкция:
выполнится так: "а" приложится к "b" и составит 1020 и к этому числу прибавится 150. В результате в переменной "c" будет 1020+150, то есть 1170. Думаю методика понятна. Ниже представлю некоторые другие команды для работы со строками, прототипы которых описаны в справке к программе: concat, chrtohex, hextochr, substr, length, createstring, rndbyte, settoclipboard. Имена команд интуитивно понятны и легко запоминаются, потому проблемы думаю не возникнут. Если и возникнут - далее язык будет рассмотрен на примерах. Со строками закончили, пора перейти к командама ввода вывода, предназначенных для общения разрабатываемого нами супер скрипта с пользователем. Весь ввод и вывод производится либо через формы запроса, либо через консоль. Вот основные команды:
По сути аналог одноименной API, только последний параметр - результат возвращаемый функцией - описывающий что за кнопку нажал юзер для контроля результата.
Форма запроса данных от пользователя. 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’е представлен на врезке "Профессиональная маскировка". Не правда ли просто?
Как видим, PEiD даже на normal scan’е наивно верит, что это C++ ![]() Определяем пикодовость VB проекта Очень часто реверсеру приходится иметь дело с VB прогами. Кто с такими сталкивался, тот знает, как иногда полезно заранее знать, псевдокод там или нормальный асмовый листинг (да, бейсик умеет и в то и в то компилять). Это бы упростило скорость подбора инструмента для исследования в несколько раз. Раскрою тебе большой секрет - если иметь под рукой DotFix Script задача решается минут за 10. Сомневаешься? Тогда давай напишем с тобой такой скрипт и разберем как он работает:
Один щелчок мыши и мы уже имеем полное представление о типе команд VB программы. Пора грузить декомпилятор :) ![]() Как видишь скрипт мегапрост. Решить ту же задачу на любом из общепризнанных языков программирования потребовало бы втрое больше времени не говоря уже о том что потребовалось бы позаботиться об открытии файла, встраивании менюшки и т.д. Все эти рутинные операции за нас выполняет скриптовый движок и сам DotFix FakeSigner, нам же остается только объяснить ему что делать с уже открытым файлом. Задача корректно закрыть файл и прочие также будут целиком и полностью ложиться на скрипт. Теперь рассмотрим только что написанный код. Суть его в том, что мы считываем сначала адрес VBHeader структуры, по этому адресу считываем саму структуру, а затем по смещению 30h относительно начала структуры считываем поле ProjectInfo. Оно в свою очередь указывает на соответствующую структуру ProjectInfo. По смещению 20h уже относительно начала ProjectInfo структуры считываем четырех байтное поле NativeCode. Если оно отлично от нуля, то мы имеем Native Code программу, иначе это пикод. Так как Dword поля расположены в EXE файле в формате справа на лево, то мы их все приводим к нормальному отображению командой invert. Затем эти адреса необходимо перевести в Offset, для этого мы отнимаем из них ImageBase. Признаюсь честно - для более корректного перевода надо скорректировать это число по Offset и VA адресам секции, в которой находится адрес, но в VB прогах эти адреса у первой секции обычно всегда равны, поэтому я решил не усложнять скрипт лишним командами. Пишем простенький криптор Теперь когда мы немного разобрались с командами скриптового языка я думаю имеет смысл написать что-нибудь гораздо более серьезное, а именно предлагаю написать криптор PE файлов. Он будет криптовать первые 10 байт в EXE файле, начиная от точки входа, а точка входа будет меняться на последнюю секцию. В нее мы запишем декриптор того криптованного участка из 10 байт и соответственно переход на оригинальную точку входа в программу. В простейшем виде скрипт будет выглядеть так:
Как видишь, то что пишут на стандартных алгоритмических языках целый день и отлаживают неделю мы в состоянии налабать за полчаса, включая время отладки :) Ладно, это мы отвлеклись. Как же работает скрипт? Все просто! Определяем точку входа и ксорим первые 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
|
|
| ||||||||||||||||||||||||||||||||||||||