D2
Администратор
- Регистрация
- 19 Фев 2025
- Сообщения
- 4,380
- Реакции
- 0
С добрым утром xss.is!
Сегодня я расскажу вам, как замутить софт, который поможет обфусцировать HTML-код электронных марекетинговых писем и обойти спам-фильтры и попасть с инбокс!
Так что запасайтесь кофе или чем покрепче, потому что мы погрузимся в детали: от идеи до архитектуры проекта, с пошаговым разбором кода и кучей примеров.
Спам-фильтры работают хитро: они ищут повторяющиеся паттерны - одинаковые куски текста, стили, ссылки или подозрительные элементы, а у гугла вообще спам фильтры обрабатывает их Gemini (я так предполагаю). Если вы отправляете тысячу одинаковых писем, фильтр быстро вычисляет шаблон и блокирует их. А вот если каждое письмо будет уникальным, то шансов проскочить у него намного больше.
Мой инструмент, который я назвал StealthHTML, как раз и делает это - генерирует уникальные версии HTML, сохраняя внешний вид и функциональность письма.
Представьте, что вы прячете своё письмо среди других писем, которые напоминают спам? Фильтру сложно вычислить, какое из них является спамом, и он решает: "Ладно, пропускай". Вот так мы и будем работать.
Пример: если выбрать маркетинговый словарь, получится что-то вроде "best deal today". Этот текст можно засунуть в скрытый <span> или комментарий, и он будет выглядеть как часть письма.
Пример:
Пример:
Пример:
Example Domain
" могут быть одинаковыми во всех письмах, что выдаёт шаблон. Мы добавляем случайные параметры: "
Example Domain
". Плюс вставляем невидимые картинки с рандомными URL.
Пример:
Маркетинговый - для рассылок, технический - для писем про софт. Это делает текст осмысленным и менее подозрительным, так как в почтовиках я всё чаще и чаще стал встречать проверку писем при помощи ИИ, так как подозрительно часто мои письма стали улетать в спам.
Python: Скопировать в буфер обмена
Тут всё просто: открываем файл словаря, берём случайное число слов и склеиваем их в строку.
Python: Скопировать в буфер обмена
Вероятность prob задаёт, как часто вставлять символы
Python: Скопировать в буфер обмена
Разделяем строку по точке с запятой, тасуем и собираем обратно.
Python: Скопировать в буфер обмена
Создаём <span> с display: none и random текстом.
Её код вставлять не буду, можете посмотреть в полных исходниках.
Так же происходит работа с хедерами, редкими тегами и прочим добром по анологии с кусками кода выше
Bash: Скопировать в буфер обмена
и получаем вывод в stdout, либо если надо в файл, то:
Bash: Скопировать в буфер обмена
и получаем 1_obfuscated.html письмо.
Вот все доступные на момент написания статьи аргументы:
Код: Скопировать в буфер обмена
Я сам проверял, как это работает, и могу сказать: современные фильтры, особенно у Gmail, прям на стероидах от искусственного интеллекта (ИИ). Они используют машинное обучение, чтобы следить не только за кодом, но и за тем, как люди реагируют на письма - открывают их, игнорят или сразу в мусорку кидают. ИИ прям вынюхивает контекст: откуда письмо, кому, как часто ты такие шлёшь. Короче, прогресс дошёл до того, что эти штуки стали умнее, чем многие спамеры.
Но тут прикол: ИИ в спам-фильтрах (в том же Gmail) ещё и подстраивается под всякие хитрые трюки, типа обфускации кода. Обход становится сложнее, но всё ещё реально.
Но скоро думаю будет так: ты замаскировал письмо, поменял HTML, чтобы фильтр не спалил. Раньше это прокатывало, но теперь ИИ такой: "Хм, а почему юзеры это не открывают? Давай-ка в спам!" Так что, чтобы пробиться в "инбокс", мало код запутать - надо ещё, чтобы люди твои письма любили и открывали. Но пока обфускация HTML и парочка хитростей спасают.
Так что, пока работает, пользуемся на полную.
Небольшой пруф про ИИ:
Вот небольшая таблица, которая поможет понять, что нужно менять вам, чтобы ваши маркетинговые письма проходили в инбокс.
Она разделена на категории: анализ кода, анализ через ИИ, поведение отправителя и поведение получателя.
В каждой категории много пнуктов того, что происходит, чтобы вы могли понять, какие аспекты вашей рассылки требуют изменений:
Публикую полный код тут https://github.com/keklick1337/StealthHTML , так что берите и используйте. Отпишите по инбоксу, интересно как работает с вашими задчами.
Так же код может ломать в некоторых случаях визуальный вид письма, об этих багах тоже сообщайте с примерами минимальными писем, буду исправлять по возможности.
Автор: keklick1337
Специально для xss.is
Сегодня я расскажу вам, как замутить софт, который поможет обфусцировать HTML-код электронных марекетинговых писем и обойти спам-фильтры и попасть с инбокс!
Так что запасайтесь кофе или чем покрепче, потому что мы погрузимся в детали: от идеи до архитектуры проекта, с пошаговым разбором кода и кучей примеров.
Что такое обфускация и зачем она нужна?
Давайте начнем с основ. Обфускация - это когда мы берём понятный код и превращаем его в какую-то кашу, которую всё ещё можно исполнить, но разобрать её без боли в голове уже сложно. В нашем случае мы будем обфусцировать HTML-код писем. Зачем? Чтобы спам-фильтры не могли понять, что это за письмо, и пропускали его в "Входящие", а не в "Спам".Спам-фильтры работают хитро: они ищут повторяющиеся паттерны - одинаковые куски текста, стили, ссылки или подозрительные элементы, а у гугла вообще спам фильтры обрабатывает их Gemini (я так предполагаю). Если вы отправляете тысячу одинаковых писем, фильтр быстро вычисляет шаблон и блокирует их. А вот если каждое письмо будет уникальным, то шансов проскочить у него намного больше.
Мой инструмент, который я назвал StealthHTML, как раз и делает это - генерирует уникальные версии HTML, сохраняя внешний вид и функциональность письма.
Представьте, что вы прячете своё письмо среди других писем, которые напоминают спам? Фильтру сложно вычислить, какое из них является спамом, и он решает: "Ладно, пропускай". Вот так мы и будем работать.
Основные техники обфускации
Чтобы сделать каждое письмо уникальным, мы используем несколько приёмов. Вот список того, что умеет StealthHTML:- Генерация случайного текста - добавляем рандомный текст из безопасных словарей (общий, технический, маркетинговый), чтобы письмо выглядело живым.
- Вставка невидимых символов - засовываем нулевые пробелы и другие невидимки, которые меняют код, но не видны глазу.
- Перемешивание стилей CSS - меняем местами свойства в стилях, чтобы запутать анализаторы.
- Случайные атрибуты и элементы - добавляем рандомные классы, ID, data-атрибуты и скрытые элементы.
- Рандомизация ссылок и изображений - кидаем случайные параметры в ссылки и вставляем невидимые картинки.
- Поддержка разных словарей - выбирайте, какие слова ближе к вашему контенту, либо дополняйте их самостоятельно.
- Настраиваемый уровень обфускации - регулируйте, насколько сильно запутать код.
Как это работает: техники в деталях
1. Генерация случайного текста
Первая фича - добавление случайного текста. Мы не будем просто пихать абракадабру вроде "dfgdfg", потому что это сразу вызовет подозрения. Вместо этого у нас есть словари с нормальными словами: общий (типа "news", "info"), технический ("server", "proxy") или маркетинговый ("sale", "offer"). Функция берёт случайные слова из словаря и лепит из них текст.Пример: если выбрать маркетинговый словарь, получится что-то вроде "best deal today". Этот текст можно засунуть в скрытый <span> или комментарий, и он будет выглядеть как часть письма.
2. Вставка невидимых символов
Тут настоящая магия. Есть такие Unicode-символы, как нулевой пробел (\u200B), которые не отображаются, но присутствуют в коде. Мы вставляем их в текст с какой-то вероятностью (например, 20%). Человек ничего не заметит, а для фильтра текст "hello" и "h\u200Be\u200Bl\u200Blo" - это две разные строки.Пример:
- До: <p>Hello world</p>
- После: <p>Hell\u200Bo wo\u200Brld</p>
3. Перемешивание стилей CSS
Спам-фильтры могут искать определённый порядок свойств в стилях, например, "color: red; font-size: 12px". Мы берём строку стилей и тасуем свойства местами. Рандомизация стилей - крайне важный шаг для попадания в инбокс.Пример:
- До: style="color: blue; margin: 10px; font-size: 14px"
- После: style="font-size: 14px; color: blue; margin: 10px"
4. Случайные атрибуты и элементы
Мы добавляем рандомные классы, ID или data-атрибуты к тегам. Ещё можем вставить скрытые <span> или <div> с display: none. Это запутывает структуру HTML.Пример:
- До: <p>Hello</p>
- После: <p class="rnd123" data-info="xyz789">Hello<span style="display: none;">random text</span></p>
5. Рандомизация ссылок и изображений
Ссылки вроде "Example Domain
" могут быть одинаковыми во всех письмах, что выдаёт шаблон. Мы добавляем случайные параметры: "
Example Domain
". Плюс вставляем невидимые картинки с рандомными URL.
Пример:
- До: <a href="http://site.com">Click</a>
- После: <a href="http://site.com?x=789">Cl<img src="http://fake.com/img123.png" style="display: none;">ick</a>
6. Поддержка разных словарей
Выбирайте словарь под задачу.Маркетинговый - для рассылок, технический - для писем про софт. Это делает текст осмысленным и менее подозрительным, так как в почтовиках я всё чаще и чаще стал встречать проверку писем при помощи ИИ, так как подозрительно часто мои письма стали улетать в спам.
7. Настраиваемый уровень обфускации
Хотите лёгкую обфускацию или полный разнос письма? Регулируйте параметры: сколько комментариев, элементов или символов добавлять, это крайне удобно.Архитектура проекта
Теперь к коду. StealthHTML написан на Python с использованием библиотеки BeautifulSoup для работы с HTML. Структура простая, но гибкая:- Словари - слова захардкоденные внутри файла. Можете добавить свои, либо использовать из списка (дополнить код не составит труда для вас).
- Модуль обфускации - куча функций, каждая отвечает за свою технику.
- Главная функция - собирает всё вместе и обрабатывает HTML.
- CLI - интерфейс командной строки через argparse для удобства.
Разбор кода пошагово
Давайте заглянем внутрь, как оно выглядит на самом деле. Вот основные функции и как они работают.Функция generate_random_text
Генерирует случайный текст из словаря.Python: Скопировать в буфер обмена
Код:
import random
DICTIONARIES = {
'general': [
'news', 'update', 'info', 'alert', 'notice', 'message', 'reminder', 'notification',
'report', 'summary', 'announcement', 'bulletin', 'memo', 'brief', 'digest', 'release',
'statement', 'communication', 'dispatch', 'correspondence', 'letter', 'note', 'post',
'article', 'piece', 'item', 'story', 'feature', 'column', 'editorial'
],
'technical': [
'code', 'system', 'data', 'network', 'server', 'software', 'hardware', 'update',
'patch', 'bug', 'feature', 'release', 'version', 'protocol', 'interface', 'module',
'function', 'algorithm', 'process', 'thread', 'query', 'database', 'backup', 'log',
'monitor', 'config', 'deploy', 'test', 'build', 'compile'
],
'marketing': [
'offer', 'deal', 'sale', 'discount', 'promo', 'gift', 'bonus', 'special', 'event',
'campaign', 'launch', 'product', 'service', 'brand', 'exclusive', 'limited', 'free',
'trial', 'benefit', 'value', 'opportunity', 'package', 'subscription', 'plan',
'feature', 'highlight', 'trend', 'news', 'update', 'announce'
]
}
def generate_random_text(min_words=2, max_words=5, dictionary='general'):
count = random.randint(min_words, max_words)
return ' '.join(random.choice(DICTIONARIES[dictionary]) for _ in range(count))
# Пример вызова
text = generate_random_text("marketing") # "promo gift subscription"
Функция insert_invisible_chars
Добавляет невидимые символыPython: Скопировать в буфер обмена
Код:
def insert_invisible_chars(text, invisible_char_prob=0.15):
invisible_chars = ['\u200B', '\u200C', '\u200D', '\uFEFF', '\u2060']
result = ''
for char in text:
result += char
if random.random() < invisible_char_prob:
result += random.choice(invisible_chars)
return result
print(insert_invisible_chars("hello", 0.2)) # "h\u200Bello"
Функция shuffle_styles
Перемешивает CSS-свойства.Python: Скопировать в буфер обмена
Код:
def shuffle_styles(style_string):
styles = [s.strip() for s in style_string.split(';') if s.strip()]
random.shuffle(styles)
return '; '.join(styles) + ';'
# Пример
style = "color: red; font-size: 12px; margin: 5px"
print(shuffle_styles(style)) # "margin: 5px; color: red; font-size: 12px"
Функция insert_random_hidden_element
Добавляет скрытый элемент.Python: Скопировать в буфер обмена
Код:
def insert_random_hidden_element(soup, dictionary='general'):
hidden_span = soup.new_tag('span', style='font-size:0px; display:inline;')
hidden_span.string = generate_random_text(1, 3, dictionary)
hidden_span['class'] = generate_random_class()
hidden_span['id'] = generate_random_class()
hidden_span[f'data-{generate_random_class()}'] = str(random.randint(0, 1000))
return hidden_span
# Пример
soup = BeautifulSoup("<body><p>Hi</p></body>", "html.parser")
soup = insert_random_hidden_element(soup, "general")
print(soup) # <body><p>Hi</p><span style="font-size:0px; display:inline;">news info</span></body>
Создаём <span> с display: none и random текстом.
Главная функция generate_emails
Собирает всё вместе.Её код вставлять не буду, можете посмотреть в полных исходниках.
Так же происходит работа с хедерами, редкими тегами и прочим добром по анологии с кусками кода выше
Как использовать
Запускаем из командной строки:Bash: Скопировать в буфер обмена
./generate_emails.py 1.html
и получаем вывод в stdout, либо если надо в файл, то:
Bash: Скопировать в буфер обмена
./generate_emails.py 1.html -o 1_obfuscated.html
и получаем 1_obfuscated.html письмо.
Вот все доступные на момент написания статьи аргументы:
Код: Скопировать в буфер обмена
Код:
./generate_emails.py -h
usage: generate_emails.py [-h] [-o OUTPUT] [--min_words MIN_WORDS] [--max_words MAX_WORDS] [--invisible_char_prob INVISIBLE_CHAR_PROB] [--span_prob SPAN_PROB]
[--comment_count COMMENT_COUNT] [--meta_count META_COUNT] [--table_count TABLE_COUNT] [--style_count STYLE_COUNT]
[--image_count IMAGE_COUNT] [--script_count SCRIPT_COUNT] [--rare_tag_count RARE_TAG_COUNT] [--header_count HEADER_COUNT]
[--dictionary {general,technical,marketing}]
input_file
Generator of randomized HTML emails to bypass spam filters
positional arguments:
input_file Path to the input HTML file
options:
-h, --help show this help message and exit
-o, --output OUTPUT Output file path (default: - for stdout)
--min_words MIN_WORDS
Minimum number of words in generated text (default: 2)
--max_words MAX_WORDS
Maximum number of words in generated text (default: 5)
--invisible_char_prob INVISIBLE_CHAR_PROB
Probability of inserting an invisible character (default: 0.15)
--span_prob SPAN_PROB
Probability of inserting a span tag (default: 0.4)
--comment_count COMMENT_COUNT
Number of random comments (default: 1)
--meta_count META_COUNT
Number of random meta tags (default: 1)
--table_count TABLE_COUNT
Number of random tables (default: 1)
--style_count STYLE_COUNT
Number of random styles (default: 1)
--image_count IMAGE_COUNT
Number of random images (default: 1)
--script_count SCRIPT_COUNT
Number of random scripts (default: 1)
--rare_tag_count RARE_TAG_COUNT
Number of random rare tags (default: 1)
--header_count HEADER_COUNT
Number of random headers (default: 1)
--dictionary {general,technical,marketing}
Dictionary for text generation (default: general)
Спам-фильтры на ИИ и пара слов напоследок
Основные фишки
Спам-фильтры - это дотошные методы, которые лазают по всему коду писем (HTML, заголовки - всё подряд), выискивая подозрительные моменты. Если в письме куча одинакового текста, стилей или ссылок, которые выглядят как "привет от спамеров", - оно тут же улетает в папку "Спам". И это не просто "ой, тут ссылка", а глубокий разбор, как будто письмо под микроскоп кладут.Я сам проверял, как это работает, и могу сказать: современные фильтры, особенно у Gmail, прям на стероидах от искусственного интеллекта (ИИ). Они используют машинное обучение, чтобы следить не только за кодом, но и за тем, как люди реагируют на письма - открывают их, игнорят или сразу в мусорку кидают. ИИ прям вынюхивает контекст: откуда письмо, кому, как часто ты такие шлёшь. Короче, прогресс дошёл до того, что эти штуки стали умнее, чем многие спамеры.
Но тут прикол: ИИ в спам-фильтрах (в том же Gmail) ещё и подстраивается под всякие хитрые трюки, типа обфускации кода. Обход становится сложнее, но всё ещё реально.
Но скоро думаю будет так: ты замаскировал письмо, поменял HTML, чтобы фильтр не спалил. Раньше это прокатывало, но теперь ИИ такой: "Хм, а почему юзеры это не открывают? Давай-ка в спам!" Так что, чтобы пробиться в "инбокс", мало код запутать - надо ещё, чтобы люди твои письма любили и открывали. Но пока обфускация HTML и парочка хитростей спасают.
Так что, пока работает, пользуемся на полную.
Небольшой пруф про ИИ:
Вот небольшая таблица, которая поможет понять, что нужно менять вам, чтобы ваши маркетинговые письма проходили в инбокс.
Она разделена на категории: анализ кода, анализ через ИИ, поведение отправителя и поведение получателя.
В каждой категории много пнуктов того, что происходит, чтобы вы могли понять, какие аспекты вашей рассылки требуют изменений:
Категория | Фактор | Описание | Что менять |
---|---|---|---|
Анализ кода | Структура HTML | Фильтры ищут подозрительные элементы (скрытый текст, избыток тегов) | Упростить HTML, убрать скрытые элементы, использовать стандартные структуры |
Анализ кода | Использование CSS | Чрезмерное использование inline-стилей или странные паттерны CSS | Сократить inline-CSS |
Анализ кода | Присутствие JavaScript | JavaScript в письмах часто воспринимается как спам или угроза | Не вставлять JavaScript в письма |
Анализ кода | Соотношение текста и изображений | Высокое соотношение изображений к тексту - сигнал спама | Добавить больше текста, сбалансировать с картинками |
Анализ кода | Сокращенные ссылки | Всякие сократители ссылок могут выглядеть как попытка скрыть вредоносные ссылки | Использовать полные ссылки или брендированные короткие URL |
Анализ кода | Встроенные формы | Формы в письмах ассоциируются с фишингом и блокируются | Не встраивать формы, перенаправлять на внешние страницы |
Анализ кода | Использование Iframe | Iframe может загружать внешний контент, что вызывает подозрения | Избегать iframe в письмах |
Анализ кода | Трюки с шрифтами и цветами | Скрытый текст (например, белый на белом) - частый прием спамеров | Убедиться, что текст читаем и соответствует фону |
Анализ кода | Комментарии в HTML | Много подозрительных комментариев могут быть флагом | Убрать лишние комментарии или сделать их естественными |
Анализ через ИИ | Сходство контента | ИИ сравнивает контент с известными спам-кампаниями | Создавать уникальный контент для каждой рассылки |
Анализ через ИИ | Языковые шаблоны | Слова вроде "срочно", "бесплатно" или избыточные предложения флагятся | Использовать естественный язык, избегать триггер-слов |
Анализ через ИИ | Персонализация | Отсутствие персонализации выдает массовую рассылку | Добавлять имена получателей или другие персональные данные |
Анализ через ИИ | Анализ тональности | Слишком позитивный или негативный тон может быть подозрительным | Держать нейтральный или умеренно позитивный тон |
Анализ через ИИ | Тематическая классификация | Темы вроде денег или здоровья часто флагятся как спам | Маскировать тему или избегать типичных спам-тем |
Анализ через ИИ | Обнаружение аномалий | ИИ ищет отклонения от "нормальных" писем | Копировать структуру легитимных писем |
Анализ через ИИ | Анализ изображений | ИИ проверяет картинки на спам-контент или скрытый текст | Использовать релевантные изображения без скрытых элементов |
Анализ через ИИ | Анализ вложений | Вложения проверяются на вирусы или подозрительные типы файлов | Избегать вложений или использовать безопасные форматы |
Поведение отправителя | Частота отправки | Слишком частые письма от одного отправителя флагятся | Ограничить частоту или варьировать временные промежутки |
Поведение отправителя | Репутация IP | Плохая репутация IP-адреса увеличивает шанс попадания в спам | Использовать чистые IP и менять их |
Поведение отправителя | Возраст домена | Новые домены вызывают больше подозрений | Использовать старые домены или наращивать репутацию новых |
Поведение отправителя | Аутентификация (SPF, DKIM, DMARC) | Отсутствие настройки ведет к классификации как спам | Настроить SPF, DKIM, DMARC корректно |
Поведение отправителя | Процент отказов | Высокий bounce rate говорит о плохом качестве списка | Очищать список, использовать только валидные адреса |
Поведение отправителя | Источник списка | Купленные или украденные списки чаще попадают в спам | Использовать только opt-in списки с согласием получателей |
Поведение отправителя | Время отправки | Отправка в странное время (ночью) может быть подозрительной | Отправлять в рабочее время |
Поведение получателя | Процент открытий | Низкий процент открытий говорит о неинтересном или спам-контенте | Улучшить заголовки и контент для роста открытий |
Поведение получателя | Клики по ссылкам | Низкий CTR показывает, что контент не цепляет | Добавить сильные призывы к действию и интересный контент |
Поведение получателя | Процент отписок | Высокий уровень отписок сигнализирует о нежелательности писем | Дать ценный контент и простой способ отписки |
Поведение получателя | Жалобы на спам | Жалобы напрямую портят репутацию отправителя | Убедиться, что письма релевантны и получатели согласны их получать |
Поведение получателя | Время взаимодействия | Короткое время чтения указывает на низкий интерес | Создавать контент, который удерживает внимание |
Поведение получателя | Пересылка писем | Редкая пересылка может говорить о недоверии к письму | Добавить контент, которым хочется делиться |
Поведение получателя | Ответы на письма | Низкий уровень ответов указывает на отсутствие доверия (за исключением no-reply) | Включать вопросы или призывы к ответам |
Идеи для улучшений кода
- Словари:
- Добавить поддержку словарей из файлов
- Добавить поддержку словарей из других языков
- Добавить поддержку словарей фраз по цепям маркова, чтобы генерировать осмысленные тексты
- Более хитрые техники, вроде изменения структуры DOM:
- Оборачивание элеметов в дополнительные теги со стилями, которые не меняют внешний вид
- Добавление более сложных конструкций в тело письма, безопасных невидимых ссылок из серии ссылок на гугл поиск, либо на ответы гугл
- Ну и любые другие изменения
Публикую полный код тут https://github.com/keklick1337/StealthHTML , так что берите и используйте. Отпишите по инбоксу, интересно как работает с вашими задчами.
Так же код может ломать в некоторых случаях визуальный вид письма, об этих багах тоже сообщайте с примерами минимальными писем, буду исправлять по возможности.
Автор: keklick1337
Специально для xss.is