Однажды, перед защитой очередной лабораторной работы мне задали вопрос: какие поля IP-пакета можно использовать для стегано? Я не знал и лишь пожал плечами. Но вскоре я всё же решил изучить этот вопрос.
Под катом вас ждёт изучение заголовков IP-пакетов, собственная утилита ping на Python и несколько способов передать данные, не привлекая внимания.
from scapy.all import *
# Создаём пакет для 10.0.0.2 с icmp-type 8 (echo-request)
pkt = IP(src="10.0.0.1", dst="10.0.0.2") / ICMP(type = 8)
# Отправляем пакет и ждём ответа
sr1(pkt)
from scapy.all import *
# Настраиваем прослушивание пакетов
# filter -- только icmp
# timeout -- слушаем только 10 секунд
# count -- ждём не больше 100 пакетов
# iface -- только на интерфейсе eth1
packets = sniff(filter = "icmp", timeout = 10, count = 100, iface = "eth1")
# Итерируемся по всем полученным пакетам
for pkt in packets:
# Нас интересуют только пришедшие echo-request
if pkt[ICMP].type != 8:
continue
# Просим красиво напечатать
pkt.show()
###[ Ethernet ]###
dst = hh:hh:hh:hh:hh:hh
src = gg:gg:gg:gg:gg:gg
type = 0x800
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 28
id = 24923
flags =
frag = 0
ttl = 64
proto = icmp
chksum = 0x4364
src = 10.0.0.1
dst = 10.0.0.2
\options ###[ ICMP ]###
type = echo-request
code = 0
chksum = 0xf7ff
id = 0x0
seq = 0x0
###[ Padding ]###
load = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
payload = ord("A") * 0x100 + ord("B")
pkt = IP(src="10.0.0.1", dst="10.0.0.2", id = payload) / ICMP(type = 8)
from scapy.all import *
import sys
packets = sniff(filter="icmp", timeout = 10, count = 100, iface="eth0")
for pkt in packets:
if pkt[ICMP].type != 8:
continue
# Разделяем два символа
a, b = divmod(pkt[IP].id, 0x100)
sys.stdout.write(chr(a))
sys.stdout.write(chr(b))
sys.stdout.flush()
4500 003c 000a 0000 8001 [checksum] c0a8 000d c0a8 000d
4500 + 003c + 000a + 0000 + 8001 + [checksum=0000] + c0a8 + 000d + c0a8 + 000e =
= (2) 46b2
46b2 + 2 = 46b4
~(46b4) = b94b
1. 4500 + 003c + 000a + 0000 + 8001 + [checksum=b94b] + c0a8 + 000d + c0a8 + 000e =
= (2) FFFD
2. FFFD + 2 = FFFF
# src - адрес отправителя
# src_nat - адрес отправителя за NAT
# dst - адрес получателя
# dttl - количество узлов на пути в получателю
# a, b -- по одному байту полезной информации
def send_stegano(src, src_nat, dst, dttl, a, b):
# Формируем полезную нагрузку из двух байт
payload = ord(a)*0x100 + ord(b)
# Создаём состояние пакета при прохождении последнего узла маршрута
pkt = IP(dst=dst, src=src_nat, ttl=64-dttl, id = payload) / ICMP(type=8)
# Заставляем Scapy вычислить chksum
pkt = IP(raw(pkt))
# Готовим пакет к отправке
pkt[IP].src = src
pkt[IP].ttl = 64
pkt[IP].id = pkt[IP].chksum
# Стираем поле chksum, чтобы Scapy перерасчитал его
del pkt[IP].chksum
# Scapy вновь вычисляет все контрольные суммы
pkt = IP(raw(pkt))
# Отправляем пакет и ждём ответ
sr1(pkt)
К сожалению, не доступен сервер mySQL