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

Как правильно начать учиться?

Я согласен с тобой насчет ВМ, это очень хорошее решение в плане анти-ав, но:
1. Свою ВМ я могу чистить, менять и так далее, а тут как бы все общеизвестно и для аверов тоже.
2. Загрузчик ВМ - про шарп не хочу говорить, но в случае с Питон. Как оно работает при конвертации в ехе (т.к. понятно, что на компах жертв нет обычно интерпретатора). Не смогут ли аверы задетектить сам загрузчик?
Для современной "малвари"( стилеры и локеры) конечно хватает питона и даже аутоита. Но если что-то посложнее.. Как написать на этих говноскриптах , скажем, шеллкод?
Я не знаю насчет шарпа, т.к. когда я начинал кодить, в приоритете была ХР, и ес-но шарп даже не рассматривался всерьез как инструмент для малвары. Сейчас, конечно,все поменялось, и много кто юзает тот же Павершелл для точечных и масс атак. Но я все равно считаю, что учиться надо начинать с натива, чтобы понять что и как работает. А там уже каждому свое.


Этим пареньком был Альберт Эйнштейн.. (с)
Спасибо всем большое за ответы. Всё-таки с мальварей торопиться не нужно и поэтому думаю покодить на питоне, поработать немножко и после чего выйду на какой-никакой заработок буду пытаться параллельно учить всё что вы описали выше и может что-то у меня и получиться..)
 
Свою ВМ я могу чистить, менять и так далее, а тут как бы все общеизвестно и для аверов тоже.
В том то и дело, что анализируя твою вм, у аверов 100500 возможностей зацепиться за саму сигнатуру вм, даже не разбирая что она там исполняет. В отличии от того же python. Они не могут его забраковать так просто, иначе пострадают остальные юзеры . Однако ты можешь мануально из исходников собрать интерпретатор Python, но слегка изменив и почистив местами правила, например.
C:
#ifndef Py_OPCODE_H
#define Py_OPCODE_H
#ifdef __cplusplus
extern "C" {
#endif


    /* Instruction opcodes for compiled code */
#define POP_TOP                   1
#define ROT_TWO                   2
#define ROT_THREE                 3
#define DUP_TOP                   4
#define DUP_TOP_TWO               5
#define ROT_FOUR                  6
#define NOP                       9
#define UNARY_POSITIVE           10
#define UNARY_NEGATIVE           11
#define UNARY_NOT                12
#define UNARY_INVERT             15
#define BINARY_MATRIX_MULTIPLY   16
#define INPLACE_MATRIX_MULTIPLY  17
#define BINARY_POWER             19
#define BINARY_MULTIPLY          20
#define BINARY_MODULO            22
#define BINARY_ADD               23
#define BINARY_SUBTRACT          24
#define BINARY_SUBSCR            25
#define BINARY_FLOOR_DIVIDE      26
#define BINARY_TRUE_DIVIDE       27
...
Заменяешь опкоды пайтона в сорцах, по определенным правилам. Потом компилируешь сборку. Потом этой сборкой собираешь py -> pyc. Получаешь байткод, сигнатур которого нет в базах ав. В памяти та же история. Если анализировать на уровень выше, на уровне не байткода а интерпретатора, то тоже ничего не выйдет толкового и достаточно точного. Интерпретатор это достаточно сложный софт и ни один авер его в памяти автоматикой не раскрутит, чтобы добраться до понимания сути, что он там интерпретирует. Полученный байт-код pyc автоматикой не дизассемблируешь, поскольку все дизасм движки работают только с оригинальной сборкой, а не твоей кастомной. Твою уникальную сборку пайтона ты можешь грузить с помощью loadpe, передавая в качестве аргумента этот уникальный байт-код на исполнение. При этом в доставляемом билде может не быть зашит интерпретатор в виде байт строки для loadpe, + pyc ты можешь доставлять так же в динамике. Это значит что вес доставляемого билда может быть в килобайтах(онли имплементация лоадпе + подтягивание с удаленного сервера 2 компонентов для запуска - байт строки интерпретатора для loadpe и pyc для этого интерпретатора). И с загрузчиком разобрались. Теперь что касается шеллкодов. Про какие ты говоришь, x86? Или pyc? Что то возможно, что то. С пайтона возможно инвокать винапи если ты об этом. И напоследок к своей речи. Делая малварь нативной (без прослоек в виде вм) и относительно простой, ты делаешь ее такой же простой для анализа. Именно анализа автоматическими системами. Нет, я не спорю, попытки изворотиться с помощью интересных техник с шеллкодами которые описывал на форуме whisper имеют место быть и это круто, но этого нет и скорее всего не будет на рынке. По понятным причинам. Убить легко, сделать сложно + время такого специалиста очень дорогое. То есть то, что есть на рынке из бинарщины - это по сути пинание мертвого жанра. Потому что нативная малварь без особых техник, просто кусок, который щелкнется аверами как орешки. Хотя бы взять тематику крипторов. Хотя бы один на рынке морфит твой pe? Именно не враппер с loadpe, а морф существующего, предоставляя метаморфный билд? Сомневаюсь, в памяти всегда оказывается то, что скрывалось за враппером. А защита у ав на основе поведенческих никогда не приходит одна, комбинация - палим ненужное поведение - осуществляем сигнатурный рескан в памяти. И на этом этапе попадается вся бинарная малварь на рынке. Сигнатурные базы под нейтив у аверов я думаю развиты лучше всего. Хотя достаточно поработать над тем, чтобы сигнатурный рескан памяти ничего не дал аверу и оп, максимум что авер сможет это крашнуть твое приложение без единого детекта либо вообще пропустить к исполнению, если с остальным все красиво, а рубить только на основе поведения и api он не может, поскольку тонны false positive и невозможность работы белого софта. Именно по этому кстати думаю, что powershell настолько пиздат. На уровне анализа процесса powershell( если анализировать его на глобальном уровне как все ехе) - тупо и бессмысленно по вышеназванным причинам. Слишком сложно раскрутить стек вызовов и добраться непосредственно к исполняемой сути, а не декларативщине, которую порождает сам интерпретатор помимо чистой полезной нагрузки исполняемого скрипта. К примеру возьмём cmdletы в пш, казалось бы пишешь Get-ChildItem -Recurse ... рекурсивный обход путей. В пш это 1 строка. Ты представляешь какой там под капотом стектрейс в рантайме, если анализировать глобально, вплоть до нативных инструкций, которые получаются с вм дотнета? Именно по этому и придумали AMSI. Чтобы быть ближе к скрипту и его сути, потому что глобально анализировать нереально, другой причины не вижу. И одно создание AMSI на уровне целой ОС! уже говорит о многом, в частности о невозможности(временной/денежной/из-за высокой сложности - не важно) аверами раскрутить рантайм популярных интерпретаторов будь то пш, модифицированный пайтон или ноджс. И это я ещё не говорю, про то что в скрипт векторе такие проблемы как смартскрин/палево по метаинформации pe/цифровые подписи(наполовину правда с подписями, но не настолько критично как в нейтив малвари) - вообще отсутствуют. Как бы смешно не звучало, но обстоит на данный момент все именно так. И суть, заметь, именно в популярных интерпретаторах, которые используются по белой, а не твоей самописной вм, которую можно забраковать парой сигнатур, поскольку нигде, кроме твоей малвари она не встречается. Это примерно такая же логика, когда связь с с&с организовывают через какой то популярный сервис, который аверская автоматика не может взять и заабузить и смысла абузить мало, поскольку сервис используют миллионы/миллиарды людей по белой и в самой модели организации подобной связи лежат фришные возможности сервиса, позволяющие проворачивать этот трюк со связью бесконечно и бесплатно.
 
Последнее редактирование:
Они не могут его забраковать так просто, иначе пострадают остальные юзеры . Однако ты можешь мануально из исходников собрать интерпретатор Python, но слегка изменив и почистив местами правила, например.
C:
C:
/* Instruction opcodes for compiled code */
#define POP_TOP 1
#define ROT_TWO 2
#define ROT_THREE 3
#define DUP_TOP 4
#define DUP_TOP_TWO 5
#define ROT_FOUR 6
#define NOP 9
#define UNARY_POSITIVE 10
#define UNARY_NEGATIVE 11
#define UNARY_NOT 12
#define UNARY_INVERT 15
#define BINARY_MATRIX_MULTIPLY 16
#define INPLACE_MATRIX_MULTIPLY 17
#define BINARY_POWER 19
#define BINARY_MULTIPLY 20
#define BINARY_MODULO 22
#define BINARY_ADD 23
#define BINARY_SUBTRACT 24
#define BINARY_SUBSCR 25
#define BINARY_FLOOR_DIVIDE 26
#define BINARY_TRUE_DIVIDE 27
...
Заменяешь опкоды пайтона в сорцах, по определенным правилам. Потом компилируешь сборку.
При этом сама ВМ реализована оператором swith? Опкодов много, стало быть swith скомпилируется в таблицу переходов. В итоге оказывается, что имеется оригинальный python.exe и пихон.ехе, отличающийся набором байт в секции данных, на которые ссылается инструкция jmp [addr]. Или я что-то упустил?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Или я что-то упустил?
Ну обычный декомпилятор это не поймет, реверсеру придется сопоставить новые значения байт-кода, поменять их в сорсах и пересобрать себе интерпретатор (ну или пропатчить существующий интерпретатор), чтобы модули типа dis корректно работали (я вангую, что все декомпиляторы так или иначе используют встроенный модуль dis). Это уже нетривиальная задача, нужен довольно опытный и целеустремленный реверсер, чтобы так заморачиваться. Ну и потом, единственное место, куда аверы могут поставить сигнатуру - новая таблица опкодов, тк в противном случае они будут палить легитимный интерпретатор.
 
А надо реверсить? Почему в случае модифицированной ВМ нельзя "зацепиться за саму сигнатуру вм, даже не разбирая что она там исполняет"? Есть 1000 одинаковых python.exe и есть почти такой же пихон.ехе, но с модификацией в секции данных.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
А надо реверсить? Почему в случае модифицированной ВМ нельзя "зацепиться за саму сигнатуру вм, даже не разбирая что она там исполняет"?
Ну реверсить надо, чтобы понять, что делает малварь. Можно какие-то моменты посмотреть и в динамике в сендбоксе, но особо нет гарантий, что малварь не имеет защиты от запуска внутри твоего сендбокса, так что, если малварь новая и ее еще не разбирали хорошо, то скорее всего ее до какой-то степени в статике (без запуска) разбирать будут.

Есть 1000 одинаковых python.exe и есть почти такой же пихон.ехе, но с модификацией в секции данных.
У Питона порядка 120 опкодов, если мне память не изменяет. Как бы количество перестановок множества из 120 элементов - это довольно большое число, так что можно очень долго переставлять и менять эту таблицу. Для аверов фолс позитивы - тоже большая проблема для имиджа, особенно когда затрагивается такой популярный софт, как Питон. Тут надо действовать аккуратнее. Они в теории не могут проверять бинарник Питона по белому списку, так как у пользователя может быть новая версия Питона, которую еще не успели добавить в белые списки (при этом формат байт-кода не стандартизирован и может меняться даже в минорных версиях), у пользователя может быть своя сборка Питона (или какая-то кастомная сборка, вроде Анаконды или АктивПайтон, или как там они назывались) с определенными настройками оптимизации, или добавленными/удаленными вкомпиленными модулями и так далее. То есть скорее всего, если эта вещь будет палиться, то будет палиться по черному списку (сигнатурам), а менять множество из 120 элементов, сбивая тем самым сигнатуры (если их поставят на джамп-таблицу с опкодами), можно довольно долго.

ЗЫ: ну почти угадал число опкодов))
Код:
$ python
Python 3.9.9 (main, Nov 20 2021, 21:30:06)
[GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> len(dis.opmap.keys())
119
 
Кстати, вместо ВМ питона можно взять ВМ WASM'а. Проще, меньше, быстрее. Ну и нет нужды писать только на питоне - сейчас уже практически любой компилируемый ЯП умеет в WASM (спасибо, LLVM).
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Кстати, вместо ВМ питона можно взять ВМ WASM'а. Проще, меньше, быстрее. Ну и нет нужды писать только на питоне - сейчас уже практически любой компилируемый ЯП умеет в WASM (спасибо, LLVM).
Ну да, но Питон то по-удобнее и по-привычнее для скриптинга. В WASM'е даже сборщика мусора нет (ну или не было, когда я последний раз его смотрел). По той же логике можно взять какой-нибудь Lua или своего рода изотерические, но в принципе хорошие языки, как Umka или Wren, даже для Nim есть доступный в пакете compiler интерпретатор байт-кода. Ну и потом выбор Питона в теории лучше в плане сложности составления сигнатуры аверами, проект большой, бинарники жирные, если они (как они это часто делают) подойдут к сигнатуре наотъебись, то будут фолс позитивы у многих людей, а это - имидживое фиаско для них. Всякий более редкий и менее популярный софт, такой как Lua или тот же Wasm3 интерпретатор можно просто зафачить лажовой сигнатурой и похер, а с Питоном скорее всего так не пройдет. Ну это, конечно, я вангую, пока не попробуешь - не узнаешь.
 
Ну да, но Питон то по-удобнее и по-привычнее для скриптинга. В WASM'е даже сборщика мусора нет (ну или не было, когда я последний раз его смотрел). По той же логике можно взять какой-нибудь Lua или своего рода изотерические, но в принципе хорошие языки, как Umka или Wren, даже для Nim есть доступный в пакете compiler интерпретатор байт-кода. Ну и потом выбор Питона в теории лучше в плане сложности составления сигнатуры аверами, проект большой, бинарники жирные, если они (как они это часто делают) подойдут к сигнатуре наотъебись, то будут фолс позитивы у многих людей, а это - имидживое фиаско для них. Всякий более редкий и менее популярный софт, такой как Lua или тот же Wasm3 интерпретатор можно просто зафачить лажовой сигнатурой и похер, а с Питоном скорее всего так не пройдет. Ну это, конечно, я вангую, пока не попробуешь - не узнаешь.
Я рассматривал вариант с использованием WASM-модулей как плагинов к боту. Васм подкупил своей простотой реализации ВМ, миниатюрным размером самих модулей (простой hello-world на Си, собранный clang'ом умещается в пол килобайта), возможностью компиляции кода на разных ЯП в wasm-байткод (тот же rust, go, c/++, ...) - лично мне как-то удобнее, когда все написано на одном ЯП.
Идея, предложенная Haunt'ом мне нравится. Думаю на саму ВМ питона никто не осмелится накидывать сигнатуры, скорее сигнатуры составят на сам метод доставки байткода на машину.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Я рассматривал вариант с использованием WASM-модулей как плагинов к боту.
А какие интерпретаторы рассматривал? Wasm3 или еще какой? Не видел, есть ли интерпретатор, который может из WASM-кода вызывать API сторонних библиотек (типа WinAPI вызвать из WASM-кода)?
 
А какие интерпретаторы рассматривал? Wasm3 или еще какой? Не видел, есть ли интерпретатор, который может из WASM-кода вызывать API сторонних библиотек (типа WinAPI вызвать из WASM-кода)?
Да можно любую реализацию ВМ взять. Вот пример: https://github.com/rustrat/rustrat
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Да можно любую реализацию ВМ взять.
Так они все умеют внешние функции вызывать из динамических библиотек? Мне казалось, что WASM (и даже WASI) стандарты имеют жестко ограниченный интерфейс и произвольную внешнюю функцию из под них не вызовешь. То есть нужна какая-то ВМ, которая реализует больший чем в стандарте функционал по FFI (foreign function interface). Хотя я толком не смотрел, могу ошибаться.

Чет стал гуглить по этому поводу, вроде есть предложение добавить всякие dlopen'ы и dlsym'ы, но что-то нихера не могу понять, сделали они это в WASI стандарте уже или нет, наверное еще нет:
 
Последнее редактирование:
То есть нужна какая-то ВМ, которая реализует больший чем в стандарте функционал по FFI (foreign function interface). Хотя я толком не смотрел, могу ошибаться
А как это вообще правильно делать? Обычную вм без внешних вызовов, либо же если язык сам по себе поддерживает рефлексию - вроде понятно как делать. В случае там С#, JS(вообще легко, все сводится к работе с object, property), Java - все достаточно понятно, как организовать, динамически искать и вызывать метод у инстанса класса либо создать инстанс класса по его имени, либо вообще задефайнить класс в динамике. Существует ли возможность создать некую generic функцию, для вызова любой WinAPI? Понятное дело, что как-то языки лоу левела с этим справляются, интересно как. К примеру функция принимает на вход некую структуру. Я правильно понимаю, что используются извраты для того, чтобы задефайнить и проинициализировать структуру на рантайме? Или это делается иначе как-то?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Существует ли возможность создать некую generic функцию, для вызова любой WinAPI?
Вообще, это не особо тривиальная херня. FFI в скриптовых языках довольно жирные, особенно в языках с динамической типизацией. Там разные объекты (а они обычно в прослойках, типа object для Питона, где любая херня - это подкласс object, а True, False и None - вообще синглтоны в рантайме, унаследованные от object) приводятся к типам, понятным процессору. В C# образно строка (которая, например в C# UTF-16) будет автоматом приводиться к ANSI для вызова WinAPI функции <что-то_там>A (при PInvoke ты для этого указываешь CharSet атрибут), поэтому в C# всегда быстрее вызывать <что-то_там>W функции. И в Питоне и в Шарпах там нихеровый такой слой, который эти все преобразования делает, а потом за собой еще и выделенную память подчищает. Но для примера можно посмотреть AngelScript, который довольно простой в этом плане: https://github.com/IngwiePhoenix/An.../angelscript/source/as_callfunc_x64_mingw.cpp - и это только для одной архитектуры - x64, где по сути только одна конвенция вызовов существует - fastcall. Мы на васме вроде обсуждали, можно ли в принципе обойтись для этого без ассемблерных вставок (на чистой православной сишечке), и, если мне не изменяет память, решили, что нельзя. Поэтому я немного удивился, когда услышал, что WASM умеет произвольные функции вызывать. Загрузить библиотеку (LoadLibrary/dlopen) и найти функцию (GetProcAddress/dlsym) - просто, сложно становится, когда эту функцию нужно вызвать. Рантайм должен точно знать, как вызывать эту функцию и как конвертировать аргументы.
 
перестановок множества из 120 элементов
Вот именно. Получается перестановочный шифр? По сути интерпретатор выполняет white-box дешифрование. При этом известны частоты появления опкодов. С частотами возможны нюансы, но так же известны образцы незашифрованного текста (какие-нибудь прологи-эпилоги или другие типовые конструкции).

Для аверов фолс позитивы - тоже большая проблема для имиджа, особенно когда затрагивается такой популярный софт, как Питон.
Ну тут я не знаю. Меня когда-то учили в школе, что решать задачи правильнее в общем виде. В таком случае сам по себе сигнатурный анализ уже имиджевая проблема. С другой стороны, можно подсчитать комбинации перестановок и анонсировать детект 100500 вариантов pyhon.zerodey.shelcodes.
 
Так они все умеют внешние функции вызывать из динамических библиотек? Мне казалось, что WASM (и даже WASI) стандарты имеют жестко ограниченный интерфейс и произвольную внешнюю функцию из под них не вызовешь. То есть нужна какая-то ВМ, которая реализует больший чем в стандарте функционал по FFI (foreign function interface). Хотя я толком не смотрел, могу ошибаться.
Да, если реализовать FFI. Пример реализации скидывал выше (https://github.com/rustrat/rustrat/).
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Да, если реализовать FFI. Пример реализации скидывал выше
Щас посмотрю, но мне кажется, что Wasm3 не умеет делать внешних вызовов.

Ну да, походу libffi используется под капотом: https://github.com/rustrat/rustrat/...58f74/rustrat-client/src/ffi/wrappers.rs#L175 - ну как бы в использовании libffi ничего плохого нет, но надо иметь ввиду, что это весьма жирная библиотека. Она много где используется, в том числе в Python, если мне память не изменяет.
 
Последнее редактирование:


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