网络安全 – 若水斋 https://blog.werner.wiki Try harder Sat, 10 Nov 2018 11:13:17 +0000 zh-Hans hourly 1 https://wordpress.org/?v=6.8.3 https://blog.werner.wiki/wp-content/uploads/2018/11/cropped-ql1-1-32x32.jpg 网络安全 – 若水斋 https://blog.werner.wiki 32 32 使用dns2tcp搭建DNS隧道 https://blog.werner.wiki/building-a-dns-tunnel-with-dns2tcp/ https://blog.werner.wiki/building-a-dns-tunnel-with-dns2tcp/#comments Sun, 05 Aug 2018 11:10:20 +0000 http://blog.werner.wiki/?p=423 0x00 问题场景

假设有如下图所示的问题场景。

问题场景

办公电脑通过防火墙与互联网相连,防火墙被配置为仅允许DNS数据通过。在此场景下,办公电脑显然无法直接访问互联网。现在我们想做的是通过使用dns2tcp建立DNS隧道,使得办公电脑可以访问互联网。

许多大学的校园网在连接后,打开浏览器会自动跳转到身份认证页面。在认证前,是无法访问互联网的,但一般来说,其DNS解析是可用的。这便是上述问题场景中的一个实例。另一个实例是有些公司的网络出口处有防火墙阻止了普通员工的办公电脑访问互联网的,但有时防火墙的配置会允许DNS数据通过。

0x01 预备知识

我们假设读者对DNS有最基本的了解,若不了解可先阅读《百度百科:DNS》。这里要介绍的是NS记录。以下内容摘自《阿里云-用户指南-记录类型》。

NS 记录

(1)什么情况下会用到NS记录?

如果需要把子域名交给其他DNS服务商解析,就需要添加NS记录。

(2)NS记录的添加方式

记录类型为NS。

主机记录处填子域名(比如需要将opo.abc.com的解析授权给其他DNS服务器,只需要在主机记录处填写opo即可,NS记录的主机记录(RR值)不能为空,主机记录@不能作为NS记录使用,且NS记录不支持泛解析【将所有子域名解析到同一地址】,授权出去的子域名不会影响其他子域名的正常解析)。

线路类型(默认为必填项,否则会导致部分用户无法解析)。

NS记录值,NS向下授权,请填写DNS域名记录值为要授权的DNS服务器域名,为了保证服务可靠性,建议您添加至少2组DNS服务(例如:ns1.alidns.com, ns2.alidns.com)。

TTL不需要填写,添加时系统会自动生成,默认为600秒(TTL为缓存时间,数值越小,修改记录各地生效时间越快)。

NS记录不是在设置某个域名的DNS服务器,而是在设置某个子域名的DNS服务器。理解这一点对于成功搭建DNS隧道至关重要。

例如我有域名“werner.wiki”,添加NS记录类型的解析,主机记录值为“test”,记录值为“dns.my.com”。则此记录生效后,所有关于“test.werner.wiki”及其子域名的DNS查询,都会找DNS服务器“dns.my.com”。

0x02 原材料

为了成功搭建DNS隧道,我们需要一台位于互联网中的(而不是在防火墙里的)服务器,我们将要搭建的隧道的一头是办公电脑,另一头便是这台服务器。在实践中,我们常常会买一台云服务器或vps来搭建DNS隧道。由于DNS的敏感性,这台服务器最好是在中国大陆。为了进行演示,我买了一台腾讯云的云服务器(刚好有快要过期的代金券~)。

我们还需要一个可以设置解析的域名。这个域名是什么无所谓,只要能设置解析就行。所以可以买一个很便宜的域名,第一年的价格在几块钱。在这篇文章中,我直接使用了自己博客的域名werner.wiki。实际上,域名是非必须的,后文中会解释这一点。

0x03 开始搭建

1 设置域名解析

首先添加一条A类解析,主机记录为“dns”,记录值为“118.xx.xx.120”,这个IP地址就是腾讯云服务器的公网IP地址。

然后添加一条NS解析,主机记录为“dns2tcp”,记录值为“dns.werner.wiki”。

这两条域名解析如下图所示。

域名解析设置

这两条域名解析做了什么?

第一条A类解析是在告诉域名系统,“dns.werner.wiki”的IP地址是“118.xx.xx.120”。

第二条NS解析是在告诉域名系统,想要知道“dns2tcp.werner.wiki”的IP地址,就去问“dns.werner.wiki”。

如何验证域名解析设置是否成功?

在随便一台电脑上ping域名“dns.werner.wiki”,若能ping通,且显示的IP地址是“118.xx.xx.120”,说明第一条A类解析设置成功并已生效。

在腾讯云服务器(118.xx.xx.120)上抓包,抓目的端口是53的udp包,命令是:

tcpdump -n -i eth0 udp dst port 53

53端口是DNS协议使用的端口。注意上述命令中的参数“eth0”,含义是网卡接口名,在不同的服务器中可能不同。

然后在随便一台电脑上运行命令:

nslookup dns2tcp.werner.wiki

这条命令是在对域名“dns2tcp.werner.wiki”进行查询。如前所述,若我们设置的域名解析生效,则对此域名的DNS查询,会最终被转发到“dns.werner.wiki”,而“dns.werner.wiki”的IP地址是“118.xx.xx.120”,也就是我们的腾讯云服务器上的的公网IP地址。

查看腾讯云服务器上的抓包情况,若抓到对域名“dns2tcp.werner.wiki”进行查询的DNS请求数据包,则说明第二条NS解析设置成功并已生效。

抓到的数据包如下图所示。图中的目的IP地址是腾讯云服务器的内网IP地址,所以我没有打码。

抓到的DNS查询数据包

2 服务器端软件配置

我买云服务器时选择了Ubuntu16.04系统。以下操作均只针对此系统。其他操作系统原理相同,细节可能有所出入。

安装配置dns2tcp

在腾讯云服务器上,我们首先需要安装dns2tcp,命令如下:

sudo apt-get install dns2tcp

我安装的版本是v0.5.2。安装完成后打开配置文件“/etc/dns2tcpd.conf”,将其中内容修改为:

listen = 0.0.0.0
port = 53
user = nobody
chroot = /tmp
domain = dns2tcp.werner.wiki
resources = socks:118.xx.xx.120:7777

在修改配置文件前可以先备份原有配置文件。关于此配置,需要说明的第一点是监听IP地址应该为“0.0.0.0”,而不是“127.0.0.1”,否则就只能监听到本地连接;第二点是域名(domain)是NS解析对应的域名;第三点是dns2tcp中的资源(resources)不是dns2tcp自带的,需要自己动手实现。在我给出的配置文件中只写了一个名为“socks”的资源,其IP地址是云服务器公网IP,端口号是我随手敲的。这个资源是一个socks代理,我想要实现的是办公电脑通过DNS隧道后直接连接到一个socks代理上,使用此代理访问互联网。

安装配置dante-server

现在让我们来搭建一个socks代理。我选择使用dante-server来搭建。首先安装它,命令如下:

apt-get install dante-server

我安装的版本是v1.4.1。安装完成后打开配置文件“/etc/danted.conf”,将其中内容修改为:

logoutput: /var/log/sockd.log
internal: eth0 port = 7777
external: eth0
socksmethod: username none
user.privileged: proxy
user.unprivileged: nobody
client pass {
    from: 0.0.0.0/0 port 1-65535 to: 0.0.0.0/0
}
socks pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
    protocol: tcp udp
}

在修改配置文件前可以先备份原有配置文件。原有配置文件对各配置项的含义与作用有充分的说明,此处不再赘述。我们现在看到的配置文件配置了一个监听端口7777的socks代理,无身份认证,允许任何客户端连接。

3 客户端软件配置

办公电脑便是这里所说的客户端。若办公电脑是Ubuntu系统,直接运行如下命令即可获得dns2tcp的客户端程序dns2tcpc:

    sudo apt-get install dns2tcp

若办公电脑是Windows系统,可以点此下载dns2tcp客户端程序dns2tcpc的Windows版。

0x04 搭建隧道

现在终于可以搭建隧道了。

首先在服务器上运行如下命令来启动socks代理:

/etc/init.d/danted start

然后在服务器上运行如下命令来启动dns2tcp的服务器端:

dns2tcpd -f /etc/dns2tcpd.conf -F -d 2

其中参数“-f /etc/dns2tcpd.conf”指定了配置文件,“-F”要求程序在前台运行,“-d 2”指明了输出调试信息,级别为2。作为首次运行,我们加上参数“-F”和“-d 2”。

最后,在办公电脑(客户端)上运行如下命令以建立DNS隧道:

dns2tcpc -r socks -z dns2tcp.werner.wiki -l 8888 -d 2

其中参数“-r socks”指明了要连接的资源,“-z dns2tcp.werner.wiki”指明了建立DNS隧道使用的域名,“-l 8888”指明了隧道的这头监听的端口,“-d 2”的作用和服务器端相同。

至此,隧道搭建完成。

0x05 测试

在办公电脑(客户端)里打开火狐浏览器,设置socksv5代理,IP地址是“127.0.0.1”,端口是8888,如下图所示。

设置火狐浏览器代理

然后用百度搜索“IP”,看到显示当前办公电脑IP地址为“118.xx.xx.120”,如下图所示。

用百度搜索“IP”

这说明DNS隧道搭建成功,实现了办公电脑访问互联网的目标。

0x06 其他

若是前面各步均正确无误,最后出现了错误:

No response from DNS xx.xx.xx.xx

那么可能的原因是中途某个DNS服务器丢弃了TXT类型的奇怪DNS查询请求。如何解决这一问题呢?其实只要我们能绕过中途那台DNS服务器就好了。但问题是我们不知道问题出在哪里,中途有哪些DNS服务器我们也是不知道的。所以一个简单的办法就是绕过中途所有的DNS服务器,把办公电脑的DNS直接设置为“118.xx.xx.120”。这固然是可行的,但还有更简单的办法,我们可以在dns2tcpc的参数中指明要使用的DNS服务器,命令如下:

dns2tcpc -r socks -z dns2tcp.werner.wiki dns.werner.wiki -l 8888

直接指明以“dns.werner.wiki”为DNS服务器,办公电脑发出的DNS查询直接指向“dns.werner.wiki”,不再经过原有DNS服务器转发。这样我们实际上完全抛开了现有的域名系统,也就没有了注册域名设置解析的必要。但若防火墙规则较为严格,只允许目的IP是特定DNS服务器的数据包通过,此方法便行不通了。

0x07 总结

我是在上周五开始尝试用dns2tcp搭建DNS隧道,到这周六才成功。中途几经波折,差点就放弃了。看来做事还是得有锲而不舍的精神,不能轻易放弃。

刚开始只是照着网上的教程搭建,以为自己是明白其中的原理的。若是没有遇到什么问题,顺顺利利地就搭建成功了,便也就失去了学习了机会。直到遇到了难以解决的问题,在网上找不到解决方法时,才只好自己去研究,尝试弄清楚事物的运作原理。只有知道了运作原理,才能定位问题、解决问题。记得《如何思考》一书中也讲到,弄清楚事物的运作原理是进行聪明思考的前提。

其实我在几年前就看到过DNS隧道的文章,当时觉得原理很简单,以为自己全都明白,要搭一个也就是分分钟的事。但现在真正动手去做,才发现并不简单。正应了古人所说“纸上得来终觉浅,绝知此事要躬行”。

]]>
https://blog.werner.wiki/building-a-dns-tunnel-with-dns2tcp/feed/ 12
LCX.exe的功能 https://blog.werner.wiki/lcx-exe/ https://blog.werner.wiki/lcx-exe/#comments Sat, 22 Jul 2017 08:14:31 +0000 http://blog.werner.wiki/?p=238 最近在看一本书,其中有一节唤作“LCX端口转发实现内网突破”,我仔细地读了几遍,竟是一头雾水,全然不知在讲些什么,遂百度lcx.exe,又看了几篇文章,依旧不知所云。所幸找到了lcx.exe的源码,读了一遍,所有疑惑都烟消云散。

原本看不懂关于lcx.exe的文章,是由于找到的那些文章都在讲解lcx.exe的用法,对于原理只字未提,功能也只是略作说明。我不了解lcx.exe的功能,不知道它是干什么的,又不满足于生硬地记下lcx.exe的几条命令、几种用法,故而疑惑重重,觉得玄妙难懂。当阅读了源码,知道其原理功能后,再看用法,便清晰明了了。原理、功能和法用有何区别?举例来说,菜刀(此处指切菜的菜刀,不是中国菜刀)的原理是刀身坚固具有刀刃,刃坚硬不易折损,面积小压强大;功能是切割物体;用法是切菜、切肉等。本文将总结lcx.exe的功能,涉及部分原理。lcx.exe的源码附在文末。

lcx.exe的功能是进行端口转发,更具体的讲是进行TCP的端口转发。何为端口转发,我们知道,TCP共有65535个端口,端口转发,便是将一个端口接受到的数据,发送到另一个端口,将另一个端口接受到的数据,发送到这个端口,仅此而已。

lcx.exe有三种工作模式。为何是三种而不是两种或四种?因为TCP协议下,一个端口可处于两种模式之一——客户端模式或服务器模式,而端口转发涉及两个端口,故有三种可能:两个端口都处于服务器模式、一个端口处于服务器模式另一个端口处于客户端模式、两个端口都处于客户端模式。下面按这三种情况分别进行讨论。

1.两个端口都处于服务器模式

这一模式对应的参数是:

  -listen <ConnectPort> <TransmitPort>

简单地讲,就是 -listen 后接两个数字,分别是两个端口号。此模式下,lcx.exe分别监听ConnectPort和TransmitPort这两个端口,也就是说,这两个端口都处于服务器模式下,等待客户端连接。当有两个客户端分别与ConnectPort和TransmitPort建立连接后,端口转发便开始工作,互换ConnectPort和TransmitPort接受/发送的数据。

2.一个端口处于服务器模式另一个端口处于客户端模式

这一模式对应的参数是:

  -tran <ConnectPort> <TransmitHost> <TransmitPort>

此模式下,lcx.exe监听ConnectPort端口,此端口处于服务器模式,等待客户端连接。当有客户端连接到此端口后,lcx.exe会发起到TransmitHost主机的TransmitPort端口的TCP连接,此连接使用的本地端口是随机的某个未使用的端口,假设其为RandomPort,若连接成功,则开始端口转发,互换ConnectPort和RandomPort接受/发送的数据。

3.两个端口都处于客户端模式

这一模式对应的参数是:

  -slave <ConnectHost> <ConnectPort> <TransmitHost> <TransmitPort>

此模式下,lcx.exe会建立到ConnectHost主机的ConnectPort端口的TCP连接,假设使用的本地端口是RandomPort1,若成功,则会接着建立到TransmitHost主机的TransmitPort端口的TCP连接,假设使用的本地端口是RandomPort2,若成功,则开始端口转发,互换RandomPort1和RandomPort2接受/发送的数据。RandomPort1和RandomPort2都是随机的未使用端口。

以上便是lcx.exe的功能与原理,了解这些后,用法便不是问题了。就如同了解菜刀是用于切割物体后,拿菜刀是去切菜还是去砍人都不是问题一般。listen、slave等名字应该来源于lcx.exe最经典的用法——内网突破。当然,有时我们也会想看看别人怎么玩菜刀的:《Lcx的多种用法:3个功能+9个参数,你会怎么玩? 》

附:lcx.exe源码:


/* ************************************************************************************ * * HTran.cpp - HUC Packet Transmit Tool. * * Copyright (C) 2000-2004 HUC All Rights Reserved. * * Author : lion * : lion#cnhonker.net * : [url]http://www.cnhonker.com[/url] * : * Notice : Thx to bkbll (bkbll#cnhonker.net) * : * Date : 2003-10-20 * : * Complie : cl HTran.cpp * : * Usage : E:\>HTran * : ======================== HUC Packet Transmit Tool V1.00 ======================= * : =========== Code by lion & bkbll, Welcome to [url]http://www.cnhonker.com[/url] ========== * : * : [Usage of Packet Transmit:] * : HTran -<listen|tran|slave> <option> [-log logfile] * : * : [option:] * : -listen <ConnectPort> <TransmitPort> * : -tran <ConnectPort> <TransmitHost> <TransmitPort> * : -slave <ConnectHost> <ConnectPort> <TransmitHost> <TransmitPort> * ************************************************************************************ */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <winsock2.h> #include <io.h> #include <signal.h> #pragma comment(lib, "ws2_32.lib") #define VERSION "1.00" #define TIMEOUT 300 #define MAXSIZE 20480 #define HOSTLEN 40 #define CONNECTNUM 5 // define 2 socket struct struct transocket { SOCKET fd1; SOCKET fd2; }; // define function void ver(); void usage(char *prog); void transmitdata(LPVOID data); void getctrlc(int j); void closeallfd(); void makelog(char *buffer, int length); void proxy(int port); void bind2bind(int port1, int port2); void bind2conn(int port1, char *host, int port2); void conn2conn(char *host1, int port1, char *host2, int port2); int testifisvalue(char *str); int create_socket(); int create_server(int sockfd, int port); int client_connect(int sockfd, char* server, int port); // define GLOBAL variable here FILE *fp; int method=0; //int connectnum=0; //************************************************************************************ // // function main // //************************************************************************************ VOID main(int argc, char* argv[]) { char **p; char sConnectHost[HOSTLEN], sTransmitHost[HOSTLEN]; int iConnectPort=0, iTransmitPort=0; char *logfile=NULL; ver(); memset(sConnectHost, 0, HOSTLEN); memset(sTransmitHost, 0, HOSTLEN); p=argv; while(*p) { if(stricmp(*p, "-log") == 0) { if(testifisvalue(*(p+1))) { logfile = *(++p); } else { printf("[-] ERROR: Must supply logfile name.\r\n"); return; } p++; continue; } p++; } if(logfile !=NULL) { fp=fopen(logfile,"a"); if(fp == NULL ) { printf("[-] ERROR: open logfile"); return; } makelog("====== Start ======\r\n", 22); } // Win Start Winsock. WSADATA wsadata; WSAStartup(MAKEWORD(1, 1), &wsadata); signal(SIGINT, &getctrlc); if(argc > 2) { if(stricmp(argv[1], "-listen") == 0 && argc >= 4) { iConnectPort = atoi(argv[2]); iTransmitPort = atoi(argv[3]); method = 1; } else if(stricmp(argv[1], "-tran") == 0 && argc >= 5) { iConnectPort = atoi(argv[2]); strncpy(sTransmitHost, argv[3], HOSTLEN); iTransmitPort = atoi(argv[4]); method = 2; } else if(stricmp(argv[1], "-slave") == 0 && argc >= 6) { strncpy(sConnectHost, argv[2], HOSTLEN); iConnectPort = atoi(argv[3]); strncpy(sTransmitHost, argv[4], HOSTLEN); iTransmitPort = atoi(argv[5]); method = 3; } } switch(method) { case 1: bind2bind(iConnectPort, iTransmitPort); break; case 2: bind2conn(iConnectPort, sTransmitHost, iTransmitPort); break; case 3: conn2conn(sConnectHost, iConnectPort, sTransmitHost, iTransmitPort); break; default: usage(argv[0]); break; } if(method) { closeallfd(); } WSACleanup(); return; } //************************************************************************************ // // print version message // //************************************************************************************ VOID ver() { } //************************************************************************************ // // print usage message // //************************************************************************************ VOID usage(char* prog) { printf("[Usage of Packet Transmit:]\r\n"); printf(" %s -<listen|tran|slave> <option> [-log logfile]\n\n", prog); printf("[option:]\n"); printf(" -listen <ConnectPort> <TransmitPort>\n"); printf(" -tran <ConnectPort> <TransmitHost> <TransmitPort>\n"); printf(" -slave <ConnectHost> <ConnectPort> <TransmitHost> <TransmitPort>\n\n"); return; } //************************************************************************************ // // test if is value // //************************************************************************************ int testifisvalue(char *str) { if(str == NULL ) return(0); if(str[0]=='-') return(0); return(1); } //************************************************************************************ // // LocalHost:ConnectPort transmit to LocalHost:TransmitPort // //************************************************************************************ void bind2bind(int port1, int port2) { SOCKET fd1,fd2, sockfd1, sockfd2; struct sockaddr_in client1,client2; int size1,size2; HANDLE hThread=NULL; transocket sock; DWORD dwThreadID; if((fd1=create_socket())==0) return; if((fd2=create_socket())==0) return; printf("[+] Listening port %d ......\r\n",port1); fflush(stdout); if(create_server(fd1, port1)==0) { closesocket(fd1); return; } printf("[+] Listen OK!\r\n"); printf("[+] Listening port %d ......\r\n",port2); fflush(stdout); if(create_server(fd2, port2)==0) { closesocket(fd2); return; } printf("[+] Listen OK!\r\n"); size1=size2=sizeof(struct sockaddr); while(1) { printf("[+] Waiting for Client on port:%d ......\r\n",port1); if((sockfd1 = accept(fd1,(struct sockaddr *)&client1,&size1))<0) { printf("[-] Accept1 error.\r\n"); continue; } printf("[+] Accept a Client on port %d from %s ......\r\n", port1, inet_ntoa(client1.sin_addr)); printf("[+] Waiting another Client on port:%d....\r\n", port2); if((sockfd2 = accept(fd2, (struct sockaddr *)&client2, &size2))<0) { printf("[-] Accept2 error.\r\n"); closesocket(sockfd1); continue; } printf("[+] Accept a Client on port %d from %s\r\n",port2, inet_ntoa(client2.sin_addr)); printf("[+] Accept Connect OK!\r\n"); sock.fd1 = sockfd1; sock.fd2 = sockfd2; hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, &dwThreadID); if(hThread == NULL) { TerminateThread(hThread, 0); return; } Sleep(1000); printf("[+] CreateThread OK!\r\n\n"); } } //************************************************************************************ // // LocalHost:ConnectPort transmit to TransmitHost:TransmitPort // //************************************************************************************ void bind2conn(int port1, char *host, int port2) { SOCKET sockfd,sockfd1,sockfd2; struct sockaddr_in remote; int size; char buffer[1024]; HANDLE hThread=NULL; transocket sock; DWORD dwThreadID; if (port1 > 65535 || port1 < 1) { printf("[-] ConnectPort invalid.\r\n"); return; } if (port2 > 65535 || port2 < 1) { printf("[-] TransmitPort invalid.\r\n"); return; } memset(buffer,0,1024); if((sockfd=create_socket()) == INVALID_SOCKET) return; if(create_server(sockfd, port1) == 0) { closesocket(sockfd); return; } size=sizeof(struct sockaddr); while(1) { printf("[+] Waiting for Client ......\r\n"); if((sockfd1=accept(sockfd,(struct sockaddr *)&remote,&size))<0) { printf("[-] Accept error.\r\n"); continue; } printf("[+] Accept a Client from %s:%d ......\r\n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port)); if((sockfd2=create_socket())==0) { closesocket(sockfd1); continue; } printf("[+] Make a Connection to %s:%d ......\r\n",host,port2); fflush(stdout); if(client_connect(sockfd2,host,port2)==0) { closesocket(sockfd2); sprintf(buffer,"[SERVER]connection to %s:%d error\r\n", host, port2); send(sockfd1,buffer,strlen(buffer),0); memset(buffer, 0, 1024); closesocket(sockfd1); continue; } printf("[+] Connect OK!\r\n"); sock.fd1 = sockfd1; sock.fd2 = sockfd2; hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, &dwThreadID); if(hThread == NULL) { TerminateThread(hThread, 0); return; } Sleep(1000); printf("[+] CreateThread OK!\r\n\n"); } } //************************************************************************************ // // ConnectHost:ConnectPort transmit to TransmitHost:TransmitPort // //************************************************************************************ void conn2conn(char *host1,int port1,char *host2,int port2) { SOCKET sockfd1,sockfd2; HANDLE hThread=NULL; transocket sock; DWORD dwThreadID; fd_set fds; int l; char buffer[MAXSIZE]; while(1) { /* while(connectnum) { if(connectnum < CONNECTNUM) { Sleep(10000); break; } else { Sleep(TIMEOUT*1000); continue; } } */ if((sockfd1=create_socket())==0) return; if((sockfd2=create_socket())==0) return; printf("[+] Make a Connection to %s:%d....\r\n",host1,port1); fflush(stdout); if(client_connect(sockfd1,host1,port1)==0) { closesocket(sockfd1); closesocket(sockfd2); continue; } // fix by bkbll // if host1:port1 recved data, than connect to host2,port2 l=0; memset(buffer,0,MAXSIZE); while(1) { FD_ZERO(&fds); FD_SET(sockfd1, &fds); if (select(sockfd1+1, &fds, NULL, NULL, NULL) == SOCKET_ERROR) { if (errno == WSAEINTR) continue; break; } if (FD_ISSET(sockfd1, &fds)) { l=recv(sockfd1, buffer, MAXSIZE, 0); break; } Sleep(5); } if(l<=0) { printf("[-] There is a error...Create a new connection.\r\n"); continue; } while(1) { printf("[+] Connect OK!\r\n"); printf("[+] Make a Connection to %s:%d....\r\n", host2,port2); fflush(stdout); if(client_connect(sockfd2,host2,port2)==0) { closesocket(sockfd1); closesocket(sockfd2); continue; } if(send(sockfd2,buffer,l,0)==SOCKET_ERROR) { printf("[-] Send failed.\r\n"); continue; } l=0; memset(buffer,0,MAXSIZE); break; } printf("[+] All Connect OK!\r\n"); sock.fd1 = sockfd1; sock.fd2 = sockfd2; hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, &dwThreadID); if(hThread == NULL) { TerminateThread(hThread, 0); return; } // connectnum++; Sleep(1000); printf("[+] CreateThread OK!\r\n\n"); } } //************************************************************************************ // // Socket Transmit to Socket // //************************************************************************************ void transmitdata(LPVOID data) { SOCKET fd1, fd2; transocket *sock; struct timeval timeset; fd_set readfd,writefd; int result,i=0; char read_in1[MAXSIZE],send_out1[MAXSIZE]; char read_in2[MAXSIZE],send_out2[MAXSIZE]; int read1=0,totalread1=0,send1=0; int read2=0,totalread2=0,send2=0; int sendcount1,sendcount2; int maxfd; struct sockaddr_in client1,client2; int structsize1,structsize2; char host1[20],host2[20]; int port1=0,port2=0; char tmpbuf[100]; sock = (transocket *)data; fd1 = sock->fd1; fd2 = sock->fd2; memset(host1,0,20); memset(host2,0,20); memset(tmpbuf,0,100); structsize1=sizeof(struct sockaddr); structsize2=sizeof(struct sockaddr); if(getpeername(fd1,(struct sockaddr *)&client1,&structsize1)<0) { strcpy(host1, "fd1"); } else { // printf("[+]got, ip:%s, port:%d\r\n",inet_ntoa(client1.sin_addr),ntohs(client1.sin_port)); strcpy(host1, inet_ntoa(client1.sin_addr)); port1=ntohs(client1.sin_port); } if(getpeername(fd2,(struct sockaddr *)&client2,&structsize2)<0) { strcpy(host2,"fd2"); } else { // printf("[+]got, ip:%s, port:%d\r\n",inet_ntoa(client2.sin_addr),ntohs(client2.sin_port)); strcpy(host2, inet_ntoa(client2.sin_addr)); port2=ntohs(client2.sin_port); } printf("[+] Start Transmit (%s:%d <-> %s:%d) ......\r\n\n", host1, port1, host2, port2); maxfd=max(fd1,fd2)+1; memset(read_in1,0,MAXSIZE); memset(read_in2,0,MAXSIZE); memset(send_out1,0,MAXSIZE); memset(send_out2,0,MAXSIZE); timeset.tv_sec=TIMEOUT; timeset.tv_usec=0; while(1) { FD_ZERO(&readfd); FD_ZERO(&writefd); FD_SET((UINT)fd1, &readfd); FD_SET((UINT)fd1, &writefd); FD_SET((UINT)fd2, &writefd); FD_SET((UINT)fd2, &readfd); result=select(maxfd,&readfd,&writefd,NULL,×et); if((result<0) && (errno!=EINTR)) { printf("[-] Select error.\r\n"); break; } else if(result==0) { printf("[-] Socket time out.\r\n"); break; } if(FD_ISSET(fd1, &readfd)) { /* must < MAXSIZE-totalread1, otherwise send_out1 will flow */ if(totalread1<MAXSIZE) { read1=recv(fd1, read_in1, MAXSIZE-totalread1, 0); if((read1==SOCKET_ERROR) || (read1==0)) { printf("[-] Read fd1 data error,maybe close?\r\n"); break; } memcpy(send_out1+totalread1,read_in1,read1); sprintf(tmpbuf,"\r\nRecv %5d bytes from %s:%d\r\n", read1, host1, port1); //printf(" Recv %5d bytes %16s:%d\r\n", read1, host1, port1); makelog(tmpbuf,strlen(tmpbuf)); makelog(read_in1,read1); totalread1+=read1; memset(read_in1,0,MAXSIZE); } } if(FD_ISSET(fd2, &writefd)) { int err=0; sendcount1=0; while(totalread1>0) { send1=send(fd2, send_out1+sendcount1, totalread1, 0); if(send1==0)break; if((send1<0) && (errno!=EINTR)) { printf("[-] Send to fd2 unknow error.\r\n"); err=1; break; } if((send1<0) && (errno==ENOSPC)) break; sendcount1+=send1; totalread1-=send1; //printf(" Send %5d bytes %16s:%d\r\n", send1, host2, port2); } if(err==1) break; if((totalread1>0) && (sendcount1>0)) { /* move not sended data to start addr */ memcpy(send_out1,send_out1+sendcount1,totalread1); memset(send_out1+totalread1,0,MAXSIZE-totalread1); } else memset(send_out1,0,MAXSIZE); } if(FD_ISSET(fd2, &readfd)) { if(totalread2<MAXSIZE) { read2=recv(fd2,read_in2,MAXSIZE-totalread2, 0); if(read2==0)break; if((read2<0) && (errno!=EINTR)) { printf("[-] Read fd2 data error,maybe close?\r\n\r\n"); break; } memcpy(send_out2+totalread2,read_in2,read2); sprintf(tmpbuf, "\r\nRecv %5d bytes from %s:%d\r\n", read2, host2, port2); //printf(" Recv %5d bytes %16s:%d\r\n", read2, host2, port2); makelog(tmpbuf,strlen(tmpbuf)); makelog(read_in2,read2); totalread2+=read2; memset(read_in2,0,MAXSIZE); } } if(FD_ISSET(fd1, &writefd)) { int err2=0; sendcount2=0; while(totalread2>0) { send2=send(fd1, send_out2+sendcount2, totalread2, 0); if(send2==0)break; if((send2<0) && (errno!=EINTR)) { printf("[-] Send to fd1 unknow error.\r\n"); err2=1; break; } if((send2<0) && (errno==ENOSPC)) break; sendcount2+=send2; totalread2-=send2; //printf(" Send %5d bytes %16s:%d\r\n", send2, host1, port1); } if(err2==1) break; if((totalread2>0) && (sendcount2 > 0)) { /* move not sended data to start addr */ memcpy(send_out2, send_out2+sendcount2, totalread2); memset(send_out2+totalread2, 0, MAXSIZE-totalread2); } else memset(send_out2,0,MAXSIZE); } Sleep(5); } closesocket(fd1); closesocket(fd2); // if(method == 3) // connectnum --; printf("\r\n[+] OK! I Closed The Two Socket.\r\n"); } void getctrlc(int j) { printf("\r\n[-] Received Ctrl+C\r\n"); closeallfd(); exit(0); } void closeallfd() { int i; printf("[+] Let me exit ......\r\n"); fflush(stdout); for(i=3; i<256; i++) { closesocket(i); } if(fp != NULL) { fprintf(fp,"\r\n====== Exit ======\r\n"); fclose(fp); } printf("[+] All Right!\r\n"); } int create_socket() { int sockfd; sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd<0) { printf("[-] Create socket error.\r\n"); return(0); } return(sockfd); } int create_server(int sockfd,int port) { struct sockaddr_in srvaddr; int on=1; memset(&srvaddr, 0, sizeof(struct sockaddr)); srvaddr.sin_port=htons(port); srvaddr.sin_family=AF_INET; srvaddr.sin_addr.s_addr=htonl(INADDR_ANY); setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR, (char*)&on,sizeof(on)); //so I can rebind the port if(bind(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr))<0) { printf("[-] Socket bind error.\r\n"); return(0); } if(listen(sockfd,CONNECTNUM)<0) { printf("[-] Socket Listen error.\r\n"); return(0); } return(1); } int client_connect(int sockfd,char* server,int port) { struct sockaddr_in cliaddr; struct hostent *host; if(!(host=gethostbyname(server))) { printf("[-] Gethostbyname(%s) error:%s\n",server,strerror(errno)); return(0); } memset(&cliaddr, 0, sizeof(struct sockaddr)); cliaddr.sin_family=AF_INET; cliaddr.sin_port=htons(port); cliaddr.sin_addr=*((struct in_addr *)host->h_addr); if(connect(sockfd,(struct sockaddr *)&cliaddr,sizeof(struct sockaddr))<0) { printf("[-] Connect error.\r\n"); return(0); } return(1); } void makelog(char *buffer,int length) { if(fp !=NULL) { // fprintf(fp, "%s", buffer); // printf("%s",buffer); write(fileno(fp),buffer,length); // fflush(fp); } }
]]>
https://blog.werner.wiki/lcx-exe/feed/ 1
ARP欺骗工具arpspoof的用法 https://blog.werner.wiki/usage-of-arpspoof/ https://blog.werner.wiki/usage-of-arpspoof/#comments Thu, 30 Mar 2017 05:47:53 +0000 http://blog.werner.wiki/?p=187 arpspoof是一个好用的ARP欺骗工具,Kali linux中自带了该工具,在ubuntu中,安装它只需运行命令:

    sudo apt-get install dsniff

安装完成后,输入命令:man arpspoof 可以查看使用手册,2.4版本的手册内容如下(自己翻译的,非官方):

    名字 
           arpspoof - 截获交换局域网中的数据包

    用法
           arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host

    描述
           arpspoof通过伪造的ARP响应包改变局域网中从目标主机(或所有主机)到另一个主机(host)的数据包转发路径。这是交换局域网中嗅探网络流量的一种极为有效的方法。
           内核IP转发(或如fragrouter这样的、用户层面的、能完成同样功能的软件)必须提前开启。

    参数
           -i interface
                  指定要使用的接口(即指定一块网卡)

           -c own|host|both
                  指定在恢复ARP配置时使用的硬件地址;当在清理(cleaning up)时,数据包的源地址可以用自己的也可以用主机(host)的硬件地址。
                  使用伪造的硬件地址可能导致某些配置下的交换网络、AP网络或桥接网络通信中断,然而它比起默认值————使用自己的硬件地址要工作地更为可靠。

           -t target
                  指定一个特殊的、将被ARP毒化的主机(如果没有指定,则认为是局域网中所有主机)。重复可以指定多个主机。

           -r     毒化两个主机(目标和主机(host))以捕获两个方向的网络流量。(仅仅在和-t参数一起使用时有效)

           host   host是你想要截获数据包的主机 (通常是网关)。

    扩展阅读
           dsniff(8), fragrouter(8)

    作者
           Dug Song <dugsong@monkey.org>

看完使用手册后其实还是不大懂是什么意思,但去实际使用它,试试便明白了。下面是我试验后的经验总结。

首先介绍试验环境,有三台虚拟机:
– 192.168.56.104 8:0:27:35:8e:19 Kali linux, 攻击机
– 192.168.56.101 8:0:27:31:bf:15 Windows XP
– 192.168.56.102 8:0:27:84:9a:41 Windows 7

在使用arpspoof前先开启Kali的IP转发,使用命令:

    echo 1 > /proc/sys/net/ipv4/ip_forward

/proc/sys/net/ipv4/ip_forward是配置文件,默认内容为0,表示IP转发是关闭的,使用上述命令将该配置文件的内容改写为1,表示开启IP转发。

arpspoof 命令的工作过程分为两部分:

  1. 发送伪造的ARP请求包,修改目标主机中ARP缓存表,实施ARP欺骗;
  2. 当攻击完成后,再次发送伪造的ARP请求包,修改目标主机中ARP缓存表为正确的值,结束ARP欺骗。

-i 参数用于指定一块网卡,必须显式地指定,没有默认值,若不指定,会报错为:arpspoof: couldn’t arp for host xxx.xxx.xxx.xxx。
若不清楚自己机器上都有哪些网卡,可用命令 ifconfig 查看。

-t 和 -r 参数与第一部分有关,-c 参数与第二部分有关。第二部分被作者称为:cleaning up,-c 中的c大概就是从这里来的。

-t 后可以是IP地址,也可以是域名,这里只使用IP地址。

-t 参数后的第一个IP地址是要欺骗的主机,第二个IP地址是你要伪装成的主机,如:

    arpspoof -i eth1 -t 192.168.56.101 192.168.56.102 

执行上述命令,Kali会向Windows XP(192.168.56.101, 8:0:27:31:bf:15)发送ARP响应包,告诉Windows XP 192.168.56.102的MAC地址是8:0:27:35:8e:19(这实际上是Kali自己的MAC地址,这是在欺骗Windows XP):

    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:35:8e:19
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:35:8e:19
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:35:8e:19
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:35:8e:19
    ......

每一行代表一个数据包,从左往右,各列的值的含义是:发送者MAC地址(8:0:27:35:8e:19)、接收者MAC地址(8:0:27:31:bf:15)、帧类型码(0806,代表ARP包)、包大小(42,字节)、包内容(arp reply 192.168.56.102 is-at 8:0:27:35:8e:19)。

这样的数据包不会只发送一次,而是周期性地、每隔2秒种就发送一次。这样做的效果是Windows XP发往Windows 7——即发往192.168.56.102的数据包都会发送到Kali,Kali若开启了IP转发,则会将Windows XP发来的数据包转发给Windows 7。这样,运行在Kali上的Wireshark等网络嗅探工具就能嗅探到Windows XP发往Windows 7的数据包了,而在交换局域网中,原本是嗅探不到这样的数据包的。但Windows 7发往Windows XP的数据包会直接往Windows XP,而不会发给Kali,因为我们目前只欺骗了Windows XP,Windows 7那的ARP信息是真实的。为了能嗅探到来往两个方向的数据包,需要欺骗Windows XP和Windows 7两个主机,这时需要使用参数 -r :

    arpspoof -i eth1 -t 192.168.56.101 -r 192.168.56.102
    arpspoof -i eth1 -t 192.168.56.101 192.168.56.102 -r

上述两条命令是等效的。执行上述命令,会欺骗Windows XP和Windows 7两个主机,发送的伪造ARP响应包如下:

    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:35:8e:19
    8:0:27:35:8e:19 8:0:27:84:9a:41 0806 42: arp reply 192.168.56.101 is-at 8:0:27:35:8e:19
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:35:8e:19
    8:0:27:35:8e:19 8:0:27:84:9a:41 0806 42: arp reply 192.168.56.101 is-at 8:0:27:35:8e:19
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:35:8e:19
    8:0:27:35:8e:19 8:0:27:84:9a:41 0806 42: arp reply 192.168.56.101 is-at 8:0:27:35:8e:19
    ......

依旧是每隔两秒发一次,不过现在一次发送两个数据包,分别发给Windows XP(8:0:27:31:bf:15)和Windows 7(8:0:27:84:9a:41)。这样,Kali便能嗅探Windows XP和Windows 7之间的往来数据了。

ARP攻击进行期间,arpspoof会不停地发送伪造的用于欺骗的ARP响应包。当攻击完成后,操作者按下Ctrl C,arpspoof并不会马上停止,而是会进行清理(cleaning up)工作,通过继续发送伪造的ARP响应包来告诉被欺骗主机目标IP真实的MAC地址。最后用于清理工作的ARP响应包的源MAC地址可以是攻击者机器的MAC地址,还可以是目标IP机器的MAC地址,或者两种都发送。这三种情况对应着 -c 参数的三个选项:own、host或both,注意这里的host就真的是h-o-s-t这四个字母,而不是主机名或主机IP。选择own或host,arpspoof在清理时会给每隔被欺骗主机每隔1秒发送共计5个ARP响应包,当然若选择both,则总共发送10个ARP响应包,耗时10秒。

如执行命令:

    arpspoof -i eth1 -c both -t 192.168.56.101  192.168.56.102

后按下Ctrl C,发送的用于清理的ARP响应包如下所示:

    8:0:27:84:9a:41 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:84:9a:41 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:84:9a:41 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:84:9a:41 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:84:9a:41 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41
    8:0:27:35:8e:19 8:0:27:31:bf:15 0806 42: arp reply 192.168.56.102 is-at 8:0:27:84:9a:41

第一个数据包是从8:0:27:84:9a:41(这是Windows 7的MAC地址,当然是Kali伪造的)发往Windows XP(8:0:27:31:bf:15),告诉Windows XP,192.168.56.102(这是Windows 7的IP)的MAC地址是8:0:27:84:9a:41,这个数据包便是 -c host 的效果。第二个数据包的源地址是8:0:27:35:8e:19,这是Kali的MAC地址,这个数据包是 -c own 的效果。由于我们刚刚选择的参数是 -c both,故两者皆有。

]]>
https://blog.werner.wiki/usage-of-arpspoof/feed/ 1
可从网络流量中自动提取图片和音频的工具driftnet https://blog.werner.wiki/auto-extraction-driftnet/ https://blog.werner.wiki/auto-extraction-driftnet/#respond Wed, 29 Mar 2017 05:45:30 +0000 http://blog.werner.wiki/?p=185 回想起来,那还是将近三年前的事了,那时候刚刚接触网络抓包、Wireshark,就想,要是有工具能自动从网络流量中提取图片等信息,那该多好。今天百度Arp攻击时,发现还真有这工具!名为driftnet,在ubuntu中安装只需:

    sudo apt-get install driftnet

就可以了。安装完成后,输入命令:driftnet -h 可以查看帮助信息。帮助信息如下所示:(自己翻译的,非官方)

    driftnet, 版本 1.1.2
    从网络流量中捕获图片并在X window中显示它们。

    用法: driftnet [选项] [过滤码]

    选项:

      -h               显示本帮助信息
      -v               冗余操作
      -b               当捕获到新照片时嘟嘟响
      -i interface     选择要监听的网卡,默认为监听所有网卡
      -f file          不从网卡监听,而是从pcap导出文件中读取数据包;为使用Kismet或similar,文件可以是一个命名管道
      -p               不设置正在被监听的网卡为混杂模式
      -a               辅助模式:不在屏幕显示图片,而是将它们保存到临时目录中,并在标准输出中显示文件名
      -m number        辅助模式下临时文件中保存的图片的最大个数
      -d directory     用于命名临时文件夹
      -x prefix        保存图片时用的前缀
      -s               除图片外,还尝试从网络流量中提取音频数据,目前仅支持MPEG数据
      -S               只提取音频数据,不提取图片
      -M command       使用给出的命令播放-s选项捕获的音频数据。这应该处理标准输入提供的MPEG帧。默认是: `mpg123 -'。

    在任何选项后,都可以指定tcpdump形式的过滤码。过滤码将以`tcp and (用户过滤码)`的形式工作。

    点击可保存图片到当前目录。

    辅助模式被设计用来被其他想要从网络流量中捕获图片的程序调用。使用 -m 选项时,若临时文件夹中图片数量超过了指定值,driftnet会静默地删除图片。这是因为我们假定了有其他程序在收集和删除图片文件。

    driftnet, copyright (c) 2001-2 Chris Lightfoot <chris@ex-parrot.com>
    主页: http://www.ex-parrot.com/~chris/driftnet/

    本程序属自由软件;你可以在自由软件基金会出版的GNU通用公共许可的条款下分发和修改本程序;无论是版本2还是(您选择的)以后的任何版本,都遵从此许可。 
]]>
https://blog.werner.wiki/auto-extraction-driftnet/feed/ 0
[译]WinArpAttacker3.50Readme https://blog.werner.wiki/winarpattacker3-50readme/ https://blog.werner.wiki/winarpattacker3-50readme/#respond Tue, 28 Mar 2017 05:38:20 +0000 http://blog.werner.wiki/?p=180 原文信息
  • 标题 : WinArpAttacker 3.50 Readme
  • 日期 : 2006年6月4日
  • 作者 : unshadow
  • 邮箱 : asia_message@hotpop.com
  • 网站 : 还没有,作者正在找一个免费的,如果你有好的建议可以告诉作者
  • 译者 : Werner(主要是意译了)

目录

  1. 前言
  2. 概览
  3. 系统要求
  4. 新特性
  5. 开始
  6. 已知问题
  7. 修订历史
  8. 下一步

0. 前言

警告:这个程序是危险的,仅供研究之用。因本程序造成的任何可能的损失都与作者(unshadow)无关,如果你不同意这一点,请立刻删除本程序。如果你使用本程序,就认为你同意以上全部观点。

WinArpAttacker基于wpcap,你必须在运行它前安装wpcap驱动。若你已经安装了老版本的winpcap,可直接安装WinPcap_3_1.exe覆盖它。

1. 概览

WinArpAttacker是一个可以扫描、攻击、检测、保护局域网中电脑的程序。

有如下特性:

1.1 扫描

  • 它可以很快地(2~3秒内)扫描和展示位于局域网内部的活动主机。它有两种扫描模式,一种是正常扫描,还有一种是反嗅探(antisniff)扫描。后一种可以发现谁正在嗅探网络。
  • 它可以保存和载入主机列表文件。
  • 它可以定期扫描以发现新增主机。
  • 通过嗅探技术,它可以被动地更新主机列表,也就是说,它不用扫描,而是通过读取ARP请求包中的源地址来更新主机列表。
  • 通过高级对话框可以完成高级扫描。
  • 通过高级对话框可以扫描一个B类网段。
  • 在事件列表视图中,它可以扫描正在搞事情的主机。

1.2 攻击

  • 可拉取并收集局域网中所有数据包。
  • 可执行下列的六种攻击:
    1. Arp Flood – 尽可能快地向目标主机发送IP地址冲突的数据包,如果你发得够多,目标主机将会被玩坏(down) 。:-(
    2. BanGateway – 告诉网关目标主机的MAC地址为一个错误的MAC地址,这样目标主机将接收不到来自互联网的数据包。这种攻击可阻止目标主机访问互联网。
    3. IPConflict – 类似Arp Flood,规律性地发送IP地址冲突的数据包,也许用户因为规律性地IP地址冲突消息而不能工作。以及,这会使目标无法访问局域网。
    4. SniffGateway – 欺骗目标和网关,这样就能用嗅探收集它们之间的数据包。
    5. SniffHosts – 欺骗两个或更多主机,这样就能用嗅探收集它们之间的数据包。(危险!!!!)
    6. SniffLan – 与SniffGateway很类似, 区别在于SniffLan会发送广播ARP报文告诉局域网中所有主机你的主机就是网关,这样你就能嗅探局域网中所有数据包(危险!!!!!!!!!!!!!!)
  • 在整个ARP欺骗期间,WinArpAttacker会作为另一个网关(或IP转发器),局域网中其他用户无法识别。
  • WinArpAttacker会收集数据包,并通过自己的IP转发函数转发,你最好禁用系统的IP转发函数,因为WinArpAttacker可以很好地搞定这件事。
  • 所有通过欺骗被嗅探的数据和被WinArpAttacker IP转发函数转发的数据都被统计,你可以在主界面看到。
  • 正如你希望的,ARP表会在很短时间内(大约5秒)自动覆盖。你也可以选择从不覆盖。

1.3 检测

最重要的是,WinArpAttacker可以检测到上述的几乎所有攻击行为以及主机状态,可以检测到的事件列表如下:

  • SrcMac_Mismath – 主机发送了一个ARP包,它的源MAC地址不匹配,故此包将被忽略。
  • DstMac_Mismath – 主机接收了一个ARP包,它的目的MAC地址不匹配,故此包将被忽略。
  • Arp_Scan – 为了得到主机列表,某主机正在用ARP请求包扫描局域网。
  • Arp_Antisniff_Scan – 主机正在为嗅探主机而扫描局域网,以获知哪台主机正在嗅探网络。
  • Host_Online – 主机现在在线。
  • Host_Modify_IP – 主机改变了IP地址或添加了新IP地址。
  • Host_Modify_MAC – 主机改变了它的MAC地址。
  • New_Host – 发现了新主机。(译注:原文为“New gost was found.”,gost当为笔误。)
  • Host_Add_IP – 主机添加了一个新IP地址。
  • Multi_IP_Host – 主机有多IP地址。
  • Multi_Mac_Host – 主机有多MAC地址。
  • Attack_Flood – 主机发送了大量ARP报文到另一台主机,故目标主机响应变慢。
  • Attack_Spoof – 主机发送了特殊ARP报文去嗅探两个目标主机间的数据,故受骗者的数据已经泄露。
  • Attack_Spoof_Lan – 主机让局域网中所有主机相信它才是网关,故攻击者可以嗅探所有主机发往网关的数据。
  • Attack_Spoof_Ban_Access – 告诉两主机对方的MAC地址为一个不存在的MAC地址,使目标主机间无法通信。
  • Attack_Spoof_Ban_Access_GW – 告诉网关某主机的MAC地址为一个不存在的MAC地址,使目标主机无法通过网关访问互联网。
  • Attack_Spoof_Ban_Access_Lan – 广播某主机的MAC地址为一个不存在的MAC地址,使目标无法和局域网中任意主机通信。
  • Attack_IP_Conflict – 主机发现另一个主机和它有相同IP,故目标将被IP冲突消息干扰。
  • Local_Arp_Entry_Change – 现在WinArpAttacker可以监视本地ARP表入口,当一个主机的ARP地址改变时, WinArpAttacker可以报告。
  • Local_Arp_Entry_Add – 当本地ARP表中新增一个MAC地址,WinArpAttacker可以报告。

可用WinArpAttacker检测来解释每个事件,也可将事件保存到文件。

1.4 保护

提供ARP表保护。当WinArpAttacker检测到本地或远程主机正在遭受ARP欺骗,它将会覆盖本地或远程主机的ARP表为你想要的值。

1.5 ARP代理

当你的局域网中的某主机请求其他主机的MAC地址时,WinArpAttacker将把你希望的某一MAC地址告诉发起请求的主机,说这就是它所请求的MAC地址。

这用于在一个新局域网中访问因特网而不用改变你的IP地址。但若你给的是一个错误的MAC地址,这将会导致你的局域网陷入大的mass。(but it also can make your lan in a big mass if you assign a wrong mac address.)

1.6 保存ARP包

可保存所有嗅探到的ARP包到文件。

1.7 其他特性

  • 支持一台主机上多网卡、多IP、多网关,你可以选择不同的网卡或IP来扫描不同的局域网。
  • 支持DHCP和固定IP地址。
  • 统计每个主机所有的ARP包,包括发送和接收的。

    Arp R/S Q/P
    | |
    Action(Recive/Send) Arp packets type(ReQuest/RePly)
    – – – –

    ArpRQ: 接收到的ARP请求包个数
    ArpRP : 接收到的ARP回应包个数
    ArpSQ : 发送的ARP请求包个数
    ArpSP : 发送的ARP回应包个数

2. 系统要求

  • 本地: Windows XP/2000/2003(但我没在Windows XP/2003下测试过)。
  • 远程:包括所有电脑和网络驱动。
  • WinPcap:至少是3.1版本。

3. 新特性

  • 通过高级模式,可以扫描一个大的IP范围内的在线主机。
  • 可以保护本地或远程主机免于ARP欺骗攻击。
  • 可启用ARP代理,充当ARP代理。
  • 可以存储所有嗅探到的ARP包到文件。

4. 开始

  • 首先,安装最新版的WinPcap驱动。
  • 然后,只需运行WinArpAttacker.exe。
  • 点击扫描按钮开始扫描。
  • 用”arp -a”查看远程主机的ARP信息。
  • 点击停止按钮停止攻击。
  • 点击选项按钮以选择一个适配器(网卡)或IP地址。
  • 点击选项按钮以修改攻击步骤。

5. 已知问题

  1. 运行这个程序需要管理员特权,否则,程序运行可能不正常。
  2. 攻击动作是很危险的,你必须谨慎。
  3. 如果局域网中电脑很多(超过50),真正的网关可能会被玩坏( may be down)。

6. 修订历史

(译者注:我并不关心修订历史,就没有翻译这部分)

7. 下一步

现在还没有下一步计划,如果你有好的建议可以给我发邮件(asia_message@hotpop.com)。

后记

(后记是译者的后记)我觉得ARP欺骗是很实用的攻击方法,想试一试,就找到了WinArpAttacker这个软件。但实在没耐心看一遍英文的文档,所以干脆翻译一遍好了。

]]>
https://blog.werner.wiki/winarpattacker3-50readme/feed/ 0
Nmap参数笔记 https://blog.werner.wiki/nmap-parameter-notes/ https://blog.werner.wiki/nmap-parameter-notes/#respond Wed, 18 Jan 2017 05:24:21 +0000 http://blog.werner.wiki/?p=172 #### 刚刚看了i春秋学院《Web安全工程师》系列教程的《第四章:网络安全审计工具:Nmap》,这是简单的笔记:
  • -PN 关闭icmp过滤不在线主机的功能
  • -sP 简单的imcp扫描
  • –exclude 不包含某些ip
  • –excludefile 不包含某些ip,这些ip在一个文件中
  • –traceroute 显示路由信息
  • –system-dns
  • –dns-servers 后接DNS服务器,指定DNS服务器
  • –scanflags 后接ACK PSH等TCP的flag
  • –osscan-guess 猜测操作系统
  • –version-trace 获取更多的版本
  • –max-parallelism 最大并行数
  • –min-parallelism 最小并行数
  • –max-hostgroup 最大同时扫描的主机个数
  • –min-hostgroup 最小同时扫描的主机个数
  • –initial-rtt-timeout 设置rtt超时时间
  • –max-retries 设置最大尝试次数
  • –mtu 指定MTU值,需接一个8的倍数的参数
  • –source-port 指定源端口
  • –data-length 指定数据长度,单位字节
  • –radomize-hosts 以随机顺序扫描主机
  • –badsum 发送检查和错误的数据包
  • –stats-every 每隔多长时间输出一次状态
  • –reason 显示原因
  • –open 只关注打开的端口
  • –iflist 显示本机网络配置
  • –script 指定一个脚本文件
  • –script-trace 跟踪一个脚本文件的运行情况
  • –script-updatedb 升级脚本数据库
  • -PS 发送SYN包
  • -PA 发送ACK包
  • -PU 发送UDP包
  • -PY 发送CTP包
  • -PE 发送ICMP包,默认值
  • -PP ICMP时间戳嗅探
  • -PR 发送ARP包,仅局域网有效
  • -oN scan.txt 将扫描结果保存到文件
  • -oX scan.xml 将扫描结果保存到文件
  • -oG scan.txt 将扫描结果保存到方便grep命令查找的文件
  • -oA scan 将扫描结果输出为以上三种格式(会产生3个文件)
  • -oS scan.txt 将扫描结果保存到文件,以一种奇怪但可以理解的格式(玩笑)
  • -D RND:10 伪装成同时有10个主机在扫描目标
  • -A 组合命令,用多种参数扫描
  • -R 反向DNS查找
  • -F 快速扫描
  • -O 操作系统指纹识别
  • -V 显示版本信息
  • -p 后接端口,表示扫描特定端口,也可接http、”ht*”
  • -h 显示帮助信息
  • -v 显示扫描过程
  • -d 显示调试信息,还可以是-d1(信息最少)、-d9(信息最多)
  • -e 指定扫描用的网络适配器
  • -P0 ICMP
  • -P2 IGMP
  • -P4 IP
]]>
https://blog.werner.wiki/nmap-parameter-notes/feed/ 0
由IP地址获得地理信息 https://blog.werner.wiki/obtaining-geographic-information-from-ip-address/ https://blog.werner.wiki/obtaining-geographic-information-from-ip-address/#comments Mon, 02 May 2016 07:14:22 +0000 http://blog.werner.wiki/?p=115 一、概述

这篇文章将总结获得一个已知的IP地址的地理信息的各种方法。如何获取IP地址则不在本文讨论范围之内。

二、WEB服务

有很多网站提供这样的服务,国内的有http://www.ip138.com/https://www.v2ex.com/ip,国外的有https://www.maxmind.com/http://ipinfo.io/,当然直接百度某个IP也可以获得其简略的地理信息。下表给出了以上四家网站查询到的信息的具体内容:

URL 主机名(Hostname) 网络类别(Network) 国家(Country) 城市(City) 经纬度(Latitude/Longitude)
http://www.ip138.com/ N Y Y Y N
https://www.v2ex.com/ip N N Y Y Y
https://www.maxmind.com/ N Y Y Y Y
http://ipinfo.io/ Y Y Y Y Y

当然有的网站还提供更多信息,只是没有被列出来,留待读者自己去探索。

通过域名就可以看出,其中最专业的应该是http://ipinfo.io/。这家网站还提供很方便的API,以下内容摘自它的官网:

在Linux终端中执行:

    curl ipinfo.io

返回自己IP地址的相关信息:

    {
      "ip": "211.69.194.67",
      "hostname": "No Hostname",
      "city": "Wuhan",
      "region": "Hubei",
      "country": "CN",
      "loc": "30.5801,114.2734",
      "org": "AS4538 China Education and Research Network Center"
    }

作为参数的IP地址是写在 / 后的:

    curl ipinfo.io/8.8.8.8

返回 / 后IP地址的相关信息:

    {
      "ip": "8.8.8.8",
      "hostname": "google-public-dns-a.google.com",
      "city": "Mountain View",
      "region": "California",
      "country": "US",
      "loc": "37.3860,-122.0838",
      "org": "AS15169 Google Inc.",
      "postal": "94040"
    }

在IP之后再加 / ,之后跟一个键值:

    curl ipinfo.io/8.8.8.8/org

可以方便的提取返回结果中的某一条:

    AS15169 Google Inc.

这个API是免费的,限制是每天最高1,000次请求。当然也有收费版本,详见其官网。

三、命令行工具geoiplookup

Ubuntu下使用如下命令安装:

    sudo apt-get install geoip-bin

在终端执行:

    geoiplookup 8.8.8.8

可以看到输出是:

    GeoIP Country Edition: US, United States

信息比较少,这是因为安装这个工具时同时下载的数据库GeoIP.dat(位于/usr/share/GeoIP)只包含了这些信息。
可以下载更多IP数据库,使geoiplookup的查询结果包含更多信息。
一个常用的下载免费IP数据库的地方是http://dev.maxmind.com/zh-hans/geoip/legacy/geolite/
更简单些,可以通过下面几条命令,用wget下载,解压后直接复制到位:

    wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
    wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
    wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz
    gunzip GeoIP.dat.gz
    gunzip GeoIPASNum.dat.gz
    gunzip GeoLiteCity.dat.gz
    sudo cp GeoIP.dat GeoIPASNum.dat GeoLiteCity.dat /usr/share/GeoIP/

GeoLite数据库在每个月的第一个星期二更新,所以上面几条命令也应该被每月执行一次。
下载好更多数据库后再来执行:

    geoiplookup 8.8.8.8

可以看到输出是:

    GeoIP Country Edition: US, United States
    GeoIP ASNum Edition: AS15169 Google Inc.

只比以前多了自治系统编号(AS Number)信息,这是因为没有添加额外参数时,geoiplookup将只使用GeoIP.dat和GeoIPASNum.dat。
添加-f参数来指定数据库文件:

    geoiplookup -f /usr/share/GeoIP/GeoLiteCity.dat 8.8.8.8

使用了GeoLiteCity.dat数据库,输出信息也是城市一级的:

    GeoIP City Edition, Rev 1: US, CA, California, Mountain View, 94040, 37.384499, -122.088097, 807, 650

四、其他

MaxMind(成立于2002年的一家公司,自称是领先业界的IP智能与在线欺诈检测工具供应商)提供了各个编程语言的API来查询IP地址的地理信息,详见http://dev.maxmind.com/zh-hans/geoip/geoip2/downloadable/#MaxMind_APIs

580scan,自我介绍是:全世界IP查询,IP地址查询,各地IP地址详细信息,IP地址段查询,地区IP地址查询;根据IP地址查询IP的详细地址;根据地区地址查询IP地址段。

(2017.03.10更新)高精度IP定位,这是目前为止我所知的精度最高的定位。参考:互联网定位技术小谈

]]>
https://blog.werner.wiki/obtaining-geographic-information-from-ip-address/feed/ 2