[ a u t h o r ] kay
Copyright 1999 kay <kay@phreedom.org>
Please contact the author and or Phreedom Magazine prior to
publication of any kind.
0. Abstract
Tazi statiq ima za cel da pokave i dwete strani na mrevowite snifferi -
kakwo sa za sistemnite administratori: kak da gi otkriem, kak da gi sprem; i
kakwo za programista. Wkljucheni sa primeri za Linux-specifichni funkcii,
kakto i za PCAP bibliotekata.
Sydyrvanie:
1. Network basics
1.1. Network design, hardware and software
1.2. Devices and interfaces
1.3. Preventing and detecting sniffers
2. Introduction to packet sniffing
2.1. Example of Linux SOCK_PACKET usage
2.2. Libpcap example
2.3. BPF Packet filter programs
2.4. Loadable kernel modules
3. Bibliography and additional files
1. Network basics
Nqkoi hora biha osporili, che snifferite sa neshto dosta iztyrkano: da, taka
e. Sled kato razpolagame s asimetrichno kodirashti algoritmi, se predpolaga,
che tezi problemi sa resheni. Wsyshtnost, wseki den hilqdi accounti,
kreditni karti i druga wavna informaciq "iztichat". Syshto taka sniferite sa
winagi polezen instrument za otkriwane na problemi w mrevowite protokoli,
kakto i za sledene na sigurnostta (IDS, Intrusion Detection Systems).
1.1. Network design, hardware and software
Nqkoi osobenosti na ustrojstwoto i dizajna na lokalnite kompjutyrni mrevi
pozwolqwat da se "podslushwa" komunikaciqta mevdu 2 stancii ot treti
kompjutri, koito sa swyrzani w syshtiq segment. Towa se dylvi na osobenost w
standarta IEEE 802.3 CSMA/CD (Carrier Sense Multiple Access with Collision
Detection) i po-specialno w algorityma za izprashtane, izpolzwan ot NIC's
(Network Interface Cards) za izbqgwane na kolizii. Koliziq nastypwa, kogato
2 stancii se opitat da predadat ednowremenno danni po mrevata. Tyj kato
wsichki izpolzwat edna i syshta chestotna lenta, towa wodi do wremenno
spirane na wsichki komunikacii. Imenno tozi algoritym w adapterite sledi
trafika po mrevata i izchakwa naj-udobniq moment "da se wkljuchi". Nqkoi
po-stari modeli mrevowi ustrojstwa syshto taka "podslushwat" wsichki paketi,
minawashti prez mrevata, za da reagirat na Broadcast syobshteniq.
Towa wse oshte ne e dostatychno za da move da se podsluswat wsichki wryzki:
Operacionnata sistema na wsqka stanciq wzima samo paketite, koito sa
prednaznacheni za neq i propuska ostanalite. Izkljuchenie prawqt Broadcast
paketite, chieto syshtestwuwane e wyzmovno samo w edin segment na lokalnite
mrevi (rqdko i w drugi sluchai) poradi imenno tezi osobenosti. Broadcast se
izprashta kym opredelen adres na mrevata, na kojto reagirat wsichki stancii.
Towa se izpolzwa za opredelqne na DHCP, BOOTP serveri, i drugi podobni
uslugi (Smurf ...).
1.2. Devices and interfaces
W Unix otdelnite fizicheski i logicheski mrevowi ustrojstwa sa predstaweni s
taka narechenite interfejsi. Mogat da se razgledat s komandata 'ifconfig' (w
nowite Linux sistemi i s 'ip'):
$ /sbin/ifconfig -a
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:3924 Metric:1
RX packets:249 errors:0 dropped:0 overruns:0 frame:0
TX packets:249 errors:0 dropped:0 overruns:0 carrier:0
Collisions:0
eth0 Link encap:Ethernet HWaddr 00:AC:3B:71:1D:D0
inet addr:192.168.0.1 Mask:255.255.255.0
MULTICAST PROMISC MTU:1500 Metric:1
RX packets:5357 errors:0 dropped:0 overruns:0 frame:0
TX packets:2397 errors:0 dropped:0 overruns:0 carrier:0
Collisions:0
Interrupt:12 Base address:0x420
ppp0 Link encap:Point-to-Point Protocol
inet addr:192.168.0.100 P-t-P:192.168.1.1 Mask:255.255.255.255
POINTOPOINT NOARP MULTICAST MTU:1500 Metric:1
RX packets:913 errors:1 dropped:0 overruns:0 frame:1
TX packets:920 errors:0 dropped:0 overruns:0 carrier:0
Collisions:0
W sluchaq - Linux sistema s loopback, edin Ethernet i edin PPP interfejs.
Wivda se, che eth0 interfejsyt e w promiscuous mode, t.e. poluchawa wsichki
paketi ot mrevata, dori i tezi, koito ne sa konkretno za dadeniq host.
Po-dolu shte widite kak move da si naprawite sobstwena takawa programa.
1.3. Kak da predotwratim snifferi w lokalnata mreva
Syshtestwuwat harduerni i sofruerni resheniq, koito prawqt po-sigurna cqlata
mreva. Prawilniqt dizajn i izgravdane na mrevowata topologiq sa predpostawka
za izoliranost na otdelnite mrevowi segmenti. Izpolzwaneto na Switch-owe,
kriptirashti Hub-owe i router-i, VPN namalqwat do golqma stepen shansa da se
podslushwat "sigurni" wryzki.
L0pth Heavy Industries obqwi softueren produkt za otkriwane na sniferi w
lokalna mreva (ili izobshto mrevowi adapteri w promiscuous revim) za NT i
Unix, kojto raboti na bazata na pasiwni priznaci i prowokira snifera da se
izdade chrez spoofnati paketi. W BugTraq ima interesna diskusiq po powod
efektiwnosta na AntiSniff, kakto i GPL AntiAntiSniff Sniffer. Velatelno e,
kogato si prowerqwate lokalnata sistema za promiscuous mode interfejsi, da
polzwate otdelna programa, a ne ifconfig, zashtoto tq move da byde
troqnizirana da ne go pokazwa. Wivte lspromisc.c po-nadolu.
Eto edin primer za zle izgradena lokalna mreva:
[Server]
|
[Bridge]--[Hub]---[Border router]------------ - - - Internet
|
|
[Another Hub]
/ | | | | | /
. . . . . . .
Po tozi nachin wsichki stancii shte mogat da podslushwat trafika mevdu
nashiq i sysedniq server, ili pyk e-mail parolata na Joe na drug server w
Internet. Trqbwa da se izpolzwat switch-owe wmesto koncentratori, da se
razdelqt mashinite na grupi i po wyzmovnost da se obosobqt w VLAN mrevi i
t.n. i t.n. Pomnete che naj-sigurnite kompjutri sa izkljuchenite. No neka
ostawim towa za sega, tyj kato tazi statiq ima druga osnowna tema.
2. Introduction to Libpcap
Wsqka operacionna sistema predstawq swoj sobstwen metod za dostyp do
naj-niskoto niwo na mrevata: Berkley Packet Filter pri BSD, Char device pri
Solaris, specialen tip socket pri Linux i t.n. Towa prawi trudno syzdawaneto
na portable programi, koito izpolzwat tezi funkcii i se kompilirat bez
promqna na razlichni tipowe Unix. Bibliotekata PCAP (ot Packet Capture) e
wsyshtnost obsht interfejs kym syotwetnite funkcii ot nisko niwo za nqkoq
operacionna sistema, predostawqjki na programista mnogo dopylnitelni i
polezni wyzmovnosti, kato dump na paketikte wyw fajl, prochitane ot fajl,
BPF filtri i prawila za poluchawane samo na opredeleni paketi, informaciq za
mrevata/hosta. Zatowa, ako poglednete nqkoj arhiw s publichni eksploiti,
shte namerite nqkolko razlichni sniferi, raboteshti samo na opredelena
operacionna sistema.
Nqkolko dumi za izgravdaneto na samiq sniffer. Nemislimo e da se pishe
paketen snifer, bez da se poznawat dostatychno dobre protokolite i paketite,
na koito move da se natyknem. Tyj kato osnownata cel na powecheto sniferi e
podlushwane na TCP wryzki w lokalna mreva, trqbwa da se zapochne ot Ethernet
ramkata, prez IPv4 (ili v6, no za sega towa ne e chak tolkowa neobhodimo) i
samiq TCP hedyr. Tyj kato ne poluchawame dannite kato potok, a razdeleni na
otdelni paketi, trqbwa da si sglobim neshto kato mini-TCP/IP-stek, za da
movem da prosledim otdelnite logicheski TCP sesii (w qdroto tazi rabota se
wyrshi ot TCP multiplexer).
struct ethhdr eth;
struct iphdr ip;
struct tcphdr tcp;
[... data ...]
Razbira se, movem da podlsushwame ICMP, IGMP, UDP i wsichko drugo, koeto
move da se prekara wyrhu IPv4, stiga da movem korektrno da razoznaem
protokola.
#define MAC_LEN 6
struct ethhdr {
u_char dst_addr[MAC_LEN];
u_char src_addr[MAC_LEN];
u_short protocol;
};
struct iphdr {
u_char ver_ihl;
u_char tos;
u_short total_len;
u_short id;
u_short frag_offset;
u_char ttl;
u_char protocol;
u_short checksum;
u_long src_addr;
u_long dst_addr;
};
struct tcphdr {
u_short src_port;
u_short dst_port;
u_long sequence;
u_long acq_seq;
u_short flags;
u_short window;
u_short checksum;
u_short urg_ptr;
};
Towa e priblizitelnata shema na dejswie (algoritym) na snifyra w psewdokod
(mrazq blokowi shemi):
while (we_want_to_sniff) {
packet = read_raw_packet();
if (starts_new_connection(packet) && port_is_interesting(packet))
add_to_stack(connection(packet));
if (packet_is_part_of_tracked_connection(packet)) {
log(packet);
if (we_have_logged_enough(connection(packet)) ||
packet_closes_connection(packet)))
remove_from_stack(connection(packet));
}
}
2.1. Example of Linux SOCK_PACKET usage
Za dostyp do link layer-a na opredelen interfejs Linux predostawq specialen
tip socket - SOCK_PACKET, pri kojto movem da poluchim/izpratim ne prosto
IPv4 + ramka, a da izgradim paketa zapochwajki Ethernet, PPP, SLIP ili
kakywto drug protokol polzwame za wryzka po syotwetniq interfejs (t.e. ot
Link Layer).
Za da poluchim wsichki interesuwashti ni paketi (wkljuchitelno i tezi, koito
ne sa za nas), trqbwa syotwetniqt interfejs da e s wdignat flag promiscuous
(IFF_PROMISC). W Linux towa stawa chrez strukturata ifreq:
struct ifreq
{
#define IFNAMSIZ 16
union
{
char ifrn_name[IFNAMSIZ];
} ifr_ifrn;
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ];
char ifru_newname[IFNAMSIZ];
char * ifru_data;
} ifr_ifru;
};
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_metric ifr_ifru.ifru_ivalue /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define ifr_map ifr_ifru.ifru_map /* device map */
#define ifr_slave ifr_ifru.ifru_slave /* slave device */
#define ifr_data ifr_ifru.ifru_data /* for use by interface */
#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */
#define ifr_newname ifr_ifru.ifru_newname /* New name */
i chrez SIOCGIFFLAGS (Socket I/O Control Get Interface Flags) i SIOCSIFFLAGS
(Socket I/O Control Set Interface Flags) ioctl() izwikwaniq. Edinstweniqt
obsht parametyr za wsichki izwikwaniq e ifr_name, ostanalite se izpolzwat
spored syotwetnata operaciq. Informaciq za konfiguraciqta na wsichki
nalichni interfejsi move da se wzeme chrez SIOCGIFCONF, kato se izpolzwa
strukturata ifconf:
struct ifconf
{
int ifc_len;
union
{
char * ifcu_buf;
struct ifreq *ifcu_req;
} ifc_ifcu;
};
#define ifc_buf ifc_ifcu.ifcu_buf
#define ifc_req ifc_ifcu.ifcu_req
W ifc_len se podawa razmer na bufera ifcu_buf, kojto shte poluchi ifreq
strukturite za wsichki interfejsi. Pri nedostatychno golqm bufer kernela
wryshta informaciq samo kolkoto buferyt move da prieme, bez da dawa greshka.
Stojnostta na ifc_len se promenq na syotwetniq broj. Wsichko towa e
neobhodimo, za da movem da wzemem spisyka s podhodqshti interfejsi za
podslushwane, w sluchaj, che nikoj ot standartnite ne syshtestwuwa, oshte
poweche che ne e zadylvitelno wseki ot tqh da otgowqrq na harduerno
ustrojstwo - kernel modul move da syzdade specialen interfejs za VPN, pri
koeto movem da podslushwame dannite predi oshte da sa kodirani. Za powecheto
interfejsi obache, wkljuchitelno i pri podslushwane prez libpcap, move da
ima dopylnitelni danni kym ramkata na paketa, chesto razlichni za ednakwi
interfejsi w razlichni operacionni sistemi.
Kogato iskame da podslushwame opredelen interfejs se izpolzwa bind()
funkciqta, po syshtiq nachin, kakto i pri normalnite soketi.
struct sockaddr {
unsigned short sa_family;
char sa_data[14];
};
w sa_data se zadawa kato null-terminated string imeto na interfejsa.
-<sockpacket.c>---------------------------------------------------------
/* Copyright (C) 1999 kay@phreedom.org; All rights reserved */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <linux/if.h>
#include "pdump.h"
int
main(int argc, char **argv)
{
struct ifreq ifr; /* Linux interface request control structure */
short ifr_flags_orig; /* Initial flags if interface */
int sockfd; /* Socket descriptor */
u_char sp[2000];
int err;
printf("Example of non-portable packet sniffer for Linux/n");
/* We want only Ethernet frames containing IP data */
sockfd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_IP));
if (sockfd < 0) {
perror("socket");
exit(1);
}
/* Make the interface promiscuous */
strcpy(ifr.ifr_name, INTERFACE);
err = ioctl(sockfd, SIOCGIFFLAGS, &ifr);
if (err < 0) {
perror("SIOCGIFFLAGS");
exit(1);
}
ifr_flags_orig = ifr.ifr_flags;
ifr.ifr_flags |= IFF_PROMISC;
err = ioctl(sockfd, SIOCSIFFLAGS, &ifr);
if (err < 0) {
perror("SIOCSIFFLAGS");
exit(1);
}
/* Read one packet */
err = read(sockfd, &sp, sizeof(sp));
if (err < 0) {
perror("read");
exit(0);
}
/* Dump what we cought */
printf("Dumping %i bytes:/n", err);
dump_eth((struct ethhdr *) &sp);
dump_ip((struct iphdr *) &sp+14L);
dump_hex((void *) &sp, err, 2, 16);
dump_ascii((void *) &sp, err, 16);
printf("/n/n");
/* Restore original interface flags */
ifr.ifr_flags = ifr_flags_orig;
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
perror("SIOCSIFFLAGS");
exit(1);
}
close(sockfd);
return EXIT_SUCCESS;
}
/* eof */
-</sockpacket.c>--------------------------------------------------------
-<getifconf.c>----------------------------------------------------------
/* Copyright 1999 Kay <kay@phreedom.org>. All rights Reserved */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_ether.h>
int main()
{
struct ifconf ifc;
struct ifreq ifr_x[20];
int sockfd, err;
sockfd = socket(PF_PACKET, SOCK_PACKET, 0);
if (sockfd < 0) {
perror("socket");
exit(1);
}
ifc.ifc_len = 20 * sizeof(struct ifreq);
ifc.ifc_req = ifr_x;
err = ioctl(sockfd, SIOCGIFCONF, &ifc);
perror("ioctl");
printf("retrieved info for %i interface(s)/n",
ifc.ifc_len / sizeof(struct ifreq));
for (err = 0; err < ifc.ifc_len / sizeof(struct ifreq); err++)
printf("%s/n", ifr_x[err].ifr_name);
return EXIT_SUCCESS;
}
/* eof */
-</getifconf.c>---------------------------------------------------------
2.2. Libpcap primer
Slednata programa wyrshi absolutno syshtite funkcii kato sockpacket.c, i
wsichko e poweche ot ochewidno kak raboti.
-<libpcap.c>------------------------------------------------------------
/* Portable packet sniffer example - needs libpcap in order to compile
* Copyright (c) 1999 kay@phreedom.org; All rights reserved */
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ether.h>
#include "pdump.h"
int main(int argc, char **argv)
{
pcap_t *pcap; /* PCAP descriptor */
u_char *packet; /* Our newly captured packet */
struct pcap_pkthdr pkthdr; /* PCAP packet information structure */
printf("Example of portable packet sniffer using Libpcap/n");
/* Obtain a descriptor for interface, capture no more than
* 8192 octets, set interface to promiscuous mode, 1000 miliseconds
* read timeout, No buffer for error messages */
pcap = pcap_open_live(INTERFACE, 8192, 1, 1000, NULL);
if (pcap == NULL) {
perror("pcap_open_live");
exit(EXIT_FAILURE);
}
/* Get the next packet from the queue */
packet = (u_char *) pcap_next(pcap, &pkthdr);
if (packet != NULL) {
packet += OFFSET;
/* Dump the packet in various forms */
printf("Dumping %i bytes:/n", pkthdr.caplen);
dump_eth((struct ethhdr *) packet);
dump_ip((struct iphdr *) packet);
dump_hex((void *) packet, pkthdr.caplen, 2, 16);
dump_ascii((void *) packet, pkthdr.caplen, 16);
printf("/n/n");
} else {
pcap_perror(pcap, "pcap_next returned NULL");
}
/* Enough for now ... */
pcap_close(pcap);
return EXIT_SUCCESS;
}
/* eof */
-</libpcap.c>-----------------------------------------------------------
const u_char *pcap_next(pcap_t *, struct pcap_pkthdr *);
Ochewidno osnownata rabota se wyrshi ot funkciqta pcap_next(), koqto wryshta
ukazatel kym sledwashtiq paket ot opashkata. Sled towa dejstwieto na
sniffera e napylno analogichno na predishniq primer. Razbira se, tezi
primeri w nikakyw sluchaj ne sa izpolzwaemi w tozi si wid, no sa edna dobra
osnowa.
2.3. BPF Packet filter programs
Chrez Berkeley Packet Filter move da se zadade programa, koqto da filtrira
whodqshtite paketi po opredeleni priznaci. Takawa programa se systoi ot
masiw BPF instrukcii "izpylnqwani" na wirtualna mashina. Intrukciite dosta
napomnqt asembleren ezik. Towa e izkljuchitelno moshten mehanizym, no
syzdawaneto na tezi programi chesto e prekaleno slovno, za da si struwa da
gi pishem. Sledniq primer ot man-stranicata pokazwa programa, izbirashta
samo IP paketi mevdu 128.3.112.15 i 128.3.112.35:
struct bpf_insn insns[] = {
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K,
ETHERTYPE_IP, 0, 8), BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 26),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x8003700f, 0, 2),
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 30), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K,
0x80037023, 3, 4), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x80037023, 0, 3),
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 30), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K,
0x8003700f, 0, 1), BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
BPF_STMT(BPF_RET+BPF_K, 0),
};
Za towa (kakto i pri normalnite ezici), w LBL e syzdaden ezik ot wisoko
niwo, kojto se "kompilira" do BPF-instrukcii. Pylnata dokumentaciq se namira
w man-stranicata na tcpdump(8). Neka poglednem sledniq primer:
-<pfilter.c>------------------------------------------------------------
/* Packet filter example
* Copyright (c) 1999 kay@phreedom.org; All rights reserved */
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ether.h>
#include "pdump.h"
int main(int argc, char **argv)
{
pcap_t *pcap; /* PCAP descriptor */
u_char *packet; /* Our newly captured packet */
struct pcap_pkthdr pkthdr; /* PCAP packet information structure */
struct bpf_program fp; /* Structure to hold the compiled prog */
char pfprogram[] = "ip host 128.3.112.15 and 128.3.112.35";
printf("Example of portable packet sniffer using Libpcap/n");
/* Obtain a descriptor for interface, capture no more than
* 8192 octets, set interface to promiscuous mode, 1000 miliseconds
* read timeout, No buffer for error messages */
pcap = pcap_open_live(INTERFACE, 8192, 1, 1000, NULL);
if (pcap == NULL) {
perror("pcap_open_live");
exit(EXIT_FAILURE);
}
/* Compile and set the filter program */
if (pcap_compile(pcap, &fp, pfprogram, 1, 0x0) == -1) {
pcap_perror(pcap, "pcap_compile");
exit(EXIT_FAILURE);
}
if (pcap_setfilter(pcap, &fp) == -1) {
pcap_perror(pcap, "pcap_setfilter");
exit(EXIT_FAILURE);
}
/* Get the next packet from the queue */
packet = (u_char *) pcap_next(pcap, &pkthdr);
if (packet) {
/* Dump the packet in various forms */
printf("Dumping %u bytes:/n", pkthdr.caplen);
packet += OFFSET;
dump_eth((struct ethhdr *) packet);
dump_ip((struct iphdr *) packet);
dump_hex((void *) packet, pkthdr.caplen, 2, 16);
dump_ascii((void *) packet, pkthdr.caplen, 16);
printf("/n/n");
} else {
printf("Packet not captured because of filter/n");
}
/* Enough for now ... */
pcap_close(pcap);
return EXIT_SUCCESS;
}
/* eof */
-</pfilter.c>-----------------------------------------------------------
Izrazyt "ip host 128.3.112.15 and 128.3.112.35" se prewevda w BPF programa
ot pcap_compile() i togawa se prikachwa kym PCAP descriptora chrez
pcap_setfilter(). Dosta po-lesno ot predniq primer, nali?
Linux Socket Filter (ili LSF) e Linux-wersiqta na BPF, s nqkoi dopylneniq.
Imenno: toj pozwolqwa na potrebitelski programi da prikachat filtri kym
tehnite soketi i po tozi nachin da filtrirat wryzkite si; syshto taka toj e
po-lesen za polzwane po otnoshenie na "prikachwaneto" si. Samite filtyrni
programi sa napylno identichni.
2.4. Loadable kernel modules
Loadable kernel modules (LKM) sa bili syzdadeni, za da se predostawi
mehanizym za dinamichno dobawqne na nowi funkcii w qdroto na operacionnata
sistema, bez da e nuven reboot ili drug wid prekyswane na normalnata rabota.
LKM, koito rabotqt w ring 0 pri powecheto OS, estestweno imat prawa wyrhu
cqlata pamet i mogat da promenqt wytreshni strukturi na kernel-a kakto i da
se skriqt ot ochite na administratora izpolzwajki razlichni tehniki. Towa e
dosta dobyr nachin za trojanizirane na crack-nati sistemi. Kokretno za Linux
kernel interfejsite i pisaneto na moduli sa mnogo dobre opisani - za obshto
wywedenie poglednete "The Linux Kernel" i "Linux Kernel Hacker's Guide" ot
Linux Documentation Project. Temata za LKM e podrobno opisana wyw Phrack 55.
3. Bibliography and additional files
Man pages: pcap(3), setsockopt(2), bpf(7)
RFC's: 791, 792, 793, 894
IEEE 802 (esp. 802.3)
UTSL: Linux kernel 2.2.12, libpcap 0.4
Libpcap: ftp://ftp.ee.lbl.gov
Linux Documentation Project: http://metalab.unc.edu/LDP
Phrack Magazine: http://www.phrack.com
W primerite za SOCK_PACKET i PCAP sa izpolzwani funkcii ot pdump.c za
pokazwane na HEX/ASCII/IP/Ethernet danni/strukturi na terminal.
Linux-specifichnite primeri za izprobwani na Debian GNU/Linux 2.1 (kernel
2.0.36 glibc 2.0.7), Debian GNU/Linux 2.2 (kernel 2.2.12 glibc 2.1.2).
PCAP-primerite sa izprobwani na Debian GNU/Linux 2.2 + libpcap 0.4 i OpenBSD
2.4 GENERIC, libpcap 0.4.
-<pdump.h>--------------------------------------------------------------
/* Packet dumping routines, Copyright (c) 1999 Kay <kay@PHREEDOM.ORG> */
void dump_eth(struct ethhdr *);
void dump_ip(struct iphdr *);
void dump_hex(void *, u_long, u_long, u_long);
void dump_ascii(void *, u_long, u_long);
-</pdump.h>-------------------------------------------------------------
-<pdump.c>--------------------------------------------------------------
/* Packet dumping routines, Copyright (c) 1999 Kay <kay@PHREEDOM.ORG> */
#include <stdio.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/ether.h>
void dump_eth(struct ethhdr *eth)
{
int cnt;
printf("/th_dest =");
for (cnt = 0; cnt < ETH_ALEN; cnt++)
printf(" %X", eth->h_dest[cnt]);
printf(";/n/th_source =");
for (cnt = 0; cnt < ETH_ALEN; cnt++)
printf(" %X", eth->h_source[cnt]);
printf(";/n/th_proto = %X;/n", eth->h_proto);
fflush(stdout);
}
void dump_ip(struct iphdr *ip)
{
struct protoent *pp;
struct in_addr ia;
printf("/tihl = %X;/n", ip->ihl);
printf("/tversion = %X;/n", ip->version);
printf("/ttos = %X;/n", ip->tos);
printf("/ttot_len = %X;/n", ip->tot_len);
printf("/tid = %X;/n", ip->id);
printf("/tfrag_off = %X;/n", ip->frag_off);
printf("/tttl = %X;/n", ip->ttl);
printf("/tprotocol = %X;", ip->protocol);
pp = getprotobynumber(ip->protocol);
if (pp == NULL) printf("/n"), perror(NULL);
else printf("/t(%s)/n", pp->p_name);
printf("/tcheck = %X;/n", ip->check);
ia.s_addr = ip->saddr;
printf("/tsaddr = %X;/t(%s)/n", ip->saddr, inet_ntoa(ia));
ia.s_addr = ip->daddr;
printf("/tdaddr = %X;/t(%s)/n", ip->daddr, inet_ntoa(ia));
fflush(stdout);
}
/* Its obvious: *data, how many octets, interval of spaces,
interval of '/n'-s */
void dump_hex(void *bare, u_long octets, u_long int_sp, u_long int_nl)
{
u_long s;
u_long spc=0, nlc=0;
char *buf = (char *) bare;
for (s=0; s<octets; s++) {
if ((u_char)buf[s]<0x10) printf("0");
printf("%X", (u_char)buf[s]);
if (++spc==int_sp) printf(" "), spc=0;
if (++nlc==int_nl) printf("/n"), nlc=0;
fflush(stdout);
}
}
int is_printable(char c)
{
if ((c >= '1')&&(c <= '0')) return 1;
if ((c >= 'A')&&(c <= 'Z')) return 1;
if ((c >= 'a')&&(c <= 'z')) return 1;
return 0;
}
void dump_ascii(void *bare, u_long octets, u_long int_nl)
{
u_long s;
u_long nlc=0;
char *buf = (char *) bare;
for(s=0; s<octets; s++) {
printf("%c", is_printable(buf[s])?buf[s]:'.');
if (++nlc==int_nl) printf("/n"), nlc=0;
fflush(stdout);
}
}
/* eof */
-</pdump.c>-------------------------------------------------------------
-<Makefile>-------------------------------------------------------------
# Makefile for examples (c) 1999 kay <kay@phreedom.org>
# Edit to suit your system.
# In case of problems when compiling on Linux 2.0 systems, try
# replacing AF_PACKET with AF_INET.
# Set interface to sniff. Some common offsets:
# Ethernet (eth0, le0) offset 0
# Loopback (lo, lo0, ...) offset 4
# PPP link (ppp0, ppp1, ...) offset 0
DEFS=-DINTERFACE=/"lo/" -DOFFSET=4
CC=cc
RM=rm -f
CFLAGS=-O2 -Wall -pipe $(DEFS)
LIBPCAP=-lpcap
default:
@echo "Type one of:"
@echo " make pcap -- build only PCAP examples"
@echo " make all -- build PCAP and Linux-specific examples"
all: libpcap pfilter sockpacket lspromisc getifconf
pcap: libpcap pfilter
.c.o: $@
$(CC) $(CFLAGS) -c $<
sockpacket: pdump.o sockpacket.o
$(CC) $(CFLAGS) -o sockpacket sockpacket.o pdump.o
pfilter: pdump.o pfilter.o
$(CC) $(CFLAGS) -o pfilter pdump.o pfilter.o $(LIBPCAP)
libpcap: libpcap.o pdump.o
$(CC) $(CFLAGS) -o libpcap libpcap.o pdump.o $(LIBPCAP)
getifconf: getifconf.c
$(CC) $(CFLAGS) -o getifconf getifconf.c
lspromisc: lspromisc.c
$(CC) $(CFLAGS) -o lspromisc lspromisc.c
clean:
$(RM) pdump.o sockpacket.o sockpacket libpcap.o /
libpcap getifconf lspromisc pfilter pfilter.o
-</Makefile>------------------------------------------------------------
-<lspromisc.c>----------------------------------------------------------
/* Copyright 1999 kay@phreedom.org. All rights Reserved */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
int main()
{
struct ifconf ifc;
struct ifreq ifr_x[50];
int sockfd, err, i;
sockfd = socket(PF_PACKET, SOCK_PACKET, 0);
if (sockfd < 0) {
perror("socket");
exit(1);
}
ifc.ifc_len = 50 * sizeof(struct ifreq);
ifc.ifc_req = ifr_x;
err = ioctl(sockfd, SIOCGIFCONF, &ifc);
if (err == -1) return EXIT_FAILURE;
for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++) {
err = ioctl(sockfd, SIOCGIFFLAGS, &ifr_x[i]);
if (err == -1) perror("SIOCGIFFLAGS: ");
else if(ifr_x[i].ifr_flags & IFF_PROMISC)
printf("Interface %s is promiscuous/n",
ifr_x[i].ifr_name);
}
return EXIT_SUCCESS;
}
/* eof */
-</lspromisc.c>---------------------------------------------------------
>> EOA <<