Сейчас на форуме: (+6 невидимых) |
eXeL@B —› Программирование —› code vs data. |
<< . 1 . 2 . 3 . >> |
Посл.ответ | Сообщение |
|
Создано: 23 декабря 2016 10:22 · Поправил: difexacaw · Личное сообщение · #1 Здрасти. Задача отличить код от данных. Тоесть имеем указатель на массив, нужно аналитически узнать что это код. Хотелось бы посмотреть что уже сделано. Когда то давно была попытка реализовать, толи deroco, толи есчо кто, не могу найти. Анализер иды не годится, он слишком толст и не профайл, а самое главное не умеет разбирать наверно дампы вне пе. ----- vx |
|
Создано: 07 января 2019 11:23 · Личное сообщение · #2 difexacaw, я не совсем понимаю суть вашей решаемую задачу, воздержусь дальше рассуждать. Говорим каждый о своём. ----- PGP key |
|
Создано: 07 января 2019 11:33 · Личное сообщение · #3 |
|
Создано: 07 января 2019 13:44 · Личное сообщение · #4 |
|
Создано: 24 апреля 2019 18:59 · Личное сообщение · #5 Vamit Я поискал по вашей активности, что бы спросить, свежих" тем у вас нет. А я хочу задать вопрос именно вам. Поэтому спрошу тут. Вы вроде бы как выполняли девирт вм(в частности вмп). Меня интересует как вы это делали, использовали автоматику или нет, как сворачивался код вм ? Мне это интересно так как возможно я буду искать решение, те это может быть задачей. Хочу знать как вы это решали. ----- vx |
|
Создано: 24 апреля 2019 22:42 · Поправил: sefkrd · Личное сообщение · #6 |
|
Создано: 24 апреля 2019 22:53 · Поправил: difexacaw · Личное сообщение · #7 |
|
Создано: 25 апреля 2019 12:23 · Поправил: Vamit · Личное сообщение · #8 difexacaw Вы вроде бы как выполняли девирт вм(в частности вмп). Меня интересует как вы это делали, использовали автоматику или нет, как сворачивался код вм ? Процесс полной девиртуализации любой вм возможен, но он очень непростой и должен учитывать специфику реализации вм. Мой девиртуализатор VMSweeper способен обрабатывать 2 типа вм - VMProtect и CodeVirtualizer. Процесс обработки вмпрота содержит более 50 различных правил, а кодевирта порядка 10, но реализовано всё это на одном движке и он может девиртуализовать любую вм при написании конкретных правил обработки под неё. Девиртуализация функций производится в статике на распакованном уже коде, распаковкой кода свипер не занимается, но позволяет её упростить. Про всё это можно почитать в теме Декомпилятор ВМ. Здесь же могу повторить основные процессы движка, применимые к любой вм, сам движок двухпроходный, на каждом из проходов производится полная статическая эмуляция виртуализованного кода функции. Первый проход это анализатор, а второй - компилятор. Для каждой инструкции кода имеется собственный обработчик, вот его общие правила: Code:
Вот краткая последовательность процессов движка без учета специфики вм: 1. Первый проход эмулятора кода (анализатор), его действия описаны выше. 2. Построение блоков кода, т.е. разбивка линейного кода на блоки, каждый блок может содержать от 1 до нескольких асм инструкций. 3. Второй проход эмулятора кода (компилятор), его действия описаны выше. 4. Тут уже имеем деобфусцированный асм код функции, далее к нему последовательно применяется набор правил для конкретной вм и выполняется свертка полученного псевдо кода в исходный асм код функции. Написал очень кратко, без конкретных вопросов чтоб описать весь процесс девиртуализации вмпрота нужно написать целую книгу. ----- Everything is relative... | Сообщение посчитали полезным: bartolomeo, difexacaw |
|
Создано: 25 апреля 2019 13:57 · Личное сообщение · #9 |
|
Создано: 25 апреля 2019 14:25 · Личное сообщение · #10 |
|
Создано: 25 апреля 2019 17:12 · Личное сообщение · #11 |
|
Создано: 25 апреля 2019 17:28 · Личное сообщение · #12 Vamit Спс что ответили. Основная суть всё равно не понятна: > USE, INIT, CHANGE Покрываем графом имеющийся вм код. Для каждой интрукции определяем параметрические зависимости, эти самые Init/change/etc. Далее находим всю функциональную цепочку до текущего места и если она не влияет на контекст(те мусорный код) удаляем его. Это просто чистка графа от простейшего мусора. Как сами операции сворачивать, на одну к примеру мат. операцию может генерится сотня инструкций. Во первых как узнать конкретную операцию ? Хардкодить шаблон для конкретной вм ? Как вы это делали ? ----- vx |
|
Создано: 25 апреля 2019 17:39 · Личное сообщение · #13 |
|
Создано: 25 апреля 2019 17:51 · Личное сообщение · #14 SegFault Никто не удалял, вот она difexacaw Когда код очищен от мусора мы имеем последовательность тел примитивов вм, т.е. её инструкции, содержащие несколько асм инструкций, их преобразовываем в промежуточный асм код сохраняя логику обработки. На этой же стадии так же решаются чисто специфические особенности вм (реализация условных переходов, crc проверки кода, антидампинг и другие защитные механизмы). Затем полученный асм код пропускаем снова через описанный выше эмулятор, получая уже новый блочный граф. На этой стадии производится ещё одна очистка от "мусора", а далее уже идет последовательность шагов по девиртуализации - на основе шаблонов виртуализации инструкций определяем границы блоков и сворачиваем их в псевдоисходную инструкцию. Этот процесс многопроходный, кол-во проходов до бесконечности, пока есть что удалять и сворачивать. А псевдокод потому, что в нем в большинстве инструкций нет реальных регистров цпу, а имеются только регистры вм. Следующая многопроходная стадия это поиск соответствия регистров вм регистрам цпу, после этого остается только произвести ассемблирование полученного кода и усё... ----- Everything is relative... |
|
Создано: 25 апреля 2019 17:59 · Личное сообщение · #15 |
|
Создано: 25 апреля 2019 18:01 · Личное сообщение · #16 Vamit Тоесть основная задача это построение графа данных, что бы вычистить мусор ? А дальше именно использование шаблонов, что бы определить конкретную операцию ? Это ведь не общее решение, это не будет работать для произвольной вм, да даже не для вм, а обычного отморфленного кода. Есчо не понятно что такое эмулятор", о котором вы говорите. Это наверно некий транслятор, зачем что то эмулировать при статическом анализе ? > вот она --> Link < Там слишком длинная тема. Добавлено спустя 1 минуту SegFault > перевести весь код в псевдокод Тут где то рядом свежая тема, кто то показал инструмент, который именно это делает(там на скринах это видно). Добавлено спустя 5 минут > Следующая многопроходная стадия это поиск соответствия регистров вм регистрам цпу Это ведь тоже зависимость в dfg, цепочка пересылки данных. Не понимаю причём тут многопроход, это наверное некий механизм в конкретно вашей реализации. Мне пока общие принципы интересны. ----- vx |
|
Создано: 25 апреля 2019 18:13 · Личное сообщение · #17 |
|
Создано: 25 апреля 2019 18:14 · Поправил: difexacaw · Личное сообщение · #18 Vamit Что бы с чего то начать, думаю вначале следует построить dfg и убрать мусор. Это не сложная задача. Можете примеры показать, те части кода вм и очищенного от функционального мусора, что бы посмотреть что получается на выходе того же вмп ? Или по проходам, как происходит чистка. Добавлено спустя 3 минуты SegFault ----- vx |
|
Создано: 25 апреля 2019 19:38 · Поправил: Vamit · Личное сообщение · #19 То есть основная задача это построение графа данных, что бы вычистить мусор ? Нет, это второстепенная задача и в большей своей части она решается сама собой. Основное назначение графа определить границы функциональных блоков и задать правила обработки для блока каждого типа. Там слишком длинная тема. Ну читать можно не все, а только мои посты, их там не так и много. Это ведь не общее решение, это не будет работать для произвольной вм, да даже не для вм, а обычного отморфленного кода. Общего решения по декомпиляции кода не существует, каждый тип вм имеет свои особенности и их нужно учитывать, иначе вместо чистого асм кода вы получите какую-то псевдо хрень описывающую процессы внутри вм, а это очень далеко от нужной цели. Общий тут только движок декомпиляции со статическим эмулятором - он пригоден для решения любых задач по трансформации кода, хоть девиртуализация, хоть декомпиляция с асма в первоначальные языки высокого уровня, на которых писалась программа. Всё дело в гибкой настройке и правилах обработки кода на каждой стадии, для этого конечно нужно писать и добавлять в декомпилятор новые модули, заточенные под конкретную задачу, главное что такая возможность в движке имеется. Это наверно некий транслятор, зачем что то эмулировать при статическом анализе ? Как это зачем, а кто будет эмулировать поведение инструкций, пересылать данные и т.д. Эмулятор инструкции не исполняет, но полностью эмулирует их работу. Он содержит в себе все регистры цпу, стек и память. Если простая инструкция inc eax прибавляет 1 к eax, то эмулятор создаст в регистре eax следующее выражение: предыдущее значение eax + 1 и установит/сбросит/изменит флаги зависимые от инструкции. Всё описать практически невозможно, да и не нужно, потому как без конкретных примеров это понять сложно. Можете примеры показать, те части кода вм и очищенного от функционального мусора, что бы посмотреть что получается на выходе того же вмп ? Или по проходам, как происходит чистка. Во вложение можно посмотреть на выхлоп декомпилятора при девиртуализации конкретной функции. В теме декомпилятора где-то есть описание всех этих файлов по типам. 7c14_25.04.2019_EXELAB.rU.tgz - Sample.rar ----- Everything is relative... |
|
Создано: 25 апреля 2019 20:10 · Личное сообщение · #20 |
|
Создано: 25 апреля 2019 20:31 · Поправил: Vamit · Личное сообщение · #21 SegFault Не знаю что такое "символическое исполнение", термины могут быть разные хотя относятся к одному и тому же. В эмуляторе есть понятие переменная, это последовательность переменных с операндами как между ними, так и пост/префикс операндами с учетом приоритетов, т.е. имеются скобочные выражения. В общем виде переменная var это произвольное выражение, например, (~eax + 15 ) ^ B3 - [mem] и т.д. Все регистры цпу, стек и память в эмуляторе оперируют переменными, при пересылке переменной из одного места в другое её можно разорвать, т.е. построить законченное выражение и начинать строить новое, а можно и не разрывать, а просто пристыковать её к уже имеющейся. Всё зависит от правил, какой код мы хотим получить. Так же можно задать разрешение константных операций на лету, т.е. все операции с константами будут решаться без построения выражения, а сразу вычислением. ----- Everything is relative... |
|
Создано: 25 апреля 2019 20:45 · Личное сообщение · #22 Насчет связей регистров ( все эти init/use/reuse ) наверное имеется ввиду теория от старушки Сифуэнтес: https://yurichev.com/mirrors/DCC_decompilation_thesis.pdf (1994й год между прочим!) глава 5.2.6. Register Copy Propagation, я в принципе тоже подобное использовал когда-то давно. Хотя тогда доку и не читал, видимо это довольно очевидное решение. |
|
Создано: 25 апреля 2019 21:26 · Личное сообщение · #23 |
|
Создано: 25 апреля 2019 21:32 · Поправил: Vamit · Личное сообщение · #24 |
|
Создано: 25 апреля 2019 21:32 · Личное сообщение · #25 RevCred Я так понимаю девиртуализатор вамита пилился 9 лет назад, там не было современных фреймворков типа miasm / z3 и прочих. И темы про виртуализатор: Code:
вот это любой солвер свернет в готовый результат сейчас. Но в те времена этого просто не было. |
|
Создано: 26 апреля 2019 10:06 · Поправил: Vamit · Личное сообщение · #26 Используется ли в статическом эмуляторе солверы(символическое исполнение)? Теперь понятно, конечно имеется, только я называю это исполнением по шаблону. Из исследуемого кода строится шаблон исполнения, а затем он исполняется. Используется для расшифровки ленты пикода, т.к. каждый примитив имеет свой уникальный алгоритм хеширования. Вот эти исполняемые шаблоны (уже нормализованные): Code:
----- Everything is relative... |
|
Создано: 26 апреля 2019 19:27 · Личное сообщение · #27 SegFault В начале этого дока есть грубейшая ошибка: mov cs:[conta],virusOffset Это говорит о том, что математики далеки от реальности. Запись в кодовый сегмент не возможна(и небыла возможной есчо до этой публикации), обработка при этом событии пойдёт вне контекста задачи и дальнейшее описание бессмысленно. Остальную чушь можно не читать, так как там утверждения мало связанные с реальным кодом/архитектурой. Это лишь гипотетические мат измышления, таких публикаций навалом и они бесполезны. Vamit Я посмотрел аттачь, он совершенно бесполезен, так как там лог автоматики. Я подумал над чисткой мусора. Походу общее решение то, о чём говорит человек выше - солверы. Вы же изначально про это не говорили, а сейчас оказывается что и они использованы У меня ход мыслей следующий. Для работы с графом нужен конкретный алгоритм. Не имея его невозможно ничего реализовать. Пусть dfg определена как совокупность частей контекста. Тогда можно определить паразитную инструкцию(мусор) - такая инструкция перезагружает все компоненты dfg, это то самое init. Тогда рекурсивно можно пройти всю цепь cfg и удалить всю цепочку. Но есть пара нюансов. Это сработает для простого мусора, который не связан в dfg. Но может быть и сложный, когда котекст после исполнения некоторой функции не изменен, но он связан в dfg. Например: sub r,x ... add r,x Тоесть получается что нужно выделить некоторую функцию, а это и есть то самое символическое исполнение, этой математикой занимаются солверы. Получается что мы имеем либо исполненный код и по контексту можно определить результат функции, но обычно код не исполняется(при статическом анализе) и тогда нужно выделить эти функции. Если же это частично динамика, то можно в виде решения(что бы не определять функцию) выполнить все возможные ветви и возвращать состояние контекста и памяти к исходному значению, таким образом определив что функция контекст не меняет. Общая задача чистки как оказывается не так проста. У вас ведь двиг использует алгоритмы чистки ? Мне интересно как это реализовано. ----- vx |
|
Создано: 26 апреля 2019 20:48 · Поправил: Vamit · Личное сообщение · #28 В начале этого дока есть грубейшая ошибка: mov cs:[conta],virusOffset Ты ещё слишком молод, чтоб знать такие вещи - во времена ДОСа и экстендеров такое было возможно, пиши куда хочешь и читай что хочешь. А в примерах там только 16 разрядный ДОС, но дело не в них, а в самой сути разбора кода. У вас ведь двиг использует алгоритмы чистки ? Основная чистка выполняется автоматом при построении блоков после первого прохода, а всё остальное реализовано в деобфускаторе двойным просмотром вперед и взад от конкретной инструкции, вперед - юзаются ли результаты этой инструкции далее, а взад - юзает ли эта инструкция результаты предыдущих. На переприсвоениях цепочка разрывается и так повторяется бесконечно долго, пока не приходим к выводу что каждая оставшаяся инструкция что-то юзает. В итоге имеем чистый код, но так удаляется только регистровая и флаговая обфускация, а ещё есть и стековая, с ней сложнее, сначала надо строить законченные выражения, а затем анализировать их результат, если результат юзается, то выражение преобразуется в соответствующую ему асм инструкцию. ----- Everything is relative... |
|
Создано: 26 апреля 2019 21:00 · Личное сообщение · #29 Vamit А как быть с памятью, ведь она является частью графа ? И вы не ответили по выделению функций, это важно. Вы можете взять произвольный код и вычистить из него не используемые части ? Точнее на сколько я понял у вас всё реализовано чисто вручную, определены все шаблоны, функции, тоесть это полностью длительный разбор конкретной вм/морфа вручную. ----- vx |
|
Создано: 26 апреля 2019 22:04 · Поправил: Vamit · Личное сообщение · #30 А как быть с памятью, ведь она является частью графа ? А что с памятью, тут всё просто - любая память приложения обфускации не подлежит, т.к. к любой её области возможен косвенный доступ. При этом стек (сам стек, локальные переменные и аргументы) не являются памятью, на него действуют свои правила. Но в контексте вм может быть своя память и с ней вм может делать что хочет. Например, вмпрот не имеет своей памяти, он все реализует в стеке, а вот кодевирт свою память имеет и это тоже надо учитывать. И вы не ответили по выделению функций, это важно. Вы можете взять произвольный код и вычистить из него не используемые части ? Да, это возможно, только необходимо задавать пограничные условия, какие регистры могут юзаться на входе и результаты каких на выходе. Тут ничего сложного нет и в общую картину это вписывается. Та же функция имеет аналогичные пограничные условия. Что такое выделение функций? Функция может быть виртуализована частично (по маркерам или при выборе произвольной точки в ней) или полностью. Начинаем с точки входа в вм (она всегда одна) и идем до тех пор пока не будет охвачена вся виртуализация (выходов из вм может быть несколько), разрешение условных переходов производим по мере их появления. В итоге получаем "кривой" граф, затем его оптимизируем на уменьшение кол-ва переходов и их длин и затем пускаем по полученному коду декомпилятор. Точнее на сколько я понял у вас всё реализовано чисто вручную, определены все шаблоны, функции, тоесть это полностью длительный разбор конкретной вм/морфа вручную. Что значит вручную? Чтобы что-то написать надо знать что пишешь, я уже говорил, чтобы сделать девиртуализатор любой вм нужно полностью знать её структуру, иначе исходный код не получить. А морф тут не при чем, он только мешает, чего его изучать - он генерится по определенным правилам и по тем же правилам убирается. Вообще любой декомпилятор это противоположность компилятору, если знаешь компилятор, то сделаешь и декомпилятор, а иначе получишь только что-то более/менее приблизительное, упрощающее понимание, но никак не исходный код. Посмотри на выхлоп хексрейса - ему до исходного кода далеко как до луны, а почему, да потому, что он не учитывает особенности компиляторов, не знает языка в который надо декомпилировать и делает все по общим своим правилам. Да, на простых функциях это помогает, но на сложном коде проще разобрать асм код, чем его выхлоп. И с вм картина полностью аналогична, только ещё усуглублена тем что свой код вм защищает разными методами и пока их не изучишь ты не поймешь что она вообще делает. Да, по пути исполнения визов/солвер пройти может, но это не полный охват при наличии ветвлений, а только его часть, которая может быть ничтожно малой от общего кода. ----- Everything is relative... |
|
Создано: 26 апреля 2019 22:18 · Личное сообщение · #31 Vamit пишет: Чтобы что-то написать надо знать что пишешь, я уже говорил, чтобы сделать девиртуализатор любой вм нужно полностью знать её структуру, иначе исходный код не получить. вот тут непонятно. Я думал автоматикой разбирается структура, а получается, что ее вручную надо разбирать? т.е. если дерматолог поменяет слегка свою вм, то придется заново разбирать ее вручную и потом писать эти шаблоны девиртуализации? |
<< . 1 . 2 . 3 . >> |
eXeL@B —› Программирование —› code vs data. |
Эта тема закрыта. Ответы больше не принимаются. |