ARP协议

ARP(Add ress Resolution Protocol)地址解析协议位于数据链路层,是根据IP地址获取MAC地址的一个协议。

ARP 查看指令

  1. arp -a 显示所有接口的当前ARP缓存表
  2. arp -d 删除指定的IP地址项
  3. arp -s 添加静态IP-MAC映射记录

ARP 缓存中毒(ARP欺骗)

arp传送原理在于主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间。

攻击者可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。

arp欺骗之所以有效,是因为特意构造的ARP数据包使两台主机相信它们是在互相通信,而实际上它们是在与一个中间转发数据包的第三方通信。

ARP格式

硬件类型:数据链路层使用的类型数据,大多数情况下,这个类型是以太网(类型 1)

协议类型:arp请求正在使用的高层协议

硬件地址长度:正在使用的物理地址长度(字节)

协议地址长度:正在使用的逻辑地址长度(字节)

操作:ARP数据包功能,1表示请求,2表示响应

发送方硬件地址:发送者的物理地址

发送方协议地址:发送者的协议地址

目标方硬件地址:接收者的物理地址(广播arp请求中接收者的物理地址常为0)

目标方协议地址:接收者的协议地址

网络编程

通过学习上面的理论知识就可以尝试着用来写一些实用的小工具练手了,例如扫描网络段存活主机与MAC地址。

发送ARP包->arp请求

发送arp包前需要了解两个函数,SendARP()与CreateThread();

SendARP()函数

这个函数用来发送ARP数据包并在定义的MAC缓冲区中返回定义的IP对应的MAC地址。

该函数有一个缺点:

该函数本质上就是向目标主机发送一个ARP请求包,然后得到应答包来更新MAC,但是ARP请求包里的发送端IP和MAC是本机的实际IP和MAC,这样对方arp -a查看缓存表时记录里就有我的IP-MAC映射记录,容易知道有人在扫描其机器或者是ARP病毒也可能。

  1. SendARP(
  2. IPAddr DestIP,
  3. IPAddr SrcIP,
  4. PULONG pMacAddr,
  5. PULONG PhyAddrLen
  6. );
  7. 第一个参数是IP地址的网络字节顺序,而不是一个指针,当初我就是赋值成指针而使得获取不了MAC地址。
  8. 第二个参数填0就可以
  9. 第三个参数是MAC缓冲区指针
  10. 第四个参数是一个指向一个DWORD型数值为6的指针

多线程函数

CreateThread()函数

Windows API函数。该函数在主线程的基础上创建一个新线程。微软在Windows API中提供了建立新的线程的函数CreateThread。

CreateThread()函数是Windows提供的API接口,作用是在主线程中再开启一个多线程。

在C/C++语言另有一个创建线程的函数_beginthreadex()

实例代码

实例代码中主要就用了SendARP()函数和CreateThread()函数,还有自定义的函数checkActive()

主要分为三步处理:

一、 main()函数中的处理

定义了IP的格式,开始IP与结束IP分别设定为:192.168.1.1,192.168.1.255;

in_addr类型是结构体组成,结构体构成如下:

传入的IP在联合体中s_b1就是192,s_b2就是168,s_b3就是1,s_b4就是IP四个段中的最后一个值X.X.X.255

  1. typedef struct in_addr {
  2. union {
  3. struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
  4. struct { USHORT s_w1,s_w2; } S_un_w;
  5. ULONG S_addr;
  6. } S_un;

通过for循环比较【开始IP】最后一段数值x.x.x.1,如果比【结束IP】的最后一段数值小x.x.x.255,进入多线程函数中CreateThread()中的线程函数threadProc()中做处理;

二、 threadPro中的处理c

这里传入的IP结构体信息进行转换,然后交给自定义函数checkActive()判断主机是否存活,然后将信息打印出来。

涉及到的系统小函数知识:

inet_ntoa()函数: 将一个IP转换成一个互联网标准点分格式的字符串;

三、checkActive()函数

整个程序的核心就用了SendARP(),将被检测的目的IP输入,源IP置为0。然后查看返回的结果值是否没有错误。

  1. #include "stdafx.h"
  2. #define _WINSOCK_DEPRECATED_NO_WARNINGS
  3. #include <winsock2.h>
  4. #pragma comment(lib,"ws2_32.lib")
  5. #include <iphlpapi.h>
  6. #pragma comment(lib,"iphlpapi.lib")
  7. //检查存活主机
  8. bool checkActive(in_addr ip)
  9. {
  10. ULONG dstMac[2] = { 0 };
  11. memset(dstMac, 0xff, sizeof(dstMac));
  12. ULONG size = 6;
  13. //这里是可以直接读取mac地址的,但是加了多线程不容易操控了。
  14. HRESULT re = SendARP(ip.S_un.S_addr, 0, dstMac, &size);
  15. if (re == NO_ERROR)
  16. {
  17. return true;
  18. }
  19. else
  20. {
  21. return false;
  22. }
  23. }
  24. //进入线程中的函数中
  25. DWORD WINAPI threadProc(LPVOID lpThreadParameter)
  26. {
  27. in_addr ip;
  28. ip.S_un.S_addr = (ULONG)lpThreadParameter;
  29. //调用自定义函数
  30. if (checkActive(ip))
  31. {
  32. printf("发现存活主机 : %s \n", inet_ntoa(ip));
  33. }
  34. return 0;
  35. }
  36. int main()
  37. {
  38. in_addr ip_start;
  39. in_addr ip_end;
  40. ip_start.S_un.S_addr = inet_addr("192.168.1.1");
  41. ip_end.S_un.S_addr = inet_addr("192.168.1.255");
  42. //循环探测主机
  43. //如果开始IP小于结束IP,那么IP的最后一段增加;
  44. for (in_addr ip = ip_start;ip.S_un.S_addr<ip_end.S_un.S_addr;ip.S_un.S_un_b.s_b4++)
  45. {
  46. printf("探测:%s\r", inet_ntoa(ip));
  47. //开启多线程
  48. CreateThread(NULL, 0, threadProc, (LPVOID)ip.S_un.S_addr, 0, 0);
  49. }
  50. getchar();
  51. return 0;
  52. }

参考:

用SendARP()获取对方的MAC地址

http://blog.csdn.net/gaojinshan/article/details/8990802

主机IP存活扫描,扫描MAC地址

以上代码单线程模式下其实是可以直接读取mac地址并输出的,但是加了多线程后就不容易操控了。因为打印出来的不知道是哪个线程获取到的数据。所以需要了解多线程内如何操控同一内存数据;

涉及到的系统小函数知识

多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,无法控制数据,变成随机变量。为解决这个问题,就需要引入互斥变量,让每个线程都按顺序地访问变量。这样就需要使用EnterCriticalSection和LeaveCriticalSection函数。

EnterCriticalSection函数原型

线程进入临界区,其他线程不能再进入,控制多线程在界面上的打印顺序

  1. WINBASEAPI
  2. VOID
  3. WINAPI
  4. EnterCriticalSection(
  5. _Inout_ LPCRITICAL_SECTION lpCriticalSection
  6. );

LeaveCriticalSection函数原型

线程离开临界区,其他线程能够继续进入

  1. WINBASEAPI
  2. VOID
  3. WINAPI
  4. LeaveCriticalSection(
  5. _Inout_ LPCRITICAL_SECTION lpCriticalSection
  6. );

实例代码

与上面的发送arp请求差不多,但是增加了对线程的处理,输出mac地址;

  1. #include "stdafx.h"
  2. #define _WINSOCK_DEPRECATED_NO_WARNINGS
  3. #include <winsock2.h>
  4. #pragma comment(lib,"ws2_32.lib")
  5. #include <iphlpapi.h>
  6. #pragma comment(lib,"iphlpapi.lib")
  7. CRITICAL_SECTION g_critical; //临界区,控制多线程打印顺序
  8. bool checkActive(in_addr ip)
  9. {
  10. ULONG dstMac[2] = { 0 };
  11. memset(dstMac, 0xff, sizeof(dstMac));
  12. ULONG size = 6;
  13. HRESULT re = SendARP(ip.S_un.S_addr, 0, dstMac, &size);
  14. if (re == NO_ERROR && size == 6)
  15. {
  16. EnterCriticalSection(&g_critical); //线程进入临界区,其他线程不能再进入,控制多线程在界面上的打印顺序
  17. printf("发现存活主机 : %-15s mac: ", inet_ntoa(ip));
  18. BYTE *bPhysAddr = (BYTE *)& dstMac;
  19. for (int i = 0; i < (int)size; i++) {
  20. if (i == (size - 1)) //如果是mac地址的最后一段,就输出换行
  21. printf("%.2X\n", (int)bPhysAddr[i]);
  22. else
  23. printf("%.2X-", (int)bPhysAddr[i]); //否则没有到最后一段,依旧输出,但不换行
  24. }
  25. LeaveCriticalSection(&g_critical); //线程离开临界区,其他线程能够继续进入
  26. return true;
  27. }
  28. else {
  29. return false;
  30. }
  31. }
  32. DWORD WINAPI threadProc(LPVOID lpThreadParameter)
  33. {
  34. in_addr ip;
  35. ip.S_un.S_addr = (ULONG)lpThreadParameter;
  36. //调用自定义函数
  37. checkActive(ip);
  38. return 0;
  39. }
  40. int main()
  41. {
  42. in_addr ip_start;
  43. in_addr ip_end;
  44. ip_start.S_un.S_addr = inet_addr("192.168.1.1");
  45. ip_end.S_un.S_addr = inet_addr("192.168.1.255");
  46. //循环探测主机
  47. InitializeCriticalSection(&g_critical); //初始临界区
  48. for (in_addr ip = ip_start;
  49. ip.S_un.S_addr < ip_end.S_un.S_addr;
  50. ip.S_un.S_un_b.s_b4++)
  51. {
  52. //开启多线程
  53. CreateThread(NULL, 0, threadProc, (LPVOID)ip.S_un.S_addr, 0, 0);
  54. }
  55. getchar();
  56. return 0;
  57. }

运行效果

【网络编程3】网络编程基础-arp请求(局域网主机扫描)的更多相关文章

  1. 三分钟网络基础-ARP协议

    什么是 ARP 协议 地址解析协议 ARP (Address Resolution Protocal):在同一局域网下,根据已知道的主机或路由器的 IP 地址,找出其相应的硬件地址. 高速缓存 每一个 ...

  2. QT---基于WinPcap的局域网络管理工具(主机扫描、包过滤、ARP攻击、端口扫描)

    主要功能 本机适配器扫描 局域网各主机扫描 类似于WinShark的抓包工具,能够简单的过滤Tcp.Udp.Arp等包 ARP攻击功能,限制局域网内指定主机上网 流量统计,统计实时网速 多线程攻击,多 ...

  3. 【网络编程4】网络编程基础-ARP响应(ARP欺骗之中间人攻击)

    arp欺骗->arp响应 ARP 缓存中毒(ARP欺骗) arp传送原理在于主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址:收到返回消 ...

  4. Winpcap网络编程九之Winpcap实战,ARP协议获得MAC表及主机通信

    大家好,本次我们须要完毕的任务是: 完毕两台主机之间的数据通信(数据链路层) 仿真ARP协议获得网段内主机的MAC表 使用帧完毕两台主机的通信(Hello! I'm -) 声明:本文章的目的是为大家的 ...

  5. Python网络编程之网络基础

    Python网络编程之网络基础 目录 Python网络编程之网络基础 1. 计算机网络发展 1.1. OSI七层模型 1.2. 七层模型传输数据过程 2. TCP/IP协议栈 2.1 TCP/IP和O ...

  6. 老师的blog整理 .网络编程部分 .网络编程部分 前端部分 django基础部分

    老师的blog整理 .网络编程部分 .网络编程部分 前端部分 django基础部分   老师的blog整理 python基础部分: 宝哥blog: https://www.cnblogs.com/gu ...

  7. (53)LINUX应用编程和网络编程之八Linux网络基础

    3.8.1.网络通信概述 3.8.1.1.从进程间通信说起:网络域套接字socket,网络通信其实就是位于网络中不同主机上面的2个进程之间的通信. 3.8.1.2.网络通信的层次 (1)硬件部分:网卡 ...

  8. 物联网网络编程、Web编程综述

    本文是基于嵌入式物联网研发工程师的视觉对网络编程和web编程进行阐述.对于专注J2EE后端服务开发的童鞋们来说,这篇文章可能稍显简单.但是网络编程和web编程对于绝大部分嵌入式物联网工程师来说是一块真 ...

  9. 物联网网络编程和web编程

    本文是基于嵌入式物联网研发project师的视觉对网络编程和web编程进行阐述. 对于专注J2EE后端服务开发的同学来说,这篇文章可能略微简单.可是网络编程和web编程对于绝大部分嵌入式物联网proj ...

随机推荐

  1. ubuntu 18.04 使用 nvm 安装 nodejs

    20190315 使用 nvm 安装 nodejs 1. 找到 nvm 官网帮助 https://github.com/creationix/nvm 我习惯于 terminal 操作,所以选择 git ...

  2. 自学Zabbix4.2 web监控项创建+item详解

    自学Zabbix4.2 web监控项创建+item详解 1. web监控项创建 1.1  Scenario 选项卡 Name: 监控项的名称 Application: 放到哪个应用中 Authenti ...

  3. 自学Zabbix6.1 Event acknowledgment 事件确认

    自学Zabbix6.1 Event acknowledgment 事件确认 1 概述以往服务器出现报警,运维人员处理完事之后,报警自动取消,但是下一次出现同样一个错误,但是换了一个运维人员,他可能需要 ...

  4. 洛谷 CF55D Beautiful numbers 解题报告

    CF55D Beautiful numbers 题意 \(t(\le 10)\)次询问区间\([l,r](1\le l\le r\le 9\times 10^{18})\)中能被每一位上数整除的数的个 ...

  5. qq空间爬取

    QQ_spider github传送门 QQ空间spider总结 花了将近3天吧,完成了低配版qq空间的爬虫,终于能上线刚一波了,还是蛮期待的. 流程很简单,模拟登录 ==>采集==>保存 ...

  6. 【POJ1015】Jury compromise 多个费用的背包

    这是一道比较综合的动态规划问题. 首先,根据题目中的从N个人中选出M个人,并且要使得某个目标函数最优,可以想到是背包问题,且因为要取出M个人,人数也应该作为背包体积的一个维度. 其次,要求输出路径,因 ...

  7. VB: 再次使用的体会

    放下VB已经有7.8年的时候了. 记得在上学的时候,一直迷恋着它,学了三年的VB,写了不少小软件. 到了工作之后,转到JAVA后,就一直没用VB. 这次的项目由于与系统的相关性高以及安装文件的大小有限 ...

  8. MATLAB:图像的与、或、非、异或逻辑运算(&、|、~、xor)

    图像的与.或.非.异或逻辑运算涉及到了&.|.~和xor符号 close all;%关闭当前所有图形窗口,清空工作空间变量,清除工作空间所有变量 clc; clear all; I=imrea ...

  9. zookeeper安装和使用(Windows环境)

    zookeeper安装和使用(Windows环境) 2017年11月27日 10:36:07 董昊炘的博客 阅读数:14785 标签: zookeeperwindows   zookeeper 一.简 ...

  10. hdu 2874(裸LCA)

    传送门:Problem 2874 https://www.cnblogs.com/violet-acmer/p/9686774.html 改了一晚上bug,悲伤辣么大,明天再补详细题解 题解: 题目中 ...