• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Обфускация С/С++ кода с помощью Python и libclang

Пожалуйста, обратите внимание, что пользователь заблокирован
Морфинг шеллкода накладывает на себя ряд ограничений: такие как отсутствие возможности использовать глобальные переменные, лямбды и шаблоны.
Ну ты можешь обернуть весь код шелла в методы некоего класс, все действующие переменные класса перемешать с мусорными переменными псевдо-случайным образом и генерировать мусорный код над этими переменными (указатель this будет автоматически передаваться из метода в метод). Это как альтернатива глобальным переменным, оптимизатор тоже не сможет их вырезать.

Ограничения libclang выглядят убедительными, чтобы искать другое решение - по этому я выше спросил за модификацию компилятора..
На уровне С++ этих ограничений нет, проблема в том, что сишные апи, которые байндит Питон не предоставляют таких функций.
 
Интересная затея еще модифицировать какой-нибудь опенсурсный сишный компилятор с целью автоморфинга и генерации идеального мусорного кода, взаимодействия с модифицируемым кодом.
Кто-нибудь баловался таким?
Не для С. Писал же вм на jscript. И компилятор js-> вм. Архитектурно можно, чтобы каждый опкод, полученный с компиляции конкретного узла - был представлен определенным сетом(то есть набором инструкций, во что, собственно, компилируется узел, можно задавать глубину ). Сначала думал только heap based делать. А потом придумал зафигачить ещё регистры и стек. Ну и получается инструкции вм умеют работать сразу со всеми моделями. Гонять данные из регистра в хип, из хипа в стек и т.д. Из-за этого получается неплохая вариативность. Сами же имена инструкций в вм каждый раз разные(и в компиляторе), билдер это все связывает воедино. Вопрос такой, есть ли какие либо алгоритмы, позволяющие в разных билдах задавать уникальный сет инструкций. Простыми словами, чтобы с точки зрения человека, анализирующего вм - эта самая вм была на каждый билд с уникальной архитектурой, а не просто с разными именами инструкций? Типо метаморфная архитектура для вм, хз как ещё описать.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Интересная затея еще модифицировать какой-нибудь опенсурсный сишный компилятор с целью автоморфинга и генерации идеального мусорного кода, взаимодействия с модифицируемым кодом.
Кто-нибудь баловался таким?
По ТСС
https://xss.pro/threads/23817/#post-137370 - эту тему также советую посмотреть целиком (хотя ты ее мб видел раньше).

По статьям. Думаю, можно не ждать конкурса, а сделать что-то вида. Автор объявляет цену статьи (скажем, штука баксов, 2, 3), люди сбрасываются , как сумма набирается, автор пишет. Статья доступна подписчикам или всем или со временем, это уже лирика, важно что будет фин. мотивация, ибо понятно что сейчас не то время, чтобы писать статьи на голом энтузиазме. Это не говно вида "подключаем реакт для вывода лайков в фейсбук".
 
По статьям. Думаю, можно не ждать конкурса, а сделать что-то вида. Автор объявляет цену статьи (скажем, штука баксов, 2, 3), люди сбрасываются , как сумма набирается, автор пишет.
Давно уже подобное реквестирую, имхо идея хороша. Продумать нюансы и жульничество только. Ресерч темы, которая интересна подписчикам, за их же деньги - лучше не придумать. Заказы предварительные на ресерч группами интересующихся, либо автор имея уже какую то тему - оглашает цену инфы.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Вопрос такой, есть ли какие либо алгоритмы, позволяющие в разных билдах задавать уникальный сет инструкций.
Ну во-первых ты можешь делать так, что при каждой пересборке каждая иснтрукция имела уникальный псевдо-случайный опкод (так например делается в KoiVM, если мне не изменяет память). То есть при одной сборке инструкция add будет иметь опкод 0x42, а при другой 0x69 например. Потом можно иметь базовый набор инструкций, которые нужны всегда, и набор необязательных инструкций, которые можно использовать в определенных ситуациях, а можно вместо них использовать базовый набор. Например сдвиг в лево можно использовать вместо умножения на 2, а можно не использовать. Можно добавлять отдельные мусорные инструкции, которые выглядят типа как будто они что-то делают, но на самом деле на поток исполнения никак не влияют. Ну и тд, тут можно многое придумать на самом деле.
 
Ну во-первых ты можешь делать так, что при каждой пересборке каждая иснтрукция имела уникальный псевдо-случайный опкод (так например делается в KoiVM, если мне не изменяет память). То есть при одной сборке инструкция add будет иметь опкод 0x42, а при другой 0x69 например. Потом можно иметь базовый набор инструкций, которые нужны всегда, и набор необязательных инструкций, которые можно использовать в определенных ситуациях, а можно вместо них использовать базовый набор. Например сдвиг в лево можно использовать вместо умножения на 2, а можно не использовать. Можно добавлять отдельные мусорные инструкции, которые выглядят типа как будто они что-то делают, но на самом деле на поток исполнения никак не влияют. Ну и тд, тут можно многое придумать на самом деле.
Так как ты описал, так и делаю по сути, это и имел ввиду под ренеймингом инструкций от билда к билду и дальше по тексту - про сдвиги, это тоже есть(идейно). Ну а больше идей, говоришь можно много придумать, но чёт в голову пока ниче не лезет большего.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Ну а больше идей, говоришь можно много придумать, но чёт в голову пока ниче не лезет большего.
Если отдельные инструкции всегда одинаковой длины, то можно изменять поток управления не линейно, о по какому-нить ГПСЧ. То есть например, сначала исполняется первая инструкция, потом пятая, потом третья и тд. Можно дублировать инструкции, например у тебя образно 80 инструкций в ВМ, в один байт влезает 255 инструкций, то есть у каждой инструкции может быть по 2 дубликата, которые будут выполнять одно и тоже действие, но в ленте байткода выглядеть поразному. Можно делать инструкции, которые комбинируют в себе несколько действий других инструкций. Если у тебя регистровая машина, то можно генерировать количество регистров в определенных пределах и делать так, чтобы алгоритм подбора регистров выбирал их в соответствии с их количеством. В конце концов можно псевдо-случайным образом выбирать между чисто стековой виртуальной машиной, чисто регистровой или комбинированной машиной.
 
Если отдельные инструкции всегда одинаковой длины, то можно изменять поток управления не линейно, о по какому-нить ГПСЧ. То есть например, сначала исполняется первая инструкция, потом пятая, потом третья и тд. Можно дублировать инструкции, например у тебя образно 80 инструкций в ВМ, в один байт влезает 255 инструкций, то есть у каждой инструкции может быть по 2 дубликата, которые будут выполнять одно и тоже действие, но в ленте байткода выглядеть поразному. Можно делать инструкции, которые комбинируют в себе несколько действий других инструкций. Если у тебя регистровая машина, то можно генерировать количество регистров в определенных пределах и делать так, чтобы алгоритм подбора регистров выбирал их в соответствии с их количеством. В конце концов можно псевдо-случайным образом выбирать между чисто стековой виртуальной машиной, чисто регистровой или комбинированной машиной.
Навёл на определенные мысли, благодарю. Про нелинейный поток управления понравилось. Сделать бы так, чтобы от билда к билду в каждом опкоде, каким нибудь образом определялся адрес для прыжка на некст инструкцию. Но определялся не явно, а непрозрачным способом. В зависимости, к примеру, от аргументов опкода. Только теперь продумать, что будет выступать той самой непрозрачностью)
Интересует кстати ещё тема ИИ. Но вот в таком русле. Видел реализации, когда кодили rnn, которая умеет складывать числа. Только нюанс в том, что rnn может складывать числа из +- диапазона обучающей выборки. Дальше точность падает. Почему, понять не могу, математика ведь это о закономерностях же. Но это второй вопрос. Основной вопрос, который меня мучает. Возьмём вм. Хэндлер опкода add который может сложить 2 числа, взяв их из регистров/стека/хипа. Внутрь тела этого хэндлера всунуть готовые веса и rnn. Цимес в том, что веса можно по немногу «доучивать», так что предикт останется таким же +-, но при этом значения весов будут каждый раз разными. Плюс мы не оперируем предназначенными для этого арифметического действия инструкциями реального процессора, чтобы сложить 2 числа, ибо по факту в rnn будет подаваться string же “2+2”. (На самом деле оперируем, умножая веса на входные сигналы + остальная математика с функциями активации, но ты понял о чем я). Ну и по аналогии развить эту тему для остальных операций. Что думаешь?
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
Видел реализации, когда кодили rnn, которая умеет складывать числа. Только нюанс в том, что rnn может складывать числа из +- диапазона обучающей выборки. Дальше точность падает. Почему, понять не могу, математика ведь это о закономерностях же.
Ну нейронка знает только про те значения, про которые уже видела. Нейронка не выдаст точный результат на значениях, которые еще не видела. Ты можешь до бесконечности ее обучать, перебрав все варианты 0xFFFFFFFF * 0xFFFFFFFF вариантов целых чисел подаваемых на вход, но на выходе она все равно может ошибится с какой то вероятностью. Потому, что ты не обучаешь ее сложению, ты говоришь, вот тебе два числа на вход и число на выходе, найди между этими числами закономерность.

Внутрь тела этого хэндлера всунуть готовые веса и rnn. Цимес в том, что веса можно по немногу «доучивать», так что предикт останется таким же +-, но при этом значения весов будут каждый раз разными. Плюс мы не оперируем предназначенными для этого арифметического действия инструкциями реального процессора, чтобы сложить 2 числа, ибо по факту в rnn будет подаваться string же “2+2”. (На самом деле оперируем, умножая веса на входные сигналы + остальная математика с функциями активации, но ты понял о чем я).
Ну можно так сделать, но нужно иметь ввиду, что это будет работать ровно до того момента, пока нейронка не ошибется, вычислит неверное число и вся оригинальная семантика твоей программы накроется медным тазом. Я бы не стал так делать. Но с другой стороны мне кажется, что выбор обработчика для опкода, вместо свича или таблицы можно заменить на нейронку. Поскольку набор опкодов ограничен и небольшой по размеру, то нейронку можно будет обучить выбирать обработчики достаточно быстро и быть уверенным, что она невыкинет никакой нелепой херни.
 
Но с другой стороны мне кажется, что выбор обработчика для опкода, вместо свича или таблицы можно заменить на нейронку.
зачем приплетать нейронку которая предназначенная для "предиктов" в предсказывание опкода в такой точной штуке как виртуальная машина.
я могу понять для чего нейронку использовать если мы касаемся вопросов оптимизации.
Но вот не могу представить себе кейса в каком нейронка бы выиграла у дефолтного механизма. Просто чтобы позлить реверсера?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Просто чтобы позлить реверсера?
Да, вместо классического свича или джамп тейбла. Определить, какой опкод какому обработчику соответствует, будет очень сложно.
 
зачем приплетать нейронку которая предназначенная для "предиктов" в предсказывание опкода в такой точной штуке как виртуальная машина.
я могу понять для чего нейронку использовать если мы касаемся вопросов оптимизации.
Но вот не могу представить себе кейса в каком нейронка бы выиграла у дефолтного механизма. Просто чтобы позлить реверсера?
Сам механизм предикта алгоритмически не линеен же вроде. Чёрная коробка как для нас, так и для реверсера. + веса могут быть уникальными от случая к случаю, без сильного изменения точности. А по поводу точности, это да. С другой стороны тот же эпл же норм твоё лицо отличают от остальных в айфонах. Было бы ненадежно - не было бы ходовым. Мб я и ошибаюсь.
 
В году эдак 2х8 помнится модифицировал компилятор фасма, после плясок вокруг костра он продюссил очень неплохой треш код. Такой код хорошо сбивал сигнатуры и били только по эвристике.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
В году эдак 2х8 помнится модифицировал компилятор фасма, после плясок вокруг костра он продюссил очень неплохой треш код. Такой код хорошо сбивал сигнатуры и били только по эвристике.
В бородатые года была какая-то библиотека на макросах для фасма, которая морфила код, заменяя инструкции. У фасма хороший процессор макросов, там забавные штуки можно было делать. Еще, если мне память не изменяет, компилятор PureBasic выводил код в синтаксисе фасма. Так что в принципе можно использовать сравнительно неплохой высокоуровневый язык, компилить его в фасм и там уже макросами морфить.
 
В бородатые года была какая-то библиотека на макросах для фасма, которая морфила код, заменяя инструкции. У фасма хороший процессор макросов, там забавные штуки можно было делать. Еще, если мне память не изменяет, компилятор PureBasic выводил код в синтаксисе фасма. Так что в принципе можно использовать сравнительно неплохой высокоуровневый язык, компилить его в фасм и там уже макросами морфить.
Статью о морфе на макросах можно найти в старых журналах хакера, видал там что то такое году в 15. Такой морф в наше время будет далеко не идеальным и эвристики не дадут ему шанса.
 
отличная статья. интересно было бы почитать про то, как защетить код самого питона .
Защитить от кого, от кражи сорцев ?

Можно также обфусцировать, можно собрать в бинарник и накрыть протектором, как вариант ?

Кстати по поводу морфинга Си кода, никто не думал создать свой компилятор, да может-быть сложно, но тогда можно гибко морфить код на уровне сборки и бинарного кода, а не на уровне исходных кодов, думаю для темных дел, это правильный подход...

Но такой подход сложный и может-быть долгий, наверное...)))
 
Пожалуйста, обратите внимание, что пользователь заблокирован
интересно было бы почитать про то, как защетить код самого питона
Можно также обфусцировать, можно собрать в бинарник и накрыть протектором, как вариант ?
В Питоне есть в стандартной библиотеке модуль ast, с его помощью можно распарсить в абстрактное синтаксическое дерево произвольный питоновский код. Потом обходишь дерево таким же образом, какой описан в статье и модифицируешь узлы. Затем используешь модуль astunparse (доступен на PyPI), чтобы преобразовать модифицированное дерево обратно в код.

Кстати по поводу морфинга Си кода, никто не думал создать свой компилятор, да может-быть сложно, но тогда можно гибко морфить код на уровне сборки и бинарного кода, а не на уровне исходных кодов, думаю для темных дел, это правильный подход...
Movfuscator вроде так и работал. А вообще говоря и к GCC/MinGW и к Clang'у можно написать плагин, который встраивается в пайплайн компилятора в указанном месте. Можно на уровне абстрактного синтаксического дерева производить манипуляции, можно на уровне трех адресного кода (LLVM IR в Clang, GIMPLE в GCC/MinGW). Но это не так просто и интуитивно понятно, как делать это внешней тулзой и обрабатывать сорсы. Дебажить такую штуку тоже мало приятного, но, если рассматривать систему обфускации в общем, то это наверное более гибкий и оптимизированный по скорости исполнения путь.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх