Обфускация с рандомизацией HTML-писем с использованием Node.js

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Автор kidkdk
Источник https://xss.is/threads/133743/

Данная статья написана для пользователей xss.is , о том, как создавать множество уникальных писем, которые обходят спам-фильтры крупных почтовых доменов без изменения структурирования. Что позволит с большей вероятностью рассылать сотни тысяч писем в инбокс без значительных затрат.

Введение

Многие люди, которые занимались или занимаются E-mail спамом зачастую испытывают большие затруднения при отправке писем - рассылка даже на маленьких объёмах может быть очень быстро забанена. А для успеха рассылки на больших объёмах требуется достаточное количество чистых качественных расходников. Поэтому суммарные затраты на отправку миллиона писем могут достигать 500$, и даже 1000$. Соответственно по многим причинам рассылка может просто не окупиться, и затратив большое количество времени на тесты и подготовку расходников можно получить разочарование.

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

I. Разбор кода

1. Рандомизация при помощи создания скрытых слов в боди, как метод добавления шумов. Создает <span> и <div> теги в письме, делая их невидимыми для получателя

JavaScript: Скопировать в буфер обмена
Код:
const safeWords = [ // Cлова для заголовков и скрытых блоков
    'news', 'update', 'info', 'alert', 'notice', 'message',
    'reminder', 'notification', 'report', 'summary'];
const generatorTexts = (minWords = 2, maxWords = 5) => {
    const count = Math.floor(Math.random() * (maxWords - minWords + 1)) + minWords;
    const words = [shreksosetbibu];
    while (words.length < count) {
        const word = safeWords[Math.floor(Math.random() * safeWords.length)];
        words.push(word);
    }
    return words.join(' ');
};

2. Изменение порядка CSS-тегов случайным образом. Изменяется style="*" в HTML верстке.
JavaScript: Скопировать в буфер обмена
Код:
const shuffleStyles = (styleString) => {
    const styles = styleString.split(';').filter(s => s.trim()); // Разделяем стили и убираем пустые
    for (let i = styles.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1)); // Случайный индекс
        [styles[i], styles[j]] = [styles[j], styles[i]]; // Меняем местами
    }
    return styles.join(';') + ';'; // Собираем обратно в строку
};

3. Добавление элементов в текст. Непроизвольное добавление тега <span> в тексте
JavaScript: Скопировать в буфер обмена
Код:
const randomSpans = (text) => { // Рандомизация span-тегов в тексте
    let result = '';
    let i = 0;
    while (i < text.length) {
        if (Math.random() < 0.3 && i < text.length - 1) { // 30% вероятность обертки
            const length = Math.floor(Math.random() * 2) + 1; // через 1-2 символа
            result += `<span>${text.substr(i, length)}</span>`;
            i += length;
        } else {
            result += text[i++];
        }
    }
    return result;
};

4. Основной функционал по развертке и созданию 100,000 вариантов при по помощи шаблона.
JavaScript: Скопировать в буфер обмена
Код:
async function generateEmails() {
    try {
        const htmlTemplate = fs.readFileSync(inputFile, 'utf8');
        if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir);

        for (let i = 1; i <= 100000; i++) {
            const $ = cheerio.load(htmlTemplate);        
            $('title').text(generatorTexts());
            const hiddenContent = `
                <div style="display:none;font-size:0;line-height:0;">
                    ${generatorTexts(5, 10)}
                    <span style="color:transparent">${Math.random().toString(36).substr(2)}</span>
                </div>`;
            $('body').prepend(hiddenContent);
            $('body').append(hiddenContent);
            $('[style]').each((_, el) => {
                const $el = $(el);
                const style = $el.attr('style');
                if (style) {
                    $el.attr('style', shuffleStyles(style));
                }
            });
            $('body *').contents().each((_, el) => {
                if (el.type === 'text' && !$(el).parent().is('style, script')) {
                    const processed = randomSpans($(el).text());
                    if (processed !== $(el).text()) {
                        $(el).replaceWith($.html(processed));
                    }
                }
            });
            fs.writeFileSync(
                path.join(outputDir, `email_${i}.html`),
                $.html()
            );

            if (i % 1000 === 0) console.log(`Generated ${i} files...`);
        }
        console.log(`Generated ${i} files in ${outputDir}/`);
    } catch (error) {
        process.exit(1);
    }
}
generateEmails();

II. Небольшое лирическое отступление

Речь пойдет про спам баллы связанные с адресатом From. Засылать письма можно разными способами: шеллы/смтп/бота/своиподсети/акки , в этом и конкретно плюс. Вариантов различное множество, но какой выбрать зависит от ваших потребностей/целей. И так, для того чтобы попасть в инбокс нужно набрать к примеру 100 баллов. Скажем у Яндекса доверие к почтам Маил ру 70 очков, маил - маил 50 очков, рамблер - гмаил 10 очков. Яндекс - гмаил 50 очков, маил - гмаил 30 очков. Это все сугубо мое мнение без прогрева, помимо этого есть множество мелких почтовиков EU стран, где доверие гмаил 100 баллов и любое письмо в инбокс. В связи с этим нужны определенные связи, прокачка почт либо доменов, айпи адресов, высылкой писем на свои почты или таргет базы.

Далее ссылки, трастовые домены +50 очков, заспамленные домены -50 соответственно. Хороший айпи +25, грязный -25. И так далее, собирайте качественный шаблон хтмл, с разными тегами, уникальным объемным текстом, что может помочь засылать даже с новых доменом в инбокс.

III. Примеры работы функционала

Показаны два изображения до/после работы скрипта, на которых видно всю разницу, при том, каждое письмо рандомизируется по своему.

1.png


2.png




Здесь можно понять, что структура письма никак не затронута, а добавляются лишь скрытые теги. Сюда же можно добавить аналогично и замену тегов, например с <p> на <div>, <strong> = <b> и так далее, но нужны наработки к определенным шабам. Тот скрипт что отправил я, работает на большинстве шаблонов без ошибок, будь то таблицы, дивы и т.п.

IV. Что умеем и имеем

Обфускацию слов в письме с помощью скрытых тегов <span>, рандомизацию тайтлов, CSS тегов. Что уже позволит создавать как минимум 100,000 уникальных писем для рассылки с различными HTML. Пониманием факторов влияющих на попадания в Inbox, но также хочу сказать не одним инбоксом едины, есть почтовые домены куда невозможно заслать в инбокс, а в спам очень даже конвертит. Либо же наоборот спам ничего не даст, только инбокс. Необходимые связки приходят только с опытом и разбором происходящего. И не забывайте прогревать домены и айпи адреса, рандомизацию текста также никто не отменял.

V. Финал

Здесь содержится собранный код из вышеупомянутых огрызков, а также письмо html с которым работали
JavaScript: Скопировать в буфер обмена
Код:
const fs = require('fs');
const path = require('path');
const cheerio = require('cheerio');
const inputFile = process.argv[2];
const outputDir = path.parse(inputFile).name;
const safeWords = [ // Cлова для заголовков и скрытых блоков
    'news', 'update', 'info', 'alert', 'notice', 'message',
    'reminder', 'notification', 'report', 'summary'];
const generatorTexts = (minWords = 2, maxWords = 5) => {
    const count = Math.floor(Math.random() * (maxWords - minWords + 1)) + minWords;
    while (words.length < count) {
        const word = safeWords[Math.floor(Math.random() * safeWords.length)];
        words.push(word);
    }
    return words.join(' ');
};
const shuffleStyles = (styleString) => { // Рандомизация порядка CSS-свойств
    const styles = styleString.split(';').filter(s => s.trim()); // Разделяем стили и убираем пустые
    for (let i = styles.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1)); // Случайный индекс
        [styles[i], styles[j]] = [styles[j], styles[i]]; // Меняем местами
    }
    return styles.join(';') + ';'; // Собираем обратно в строку
};
const randomSpans = (text) => { // Рандомизация span-тегов в тексте
    let result = '';
    let i = 0;
    while (i < text.length) {
        if (Math.random() < 0.3 && i < text.length - 1) { // 30% вероятность обертки
            const length = Math.floor(Math.random() * 2) + 1; // 1-2 символа
            result += `<span>${text.substr(i, length)}</span>`;
            i += length;
        } else {
            result += text[i++];
        }
    }
    return result;
};
// Основная функция
async function generateEmails() {
    try {
        const htmlTemplate = fs.readFileSync(inputFile, 'utf8');
        if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir);

        for (let i = 1; i <= 100000; i++) {
            const $ = cheerio.load(htmlTemplate);        
            $('title').text(generatorTexts());
            const hiddenContent = `
                <div style="display:none;font-size:0;line-height:0;">
                    ${generatorTexts(5, 10)}
                    <span style="color:transparent">${Math.random().toString(36).substr(2)}</span>
                </div>`;
            $('body').prepend(hiddenContent);
            $('body').append(hiddenContent);
            $('[style]').each((_, el) => {
                const $el = $(el);
                const style = $el.attr('style');
                if (style) {
                    $el.attr('style', shuffleStyles(style));
                }
            });
            $('body *').contents().each((_, el) => {
                if (el.type === 'text' && !$(el).parent().is('style, script')) {
                    const processed = randomSpans($(el).text());
                    if (processed !== $(el).text()) {
                        $(el).replaceWith($.html(processed));
                    }
                }
            });
            fs.writeFileSync(
                path.join(outputDir, `email_${i}.html`),
                $.html()
            );

            if (i % 1000 === 0) console.log(`Generated ${i} files...`);
        }
        console.log(`Generated ${i} files in ${outputDir}/`);
    } catch (error) {
        process.exit(1);
    }
}
generateEmails();

Создает папку с названием вашего .html файла, а также необходимо установить инструментарий nodejs на вашу ОС

Для MacOS: (предварительно установив менеджер пакетов homebrew)
brew install node

Ubuntu/Debian:
sudo apt install nodejs npm

Windows:
Link

После распаковки ноды, установите зависимость cheerio
npm install cheerio

Затем запустите скрипт в папке с письмом
node script.js filename.html

Файлы используемые в статье Скачать

View hidden content is available for registered users!
 
Сверху Снизу