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

Статья Подделка фингерпринтов на linux

hipeople

RAM
Пользователь
Регистрация
13.05.2022
Сообщения
123
Реакции
103
Гарант сделки
3
Депозит
0.0022
Источник https://xss.pro
Автор hipeople


Представьте себе: вы сидите за своим ноутбуком, попиваете кофе, а где-то там, в интернетах, кто-то уже знает, что у вас экран 1920x1080, Firefox последней версии и, возможно, даже то, что вы вчера гуглили "как спрятаться от федерала". Это и есть фингерпринты — цифровые отпечатки, которые оставляет ваше устройство.

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

Именно для этого и нужна подделка отпечатка пальца. Многие, например, постоянно меняют User-Agent или IP, но при этом упускают из виду другие аспекты — вроде TTL, Canvas или шрифтов в браузере, — которые с лёгкостью выдают их противнику.

Модель угроз — это, по сути, карта рисков, которая показывает, кто стоит за сбором данных и что им от Вас нужно.

Начнём с рекламных платформ, таких как Google Ads или Meta. Для них ваш фингерпринт — это способ привязать все ваши действия к одному устройству: что вы смотрели, где кликали, что покупали. Они строят ваш профиль, чтобы потом заваливать вас рекламой.

Антифрод-системы банков и PayPal тоже не спят: они сканируют отпечатки, чтобы выловить тех, кто крутит мутные схемы с картами или аккаунтами. Но это всё мелочь по сравнению с государством. Эти ребята играют по-крупному. Для них ваш фингерпринт — это не просто данные, а способ привязать вас к конкретному железу, IP или отпечатку браузера. Они собирают всё: через провайдеров, через анализ трафика, через косяки в настройках браузера. Зачем? Чтобы знать, кто вы, где вы и что делаете. Если вы хоть раз светили свой реальный отпечаток - поздравляю, вы уже в чьём-то списке.

Но вот в чём загвоздка: от каждого из этих противников нужно защищаться по-своему. От рекламщиков достаточно запутать следы — подменить User-Agent, заблокировать Canvas. С антифродом сложнее: тут важно не переборщить с подделкой. Если ваш TTL вдруг скачет от 64 до 128, а MAC-адрес меняется каждые пять минут, их алгоритмы решат, что вы бот или фродер, и привет, блокировка. Лучше аккуратно подогнать параметры под типичную винду — TTL 128, User-Agent от Edge, и не дёргаться А вот с государством — это уже другая лига. Тут нужна полная маскировка: смена MAC-адресов, ротация IP через Tor, подделка железа, браузера, и много чего еще.

Так с чего начать, если вы решили подделать свой отпечаток?
Первое — выстроить свою модель угроз. Представь себе ситуацию: человек, пусть будет Боб, хочет скрыть свою личность в интернете и решает поменять User-Agent в браузере, думая, что этого достаточно, чтобы запутать следы. Но Боб даже не подозревает, что его провайдер видит куда больше, чем он думает. Например, значение TTL в IP-пакетах выдает его операционную систему, несмотря на подмену юзер-агента. Или, скажем, порядок TCP-заголовков, который уникален для каждого стека протоколов, остается неизменным. А если зайти дальше — шрифты, установленные на его машине, разрешение экрана или даже паттерны движения мыши, которые передаются через WebGL или Canvas API, с потрохами выдают его реальное устройство.

Боб мог бы поставить себе Tor или VPN, но и тут его ждут сюрпризы. Если он не учел утечки DNS-запросов или не отключил WebRTC, его настоящий IP всё равно просочится. А может, он вообще забыл, что заходил с этого же устройства в телеграм, без маскировки пару дней назад. Он думает, что Telegram шифрует всё и не выдаёт его, но не знает, что приложение собирает отпечаток устройства: модель телефона, версию операционной системы, уникальный идентификатор, да даже IP-адрес при подключении. Теперь представь: Боб сидит в каких-нибудь чатах, обсуждает свои дела, а потом решает "спрятаться" и начинает использовать VPN для других дел. Но Telegram уже привязал его активность к этому устройству. В конечном итоге, пока наивный Боб думает, что обманул систему, на деле он оставил за собой такой след, что любой мало-мальски грамотный аналитик вычислит его за полчаса.

В этой статье я покажу методы сокрытия фингерпринтов на Linux — от подмены MAC и TTL до автоматизации ротации User-Agent в браузере, — но что именно вам нужно под вашу модель угроз, решайте сами.


Базовая подделка фингерпринта

Давайте разберёмся с аппаратными фингерпринтами на Linux, и начнём с подмены MAC-адреса.
MAC-адрес — это уникальный идентификатор вашей сетевой карты, и если он светится где-то не там, то вас могут привязать к конкретному устройству быстрее, чем вы успеете допить свой кофе. Так что давайте посмотрим, как его подменять, и заодно разберём несколько способов, чтобы вы могли выбрать, что вам по душе.

Самый простой метод — это утилита macchanger. С ней можно быстро поменять MAC-адрес на что-то случайное.
Для установки macchanger на debian введите:

Код:
sudo apt install macchanger -y

Сразу после установки macchanger спросит стоит ли автаматический запуск при каждом запуске, нажмите Yes.
photo_2025-04-04_16-38-22.jpg


Сама подмена mac делается одной командой:

Bash:
sudo macchanger -r eth0

Тут -r генерирует полностью рандомный адрес, и ваш интерфейс (например, eth0) сразу начинает выглядеть как другое устройство. Удобно, быстро, но есть нюанс: сгенерированный MAC может оказаться слишком уж "левым" — из тех, что в реальной жизни никто не использует. А это уже звоночек для тех, кто умеет анализировать трафик.
Можно пойти чуть дальше и задать конкретный адрес вручную, например:

Bash:
sudo macchanger -m 00:14:22:33:44:55 eth0

Вот как будет выглядеть смена mac этим способом:
photo_2025-04-04_16-33-36.jpg


Тут вы сами решаете, какой MAC подставить, но откуда его взять и как сделать правдоподобно — об этом чуть позже в статье, когда дойдём до источников данных.

Ещё один способ — использовать встроенные инструменты Linux, вроде ip или ifconfig.

С ip это выглядит так:

Bash:
sudo ip link set eth0 address 00:16:17:AA:BB:CC

Сначала выключаем интерфейс командой sudo ip link set eth0 down, задаём новый адрес, потом поднимаем обратно с sudo ip link set eth0 up.

С ifconfig похожая история:

Bash:
sudo ifconfig eth0 hw ether 00:16:17:AA:BB:CC

Оба метода работают, но требуют ручной возни, да и без перезапуска сети иногда настройки слетают. Плюс, если вы генерируете MAC наобум, есть риск нарваться на невалидный адрес или что-то, что кричит "я фейк!".

Кстати, о генерации, если валидность адреса для ваших противников не принципиальна: можно сварганить случайный MAC прямо в терминале через что-то вроде openssl.

Вот пример:

Bash:
openssl rand -hex 6 | sed 's/\(..\)/\1:/g; s/.$//'

Теперь, когда мы разобрались с методами, давайте добавим немного автоматизации, чтобы MAC-адрес сам менялся, скажем, при каждом перезапуске сети. Вот простенький скрипт на баш, который можно закинуть в cron или systemd(о чем мы тоже поговрим далее):

Bash:
#!/bin/bash
MAC_LIST=("00:14:22:33:44:55" "00:16:17:AA:BB:CC" "00:1A:2B:11:22:33")
MY_INTERFACE=eno0


# Выбираем случайный MAC из списка
NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}


sudo ip link set $MY_INTERFACE down
sudo ip link set $MY_INTERFACE address "$NEW_MAC"
sudo ip link set $MY_INTERFACE up
echo "Новый MAC: $NEW_MAC"

Выполняем:
photo_2025-04-04_16-41-30.jpg

Сохраните это как change_mac.sh, дайте права на выполнение с chmod +x change_mac.sh, и можно запускать хоть вручную, вроде:
./change_mac.sh

Мы уже разобрались, как подменять MAC-адрес, но это только верхушка айсберга. Теперь давайте копнём глубже в остальные аппаратные фингерпринты и научимся подделывать их так, чтобы всё выглядело правдоподобно, а система не начала кашлять ошибками. Моменты, которые могут порушить работу, трогать не станем — это как лезть в двигатель машины с кувалдой, можно всё разнести. Вместо этого поиграем с тем, что можно подправить на реальном железе без последствий. Потому если вам нужно подделать прям все до серийного номера, вы можете использочать vm вроде QEMU/KVM .

Размер экрана и DPI из xrandr --current или EDID монитора из cat /sys/class/drm/*/edid | parse-edid — ещё одна зацепка. На реальной машине подменяем через фейковый X-сервер с помощью Xvfb.

Команда:

Bash:
Xvfb :1 -screen 0 1366x768x24 &

А потом запускаем нужное приложение в этой среде:

Код:
DISPLAY=:1 /usr/bin/google-chrome-stable

XFCL.jpg

Снаружи увидят только поддельное разрешение. Убить Xvfb можно через killall Xvfb, если надо вернуть всё обратно.

Часовой пояс из timedatectl меняем:

Bash:
sudo timedatectl set-timezone Europe/London

TTL — это параметр в заголовке IP-пакета, который определяет, сколько "прыжков" (hops) между маршрутизаторами пакет может сделать, прежде чем будет отброшен. Каждый маршрутизатор, через который проходит пакет, уменьшает значение TTL на 1. Когда TTL достигает нуля, пакет уничтожается, чтобы избежать бесконечного циркулирования в сети. По умолчанию разные операционные системы задают свои значения TTL: например, Windows обычно использует 128, а Linux — 64. Подмена TTL (например, установка 128) позволяет маскировать вашу систему под Windows, что полезно для обхода анализа отпечатков сети. Изменение через sysctl временное и не требует перезагрузки, а вернуть исходное значение можно, просто перезаписав параметр снова.

TTL из сетевых пакетов подменяем через sysctl:

Bash:
sudo sysctl -w net.ipv4.ip_default_ttl=128

Это делает вас похожим на Windows, и система не страдает.

Maximum Segment Size — это параметр протокола TCP, который определяет максимальный размер полезного блока данных в байтах для TCP-пакета. Он не учитывает длину заголовков TCP и IP. Подмена MSS может помочь имитировать поведение другой ОС.
Например:

Притворяемся Windows:

Bash:
sudo sysctl -w net.ipv4.route.min_adv_mss=1460

Или Android:

Bash:
sudo sysctl -w net.ipv4.route.min_adv_mss=156

SACK — это механизм TCP, позволяющий подтверждать отдельные блоки данных, а не только непрерывный поток. Он поддерживается и в Windows, и в Linux, и включается для оптимизации соединений, особенно с большими окнами TCP.

Включить можно так:

Bash:
sudo sysctl -w net.ipv4.tcp_sack=1

Хотя SACK сам по себе не уникален для Windows, его использование в сочетании с другими параметрами делает маскировку более правдоподобной.

Итоговый код
А теперь — итоговый скрипт. Всё в одном месте, с функциями для каждой подделки и автоматизацией:

Bash:
#!/bin/bash


MY_INTERFACE="eno0" 
MAC_LIST=("00:14:22:33:44:55" "00:16:17:AA:BB:CC" "00:1A:2B:11:22:33")
TIMEZONE_LIST=("America/New_York" "Europe/London" "Asia/Tokyo")
RESOLUTION_LIST=("1366x768" "1920x1080" "1280x720")
TIME_CHANGE=1800 # 30 минут


spoof_mac() {
    NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}
    sudo ip link set $MY_INTERFACE down
    sudo ip link set $MY_INTERFACE address "$NEW_MAC"
    sudo ip link set $MY_INTERFACE up
    echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
    NEW_TTL=128  # Windows-style
    sudo sysctl -w net.ipv4.ip_default_ttl=$NEW_TTL > /dev/null
    echo "Новый TTL: $NEW_TTL"


    sudo sysctl -w net.ipv4.tcp_sack=1 > /dev/null
    echo "SACK включен"


    MSS_LIST=("1460" "156")
    NEW_MSS=${MSS_LIST[$RANDOM % ${#MSS_LIST[@]}]}
    sudo sysctl -w net.ipv4.route.min_adv_mss=$NEW_MSS > /dev/null
    if [ "$NEW_MSS" == "1460" ]; then
        echo "MSS установлен для Windows: $NEW_MSS"
    else
        echo "MSS установлен для Android: $NEW_MSS"
    fi
}

spoof_timezone() {
    NEW_TZ=${TIMEZONE_LIST[$RANDOM % ${#TIMEZONE_LIST[@]}]}
    sudo timedatectl set-timezone "$NEW_TZ"
    echo "Новый часовой пояс: $NEW_TZ"
}
spoof_resolution() {
    NEW_RES=${RESOLUTION_LIST[$RANDOM % ${#RESOLUTION_LIST[@]}]}
    killall Xvfb 2>/dev/null  # Убиваем старый Xvfb, если был
    Xvfb :1 -screen 0 ${NEW_RES}x24 &  # Запускаем в фоне
    echo "Новый размер экрана: $NEW_RES (используйте DISPLAY=:1 для приложений)"
}

spoof_all() {
    spoof_mac
    spoof_tcp
    spoof_timezone
    spoof_resolution
}

auto_spoof() {
    while true; do
        spoof_all
        echo "Подмена выполнена, жду $TIME_CHANGE минут..."
        sleep $TIME_CHANGE
    done
}

case "$1" in
    "mac") spoof_mac ;;
    "tcp") spoof_tcp ;;
    "timezone") spoof_timezone ;;
    "resolution") spoof_resolution ;;
    "all") spoof_all ;;
    "auto") auto_spoof ;;
    *) echo "Использование: $0 {mac|dmi|tcp|timezone|layout|resolution|all|auto}" ;;
esac

Пробуем запустить:
photo_2025-04-04_14-50-37.jpg


Сохраните как spoof_linux.sh, дайте права chmod +x spoof_linux.sh, и запускайте: ./spoof_linux.sh mac для MAC, ./spoof_linux.sh resolution для экрана, ./spoof_linux.sh all для всего, или ./spoof_linux.sh auto для ротации каждые полчаса. Интерфейс eno0 замените на свой через ip link. Для Xvfb после запуска используйте DISPLAY=:1 firefox, чтобы браузер видел фейковое разрешение. Всё временное, кроме TTL и часового пояса, которые держатся до перезагрузки или ручного сброса.

Не могу не упомянуть, что если на вашем устройстве установлен SSH или FTP, их тоже нужно грамотно настроить, чтобы баннеры не палились всяким сканерам вроде Nmap или других любопытных глаз, которые шарят по сети в поисках уязвимостей. Тут сразу важный момент: полностью убирать баннеры — не всегда лучший ход. Почему? Потому что пустой баннер или его отсутствие может кричать: "Тут что-то интересное!" — и привлекать лишнее внимание. Куда умнее заменить их на что-то правдоподобное. Давайте разберёмся, как это сделать для SSH и FTP на Linux, и заодно напишем пару скриптов для автоматизации.

SSH — это как парадный вход в ваш сервер, и если он светит версией вроде "OpenSSH_8.9p1 Ubuntu" или чем-то подобным, любой сканер тут же поймёт, с чем имеет дело. Хуже того, старые версии могут намекнуть на уязвимости, которые уже в базах эксплойтов. Но если вы просто вырубите баннер, это тоже звоночек: "О, кто-то слишком умный, давай-ка присмотримся". Лучше подменить его на что-то реалистичное — например, на баннер от другой системы или версии, которая не выдаёт ваш дистрибутив.

Вот как это можно провернуть. Сначала ставим кастомный баннер через файл конфига /etc/ssh/sshd_config. Но перед этим — скрипт, который не только спрячет лишнее, но и замаскирует ваш SSH под что-то типичное, скажем, под Windows-сервер с SSH или просто под другой дистрибутив.

Bash:
#!/bin/bash


if [ "$EUID" -ne 0 ]; then
    echo "Ошибка: Скрипт должен быть запущен с правами root (sudo)."
    exit 1
fi


SSHD_CONFIG="/etc/ssh/sshd_config"
FAKE_BANNER="/etc/ssh/fake_banner"
FAKE_BANNER_TEXT = "SSH-2.0-GenericServer 1.0"


# Бэкап конфига
if [ -f "$SSHD_CONFIG" ]; then
    cp "$SSHD_CONFIG" "$SSHD_CONFIG.bak_$(date +%F_%T)"
    echo "Резервная копия $SSHD_CONFIG создана."
else
    echo "Ошибка: Файл $SSHD_CONFIG не найден."
    exit 1
fi


echo $FAKE_BANNER_TEXT > "$FAKE_BANNER"
echo "Фейковый баннер создан в $FAKE_BANNER"




echo "Настройка SSH для маскировки..."
{
    echo "# Кастомный баннер для маскировки"
    echo "Banner $FAKE_BANNER"
    echo "# Убираем лишние логи"
    echo "LogLevel QUIET"
    echo "# Только второй протокол"
    echo "Protocol 2"
    echo "# Отключаем специфичный баннер"
    echo "DebianBanner no"
} >> "$SSHD_CONFIG"




if sshd -t; then
    echo "Конфигурация SSH проверена успешно."
else
    echo "Ошибка в конфигурации SSH. Восстанавливаем резервную копию..."
    cp "$SSHD_CONFIG.bak_$(date +%F_%T)" "$SSHD_CONFIG"
    exit 1
fi


systemctl restart sshd
if [ $? -eq 0 ]; then
    echo "SSH-сервер перезапущен успешно."
else
    echo "Ошибка при перезапуске SSH. Проверьте статус: systemctl status sshd"
    exit 1
fi


echo "SSH замаскирован."

Запускаем:
photo_2025-04-04_14-55-06.jpg


Что тут происходит? Мы задаём фейковый баннер SSH-2.0-GenericServer 1.0 для примера. Логи ставим на QUIET, а DebianBanner no убирает любые намёки на вашу систему. Сохраните как ssh.sh, дайте права sudo chmod +x ssh.sh, и запускайте: sudo ./ssh.sh


С FTP похожая история. Если у вас стоит vsftpd (а он популярен на Linux), то по умолчанию он может выдать что-то вроде "220 (vsftpd 3.0.3)" при подключении. Это сразу говорит: "Привет, я Linux-сервер, давай ломай меня". Убрать баннер полностью — опять же, не вариант, потому что пустой ответ или ошибка подключения наведёт на мысль, что вы что-то скрываете. Вместо этого давайте заменим его на что-то правдоподобное, например, на баннер, который мог бы быть у типичного FTP-сервера без явных привязок к vsftpd.

Вот скрипт для настройки:

Bash:
#!/bin/bash


if [ "$EUID" -ne 0 ]; then
    echo "Ошибка: Скрипт должен быть запущен с правами root (sudo)."
    exit 1
fi


VSFTPD_CONFIG="/etc/vsftpd.conf"
FTP_BANNER="Welcome to Secure FTP Service"


if ! command -v vsftpd &> /dev/null; then
    echo "Ошибка: vsftpd не установлен. Установите его: sudo apt install vsftpd"
    exit 1
fi


if [ -f "$VSFTPD_CONFIG" ]; then
    cp "$VSFTPD_CONFIG" "$VSFTPD_CONFIG.bak_$(date +%F_%T)"
    echo "Резервная копия $VSFTPD_CONFIG создана."
else
    echo "Ошибка: Файл $VSFTPD_CONFIG не найден."
    exit 1
fi


echo "Настройка vsftpd для маскировки баннеров..."
{
    echo "# Кастомный баннер для маскировки"
    echo "ftpd_banner=$FTP_BANNER"
    echo "# Скрываем версию vsftpd"
    echo "hide_version=YES"
    echo "# Отключаем лишние идентификаторы"
    echo "banner_file=NO"
} >> "$VSFTPD_CONFIG"


echo "Проверка настроек через перезапуск сервиса..."
systemctl restart vsftpd
if [ $? -eq 0 ]; then
    echo "vsftpd перезапущен успешно."
else
    echo "Ошибка при перезапуске vsftpd. Восстанавливаем резервную копию..."
    cp "$VSFTPD_CONFIG.bak_$(date +%F_%T)" "$VSFTPD_CONFIG"
    systemctl restart vsftpd
    exit 1
fi


echo "FTP замаскирован"

Запускаем:
photo_2025-04-04_14-56-28.jpg


Что мы сделали? Поставили баннер "Welcome to Secure FTP Service" — ничего необычного, просто приветствие, которое можно встретить на любом сервере. hide_version=YES убирает версию vsftpd из ответа, а banner_file=NO гарантирует, что не подтянется какой-нибудь стандартный файл с инфой о системе. Сохраните как ftp.sh, дайте права sudo chmod +x ftp.sh, и запускайте: sudo ./ftp.sh


Подделка фингирпринтов с реальными данными

Чтож на этом мы закончим говорить про подделку данных на уровне железа и софта в Linux. Теперь давайте копнём глубже: где брать данные, которые мы хотим подделать, чтобы они выглядели правдоподобно?

Создание реалистичного mac адреса
Начнём с MAC-адресов — это одна из самых заметных меток вашего устройства в сети. Если вы просто генерируете их наобум как я и говорил, кто хоть немного шарит, сразу заметит фейк. Так что давайте разберём, как устроен MAC-адрес, из чего он состоит и где взять базу для генерации адресов, которые не будут кричать "я подделка!".

MAC-адрес — это 48-битный (6 байт) идентификатор, который присваивается сетевым интерфейсам. Обычно он записывается в виде шести пар шестнадцатеричных чисел, разделённых двоеточиями или дефисами, например, 00:14:22:33:44:55. Первые три байта (24 бита) — это OUI, уникальный код, который выдаётся производителям оборудования организацией IEEE. Например, 00:14:22 — это OUI компании Dell, а 00:16:17 может быть у D-Link. Оставшиеся три байта (24 бита) — это идентификатор устройства, который производитель присваивает сам. Итого: первая половина говорит, кто сделал железо, вторая — что это за конкретный девайс.

Теоретически, можно сгенерировать MAC-адрес прямо в терминале через openssl rand -hex 6, как мы делали раньше, но проблема в том, что случайный набор чисел может не попасть в реальный OUI.

Готовых баз с полными MAC-адресами в открытом доступе нет(Ну по крайней мере я не нашел). Зато есть базы данных с OUI, привязанными к производителям. К примеру IEEE публикует такие списки, и их можно найти по адресу: https://maclookup.app/downloads/csv-database в виде CSV.

photo_2025-04-04_14-20-44.jpg


Эти базы содержат только первые три байта (OUI), а вторую половину вам нужно генерировать самим. Допустим, вы скачали файл с OUI с maclookup.txt. Он обычно приходит в формате CSV или TXT, где каждая строка — это OUI и информация о производителе. Пример:
photo_2025-04-04_15-00-00.jpg


Теперь ваша задача — сгенерировать полноценные MAC-адреса, добавив к OUI вторую половину. Вот как это можно сделать.

Вот скрипт для работы с CSV-файлом, который берёт OUI и лепит к ним уникальную часть на основе текущего времени:

Bash:
#!/bin/bash


# Файл с базой данных MAC-адресов
MAC_FILE="mac_list.csv"


OUI_LIST=$(awk -F',' '{print $1}' "$MAC_FILE")


if [ -z "$OUI_LIST" ]; then
    echo "Ошибка: Не удалось извлечь OUI из файла $MAC_FILE. Проверьте файл."
    exit 1
fi


DATE=$(date +%Y%m%d)
DATE_HEX=$(printf '%x' $(date +%s) | tr '[:lower:]' '[:upper:]')
DATE_HEX_SHORT=$(openssl rand -hex 3 | tr '[:lower:]' '[:upper:]')


format_mac() {
    echo "$1" | sed 's/../&:/g' | sed 's/:$//'
}


declare -a GENERATED_MACS
count=0


while IFS= read -r oui; do
    oui_clean=$(echo "$oui" | tr -d ':')
    mac="$oui_clean$DATE_HEX_SHORT"
    formatted_mac=$(format_mac "$mac")
    GENERATED_MACS+=("$formatted_mac")
    ((count++))
done <<< "$OUI_LIST"


echo "Количество сгенерированных MAC-адресов: $count"
echo "Сгенерированные MAC-адреса:"
for mac in "${GENERATED_MACS[@]}"; do
    echo "$mac"
done

Вывод функции:
photo_2025-04-04_09-02-14.jpg


Обьясню как работает эта функция: cначала она смотрит, что лежит в файле mac_list.csv. Он использует команду awk, чтобы вытащить из этого файла только первую колонку — то есть сами OUI. Если ничего не нашёл (например, файл пустой или сломанный), он ругается: "Не могу найти OUI, проверь файл!" — и останавливается.
Дальше скрипт получает текущую дату и время. Он делает это в два шага: сначала получает дату в формате "год-месяц-день" (например, 20250330), а потом превращает текущее время в секундах (так называемую "эпоху") в шестнадцатеричный вид — это что-то вроде 1711843200 превращается в 6626C400. Но нам не нужно всё это длинное число, поэтому скрипт обрезает его до трёх случайных символов с помощью openssl rand -hex 3 — например, 1A2. Это будет наша уникальная часть MAC-адреса.
Теперь нужно красиво оформить MAC-адрес. Для этого есть функция format_mac: она берёт строку вроде 0014221A2 и вставляет двоеточия через каждые два символа, чтобы получилось 00:14:22:1A:2.
Подобным образом функция проходится по каждому OUI из списка и сохраняет в массив GENERATED_MACS. Заодно он считает, сколько адресов получилось.


К статье я приклеплю текстовый файл mac_list.txt с OUI в формате 00-14-22, вот функция для генерации адресов с его использованием:

Bash:
generate_random_macs() {
    
    DATE=$(date +%Y%m%d) # Текущая дата динамически
    
    MAC_FILE="mac_list.txt" # Файл с адресами
    
    OUI_LIST=$(grep -E '^[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}' "$MAC_FILE" | awk '{print $1}')
    
    if [ -z "$OUI_LIST" ]; then
        echo "Ошибка: Не удалось извлечь OUI из файла $MAC_FILE. Проверьте файл."
        exit 1
    fi
    
    DATE_HEX=$(printf '%x' $(date +%s) | tr '[:lower:]' '[:upper:]')
    DATE_HEX_SHORT=$(echo "$DATE_HEX" | tail -c 7)
    
    format_mac() {
        echo "$1" | sed 's/../&:/g' | sed 's/:$//'
    }
  
    declare -ga GENERATED_MACS=()
    local count=0
    
    while IFS= read -r oui; do
        oui_clean=$(echo "$oui" | tr -d '-')
        mac="$oui_clean$DATE_HEX_SHORT"
        formatted_mac=$(format_mac "$mac")
        GENERATED_MACS+=("$formatted_mac")
        ((count++))
        echo $GENERATED_MACS
    done <<< "$OUI_LIST"
    
    echo "Количество сгенерированных MAC-адресов: $count"
}


generate_random_macs

Вывод функции:
photo_2025-04-04_14-19-31.jpg


Эта фукция работает похоже на прошлую, но немного по другому. Сначала функция берёт текущую дату в формате "год-месяц-день". Потом она смотрит в файл mac_list.txt и с помощью grep ищет строки, которые выглядят как XX-XX-XX (где X — цифры или буквы A-F). Это фильтр, чтобы отсечь мусор, если он есть в файле. Затем вытаскивает первую колонку — сами OUI.
Дальше берётся текущее время в секундах, переводится в шестнадцатеричный вид, и из этого числа берутся последние 6 символов — скажем,26C400. Это будет уникальная часть MAC-адреса. Здесь отличие от первого скрипта: вместо случайных трёх символов используется кусок времени, что делает адреса чуть более предсказуемыми, но всё ещё уникальными в пределах одного запуска.
Функция format_mac работает так же как и в прошлой фукции по этому не виду смысла это объяснять. Потом все адреса складываться в GENERATED_MACS.

Мы с вами сгенерировали адрес, но как убедиться, что он выглядит правдоподобно? Зайдите на сайт вроде macvendorlookup.com или maclookup.app, вбейте свой MAC, и увидите, что OUI привязан к реальному производителю

Вот пример с сгенерировали мной адресом:

photo_2025-04-04_14-22-32.jpg


Код для подделки фингерпринтов с генерацией mac
Вот доработанный скрипт spoof_linux.sh, куда я интегрировал функцию генерации MAC-адресов из текстового файла(но вы можете интегрировать свою функцию).

Bash:
#!/bin/bash


# Функция генерации случайных MAC-адресов
generate_random_macs() {
    
    DATE=$(date +%Y%m%d) # Текущая дата динамически
    
    MAC_FILE=$MAC_FILE_LINK
    
    OUI_LIST=$(grep -E '^[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}' "$MAC_FILE" | awk '{print $1}')
    
    if [ -z "$OUI_LIST" ]; then
        echo "Ошибка: Не удалось извлечь OUI из файла $MAC_FILE. Проверьте файл."
        exit 1
    fi
    
    DATE_HEX=$(printf '%x' $(date +%s) | tr '[:lower:]' '[:upper:]')
    DATE_HEX_SHORT=$(echo "$DATE_HEX" | tail -c 7)
    
    format_mac() {
        echo "$1" | sed 's/../&:/g' | sed 's/:$//'
    }
  
    declare -ga GENERATED_MACS=()
    local count=0
    
    while IFS= read -r oui; do
        oui_clean=$(echo "$oui" | tr -d '-')
        mac="$oui_clean$DATE_HEX_SHORT"
        formatted_mac=$(format_mac "$mac")
        GENERATED_MACS+=("$formatted_mac")
        ((count++))
    done <<< "$OUI_LIST"
    
    echo "Количество сгенерированных MAC-адресов: $count"
}


MAC_FILE_LINK="mac_list.txt"
MY_INTERFACE="eno0"
TIMEZONE_LIST=("America/New_York" "Europe/London" "Asia/Tokyo")
RESOLUTION_LIST=("1366x768" "1920x1080" "1280x720")
TIME_CHANGE=1800 # 30 минут


spoof_mac() {


    generate_random_macs
    MAC_LIST=("${GENERATED_MACS[@]}")


    if [ ${#MAC_LIST[@]} -eq 0 ]; then
       echo "Ошибка: Список MAC-адресов пуст. Выход."
       exit 1
    fi
    NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}
    echo "Выбранный MAC для подмены: $NEW_MAC" # Отладочный вывод
    sudo ip link set $MY_INTERFACE down
    sudo ip link set $MY_INTERFACE address "$NEW_MAC"
    sudo ip link set $MY_INTERFACE up
    echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
    NEW_TTL=128  # Windows-style
    sudo sysctl -w net.ipv4.ip_default_ttl=$NEW_TTL > /dev/null
    echo "Новый TTL: $NEW_TTL"


    sudo sysctl -w net.ipv4.tcp_sack=1 > /dev/null
    echo "SACK включен"


    MSS_LIST=("1460" "156")
    NEW_MSS=${MSS_LIST[$RANDOM % ${#MSS_LIST[@]}]}
    sudo sysctl -w net.ipv4.route.min_adv_mss=$NEW_MSS > /dev/null
    if [ "$NEW_MSS" == "1460" ]; then
        echo "MSS установлен для Windows: $NEW_MSS"
    else
        echo "MSS установлен для Android: $NEW_MSS"
    fi
}




spoof_timezone() {
    NEW_TZ=${TIMEZONE_LIST[$RANDOM % ${#TIMEZONE_LIST[@]}]}
    sudo timedatectl set-timezone "$NEW_TZ"
    echo "Новый часовой пояс: $NEW_TZ"
}


spoof_resolution() {
    NEW_RES=${RESOLUTION_LIST[$RANDOM % ${#RESOLUTION_LIST[@]}]}
    killall Xvfb 2>/dev/null  # Убиваем старый Xvfb, если был
    Xvfb :1 -screen 0 ${NEW_RES}x24 &  # Запускаем в фоне
    echo "Новый размер экрана: $NEW_RES (используйте DISPLAY=:1 для приложений)"
}


spoof_all() {
    spoof_mac
    spoof_tcp
    spoof_timezone
    spoof_resolution
}


auto_spoof() {
    while true; do
        spoof_all
        echo "Подмена выполнена, жду $TIME_CHANGE секунд..."
        sleep $TIME_CHANGE
    done
}


case "$1" in
    "mac") spoof_mac ;;
    "tcp") spoof_tcp ;;
    "timezone") spoof_timezone ;;
    "resolution") spoof_resolution ;;
    "all") spoof_all ;;
    "auto") auto_spoof ;;
    *) echo "Использование: $0 {mac|tcp|timezone|resolution|all|auto}" ;;
esac

Пробуем сгенерировать mac адрес и изменит на него свой, вывод должен выглядеть подобным образом:
photo_2025-04-04_14-24-58.jpg



Добавление реалистичных таймзон
Мы поговрили про герацию mac теперь быстренько пройдемсчя как и от куда брать списки часовых поясов. Таких списокв достаточно много, но лично я вольму отсюда, https://github.com/maxmind/geoip-api-c/blob/main/timezone/timezone.txt в качестве примера:
photo_2025-04-04_14-26-25.jpg


Функция для подмены часовых поясов:

Bash:
get_random_timezone() {
    local input_file="$1"
    
    if [ ! -f "$input_file" ]; then
        echo "Ошибка: Файл $input_file не найден"
        return 1
    fi


    local line_count=$(wc -l < "$input_file")
    if [ "$line_count" -eq 0 ]; then
        echo "Ошибка: Файл $input_file пуст"
        return 1
    fi


    local random_line=$(( RANDOM % line_count + 1 ))
    
    local line=$(sed -n "${random_line}p" "$input_file")
    NEW_TZ=$(echo "$line" | grep -o '"[^"]*"$' | tr -d '"')
    
    if [ -z "$NEW_TZ" ]; then
        echo "Ошибка: Не удалось извлечь часовой пояс из строки"
        return 1
    fi
    
    echo "Выбран часовой пояс: $NEW_TZ"
}


get_random_timezone "timezone.txt"

Вывод функции:
photo_2025-04-04_18-03-57.jpg


Эта функция работает просто: она берёт файл с часовыми поясами и сразу выбирает из него случайный часовой пояс. Вместо того чтобы создавать Сначала функция проверяет, существует ли файл, который ей передали. Потом она считает, сколько строк в файле, с помощью команды wc -l.
Дальше функция выбирает случайный номер строки с помощью переменной RANDOM, которая генерирует случайное число, и делит его по модулю на количество строк, чтобы попасть в диапазон файла (плюс 1, потому что строки нумеруются с 1). Затем она использует sed, чтобы вытащить эту случайную строку из файла.
Из выбранной строки функция вырезает часть в кавычках с конца(например, "Europe/Moscow"), убирает кавычки с помощью tr -d '"', и сохраняет результат в переменную NEW_TZ.

Код подделки фингерпинтов с рандомными временными зонами
Добавим ее в общий код:

Bash:
#!/bin/bash


# Функция генерации случайных MAC-адресов
generate_random_macs() {
   #код функции генерации mac, упущу для краткости, но ествественно в исходниках к статье код будет полным
}




# Функция для выбора случайного часового пояса из файла
get_random_timezone() {
    local input_file="$1"
    
    if [ ! -f "$input_file" ]; then
        echo "Ошибка: Файл $input_file не найден"
        return 1
    fi


    local line_count=$(wc -l < "$input_file")
    if [ "$line_count" -eq 0 ]; then
        echo "Ошибка: Файл $input_file пуст"
        return 1
    fi


    local random_line=$(( RANDOM % line_count + 1 ))
    
    local line=$(sed -n "${random_line}p" "$input_file")
    NEW_TZ=$(echo "$line" | grep -o '"[^"]*"$' | tr -d '"')
    
    if [ -z "$NEW_TZ" ]; then
        echo "Ошибка: Не удалось извлечь часовой пояс из строки"
        return 1
    fi
    
    echo "Выбран часовой пояс: $NEW_TZ"
}


MAC_FILE_LINK="mac_list.txt"
MY_INTERFACE="eno0"
RESOLUTION_LIST=("1366x768" "1920x1080" "1280x720")
TIME_CHANGE=1800 # 30 минут


spoof_mac() {


    generate_random_macs
    MAC_LIST=("${GENERATED_MACS[@]}")


    if [ ${#MAC_LIST[@]} -eq 0 ]; then
       echo "Ошибка: Список MAC-адресов пуст. Выход."
       exit 1
    fi
    NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}
    echo "Выбранный MAC для подмены: $NEW_MAC" # Отладочный вывод
    sudo ip link set $MY_INTERFACE down
    sudo ip link set $MY_INTERFACE address "$NEW_MAC"
    sudo ip link set $MY_INTERFACE up
    echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
    NEW_TTL=128  # Windows-style
    sudo sysctl -w net.ipv4.ip_default_ttl=$NEW_TTL > /dev/null
    echo "Новый TTL: $NEW_TTL"


    sudo sysctl -w net.ipv4.tcp_sack=1 > /dev/null
    echo "SACK включен"


    MSS_LIST=("1460" "156")
    NEW_MSS=${MSS_LIST[$RANDOM % ${#MSS_LIST[@]}]}
    sudo sysctl -w net.ipv4.route.min_adv_mss=$NEW_MSS > /dev/null
    if [ "$NEW_MSS" == "1460" ]; then
        echo "MSS установлен для Windows: $NEW_MSS"
    else
        echo "MSS установлен для Android: $NEW_MSS"
    fi
}


spoof_timezone() {
    get_random_timezone "timezone.txt"
    if [ -z "$NEW_TZ" ]; then
        echo "Ошибка: Не удалось выбрать часовой пояс"
        return 1
    fi
    sudo timedatectl set-timezone "$NEW_TZ"
    echo "Новый часовой пояс: $NEW_TZ"
}


spoof_resolution() {
    NEW_RES=${RESOLUTION_LIST[$RANDOM % ${#RESOLUTION_LIST[@]}]}
    killall Xvfb 2>/dev/null  # Убиваем старый Xvfb, если был
    Xvfb :1 -screen 0 ${NEW_RES}x24 &  # Запускаем в фоне
    echo "Новый размер экрана: $NEW_RES (используйте DISPLAY=:1 для приложений)"
}


spoof_all() {
    spoof_mac
    spoof_tcp
    spoof_timezone
    spoof_resolution
}


auto_spoof() {
    while true; do
        spoof_all
        echo "Подмена выполнена, жду $TIME_CHANGE секунд..."
        sleep $TIME_CHANGE
    done
}


case "$1" in
    "mac") spoof_mac ;;
    "tcp") spoof_tcp ;;
    "timezone") spoof_timezone ;;
    "resolution") spoof_resolution ;;
    "all") spoof_all ;;
    "auto") auto_spoof ;;
    *) echo "Использование: $0 {mac|tcp|timezone|resolution|all|auto}" ;;
esac

Пробуем выполнить итоговый код:
photo_2025-04-04_18-02-23.jpg


Как мы видим, всё работает корректно.

Установка реалистичного рассширения экрана
Теперь давайте составим список правдоподобных разрешений экрана, которые можно использовать для подделки. Поиск списка разрешений оказался чуть сложнее, чем я ожидал. Готовых списков в формате CSV или TXT мне найти не удалось (возможно, я недостаточно старался, но максимум, что попалось — это один список мобильных разрешений на GitHub в CSV). Однако я обнаружил подробную статистику в виде таблицы на сайте https://www.screenresolution.org/.

Недолго думая, я написал простой скрипт на Python, который парсит разрешения с этого сайта и сохраняет их в файл resolutions.txt.

Вот сам скрипт:


Python:
import requests
from bs4 import BeautifulSoup


url = "https://www.screenresolution.org/"


response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')


resolutions = soup.find_all('td', title=True)
unique_resolutions = set()


for res in resolutions:
    title = res.get('title')
    if title and 'x' in title and ':' in title:
        resolution = title.split(':')[0].strip()
        unique_resolutions.add(resolution)


sorted_resolutions = sorted(list(unique_resolutions))


with open('resolutions.txt', 'w', encoding='utf-8') as file:
    for resolution in sorted_resolutions:
        file.write(f"{resolution}\n")

print(f"Найдено и сохранено {len(sorted_resolutions)} уникальных разрешений в файл resolutions.txt")

Вывод скрипта:
photo_2025-04-04_18-09-50.jpg


Для его запуска вам необходимо умстановить питон, у меня стоит 3.11. Поместите этот код в файл resolutions_parse.py.

Установите библиотеки:
Код:
pip install bs4; pip install requests

Теперь у вас будет аккуратный список разрешений в файле resolutions.txt!

Код подделки фингерпинтов с рандомными рассширений
Далее на нам нужно сделать функцию на bash для использования рассширений:

Bash:
get_random_resolution() {
    local input_file="$1"
    
    if [ ! -f "$input_file" ]; then
        echo "Ошибка: Файл $input_file не найден"
        return 1
    fi


    local line_count=$(wc -l < "$input_file")
    if [ "$line_count" -eq 0 ]; then
        echo "Ошибка: Файл $input_file пуст"
        return 1
    fi


    local random_line=$(( RANDOM % line_count + 1 ))
    
    NEW_RES=$(sed -n "${random_line}p" "$input_file")
    echo "Выбрано разрешение: $NEW_RES"
}


get_random_resolution "resolutions.txt"


Вывод функции:
photo_2025-04-04_11-38-40.jpg


Функция берёт файл с разрешениями, считает количество строк, выбирает случайную с помощью RANDOM, достаёт эту строку через sed и сохраняет её в NEW_RES.

Интегрируем ее в общий код:
#!/bin/bash


# Функция генерации случайных MAC-адресов
generate_random_macs() {
# типо код функции
}




# Функция для выбора случайного часового пояса из файла
get_random_timezone() {
# типо код функции
}


get_random_resolution() {
local input_file="$1"

if [ ! -f "$input_file" ]; then
echo "Ошибка: Файл $input_file не найден"
return 1
fi


local line_count=$(wc -l < "$input_file")
if [ "$line_count" -eq 0 ]; then
echo "Ошибка: Файл $input_file пуст"
return 1
fi


local random_line=$(( RANDOM % line_count + 1 ))

NEW_RES=$(sed -n "${random_line}p" "$input_file")
echo "Выбрано разрешение: $NEW_RES"
}


MAC_FILE_LINK="mac_list.txt"
MY_INTERFACE="eno0"
TIME_CHANGE=1800 # 30 минут




spoof_mac() {


generate_random_macs
MAC_LIST=("${GENERATED_MACS[@]}")


if [ ${#MAC_LIST[@]} -eq 0 ]; then
echo "Ошибка: Список MAC-адресов пуст. Выход."
exit 1
fi
NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}
echo "Выбранный MAC для подмены: $NEW_MAC" # Отладочный вывод
sudo ip link set $MY_INTERFACE down
sudo ip link set $MY_INTERFACE address "$NEW_MAC"
sudo ip link set $MY_INTERFACE up
echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
NEW_TTL=128 # Windows-style
sudo sysctl -w net.ipv4.ip_default_ttl=$NEW_TTL > /dev/null
echo "Новый TTL: $NEW_TTL"


sudo sysctl -w net.ipv4.tcp_sack=1 > /dev/null
echo "SACK включен"


MSS_LIST=("1460" "156")
NEW_MSS=${MSS_LIST[$RANDOM % ${#MSS_LIST[@]}]}
sudo sysctl -w net.ipv4.route.min_adv_mss=$NEW_MSS > /dev/null
if [ "$NEW_MSS" == "1460" ]; then
echo "MSS установлен для Windows: $NEW_MSS"
else
echo "MSS установлен для Android: $NEW_MSS"
fi
}


spoof_timezone() {
get_random_timezone "timezone.txt"
if [ -z "$NEW_TZ" ]; then
echo "Ошибка: Не удалось выбрать часовой пояс"
return 1
fi
sudo timedatectl set-timezone "$NEW_TZ"
echo "Новый часовой пояс: $NEW_TZ"
}


spoof_resolution() {
get_random_resolution "resolutions.txt"
if [ -z "$NEW_RES" ]; then
echo "Ошибка: Не удалось выбрать разрешение"
return 1
fi
killall Xvfb 2>/dev/null
Xvfb :1 -screen 0 ${NEW_RES}x24 &
echo "Новый размер экрана: $NEW_RES (используйте DISPLAY=:1 для приложений)"
}


spoof_all() {
spoof_mac
spoof_tcp
spoof_timezone
spoof_resolution
}


auto_spoof() {
while true; do
spoof_all
echo "Подмена выполнена, жду $TIME_CHANGE секунд..."
sleep $TIME_CHANGE
done
}


case "$1" in
"mac") spoof_mac ;;
"tcp") spoof_tcp ;;
"timezone") spoof_timezone ;;
"resolution") spoof_resolution ;;
"all") spoof_all ;;
"auto") auto_spoof ;;
*) echo "Использование: $0 {mac|tcp|timezone|resolution|all|auto}" ;;
esac[/CODE]

Пробуем выполнить:
photo_2025-04-04_18-15-26.jpg


Всё работает как надо, общий скрипт для подмены данных готов! Чуть позже я объясню, как его можно слегка оптимизировать и добавить автозапуск.

Подделка реалистичного баннера ssh
А пока, на десерт, расскажу, как получать баннеры и динамически менять их через некоторое время — например, в коде с заменой конфигурации SSH, который я показывал раньше.

Я нашел баннеры для SSH в репозитории https://github.com/richlamdev/ssh-default-banners, но они были разбиты по отдельным файлам:
photo_2025-04-04_18-16-24.jpg


Потому я решил собрать все банеры в один файл, для этого я написал скрипт на bash:

Bash:
#!/bin/bash


> all_banners.txt


for file in *tsv.txt; do


    if [ -f "$file" ]; then
        echo "Добавляем $file"
        cat "$file" >> all_banners.txt
    fi
done

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

Функция для обновления баннеров выглядит так:

Bash:
update_fake_banner() {
    local BANNER_FILE="/etc/ssh/fake_banner"
    local ALL_BANNERS="all_banners.txt"
    
    if [ ! -f "$ALL_BANNERS" ]; then
        echo "Ошибка: Файл $ALL_BANNERS не найден."
        return 1
    fi
    local NEW_BANNER=$(shuf -n 1 "$ALL_BANNERS" | awk '{print $NF}')
    
    echo "$NEW_BANNER" > "$BANNER_FILE"
    echo "Установлен новый баннер: $NEW_BANNER"
}

Функция работает просто: она проверяет, существует ли файл all_banners.txt, затем случайным образом выбирает одну строку из него с помощью shuf, берет последнее поле строки через awk и записывает его в файл /etc/ssh/fake_banner, после чего выводит сообщение о новом баннере.

Итоговая функция подделки баннеров ssh
Давайте интегрируем ее в общий код и добавим смену баннеров раз в 24 часа:


Bash:
#!/bin/bash


update_fake_banner() {
    local BANNER_FILE="/etc/ssh/fake_banner"
    local ALL_BANNERS="all_banners.txt"
    
    if [ ! -f "$ALL_BANNERS" ]; then
        echo "Ошибка: Файл $ALL_BANNERS не найден."
        return 1
    fi
    
    local NEW_BANNER=$(shuf -n 1 "$ALL_BANNERS" | awk '{print $NF}')
    
    echo "$NEW_BANNER" > "$BANNER_FILE"
    echo "Установлен новый баннер: $NEW_BANNER"
}


setup_banner_rotation() {
    local CRON_JOB="0 0 * * * root /bin/bash $0 --update-banner"
    
    if ! crontab -l 2>/dev/null | grep -q "$0 --update-banner"; then
        (crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
        echo "Настроено ежедневное обновление баннера в 00:00."
    else
        echo "Обновление баннера уже настроено в cron."
    fi
}


if [ "$EUID" -ne 0 ]; then
    echo "Ошибка: Скрипт должен быть запущен с правами root (sudo)."
    exit 1
fi


if [ "$1" == "--update-banner" ]; then
    update_fake_banner
    systemctl restart sshd
    exit 0
fi


SSHD_CONFIG="/etc/ssh/sshd_config"
FAKE_BANNER="/etc/ssh/fake_banner"


if [ -f "$SSHD_CONFIG" ]; then
    cp "$SSHD_CONFIG" "$SSHD_CONFIG.bak_$(date +%F_%T)"
    echo "Резервная копия $SSHD_CONFIG создана."
else
    echo "Ошибка: Файл $SSHD_CONFIG не найден."
    exit 1
fi


update_fake_banner


echo "Настройка SSH для маскировки..."
{
    echo "# Кастомный баннер для маскировки"
    echo "Banner $FAKE_BANNER"
    echo "# Убираем лишние логи"
    echo "LogLevel QUIET"
    echo "# Только второй протокол"
    echo "Protocol 2"
    echo "# Отключаем специфичный баннер"
    echo "DebianBanner no"
} >> "$SSHD_CONFIG"


if sshd -t; then
    echo "Конфигурация SSH проверена успешно."
else
    echo "Ошибка в конфигурации SSH. Восстанавливаем резервную копию..."
    cp "$SSHD_CONFIG.bak_$(date +%F_%T)" "$SSHD_CONFIG"
    exit 1
fi


systemctl restart sshd
if [ $? -eq 0 ]; then
    echo "SSH-сервер перезапущен успешно."
else
    echo "Ошибка при перезапуске SSH. Проверьте статус: systemctl status sshd"
    exit 1
fi


setup_banner_rotation


echo "SSH замаскирован с ротацией баннеров."

Вывод функции:
photo_2025-04-04_11-42-07.jpg


Если скрипт вызвать с параметром --update-banner, он просто обновляет баннер и перезапускает SSH. Без параметра он делает больше: создает резервную копию конфига SSH, ставит первый баннер, добавляет в конфиг настройки вроде кастомного баннера и отключения лишней информации, проверяет, что все работает, и перезапускает сервер. setup_banner_rotation добавляет задачу в cron, чтобы баннер менялся каждый день в полночь, но только если такой задачи еще нет. В итоге нашего кода SSH маскируется, а баннеры обновляются автоматически.

Подделка реалистичного баннера ftp
С баннерами для ftp вышло чуть труднее я не нашел списки баннеров по тому пришлось покопаться в открытых источниках в итоге я составил свой список там около 30 баннеров различных сервисов ftp, список я прикреплю к статье.

Итоговая функция подделки баннеров ftp

Теперь сразу модифицирую код чтобы он брал ftp баннер из списка и меня его каждые 24 часа:


Bash:
#!/bin/bash


if [ "$EUID" -ne 0 ]; then
    echo "Ошибка: Скрипт должен быть запущен с правами root (sudo)."
    exit 1
fi


VSFTPD_CONFIG="/etc/vsftpd.conf"
BANNERS_FILE="ftp_banners.txt"  # Путь к файлу ftp_banners.txt


if ! command -v vsftpd &> /dev/null; then
    echo "Ошибка: vsftpd не установлен. Установите его: sudo apt install vsftpd"
    exit 1
fi


if [ -f "$VSFTPD_CONFIG" ]; then
    cp "$VSFTPD_CONFIG" "$VSFTPD_CONFIG.bak_$(date +%F_%T)"
    echo "Резервная копия $VSFTPD_CONFIG создана."
else
    echo "Ошибка: Файл $VSFTPD_CONFIG не найден."
    exit 1
fi


if [ ! -f "$BANNERS_FILE" ]; then
    echo "Ошибка: Файл $BANNERS_FILE с баннерами не найден."
    exit 1
fi


set_random_banner() {
    FTP_BANNER=$(shuf -n 1 "$BANNERS_FILE")
    echo "Выбран баннер: $FTP_BANNER"


    sed -i '/^ftpd_banner=/d' "$VSFTPD_CONFIG"


    echo "Настройка vsftpd для маскировки баннеров..."
    {
        echo "# Кастомный баннер для маскировки"
        echo "ftpd_banner=$FTP_BANNER"
        echo "# Скрываем версию vsftpd"
        echo "hide_version=YES"
        echo "# Отключаем лишние идентификаторы"
        echo "banner_file=NO"
    } >> "$VSFTPD_CONFIG"
}


setup_banner_rotation() {
    local CRON_JOB="0 0 * * * root /bin/bash $0"
    
    if ! crontab -l 2>/dev/null | grep -q "$0"; then
        (crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
        echo "Настроено ежедневное обновление баннера в 00:00."
    else
        echo "Обновление баннера уже настроено в cron."
    fi
}


set_random_banner


echo "Проверка настроек через перезапуск сервиса..."
systemctl restart vsftpd
if [ $? -eq 0 ]; then
    echo "vsftpd перезапущен успешно."
else
    echo "Ошибка при перезапуске vsftpd. Восстанавливаем резервную копию..."
    cp "$VSFTPD_CONFIG.bak_$(date +%F_%T)" "$VSFTPD_CONFIG"
    systemctl restart vsftpd
    exit 1
fi


setup_banner_rotation


echo "FTP замаскирован с ротацией баннеров."


Вывод функции:
photo_2025-04-04_11-46-41.jpg


Я добавил штуки для автоматической смены баннеров в FTP, сейчас расскажу как это работает. Сначала скрипт проверяет, файл с баннерами ftp_banners.txt — если чего-то нет, выходит с ошибкой. Функция set_random_banner берет случайный баннер из ftp_banners.txt, убирает старый баннер из конфига и добавляет новый. После этого скрипт перезапускает vsftpd, и если все прошло гладко, говорит, что FTP замаскирован. Если что-то пошло не так, восстанавливает копию конфига и пробует перезапустить снова. Функция setup_banner_rotation добавляет задачу в cron, чтобы скрипт запускался каждый день в полночь и менял баннер, но только если такой задачи еще нет.


Методы автозапуска linux

Как вы видите, для автопостановки баннеров мы использовали cron-задачи, но давайте разберёмся, какие ещё методы установки задач в Linux есть. Кстати, это в теории может пригодиться не только для нашей темы с подменой отпечатков, но и, например, чтобы добавить автозапуск какого-нибудь зловредного кода. Короче, в Linux есть несколько способов заставить систему что-то делать сама по себе.

Сначала про cron. Он работает по принципу, что ты задаёшь системе точное время или интервал, когда нужно что-то выполнить — в общем, почти как "Планировщик задач" в Windows, только с чуть другим подходом. Всё вертится вокруг файла crontab — это как таблица расписания, где прописано, что и когда делать. Открываешь её командой "crontab -e", и каждая строка там — это правило. Например, "0 0 * * *" означает "в полночь каждый день", а потом идёт команда, которую надо запустить. Cron — это демон, то есть программа, которая постоянно сидит в фоне и каждую минуту сверяется с системным временем. Если время совпадает с тем, что ты указал в crontab, он тут же выполняет задачу. Можно сделать так, чтобы что-то срабатывало хоть каждую минуту, хоть раз в год. Но есть подвох, если система выключена в момент, когда задача должна стартануть, cron её пропустит и не будет потом догонять.

Теперь про systemd. Это уже не просто таймер, а целая система управления. Она отвечает за запуск всего в Linux, когда машина стартует: от сетей до графического интерфейса. Но её можно приспособить и для твоих задач. Работает это через так называемые юниты — файлы с настройками, которые говорят, что делать. Например, создаёшь файл с расширением .service, где указываешь команду для запуска и условия — скажем, стартовать после того, как сеть поднялась. Systemd постоянно следит за состоянием системы и может запускать твою задачу при загрузке, при определённых событиях или держать её в работе как сервис. Если процесс упадёт, systemd может его перезапустить автоматически, а все логи пишутся в журнал, который можно глянуть через journalctl. Принцип тут в контроле и зависимости: ты задаёшь не только "когда", но и "при каких условиях", и система сама решает, как это выполнить. Это мощнее cron, но требует больше возни с настройкой.

Дальше rc.local. Это старый способ, который остался ещё с времён, когда systemd не было. По сути, это просто скрипт, который Linux выполняет один раз при загрузке. Принцип работы примитивный: система доходит до конца процесса старта, смотрит в файл /etc/rc.local и запускает всё, что там написано. Ты просто добавляешь туда команду, и она сработает, как только машина загрузится. Никаких расписаний или сложных условий тут нет — просто "сделай это при включении". Раньше это был популярный метод, но сейчас он считается устаревшим, и на многих современных системах его надо включать вручную, потому что по умолчанию он может быть отключён. Работает без лишних наворотов, но гибкости никакой.

Потом есть anacron . Это как улучшенный cron для тех случаев, когда машина не всегда включена. Если cron завязан на точное время, то anacron больше про "выполнить задачу хотя бы раз в период". Он использует файлы в папках вроде /etc/cron.daily, /etc/cron.weekly или /etc/cron.monthly. Ты кладешь туда скрипт, и anacron проверяет, когда его в последний раз запускали. Если с прошлого запуска прошло больше, чем день, неделя или месяц (в зависимости от папки), он выполнит задачу при следующем удобном моменте — например, когда система включится. Принцип в том, что он не привязан к реальному времени, а смотрит на интервалы и историю выполнения. Это удобно для редких задач, вроде резервного копирования, но точности, как у cron, тут не жди.

И наконец, запуск через shell-скрипты, которые срабатывают при входе в систему. Это работает через файлы вроде /etc/profile или ~/.bashrc — они выполняются, когда ты открываешь терминал или логинишься. Принцип простой: система видит, что ты вошёл, и прогоняет команды из этих файлов. Ты можешь добавить туда запуск чего угодно, и оно сработает, но только для твоей сессии. Если ты выйдешь, всё остановится, потому что это не фоновая задача, а часть твоего окружения. Это больше для личных штук, вроде настройки терминала или запуска утилит, а не для чего-то серьёзного или постоянного.

Автозапуск с cron
Чтож мы разобрались какие есть методы автозапуска кода, первым делом давайте попробуем добавить функцию для автозапуска нашего кода каждые 30 минут через corn:

Bash:
setup_cron() {
    local SCRIPT_PATH="$(realpath "$0")"
    local CRON_JOB="*/30 * * * * /bin/bash $SCRIPT_PATH auto


    if ! crontab -l 2>/dev/null | grep -q "$SCRIPT_PATH auto"; then
        # Если нет, добавляем её
        (crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
        echo "Задача для cron добавлена: запуск каждые 30 минут в режиме auto"
    else
        echo "Задача уже есть в cron, ничего не меняю"
    fi
}

Теперь объясню, как это работает. Функция делает три вещи. Сначала она узнаёт полный путь к твоему скрипту — это нужно, чтобы cron знал, где искать spoof_linux.sh. Потом она задаёт строку для cron: "/30 * * * * /bin/bash $SCRIPT_PATH auto". Тут "/30" в первом поле значит "каждые 30 минут", остальные звёздочки — это "в любой час, день, месяц и день недели", а дальше — команда для запуска скрипта с параметром auto.
Дальше функция проверяет, есть ли уже такая задача в crontab. Если ничего не нашлось (или crontab вообще пустой, что скрывает 2>/dev/null), она добавляет новую задачу. Если задача уже есть, она просто говорит "всё уже настроено" и ничего не трогает.

Теперь интегрируем функцию в общий скрипт:
Bash:
#!/bin/bash


SCRIPT_DIR="$(dirname "$(realpath "$0")")"


# Функция генерации случайных MAC-адресов
generate_random_macs() {
   # типо код функции
}




# Функция для выбора случайного часового пояса из файла
get_random_timezone() {
   # типо код функции
}


get_random_resolution() {
     # типо код функции
}




setup_cron() {
    local SCRIPT_PATH="$(realpath "$0")"
    local CRON_JOB="*/30 * * * * /bin/bash $SCRIPT_PATH auto


    if ! crontab -l 2>/dev/null | grep -q "$SCRIPT_PATH auto"; then
        # Если нет, добавляем её
        (crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
        echo "Задача для cron добавлена: запуск каждые 30 минут в режиме auto"
    else
        echo "Задача уже есть в cron, ничего не меняю"
    fi
}




MAC_FILE_LINK="$SCRIPT_DIR/mac_list.txt"
MY_INTERFACE="eno0"
TIME_CHANGE=1800 # 30 минут


spoof_mac() {


    generate_random_macs
    MAC_LIST=("${GENERATED_MACS[@]}")


    if [ ${#MAC_LIST[@]} -eq 0 ]; then
       echo "Ошибка: Список MAC-адресов пуст. Выход."
       exit 1
    fi
    NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}
    echo "Выбранный MAC для подмены: $NEW_MAC" # Отладочный вывод
    sudo ip link set $MY_INTERFACE down
    sudo ip link set $MY_INTERFACE address "$NEW_MAC"
    sudo ip link set $MY_INTERFACE up
    echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
    NEW_TTL=128  # Windows-style
    sudo sysctl -w net.ipv4.ip_default_ttl=$NEW_TTL > /dev/null
    echo "Новый TTL: $NEW_TTL"


    sudo sysctl -w net.ipv4.tcp_sack=1 > /dev/null
    echo "SACK включен"


    MSS_LIST=("1460" "156")
    NEW_MSS=${MSS_LIST[$RANDOM % ${#MSS_LIST[@]}]}
    sudo sysctl -w net.ipv4.route.min_adv_mss=$NEW_MSS > /dev/null
    if [ "$NEW_MSS" == "1460" ]; then
        echo "MSS установлен для Windows: $NEW_MSS"
    else
        echo "MSS установлен для Android: $NEW_MSS"
    fi
}


spoof_timezone() {
    get_random_timezone "$SCRIPT_DIR/timezone.txt"
    if [ -z "$NEW_TZ" ]; then
        echo "Ошибка: Не удалось выбрать часовой пояс"
        return 1
    fi
    sudo timedatectl set-timezone "$NEW_TZ"
    echo "Новый часовой пояс: $NEW_TZ"
}


spoof_resolution() {
    get_random_resolution "$SCRIPT_DIR/resolutions.txt"
    if [ -z "$NEW_RES" ]; then
        echo "Ошибка: Не удалось выбрать разрешение"
        return 1
    fi
    killall Xvfb 2>/dev/null
    Xvfb :1 -screen 0 ${NEW_RES}x24 &
    echo "Новый размер экрана: $NEW_RES (используйте DISPLAY=:1 для приложений)"
}


spoof_all() {
    spoof_mac
    spoof_tcp
    spoof_timezone
    spoof_resolution
}


auto_spoof() {
    while true; do
        spoof_all
        echo "Подмена выполнена, жду $TIME_CHANGE секунд..."
        sleep $TIME_CHANGE
    done
}


case "$1" in
    "mac") spoof_mac ;;
    "tcp") spoof_tcp ;;
    "timezone") spoof_timezone ;;
    "resolution") spoof_resolution ;;
    "all") spoof_all ;;
    "auto") auto_spoof ;;
    "setup-cron") setup_cron ;; 
    *) echo "Использование: $0 {mac|tcp|timezone|resolution|all|auto|setup-cron}" ;;
esac

Вывод функции:
photo_2025-04-04_16-22-22.jpg


Чтобы все коректно работало я переписал скрипт, чтобы он брал файлы списоков из папки где сам лежит. Для запуска скрипта надо просто написать в терминале "./spoof_linux.sh setup-cron", и всё — cron теперь будет каждые 30 минут врубать скрипт в режиме auto, который сам по себе бесконечно крутит spoof_all с паузой в 30 минут.

Автозапуск с systemd
Теперь давайте разберемя как запускать наш spoof_linux.sh с помощью systemd. Напрямую одинм скриптом сделать запуск по тафмеру как в cron в systemd нельзя, но не расстраеваемся, мы сделаем два файла: сервис (.service) и таймер (.timer). Сервис будет говорить, что запускать, а таймер — когда. Вот как это сделать.

Создай файл /etc/systemd/system/spoof.service с таким содержимым:

Код:
[Unit]
Description=Spoofing service for fingerprint obfuscation
After=network.target


[Service]
Type=oneshot
ExecStart=/bin/bash /home/user/spoof_linux.sh all
User=root

Тут Type=oneshot значит, что скрипт выполнится один раз и завершится (в отличие от simple, где он бы крутился постоянно). ExecStart указывает, что запускать — наш скрипт с параметром all.


Теперь создай файл /etc/systemd/system/spoof.timer рядом с сервисом:

Код:
[Unit]
Description=Timer for spoofing service


[Timer]
OnBootSec=10 
OnUnitActiveSec=5m  
Unit=spoof.service


[Install]
WantedBy=timers.target

Как это работает? OnBootSec=10 — сервис стартует через 10 секунд после загрузки системы, чтобы сеть успела подняться. OnUnitActiveSec=5m — повторный запуск каждые 5 минут. Unit=spoof.service — связывает таймер с нашим сервисом.

Чтобы запусить наш unit нужно выполнить команды:

Bash:
sudo systemctl daemon-reload 
sudo systemctl enable spoof.timer 
sudo systemctl start spoof.timer

Если все нормально вы увидите:
photo_2025-04-04_16-26-31.jpg



Автозапуск с anacron
Давайте теперь настоим автозапуск spoof_linux.sh с помощью anacron. Но только в anacron есть нюанс: anacron не предназначен для интервалов меньше одного дня — он работает с периодами в днях (минимум 1 день). Чтобы добиться запуска каждые 30 минут, проще всего использовать режим auto в скрипте с нужным интервалом (TIME_CHANGE=1800), а anacron настроить так, чтобы он просто запускал этот режим один раз после включения системы. Тогда anacron даст старт, а скрипт сам будет крутиться каждые 30 минут.

Сам доработанный код:

Bash:
#!/bin/bash


SCRIPT_DIR="$(dirname "$(realpath "$0")")"


generate_random_macs() {
   #код функции
}




get_random_timezone() {
   #код функции
}


get_random_resolution() {
   #код функции
}


setup_anacron() {
    local SCRIPT_PATH="$(realpath "$0")"
    local ANACRON_JOB="1 5 spoof_auto /bin/bash $SCRIPT_PATH auto"
    local ANACRON_FILE="/etc/anacrontab"


    if ! sudo grep -q "$SCRIPT_PATH auto" "$ANACRON_FILE" 2>/dev/null; then
        echo "$ANACRON_JOB" | sudo tee -a "$ANACRON_FILE" > /dev/null
        echo "Задача для anacron добавлена: запуск режима auto через 5 минут после старта системы"
        sudo systemctl restart anacron
    else
        echo "Задача уже есть в anacrontab, ничего не меняю"
    fi
}


MAC_FILE_LINK="$SCRIPT_DIR/mac_list.txt"
MY_INTERFACE="eno0"
RESOLUTION_LIST=("1366x768" "1920x1080" "1280x720")
TIME_CHANGE=1800 # 30 минут (1800 секунд)


spoof_mac() {
    generate_random_macs
    MAC_LIST=("${GENERATED_MACS[@]}")


    if [ ${#MAC_LIST[@]} -eq 0 ]; then
        echo "Ошибка: Список MAC-адресов пуст. Выход."
        exit 1
    fi
    NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}
    echo "Выбранный MAC для подмены: $NEW_MAC"
    sudo ip link set $MY_INTERFACE down
    sudo ip link set $MY_INTERFACE address "$NEW_MAC"
    sudo ip link set $MY_INTERFACE up
    echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
    NEW_TTL=128
    sudo sysctl -w net.ipv4.ip_default_ttl=$NEW_TTL > /dev/null
    echo "Новый TTL: $NEW_TTL"


    sudo sysctl -w net.ipv4.tcp_sack=1 > /dev/null
    echo "SACK включен"


    MSS_LIST=("1460" "156")
    NEW_MSS=${MSS_LIST[$RANDOM % ${#MSS_LIST[@]}]}
    sudo sysctl -w net.ipv4.route.min_adv_mss=$NEW_MSS > /dev/null
    if [ "$NEW_MSS" == "1460" ]; then
        echo "MSS установлен для Windows: $NEW_MSS"
    else
        echo "MSS установлен для Android: $NEW_MSS"
    fi
}


spoof_timezone() {
    get_random_timezone
    if [ -z "$NEW_TZ" ]; then
        echo "Ошибка: Не удалось выбрать часовой пояс"
        return 1
    fi
    sudo timedatectl set-timezone "$NEW_TZ"
    echo "Новый часовой пояс: $NEW_TZ"
}


spoof_resolution() {
    get_random_resolution
    if [ -z "$NEW_RES" ]; then
        echo "Ошибка: Не удалось выбрать разрешение"
        return 1
    fi
    killall Xvfb 2>/dev/null
    Xvfb :1 -screen 0 ${NEW_RES}x24 &
    echo "Новый размер экрана: $NEW_RES (используйте DISPLAY=:1 для приложений)"
}


spoof_all() {
    spoof_mac
    spoof_tcp
    spoof_timezone
    spoof_resolution
}


auto_spoof() {
    while true; do
        spoof_all
        echo "Подмена выполнена, жду $TIME_CHANGE секунд..."
        sleep $TIME_CHANGE
    done
}


case "$1" in
    "mac") spoof_mac ;;
    "tcp") spoof_tcp ;;
    "timezone") spoof_timezone ;;
    "resolution") spoof_resolution ;;
    "all") spoof_all ;;
    "auto") auto_spoof ;;
    "setup-anacron") setup_anacron ;;  # Добавляем новый параметр
    *) echo "Использование: $0 {mac|tcp|timezone|resolution|all|auto|setup-anacron}" ;;
esac

Как мы видим все работает хорошо:
photo_2025-04-04_16-29-14.jpg


Функция setup_anacron() работает давольно просто, сначала она берёт полный путь к скрипту через. Потом создаёт строку ANACRON_JOB="1 5 spoof_auto /bin/bash $SCRIPT_PATH auto", которая говорит anacron: запускай скрипт в режиме auto через 5 минут после включения системы и повторяй это раз в день. Дальше она проверяет с помощью grep -q, есть ли уже такая строка в файле /etc/anacrontab. Если нет, то tee -a добавляет эту строку в конец файла с правами root. И наконец, перезапускает anacron, чтобы он сразу увидел новую задачу и начал её.

Автозапуск с rc.local
Переходим к rc.local. Как и anacron, rc.local сам по себе не умеет выполнять задачи по расписанию — он запускается один раз при старте системы. Поэтому аналогично anacron мы добавим функцию setup_rclocal(), которая запишет в /etc/rc.local команду для запуска скрипта в режиме auto, а интервал 30 минут:

Код с автозапуском с помощью rc.local:

Bash:
#!/bin/bash


SCRIPT_DIR="$(dirname "$(realpath "$0")")"


generate_random_macs() {
    #код
}


get_random_timezone() {
        #код
}


get_random_resolution() {
        #код
}


# Новая функция для настройки rc.local
setup_rclocal() {
    local SCRIPT_PATH="$(realpath "$0")"
    local RC_LOCAL="/etc/rc.local"
    local RC_CONTENT="#!/bin/bash\n/bin/bash $SCRIPT_PATH auto &\nexit 0"


    if [ ! -f "$RC_LOCAL" ] || ! grep -q "$SCRIPT_PATH auto" "$RC_LOCAL" 2>/dev/null; then
        echo -e "$RC_CONTENT" | sudo tee "$RC_LOCAL" > /dev/null
        sudo chmod +x "$RC_LOCAL"
        echo "Задача для rc.local добавлена: запуск режима auto при старте системы"
    else
        echo "Задача уже есть в rc.local, ничего не меняю"
    fi
}


MAC_FILE_LINK="$SCRIPT_DIR/mac_list.txt"
MY_INTERFACE="eno0"
TIME_CHANGE=1800 # 30 минут


spoof_mac() {
    generate_random_macs
    MAC_LIST=("${GENERATED_MACS[@]}")


    if [ ${#MAC_LIST[@]} -eq 0 ]; then
        echo "Ошибка: Список MAC-адресов пуст. Выход."
        exit 1
    fi
    NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}
    echo "Выбранный MAC для подмены: $NEW_MAC"
    sudo ip link set $MY_INTERFACE down
    sudo ip link set $MY_INTERFACE address "$NEW_MAC"
    sudo ip link set $MY_INTERFACE up
    echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
    NEW_TTL=128
    sudo sysctl -w net.ipv4.ip_default_ttl=$NEW_TTL > /dev/null
    echo "Новый TTL: $NEW_TTL"


    sudo sysctl -w net.ipv4.tcp_sack=1 > /dev/null
    echo "SACK включен"


    MSS_LIST=("1460" "156")
    NEW_MSS=${MSS_LIST[$RANDOM % ${#MSS_LIST[@]}]}
    sudo sysctl -w net.ipv4.route.min_adv_mss=$NEW_MSS > /dev/null
    if [ "$NEW_MSS" == "1460" ]; then
        echo "MSS установлен для Windows: $NEW_MSS"
    else
        echo "MSS установлен для Android: $NEW_MSS"
    fi
}


spoof_timezone() {
    get_random_timezone "$SCRIPT_DIR/timezone.txt"
    if [ -z "$NEW_TZ" ]; then
        echo "Ошибка: Не удалось выбрать часовой пояс"
        return 1
    fi
    sudo timedatectl set-timezone "$NEW_TZ"
    echo "Новый часовой пояс: $NEW_TZ"
}


spoof_resolution() {
    get_random_resolution "$SCRIPT_DIR/resolutions.txt"
    if [ -z "$NEW_RES" ]; then
        echo "Ошибка: Не удалось выбрать разрешение"
        return 1
    fi
    killall Xvfb 2>/dev/null
    Xvfb :1 -screen 0 ${NEW_RES}x24 &
    echo "Новый размер экрана: $NEW_RES (используйте DISPLAY=:1 для приложений)"
}


spoof_all() {
    spoof_mac
    spoof_tcp
    spoof_timezone
    spoof_resolution
}


auto_spoof() {
    while true; do
        spoof_all
        echo "Подмена выполнена, жду $TIME_CHANGE секунд..."
        sleep $TIME_CHANGE
    done
}


case "$1" in
    "mac") spoof_mac ;;
    "tcp") spoof_tcp ;;
    "timezone") spoof_timezone ;;
    "resolution") spoof_resolution ;;
    "all") spoof_all ;;
    "auto") auto_spoof ;;
    "setup-rclocal") setup_rclocal ;;  # Добавили новый параметр
    *) echo "Использование: $0 {mac|tcp|timezone|resolution|all|auto|setup-rclocal}" ;;
esac

Проверяем на работспособность:
photo_2025-04-04_20-01-26.jpg


Функция setup_rclocal() работает очень похоже на то код для anacron: определяет файл /etc/rc.local и создаёт строку с содержимым #!/bin/bash\n/bin/bash $SCRIPT_PATH auto &\nexit 0. Эта строка говорит системе запускать скрипт в режиме auto в фоновом режиме (за счёт &) при старте. Потом она проверяет, есть ли уже такой запуск в /etc/rc.local. Если файла нет или команды там нет, она записывает новое содержимое через tee с правами root.

Автозапуск через shell-скрипт
Двайте попробуем пройти по чуть менее протоптанной дорожке — автозапуску через shell-скрипты в ~/.bashrc. Это не самый практичный способ, но вдруг он пригодится кому то из вас, даже если не сейчас с этим скриптом, то в будущем? Эти файлы выполняются, только когда ты входишь в систему или открываешь терминал, а не сидят в фоне.
Чтобы заставить их повторять задачу каждые 30 минут, придётся либо пустить в ход фоновый процесс с бесконечным циклом, либо хитро запустить отдельный скрипт, который будет крутиться сам по себе. Я добавлю в код функцию setup_shell(), которая вплетёт запуск в ~/.bashrc, и скрипт начнёт работать, как только вы войдете в систему.

Доработаный код:
Bash:
#!/bin/bash


SCRIPT_DIR="$(dirname "$(realpath "$0")")"


generate_random_macs() {
    #код
}


get_random_timezone() {
    #код
}


get_random_resolution() {
    #код
}


setup_shell() {
    local SCRIPT_PATH="$(realpath "$0")"
    local BASHRC="$HOME/.bashrc"
    local SHELL_CMD="/bin/bash $SCRIPT_PATH auto &"


    if ! grep -q "$SCRIPT_PATH auto" "$BASHRC" 2>/dev/null; then
        echo "$SHELL_CMD" >> "$BASHRC"
        echo "Задача добавлена в ~/.bashrc: запуск режима auto при входе в систему"
    else
        echo "Задача уже есть в ~/.bashrc, ничего не меняю"
    fi
}


MAC_FILE_LINK="$SCRIPT_DIR/mac_list.txt"
MY_INTERFACE="eno0"
TIME_CHANGE=1800 # 30 минут


spoof_mac() {
    generate_random_macs
    MAC_LIST=("${GENERATED_MACS[@]}")


    if [ ${#MAC_LIST[@]} -eq 0 ]; then
        echo "Ошибка: Список MAC-адресов пуст. Выход."
        exit 1
    fi
    NEW_MAC=${MAC_LIST[$RANDOM % ${#MAC_LIST[@]}]}
    echo "Выбранный MAC для подмены: $NEW_MAC"
    sudo ip link set $MY_INTERFACE down
    sudo ip link set $MY_INTERFACE address "$NEW_MAC"
    sudo ip link set $MY_INTERFACE up
    echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
    NEW_TTL=128
    sudo sysctl -w net.ipv4.ip_default_ttl=$NEW_TTL > /dev/null
    echo "Новый TTL: $NEW_TTL"


    sudo sysctl -w net.ipv4.tcp_sack=1 > /dev/null
    echo "SACK включен"


    MSS_LIST=("1460" "156")
    NEW_MSS=${MSS_LIST[$RANDOM % ${#MSS_LIST[@]}]}
    sudo sysctl -w net.ipv4.route.min_adv_mss=$NEW_MSS > /dev/null
    if [ "$NEW_MSS" == "1460" ]; then
        echo "MSS установлен для Windows: $NEW_MSS"
    else
        echo "MSS установлен для Android: $NEW_MSS"
    fi
}


spoof_timezone() {
    get_random_timezone "$SCRIPT_DIR/timezone.txt"
    if [ -z "$NEW_TZ" ]; then
        echo "Ошибка: Не удалось выбрать часовой пояс"
        return 1
    fi
    sudo timedatectl set-timezone "$NEW_TZ"
    echo "Новый часовой пояс: $NEW_TZ"
}


spoof_resolution() {
    get_random_resolution "$SCRIPT_DIR/resolutions.txt"
    if [ -z "$NEW_RES" ]; then
        echo "Ошибка: Не удалось выбрать разрешение"
        return 1
    fi
    killall Xvfb 2>/dev/null
    Xvfb :1 -screen 0 ${NEW_RES}x24 &
    echo "Новый размер экрана: $NEW_RES (используйте DISPLAY=:1 для приложений)"
}


spoof_all() {
    spoof_mac
    spoof_tcp
    spoof_timezone
    spoof_resolution
}


auto_spoof() {
    while true; do
        spoof_all
        echo "Подмена выполнена, жду $TIME_CHANGE секунд..."
        sleep $TIME_CHANGE
    done
}


case "$1" in
    "mac") spoof_mac ;;
    "tcp") spoof_tcp ;;
    "timezone") spoof_timezone ;;
    "resolution") spoof_resolution ;;
    "all") spoof_all ;;
    "auto") auto_spoof ;;
    "setup-shell") setup_shell ;;  # Добавили новый параметр
    *) echo "Использование: $0 {mac|tcp|timezone|resolution|all|auto|setup-shell}" ;;
esac

Выполняем скрипт:
photo_2025-04-04_20-04-14.jpg


Функция setup_shell() определяет файл ~/.bashrc для текущего пользователя через $HOME/.bashrc и создаёт команду /bin/bash $SCRIPT_PATH auto &, которая запускает скрипт в режиме auto в фоне. Она проверяет с помощью grep -q, есть ли уже такая строка в ~/.bashrc. Если нет, добавляет её в конец файла через >>, чтобы не переписывать существующий контент. Если строка уже есть, просто сообщает, что ничего не изменилось.

Мы прошлись по всем способам засунуть наш скрипт в автозапуск — теперь вы точно сможете поставить его автозапуск почти везде ;)


Оптимизация кода

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

Мы можем ускорить чтение файлов и генерацию MAC-адресов, а заодно сделать spoof_all чуть шустрее. Это можно сделать кэшируя данные, убрав лишние процессы и добавив лёгкий параллелизм там, где он реально поможет:

Bash:
#!/bin/bash


SCRIPT_DIR="$(dirname "$(realpath "$0")")"


# Переменные для кэша, пока пустые
declare -a OUI_LIST TZ_LIST RES_LIST


# Функции загрузки файлов — вызываем только при необходимости
load_macs() {
    [ ${#OUI_LIST[@]} -eq 0 ] && mapfile -t OUI_LIST < <(grep -E '^[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}' "$SCRIPT_DIR/mac_list.txt" | awk '{print $1}')
    [ ${#OUI_LIST[@]} -eq 0 ] && { echo "Ошибка: mac_list.txt пуст или битый"; exit 1; }
}


load_timezones() {
    [ ${#TZ_LIST[@]} -eq 0 ] && mapfile -t TZ_LIST < "$SCRIPT_DIR/timezone.txt"
    [ ${#TZ_LIST[@]} -eq 0 ] && { echo "Ошибка: timezone.txt пуст"; exit 1; }
}


load_resolutions() {
    [ ${#RES_LIST[@]} -eq 0 ] && mapfile -t RES_LIST < "$SCRIPT_DIR/resolutions.txt"
    [ ${#RES_LIST[@]} -eq 0 ] && { echo "Ошибка: resolutions.txt пуст"; exit 1; }
}


# Генерация MAC-адресов
generate_random_macs() {
    load_macs  # Грузим только если ещё не грузили
    DATE_HEX=$(printf '%x' "$(date +%s)")
    DATE_HEX_SHORT="${DATE_HEX: -6}"     
    
    declare -ga GENERATED_MACS=()
    for oui in "${OUI_LIST[@]}"; do
        oui_clean="${oui//-}"
        mac="${oui_clean}${DATE_HEX_SHORT}"
        formatted_mac="${mac:0:2}:${mac:2:2}:${mac:4:2}:${mac:6:2}:${mac:8:2}:${mac:10:2}"
        GENERATED_MACS+=("$formatted_mac")
    done
    echo "Сгенерировано MAC-ов: ${#GENERATED_MACS[@]}"
}


# Случайный часовой пояс
get_random_timezone() {
    load_timezones  # Грузим только если нужно
    NEW_TZ="${TZ_LIST[RANDOM % ${#TZ_LIST[@]}]}" 
    NEW_TZ="${NEW_TZ#*\"}"                     
    NEW_TZ="${NEW_TZ%\"*}"                     
    [ -z "$NEW_TZ" ] && { echo "Ошибка: часовой пояс не распарсился"; return 1; }
    echo "Выбран пояс: $NEW_TZ"
}


# Случайное разрешение
get_random_resolution() {
    load_resolutions  # Грузим только если нужно
    NEW_RES="${RES_LIST[RANDOM % ${#RES_LIST[@]}]}"
    [ -z "$NEW_RES" ] && { echo "Ошибка: разрешение не выбрано"; return 1; }
    echo "Выбрано: $NEW_RES"
}


MY_INTERFACE="eno0"
TIME_CHANGE=1800


spoof_mac() {
    generate_random_macs
    NEW_MAC="${GENERATED_MACS[RANDOM % ${#GENERATED_MACS[@]}]}"
    echo "Выбран MAC: $NEW_MAC"
    sudo ip link set "$MY_INTERFACE" down
    sudo ip link set "$MY_INTERFACE" address "$NEW_MAC"
    sudo ip link set "$MY_INTERFACE" up
    echo "Новый MAC: $NEW_MAC"
}


spoof_tcp() {
    sudo sysctl -w net.ipv4.ip_default_ttl=128 >/dev/null
    sudo sysctl -w net.ipv4.tcp_sack=1 >/dev/null
    MSS_LIST=("1460" "156")
    NEW_MSS="${MSS_LIST[RANDOM % 2]}"
    sudo sysctl -w net.ipv4.route.min_adv_mss="$NEW_MSS" >/dev/null
    echo "TCP: TTL=128, SACK=1, MSS=$NEW_MSS"
}


spoof_timezone() {
    get_random_timezone
    sudo timedatectl set-timezone "$NEW_TZ" &
    echo "Пояс: $NEW_TZ"
}


spoof_resolution() {
    get_random_resolution
    killall Xvfb 2>/dev/null
    Xvfb :1 -screen 0 "${NEW_RES}x24" &
    echo "Экран: $NEW_RES"
}


spoof_all() {
    spoof_mac 
    spoof_tcp &
    spoof_timezone & 
    spoof_resolution & 
    wait
}


auto_spoof() {
    while true; do
        spoof_all
        echo "Готово, жду $TIME_CHANGE сек..."
        sleep "$TIME_CHANGE"
    done
}


case "$1" in
    "mac") spoof_mac ;;
    "tcp") spoof_tcp ;;
    "timezone") spoof_timezone ;;
    "resolution") spoof_resolution ;;
    "all") spoof_all ;;
    "auto") auto_spoof ;;
    *) echo "Чё делать? $0 {mac|tcp|timezone|resolution|all|auto}" ;;
esac

Давай разберёмся, почему скрипт теперь быстрее работает?
Я добавил ленивое кэширование — mac_list.txt, timezone.txt и resolutions.txt загружаются через mapfile только когда нужны, дальше диск не трогаем, всё крутится в памяти.
При генерации MAC я выкинул два sed из format_mac, тперь скрипт форматирует прямо в Bash, tr я тоже убрал, ведь printf '%x' сам справляется с регистром, а for вместо while read шустрее проходиться по массиву.
При чтение строк теперь скрипт берет случайный элемент из массива напрямую, еще я упростил парсинг часовых поясов до чистого Bash, без grep и tr. Так же в spoof_all теперь скрипт пускает spoof_tcp, spoof_timezone и spoof_resolution в фон с &, а wait ждёт, пока они отработают. Плюс по мелочи вычистил лишние переменные и проверки, где они не нужны, а вывод сжал до пары слов.


Вывод

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

На практике мы прошлись по подмене аппаратных и сетевых отпечатков на Linux. Научились менять MAC-адреса, TTL, часовые пояса, разрешения экрана и даже маскировать баннеры SSH и FTP, чтобы не светить систему. Плюс разобрались, где брать правдоподобные данные — от OUI для MAC до списков разрешений экрана, — чтобы подделка не выглядела подозрительно.

Я показал, как это всё крутится на моей машине без виртуалок — чисто на железе и софте. Но если вам нужна подделка поглубже, лучше брать VM, вроде QEMU/KVM. Правда, тогда придётся ещё и маскировать, что это виртуалка:), потому что такие штуки часто палятся. Думаю в будующем я сделаю статью на эту тему.

Еще мы с вами разобрали автозапуск через cron, systemd, anacron, rc.local и даже ~/.bashrc. Мы оптимизировали код, добавили кэширование и параллелизм, чтобы всё работало шустро и без лишней нагрузки.

Надеюсь, вам было полезно! Ведь это только начало. Во второй части разберём браузеры — это отдельная большая тема. Например, разберемся как замаскировать расширения в Chrome, по которым вас чаще всего вычисляют юзера, и другие штуки вроде User-Agent, Canvas, шрифтов и WebRTC.

Исходники spoof_linux.sh и все остальные необходимые файлы вы сможете найти в архиве xss_assets.zip
 

Вложения

  • xss_assets.zip
    982.2 КБ · Просмотры: 25
Последнее редактирование модератором:
Это конечно все интересно, но на уровне гайдов из интернета с подменой мака. Что это дает? Зададим вопрос позже. При запуске браузера собирается некая информация, в случае файерфокс - это вся инфа про биос и ОЗУ (просмотреть запросы можно с помощью wmimon). И тор браузер также это собирает. Однако, я не проверял, какая информация собирается при установки браузера. Могут ли браузеры ее куда то отправить? Могут или нет уже не столь важно, ведь инфа уже собрана. Нужно воспрепятствовать отправке. Можно установить плагины, да бы заблокировать кросс-запросы на всякие рекламные сайты, можно заблокировать не нужные скрипты, кросс-скрипты. И что-то даже получиться в итоге, однако, в большинстве случаев сайты будут отображаться странным образом. Ведь почти все сайты завязаны на скриптах гугл, яндекс и тд. Рано или поздно это надоест и захотеться нормально посидеть в интернете. И мы такие плагины просто отключим. Для подменить всех идентификаторов не нужно изменять в браузере или системе настройки, к сожалению, мы физически даже все не сможем изменить. Поэтому нужно изменять саму систему, которая генерирует эти самые идентификаторы. Разумеется, при использовании виртуальных машин, гостевая система будет иметь отличимые идентификаторы от реальной системы. И при установке браузера идентификаторы будут иные. Вот только чтобы их изменить снова, нужно установить браузер заново (как будто в первый раз) - делаем с помощью снапшотов. ДА, еще момент, некоторые идентификаторы меняются только при смене ОС (разумеется, не нужно каждый раз ОС устанавливать, достаточно в финальном процессе установки поймать момент и сделать снапшот, и потом к нему возвращаться).
 
Последнее редактирование:
Это конечно все интересно, но на уровне гайдов из интернета с подменой мака. Что это дает? Зададим вопрос позже. При запуске браузера собирается некая информация, в случае файерфокс - это вся инфа про биос и ОЗУ (просмотреть запросы можно с помощью wmimon). И тор браузер также это собирает. Однако, я не проверял, какая информация собирается при установки браузера. Могут ли браузеры ее куда то отправить? Могут или нет уже не столь важно, ведь инфа уже собрана. Нужно воспрепятствовать отправке. Можно установить плагины, да бы заблокировать кросс-запросы на всякие рекламные сайты, можно заблокировать не нужные скрипты, кросс-скрипты. И что-то даже получиться в итоге, однако, в большинстве случаев сайты будут отображаться странным образом. Ведь почти все сайты завязаны на скриптах гугл, яндекс и тд. Рано или поздно это надоест и захотеться нормально посидеть в интернете. И мы такие плагины просто отключим. Для подменить всех идентификаторов не нужно изменять в браузере или системе настройки, к сожалению, мы физически даже все не сможем изменить. Поэтому нужно изменять саму систему, которая генерирует эти самые идентификаторы. Разумеется, при использовании виртуальных машин, гостевая система будет иметь отличимые идентификаторы от реальной системы. И при установке браузера идентификаторы будут иные. Вот только чтобы их изменить снова, нужно установить браузер заново (как будто в первый раз) - делаем с помощью снапшотов. ДА, еще момент, некоторые идентификаторы меняются только при смене ОС (разумеется, не нужно каждый раз ОС устанавливать, достаточно в финальном процессе установки поймать момент и сделать снапшот, и потом к нему возвращаться).
Спасибо за комментарий. Да, в браузерах запрашивается низкоуровневая информация, вроде графического процессора или подобного,хотя mac адрес тоже, часовые пояса, локализации, таймзоны и тд.
Данная статья это как фундамент, на котором потом можно строить более специфичные меры безопасности. К примеру для тех же браузеров, или допустем мессенжеров. Нынешние меры безопасности могут быть полезны допустим локальных сетях где MAC-адрес может попасть в логи роутера или подобное. А так это будет цикл из нескольких статей. Во второй части я расскажу именно про сокрытия информации от браузеров, ибо это отдельная большая тема и на нее лучше выделить отдельную статью.
 
Нынешние меры безопасности могут быть полезны допустим локальных сетях где MAC-адрес может попасть в логи роутера или подобное.

Что вы так зациклились на этом мак адресе? Он дальше локальной сети не распространяется.

Во второй части я расскажу именно про сокрытия информации от браузеров, ибо это отдельная большая тема и на нее лучше выделить отдельную статью.

Чем больше информации вы пытаетесь скрыть, тем больше вы становитесь уникальным. Серфя по интернету мы посещаем больше сайтов чем у нас открыто было во вкладках. Информация остается в базах и другой какой то сайт может узнать ее (кросс-запросы). Поэтому нужно задуматься о разделение трафика на критический и мусорный. Если юзер с одного браузера сидит в вк, играет на бирже, сидит в покере, и вдруг, с перепуга задумал отослать Боссу письмо с левого акк, шантажируя и вымогая деньги. Вот для этих целей и существует разделения трафика. Разумеется, без виртуальных машин нельзя обойтись, так как это фундаментальная основа любой анонимности и безопасности.
 
Что вы так зациклились на этом мак адресе? Он дальше локальной сети не распространяется.
злонамеренный софт типа веб браузера может отправлять его своим хозяевам.
 
злонамеренный софт типа веб браузера может отправлять его своим хозяевам.
Нужно сначала удостовериться, что он его считывает. Также мак не является одним из главным идентификаторов компьютера, так как его можно легко сменить.
 


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