Возможно вы искали: 'Нэнси Дрю. Призрак Вен...'

May 15 2025 19:12:32
  • Как сделать 8Gamers.Ru домашней страницей?
  • Игры
    • База данных по играх
    • Игровые новости
    • Игровая индустрия
    • Обзоры на игры
    • Прохождения игр
    • Гайды к играм
    • Превью о играх
    • Игровые тизеры
    • Игровые арты
    • Игровые обои
    • Игровые скриншоты
    • Игровые обложки
    • Игровые трейлеры
    • Игровое видео
    • Вышедшие игры
    • Ближайшие релизы игр
  • Кино и ТВ
    • База данных по кино
    • Статьи о кино
    • Постеры
    • Кадры из кино
    • Кино трейлеры
    • Сегодня в кино
    • Скоро в кино
  • Комиксы и манга
    • Манга по алфавиту
    • База данных по комиксах
    • Читать онлайн комиксы
    • Читать онлайн манга
    • База персонажей
  • Читы и коды
    • Чит-коды для PC игр
    • Чит-коды для консольных игр
    • Трейнеры
    • Коды Game Genie
  • Моддинг
    • Модификации
    • Карты к играм
    • Программы для моддинга
    • Статьи о моддинге
  • Геймдев
    • Всё о создании игр
    • Список движков
    • Утилиты в помощь игроделу
    • Конструкторы игр
    • Игровые движки
    • Библиотеки разработки
    • 3D-модели
    • Спрайты и тайлы
    • Музыка и звуки
    • Текстуры и фоны
  • Рецензии
    • Игры
    • Кино
    • Аниме
    • Комиксы
    • Мангу
    • Саундтреки
  • Саундтреки
    • Лирика
  • Файлы
    • Патчи к играм
    • Русификаторы к играм
    • Сохранения к играм
    • Субтитры к кино
  • Медиа
    • Видео
    • Фото
    • Аудио
    • Фан-арты
    • Косплей
    • Фото с виставок
    • Девушки из игр
    • Рисунки
    • Рисуем онлайн
    • Фотохостинг
  • Юмор
    • Анекдоты
    • Афоризмы
    • Истории
    • Стишки и эпиграммы
    • Тосты
    • Цитаты
  • Флеш
    • Азартные
    • Аркады
    • Бродилки
    • Гонки
    • Для девочек
    • Для мальчиков
    • Драки
    • Квесты
    • Леталки
    • Логические
    • Мультфильмы
    • Открытки
    • Приколы
    • Разное
    • Спорт
    • Стратегии
    • Стрелялки
Статистика

Статей: 87772
Просмотров: 96111483
Игры
Injustice:  Gods Among Us
Injustice: Gods Among Us
...
Dark Souls 2
Dark Souls 2
Dark Souls II - вторая часть самой хардкорной ролевой игры 2011-2012 года, с новым героем, сюжето...
Battlefield 4
Battlefield 4
Battlefield 4 - продолжение венценосного мультиплеер-ориентированного шутера от первого ли...
Кино
Steins;Gate
Steins;Gate
Любители японской анимации уже давно поняли ,что аниме сериалы могут дать порой гораздо больше пи...
Ку! Кин-дза-дза
Ку! Кин-дза-дза
Начинающий диджей Толик и всемирно известный виолончелист Владимир Чижов встречают на шумной моск...
Обзоры на игры
• Обзор Ibara [PCB/PS2] 18357
• Обзор The Walking ... 18801
• Обзор DMC: Devil M... 19879
• Обзор на игру Valk... 15877
• Обзор на игру Stars! 17764
• Обзор на Far Cry 3 17948
• Обзор на Resident ... 16024
• Обзор на Chivalry:... 17508
• Обзор на игру Kerb... 17981
• Обзор игры 007: Fr... 16619
Превью о играх
• Превью к игре Comp... 17960
• Превью о игре Mage... 14464
• Превью Incredible ... 14721
• Превью Firefall 13479
• Превью Dead Space 3 16334
• Превью о игре SimC... 14730
• Превью к игре Fuse 15442
• Превью Red Orche... 15542
• Превью Gothic 3 16343
• Превью Black & W... 17354
Главная » Статьи » Разное » Основы программирования Netfilter на ассемблере. (linux assembler kernel iptables network)

Основы программирования Netfilter на ассемблере. (linux assembler kernel iptables network)

Ключевые слова: linux, assembler, kernel, iptables, network, (найти похожие документы)

From: intuit <intuit[at]rootshell.be>
Date: Mon, 7 Apr 2004 14:31:37 +0000 (UTC)
Subject: Основы программирования Netfilter на ассемблере.

Оригинал: http://rootshell.be/~intuit/nf.txt

author: intuit
mail: intuit[at]rootshell.be




Основы программирования Netfilter на ассемблере.




Многие слышали фразу:
"ОС Linux создана программистами
для программистов"

На самом деле она звучит иначе:
"ОС Linux создана Си-программистами
для Си-программистов....."






[1. ][Вступление]
[2. ][О чем статья]
[3. ][Теория]
[4. ][Примеры LKM]
[5. ][Заключение]






[1. ][Вступление]

Netfilter - подсистема ядра linux 2.4(экспериментальная поддержка была включена
начиная с версий 2.3). Netfilter позволяет осуществлять пакетную фильтрацию, NAT
и существенно расширить возможности работы с сетью за счёт установки специальных
"hook'ов" в часть ядра ОС, ответственной за network. Их можно устанавливать в
ядро одним из двух способов: статически(требуется перекомпиляция ядра) или в виде
LKM, регистрируя тем самым разнообразные функции, которые будут вызываться при
определенных условиях. Например, при получении определенного сетевого пакета.



[2. ][О чем статья]

Статья о работе с Netfilter, подсистемой ядра, расширяющей возможности ОС в ра-
боте с сетевыми фреймами. Язык программирования - ассемблер. Синтаксис GAS.
В статье описано создание простейших модулей(LKM) для демонстрации возможностей
данной подсистемы. Желательно иметь под рукой заголовочные файлы с рассматрива-
емыми в статье структурами. Ну, и разумеется для загрузки(тестирования) модулей
вам необходимы привилегии root ;).



[3. ][Теория]

Ядро подсистемы Netfilter состоит из 5-ти hook-функций, обьявленных в
linux/netfilter_ipv4.h. Видно, что эти функциии для IPv4, хотя больших отличий
от их аналогов для IPv6 нет. С помощью них можно контроллировать пакеты на раз-
личных уровнях сетевого стека.
Ниже приведена схема анализа сетевого пакета системой Netfilter:


[INPUT]--->[1]--->[ROUTE]--->[3]--->[4]--->[OUTPUT]
| ^
| |
| [ROUTE]
v |
[2] [5]
| ^
| |
v |
[INPUT*] [OUTPUT*]

Таблица функций Netfilter с их кодами в правой части
(используются в struct nf_hook_ops, см. ниже)

[1] - NF_IP_PRE_ROUTING = 0
[2] - NF_IP_LOCAL_IN = 1
[3] - NF_IP_FORWARD = 2
[4] - NF_IP_POST_ROUTING = 3
[5] - NF_IP_LOCAL_OUT = 4
[*] - Network Stack

NF_IP_PRE_ROUTING - первый хук, используемый ядром при получении пакета.
NF_IP_LOCAL_IN - используется в тех случаях, когда поступивший пакет предназна-
чен нашей машине и далее такой пакет "форвардится" не будет.
NF_IP_FORWARD - для пакетов, предназначенных для другого интерфейса.
NF_IP_POST_ROUTING - для пакетов, которые уже настроены для дальнейшего "путе-
шествия" по сети к своему адресату и готовы покинуть наш сетевой стек.
NF_IP_LOCAL_OUT - этой функцией обрабатываются пакеты, исходяшие непосредствен-
но от нас(из нашего собственного сетевого стека).

Несомненно все хук-функции важны, но мы пока сосредоточимся только на первой из
них. После обработки(проверки) пакета функция NF_IP_PRE_ROUTING должна возвра-
тить одно из предопределенных значений(код), чтобы решить дальнейший "маршрут"
пакета:

0 = "NF_DROP" Отбросить пакет.
1 = "NF_ACCEPT" Сохранить пакет.(Отправить пакет след. хук-ф-ии.)
2 = "NF_STOLEN" "Забыть" о пакете.
3 = "NF_QUEUE" Поставить пакет в очередь.
4 = "NF_REPEAT" Вызвать этот хук еще раз.


Установить новый хук в системе очень просто. Во-первых, нужно заполнить струк-
туру nf_hook_ops, определенную в linux/netfilter.h.
На Си структура nf_hook_ops выглядит так:



struct nf_hook_ops {

struct list_head list; //Заполнение данной структуры не является
//обязательным для регистрации хука в системе.

/* Поля которые идут далее заполнять обязательно */

nf_hookfn *hook; //Указатель на нашу главную подпрограмму, которая
//будет вызываться всякий раз при срабатывании нашего
//хука.

int pf; //Семейство протоколов с которым будет работать наш хук,
//обычно PF_INET(см. таблицу ниже и bits/socket.h).

int hooknum; //Одна из 5-ти функций, на которой будет висеть наш хук.
//У нас - NF_IP_PRE_ROUTING(код из таблицы).

int priority; //Приоритет. Подробнее см. linux/netfilter_ipv4.h
// У нас - NF_IP_PRI_FIRST = INT_MIN
//INT_MIN - константа, равная (-(2^32)/2)
};



Таблица кодов семейств протоколов:

PF_UNSPEC = 0
PF_LOCAL = 1
PF_INET = 2
PF_AX25 = 3
PF_IPX = 4
<...>

На ассемблере заполнение данной структуры выглядит следующим образом:
(более подробно см. source ниже)

<...>
.comm nf_my_ops,24
<...>
movl $our_hook, nf_my_ops+8
movl $2, nf_my_ops+12
movl $0, nf_my_ops+16
movl $int_minimum, nf_my_ops+20
<...>

Второе, что нужно сделать - необходимо зарегистрировать свой hook в сис-
теме. Это делается с помощью системной функции nf_register_hook(). Данная
функция при успешном завершении возвращает 0. В качестве параметра ей пе-
редается - указатель на struct nf_hook_ops(см. net/core/netfilter.c):

<...>
pushl $nf_my_ops
call nf_register_hook
<...>

Теперь, разберем подробнее прототип функции nf_hookfn, указатель на кото-
рую передаем в struct nf_hook_ops через nf_hookfn *hook.
На Си он выглядит так:

typedef unsigned int nf_hookfn(unsigned int hooknum,
struct sk_buff **skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *));

Первый аргумент - название(код) одной из пяти типов хук-функций Netfilter.
Например, NF_IP_PRE_ROUTING = 0.
Второй - указатель на указатель на структуру sk_buff(управляющая структура
для описания сетевого пакета, см. linux/skbuff.h).
net_device *in и net_device *out - указатели на структуру net_device(каж-
дое сетевое устройство в ОС Linux описывается этой структурой, например,
используется для описания интерфейсов lo, eth0). Соответственно, in - для
входящего траффика(пакетов), out - для исходящего.
Последний аргумент - указатель функции, также принимающей в качестве аргу-
мента sk_buff struct и возвращающей целое число(см. net/core/netfilter.c).

Работа со структурами, передаваемыми этими аргументами, из нашей функции
our_hook на ассемблере происходит следующим образом:

Пример 1. Проверка имени интерфейса net_device *in:
---------
<...>
interface: .string "lo"
<...>

our_hook:
pushl %ebp
movl %esp, %ebp <---*
subl $16, %esp <---резервируем место в стеке под локальные
переменные
pushl interface
pushl 16(%ebp) <---указатель на struct net_device *in,
в частности на поле char name[IFNAMSIZ]
call strcmp
<...>

На момент исполнения инструкции по адресу (*) программный стек будет выгля-
деть таким образом:



| [...верхние адреса памяти...]
| [...........................] _
| [ *okfn ] - 24(%ebp)
| [ *out ] - 20(%ebp) |
рост [ *in ] - 16(%ebp) >---параметры our_hook
стека [ **skb ] - 12(%ebp) | на стеке
| [ hooknum ] - 8(%ebp)_/
| [ EIP ] - 4(%ebp)
| [ EBP ] - 0(%ebp)
| [ <next 4 bytes> ] <--- ESP point here
| [...........................]
V [....нижние адреса памяти...]



Приведу небольшую часть структуры net_device:

struct net_device {

/*
* This is the first field of the "visible" part of this structure
* (i.e. as seen by users in the "Space.c" file). It is the name
* the interface.
*/
char name[IFNAMSIZ]; - offset 0

/*
* I/O specific fields
* FIXME: Merge these and struct ifmap into one
*/
unsigned long rmem_end; /* shmem "recv" end */ - offset 16
unsigned long rmem_start; /* shmem "recv" start */ - offset 20
unsigned long mem_end; /* shared mem end */ - offset 24
unsigned long mem_start; /* shared mem start */ - offset 28
unsigned long base_addr; /* device I/O address */ - offset 32
unsigned int irq; /* device IRQ number */ - offset 36
...
}

Как видно начало структуры, как раз содержит имя интерфейса..


Пример 2. Проверка IP адреса отправителя:
---------

Для начала приведу кусок struct sk_buff:


struct sk_buff {

/* These two members must be first. */
/* Next buffer in list */
struct sk_buff * next; - offset 0

/* Previous buffer in list */
struct sk_buff * prev; - offset 4

/* List we are on */
struct sk_buff_head * list; - offset 8

/* Socket we are owned by */
struct sock *sk; - offset 12

/* Time we arrived */
struct timeval stamp; - offset 16

/* Device we arrived on/are leaving by */
struct net_device *dev; - offset 24

/* Transport layer header */
union
{
struct tcphdr *th; - offset 28
struct udphdr *uh; - offset 28
struct icmphdr *icmph; - offset 28
struct igmphdr *igmph; - offset 28
struct iphdr *ipiph; - offset 28
struct spxhdr *spxh; - offset 28
unsigned char *raw; - offset 28
} h;

/* Network layer header */
union
{
struct iphdr *iph; - offset 32
struct ipv6hdr *ipv6h; - offset 32
struct arphdr *arph; - offset 32
struct ipxhdr *ipxh; - offset 32
unsigned char *raw; - offset 32
} nh;
....
}

Видно, что для работы с заголовком IP-пакета(IPv4) используется поле по
смещению 32 bytes от начала структуры sk_buff, содержащее *iph(указатель
на заголовок IP-пакета). Сл-но, для определения IP-адреса отправителя мы
должны работать со структурой на которую указывает данное поле..

Теперь посмотрим на саму структуру базового IP-пакета:

|<-------- 8 бит -------->|<-------- 8 бит -------->|
|-------------------------------------------------------------|
0| Версия | Длина | Тип обслуживания |
|-------------------------------------------------------------|
2| Длина пакета |
|-------------------------------------------------------------|
4| Идентификатор |
|-------------------------------------------------------------|
6| 0 | DF | MF | Смещение фрагмента |
|-------------------------------------------------------------|
8| Число переходов | Протокол |
|-------------------------------------------------------------|
10| Контрольная сумма заголовка |
|-------------------------------------------------------------|
12| IP-адрес отправителя |
|-------------------------------------------------------------|
16| IP-адрес получателя |
|-------------------------------------------------------------|
20~ Параметры (до 40 байт) ~
|-------------------------------------------------------------|
20-60~ Данные (до 65535 байт минус заголовок) ~
|-------------------------------------------------------------|

IP адрес отправителя находится по смещению 12 bytes, от начала IP-пакета.

Непосредственное определение структуры IP-пакета на Си:

#typedef unsigned int uint;
#typedef unsigned char uchar;

struct ip_packet {

uint version:4; /* 4-bit version */
uint header_len:4; /* header length in words in 32bit words */
uint serve_type:8; /* how to service packet */
uint packet_len:16; /* total size of packet in bytes */
uint ID:16; /* fragment ID */
uint __reserved:1; /* always zero */
uint dont_frag:1; /* flag to permit fragmentation */
uint more_frags:1; /* flag for "more frags to follow" */
uint frag_offset:13; /* to help reassembly */
uint time_to_live:8; /* maximum router hop count */
uint protocol:8; /* ICMP, UDP, TCP */
uint hdr_chksum:16; /* ones-comp. checksum of header */
uchar IPv4_source; /* IP address of originator */
uchar IPv4_dest; /* IP address of destination */
uchar options[]; /* up to 40 bytes */
uchar data[]; /* message data up to 64KB */
};

На ассемблере определение IP-адреса отправителя будет выглядеть так:


.comm sock_buff,4

/* blocked ip = 127.0.0.1 */
ip_address: .string "x7fx00x00x01"
<...>

our_hook:
pushl %ebp
movl %esp, %ebp <--- (см. схему строения стека)
<...>

/* Проверка структуры sk_buff */
movl 12(%ebp), %eax <--- вытащим адрес
movl (%eax), %eax <--- структуры sk_buff..
movl %eax, sock_buff <--- в переменную sock_buff
cmpl $0, sock_buff
jne .ip_head
movl $1, %eax
jmp .quit

/* Проверка валидности IP пакета */
.ip_head:
movl sock_buff, %eax
cmpl $0, 32(%eax)
jne .check_saddr
movl $1, %eax
jmp .quit

/* Проверка IP-адреса отправителя */
.check_saddr:
movl sock_buff, %eax
movl 32(%eax), %eax <--- вытащим указатель на IP-header из sk_buff..
movl 12(%eax), %eax <--- и source IP из IP-header
movl ip_address, %edx
cmpl (%edx), %eax
jne .accept_packet
movl $0, %eax <--- drop packet, if source == blocked ip
jmp .quit
<...>

Также можно фильтровать пакеты по порту получателя.. здесь я этого не рассма-
триваю, пусть это будет вашим д/з :)
Надеюсь, что работу со струтурами на ассемблере обьяснил более-менее понятно,
если будут вопросы стучите в асю or use mail, а лучше смотрите нужные заголо-
вочные файлы и ковыряйте сами ;)



[4. ][Примеры LKM]


Модуль, блокирующий все входящие пакеты:

/* ---drop_all_incoming_packets.s--- */

/* резервируем поименованную область nf_my_ops в секции bss */
.comm nf_my_ops,24
.globl init_module
.globl cleanup_module

.section .modinfo
__module_kernel_version: .string "kernel_version=2.4.18-6mdk"

.data
.align 32
int_minimum: .int -2147483648

.text
.align 32

init_module:
pushl %ebp
movl %esp, %ebp
subl $20, %esp

/* Заполняем структуру nf_my_ops = nf_hook_ops
* nf_my_ops+0: struct list_head list - не заполняем
* Заносим адрес нашей главной процедуры our_hook в поле nf_hookfn *hook
*/
movl $our_hook, nf_my_ops+8

/* PF_INET = 2 */
movl $2, nf_my_ops+12

/* NF_IP_PRE_ROUTING = 0 */
movl $0, nf_my_ops+16

/* NF_IP_PRI_FIRST = INT_MIN */
movl $int_minimum, nf_my_ops+20

/* адрес структуры -> в стек */
pushl $nf_my_ops

/* вызываем nf_register_hook */
call nf_register_hook

/* в eax -> 0 - код успешной загрузки модуля */
movl $0, %eax
movl %ebp, %esp
popl %ebp
ret

cleanup_module:
pushl %ebp
movl %esp, %ebp
subl $20, %esp
pushl $nf_my_ops
call nf_unregister_hook
movl %ebp, %esp
popl %ebp
ret

our_hook:
pushl %ebp
movl %esp, %ebp

/* Возвращаемое функцией значение 0 = "NF_DROP" */
movl $0, %eax
popl %ebp
ret

/* ---EOF--- */


Модуль, блокирующий все входящие пакеты с определенного IP адреса:

/* ---drop_all_incoming_packets_from_spec_saddr.s--- */

/* for BSS section */
.comm nf_my_ops,24
.comm sock_buff,4

.globl our_hook
.globl init_module
.globl cleanup_module

.section .modinfo
__module_kernel_version: .string "kernel_version=2.4.18-6mdk"

.section .rodata
.align 32

/* blocked ip = 192.168.16.21 */
.IP: .string "xC0xA8x10x15"

.data
.align 32

ip_address: .long .IP
int_minimum: .int -2147483648

.text
.align 32

our_hook:
pushl %ebp
movl %esp, %ebp

.check_sk_buff:
movl 12(%ebp), %eax
movl (%eax), %eax
movl %eax, sock_buff
cmpl $0, sock_buff
jne .ip_head
movl $1, %eax
jmp .quit

.ip_head:
movl sock_buff, %eax
cmpl $0, 32(%eax)
jne .check_saddr
movl $1, %eax
jmp .quit

.check_saddr:
movl sock_buff, %eax
movl 32(%eax), %eax
movl 12(%eax), %eax
movl ip_address, %edx
cmpl (%edx), %eax
jne .accept_packet
movl $0, %eax
jmp .quit

.accept_packet:
movl $1, %eax
.quit:
popl %ebp
ret

init_module:
pushl %ebp
movl %esp, %ebp
subl $20, %esp
movl $our_hook, nf_my_ops+8
movl $2, nf_my_ops+12
movl $0, nf_my_ops+16
movl $int_minimum, nf_my_ops+20
pushl $nf_my_ops
call nf_register_hook
movl $0, %eax
movl %ebp, %esp
popl %ebp
ret

cleanup_module:
pushl %ebp
movl %esp, %ebp
subl $20, %esp
pushl $nf_my_ops
call nf_unregister_hook
movl %ebp, %esp
popl %ebp
ret


/* ---EOF--- */



[5. ][Заключение]

С помощью широких возможностей предоставляемых подсистемой Netfilter можно без
особых усилий написать свой собственный фаерволл под требуемые задачи.
to be continued...

---$---

Greetz to all ppl on #m00@EFNet.

---$---
682 Прочтений •  [Основы программирования Netfilter на ассемблере. (linux assembler kernel iptables network)] [08.05.2012] [Комментариев: 0]
Добавил: Ukraine Vova
Ссылки
HTML: 
[BB Url]: 
Похожие статьи
Название Добавил Добавлено
• Основы программирования Netfilter н... Ukraine Vova 08.05.2012
Ни одного комментария? Будешь первым :).
Пожалуйста, авторизуйтесь для добавления комментария.

Проект входит в сеть сайтов «8Gamers Network»

Все права сохранены. 8Gamers.NET © 2011 - 2025

Статьи
Рецензия на Pressure
Рецензия на Pressure
Чтобы обратить на себя внимание, начинающие маленькие разработчики, как правило, уходят в жанры, ...
Рецензия на Lost Chronicles of Zerzura
Рецензия на Lost Chron...
Игры, сделанные без любви и старания, похожи на воздушный шар – оболочка есть, а внутри пусто. Lo...
Рецензия на The Bridge
Рецензия на The Bridge
«Верх» и «низ» в The Bridge — понятия относительные. Прогуливаясь под аркой, можно запросто перей...
Рецензия на SimCity
Рецензия на SimCity
Когда месяц назад состоялся релиз SimCity, по Сети прокатилось цунами народного гнева – глупые ош...
Рецензия на Strategy & Tactics: World War 2
Рецензия на Strategy &...
Название Strategy & Tactics: World War II вряд ли кому-то знакомо. Зато одного взгляда на ее скри...
Рецензия на игру Scribblenauts Unlimited
Рецензия на игру Scrib...
По сложившейся традиции в информационной карточке игры мы приводим в пример несколько похожих игр...
Рецензия на игру Walking Dead: Survival Instinct, The
Рецензия на игру Walki...
Зомби и продукция-по-лицензии — которые и сами по себе не лучшие представители игровой биосферы —...
Обратная связь | RSS | Донейт | Статистика | Команда | Техническая поддержка