Linux下C/C++ 网络扫描(主机扫描技术)
主机扫描是网络扫描的基础,通过对目标网络中主机IP地址的扫描,从一堆主机中扫描出存活的主机,然后以他们为目标进行后续的攻击。一般会借助于ICMP、TCP、UDP等协议的工作机制,检查打开的进程,开放的端口号等等。
主机扫描
主机扫描是在可达状态下检测,局域网下的 ARP 扫描和广域网下的 ICMP Echo 扫描、ICMP Sweep 扫描、ICMP Broadcast 扫描、ICMP Non-Echo 扫描都是基本的扫描技术。还有绕过防火墙和网络过滤设备的高级技术。
- ARP 扫描
向目标主机所在的局域网发送 ARP 广播请求,在局域网连通状态下目标主机必定会响应正常的 ARP 广播请求。故而便可获得IP地址和 MAC 地址等信息。
...
int convertNetworkAddr(const char *inString,uint8_t outNetAddr[PROTOCOL_ADDRESS_LENGTH],uint8_t *netPrefix)
{char *invalidCharPtr;// 读取3个八位字节for (int i = 0; i < PROTOCOL_ADDRESS_LENGTH - 1; ++i) {unsigned long octet = strtoul(inString, &invalidCharPtr, 10);if (octet >= 256 || *invalidCharPtr != '.') {return 1;}inString = invalidCharPtr + 1;outNetAddr[i] = (uint8_t) octet;}// 读取最后一个八位字节unsigned long octet = strtoul(inString, &invalidCharPtr, 10);if (octet >= 256 || *invalidCharPtr != '/') {return 1;}inString = invalidCharPtr + 1;outNetAddr[PROTOCOL_ADDRESS_LENGTH - 1] = octet;unsigned long prefix = strtoul(inString, &invalidCharPtr, 10);if (prefix > 32 || invalidCharPtr == inString) {return 1;}*netPrefix = prefix;// 按位AND ip地址和网络掩码uint8_t hostPartLength = PROTOCOL_ADDRESS_LENGTH * 8 - prefix;for (int j = 0; j < hostPartLength / 8; ++j) {outNetAddr[PROTOCOL_ADDRESS_LENGTH - 1 - j] = 0x00;}if (hostPartLength % 8) {uint8_t mask = (0xFF >> hostPartLength % 8) << hostPartLength % 8;outNetAddr[PROTOCOL_ADDRESS_LENGTH - hostPartLength / 8 - 1] &= mask;}return 0;
}
...
void printPacket(struct ArpPacket *p)
{for (int i = 0; i < sizeof(struct ArpPacket); ++i) {int c = *((char*)p+i) & 0xFF;printf("%2x ", c);if (i%8 == 7)printf("\n");}printf("\n");
}int readNetworkAddr(const char *string,uint8_t dstAddr[PROTOCOL_ADDRESS_LENGTH],uint8_t *dstPrefix)
{if (convertNetworkAddr(string, dstAddr, dstPrefix)) {fprintf(stderr, "Cannot recognize network address from: %s\n", string);exit(1);}DEBUG(printf("========= RECOGNIZED NETWORK ADDRESS ===========\n");printf("IP address: ");for (int j = 0; j < PROTOCOL_ADDRESS_LENGTH; ++j) {printf("%i ", (int)dstAddr[j]);}printf("\nNet prefix: %i\n", (int)(*dstPrefix) );)
}int main(int argc, char **argv)
{
...if (argc != 3) {fprintf(stderr, "Usage: <interface name> <network address>.\n""For example: scan eth0 192.168.0.1/24\n");return 1;}// 打开套接字int s = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));if (s == -1) {perror("Error in opening socket: ");return 1;}// 读取网络地址uint8_t netAddr[PROTOCOL_ADDRESS_LENGTH];uint8_t netPrefix;readNetworkAddr(argv[2], netAddr, &netPrefix);DEBUG(setHostPart(netAddr, 255, 8);printf("IP address: ");for (int j = 0; j < PROTOCOL_ADDRESS_LENGTH; ++j) {printf("%i ", (int)netAddr[j]);}printf("\n");)struct sockaddr_ll addr;prepareSockaddrll(&addr, argv[1]);struct ArpPacket packet;prepareArpPacket(&packet, &addr, argv[1]);DEBUG(printf("Packet hex dump: \n");printPacket(&packet);)for (int i = 1; i < powl(2, (32 - netPrefix) ) - 1; ++i) {setHostPart(netAddr, i, 32 - netPrefix);setDstIP(netAddr, &packet);DEBUG(printf("Sending ARP request to IP ");printIP(netAddr, stdout);printf(" ..............");)if(sendto(s, &packet, sizeof(packet), 0,(struct sockaddr*) &addr, sizeof(addr)) == -1) {perror("Error in sending ARP request: ");fprintf(stderr, "Error in sending ARP request: %s\n", strerror(errno));return 1;}DEBUG(printf("[ DONE ]\n");)// waiting for responseusleep(200);struct ArpPacket response;ssize_t receivedResponseSize;if (receivedResponseSize = recv(s, &response, sizeof(response), MSG_DONTWAIT | MSG_TRUNC) > 0) {DEBUG(printf("Received %ld bytes of response: \n", (long) receivedResponseSize);printPacket(&response);)if (memcmp(response.senderLogicAddress, packet.senderLogicAddress, sizeof(packet.senderLogicAddress))) {printf("IP ");printIP(response.senderLogicAddress, stdout);printf(" has MAC: ");for (int j = 0; j < HARDWARE_ADDRESS_LENGTH; ++j) {printf("%x:", (int)response.senderHardwareAddress[j]);}printf("\n");}}}return 0;
}
运行结果:

If you need the complete source code, please add the WeChat number (c17865354792)
tcpdump抓包


- ICMP Echo 扫描
向目标主机发送ICMP Echo Request (type 8)数据包,等待回复的ICMP Echo Reply 包(type 0) 。如果能收到,则表明目标系统可达,否则表明目标系统已经不可达或发送的包被对方的设备过滤掉。
...
/*
获取网络接口的本地信息。*/
int loadLocalData( LocalData *dst, const char *ifname )
{struct ifreq nic;int sock = socket( AF_INET, SOCK_DGRAM, 0 );strncpy( nic.ifr_name, ifname, IFNAMSIZ-1 );nic.ifr_name[IFNAMSIZ-1] = '\0';if( ioctl( sock, SIOCGIFINDEX, &nic ) < 0 ){close( sock );return -1;}dst->ifindex = nic.ifr_ifindex;// 分配的IP地址if( ioctl( sock, SIOCGIFADDR, &nic ) < 0 ){close( sock );return -1;}memcpy( &dst->ip, nic.ifr_addr.sa_data + 2, INET_ALEN );// MAC地址 if( ioctl( sock, SIOCGIFHWADDR, &nic ) < 0 ){close( sock );return -1;}memcpy( &dst->mac, nic.ifr_hwaddr.sa_data, ETH_ALEN );// 子网掩码if( ioctl( sock, SIOCGIFNETMASK, &nic ) < 0 ){close( sock );return -1;}memcpy( &dst->netmask, nic.ifr_netmask.sa_data + 2, INET_ALEN ); close( sock );return 0;
}/*** 为特定协议创建套接字。*/
int createSocket( SocketType type, int msecs )
{int sfd;struct timeval timer;if( type == ICMPSocket )sfd = socket( AF_INET, SOCK_RAW, IPPROTO_ICMP );elsesfd = socket( AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP) );if( sfd < 0 )return -1;// 设置接收数据的最大时间timer.tv_sec = msecs / 1000;timer.tv_usec = msecs % 1000 * 1000;if( setsockopt( sfd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer) ) < 0 ){close( sfd );return -1;}return sfd;
}
.../*** 计算增加一个IP地址的结果。*/
struct in_addr ipAddOne( struct in_addr ip )
{struct in_addr aux = { ntohl( ip.s_addr ) };aux.s_addr++;aux.s_addr = htonl( aux.s_addr );return aux;
}/*** 交换两个IP地址的值*/
void ipSwap( struct in_addr *a, struct in_addr *b )
{a->s_addr = a->s_addr ^ b->s_addr; b->s_addr = a->s_addr ^ b->s_addr;a->s_addr = a->s_addr ^ b->s_addr;
}
...int main( int argc, char **argv )
{
...// 验证接口if( !interface ){fprintf( stderr, "Error: No interface given. Use -h for help\n" );return -1;}// 加载本地数据if( loadLocalData( &data, interface ) < 0 ){perror( interface );return -1;}// 验证是否有特定的IP if( strFirst ){if( !inet_aton( strFirst, &first ) ){fprintf( stderr, "%s: Invalid address\n", strFirst );return -1;}if( strLast ){ // 验证是否有范围if( !inet_aton( strLast, &last ) ){fprintf( stderr, "%s: Invalid address\n", strLast );return -1;}else{total = ntohl( last.s_addr ) - ntohl( first.s_addr );if( total < 0 ){total = -total;ipSwap( &first, &last );}total++;}}else{total = 1;}}else{ // 如果没有,则从本地网络数据中获取范围。first.s_addr = data.ip.s_addr & data.netmask.s_addr;first = ipAddOne( first );last.s_addr = data.ip.s_addr | ~data.netmask.s_addr;total = ntohl( last.s_addr ) - ntohl( first.s_addr );}// 创建套接字if( (sfd = createSocket( type, waitTime ) ) < 0 ){perror( "Failed to create socket" );return 2;}...// 扫描周期for( int i = 1 ; i <= total && running ; i++, first = ipAddOne(first) ){printf( "\r(%d%%) Testing %s...", (int)(100.0 / total * i), inet_ntoa(first) );fflush( stdout );if( first.s_addr == data.ip.s_addr ){printf( " (this host)\n" );ups++;}else{switch( isUp(sfd, first, &data) ){case -1:perror( " send request" );break;case 1:puts( " is up" );ups++;}}}close( sfd );printf( "\n%d hosts up\n", ups );return 0;
}
运行结果:

If you need the complete source code, please add the WeChat number (c17865354792)
tcpdump抓包:


- ICMP Sweep 扫描


总结
这里我们就知道了其实主机扫描很简单,只需要证明其主机存活就好。我们只需要对目标主机发送特定的数据包,如果目标主机有回应,那么我们就认为该主机是存活的;反之如果对方不回应,我们就认为其不是存活主机。
Welcome to follow WeChat official account【程序猿编码】
相关文章:
Linux下C/C++ 网络扫描(主机扫描技术)
主机扫描是网络扫描的基础,通过对目标网络中主机IP地址的扫描,从一堆主机中扫描出存活的主机,然后以他们为目标进行后续的攻击。一般会借助于ICMP、TCP、UDP等协议的工作机制,检查打开的进程,开放的端口号等等。 主机…...
无法将“vue-cli-service”项识别为 cmdlet、函数、脚本文件或不是内部命令的原因和解决方案
经常有小伙伴问我说,为什么我们在开发vue项目的时候,需要在package.json的script对象中,去设置命令启动项目,而不是直接的通过"vue-cli-service serve"命令去把项目跑起来。带着这些疑问,小生在此总结了以下…...
逆流程 场景下 处理状态机变化的方案
背景: 针对某些业务场景下,存在逆流程。 比如场景的场景 正向流程如,发起某项申请->对某项申请进行审批。(审批为通过/驳回)。这样这个工作流程就算到最终态。 常见的状态机如, 申请未提交࿰…...
【剧前爆米花--爪哇岛寻宝】Java实现无头单向非循环链表和无头双向链表与相关题目
作者:困了电视剧 专栏:《数据结构--Java》 文章分布:这是关于数据结构链表的文章,包含了自己的无头单向非循环链表和无头双向链表实现简单实现,和相关题目,想对你有所帮助。 目录 无头单向非循环链表实现 …...
学习MvvmLight工具
最近学习了一下MvvmLight,觉得有些功能还是挺有特色的,所以记录一下 首先新建也给WPF程序 然后在Nuget里面安装MvvmLightLib 包,安装上面那个也可以,但是安装上面那个会自动在代码里面添加一些MvvmLight的demo ,安装M…...
基于BiLSTM+CRF医学病例命名实体识别项目
研究背景 为通过项目实战增加对命名实体识别的认识,本文找到中科院软件所刘焕勇老师在github上的开源项目,中文电子病例命名实体识别项目MedicalNamedEntityRecognition。对其进行详细解读。 原项目地址:https://github.com/liuhuanyong/Med…...
05 C语言数据类型
05 C语言数据类型 1、数据类型 编程语言对数据类型分为两派:一种认为要注重,一种认为可以忽视。 C语言类型 1、整数 : char < short < int < long < long long ,bool 2、浮点数:float < double < long doub…...
C++11:右值引用和移动语义
文章目录1. 左值和右值表达式1.1 概念1.2 左值和右值2. 左值引用和右值引用2.1 相互引用2.2 示例代码2.3 左值引用使用场景缺点2.4 右值引用和移动语义小结2.5 移动赋值2.6 右值引用的其他使用场景右值引用版本的插入函数3. 完美转发3.1 万能引用3.2 如何实现完美转发3.3 完美转…...
tcpdump网络抓包工具
tcpdump 是一个强大的网络抓包工具,在分析服务之间调用时非常有用。可以将网络中传送的数据包抓取下来进行分析。tcpdump 提供灵活的抓取策略,支持针对网络层、协议、主机、网络或端口的过滤,并提供 and、or、not 等逻辑语句来去掉不想要的信…...
MaxCompute SQL中的所有保留字与关键字如下
– MaxCompute SQL中的所有保留字与关键字如下 注意 命名表、列或分区时,不要使用保留字与关键字,否则可能会报错。 保留字不区分大小写。 在对表、列或是分区命名时如若使用关键字,需给关键字加符号进行转义,否则会报错。 % &am…...
Kafka 压缩算法
压缩 (compression) : 用时间换空间的思想 用较小的 CPU 开销获得磁盘少占用或网络 I/O 少传输 Kafka 消息分两层: 消息日志组成 : n 个消息集合消息集合 (message set) 组成 : n 条日志项 (record item)日志项封装了消息 (message)Kafka 在消息集合层上进行写入…...
关于React Hook(18)
useState():👉详情 (必须“有条件地调用”;注意避免冗余状态的产生) 关于useState的两种使用方式的区别:👉详情 关于batch机制:有条件地调用一些状态的set方…...
计算机网络:BGP协议
BGP协议 与其他AS的邻站BPG发言人交换信息。 交换的网络可达性信息,即要到达某一个网络所要经历的一系列AS 发生变化时,更新有变化的部分 BGP协议交换信息的过程:所交换的网络可达性信息就是要到达某一个网络所要经历的一系列ASÿ…...
91. 解码方法 ——【Leetcode每日刷题】
91. 解码方法 一条包含字母 A-Z 的消息通过以下映射进行了 编码 : ‘A’ -> “1” ‘B’ -> “2” … ‘Z’ -> “26” 要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法࿰…...
人体存在传感器成品方案,精准感知静止存在,实时智能化感控技术
随着现今智能时代的发展,酒店也越来越趋于智能化,也在不断地推行智慧酒店,这也给人们入住酒店提供了良好的体验。 人体存在感知是智能酒店中极其重要的一项应用技术,只有智能设备通过精准地感知人体存在,才能更好地做…...
mysql连接池的实现
目录 1 池化技术 2 什么是数据库连接池 3 为什么使用数据库连接池 3.1 不使用连接池 3.2 使用连接池 3.3 长连接和连接池的区别 4 数据库连接池运行机制 5 连接池和线程池的关系 6 线程池设计要点 6.1 连接池设计逻辑 构造函数 初始化 请求获取连接 归还连接 析…...
哪种类型蓝牙耳机佩戴最舒服?舒适度最好的蓝牙耳机推荐
如果您想在外出时听自己喜欢的音乐,您需要佩戴耳机,当前的耳机都足够小,可以将它们放在口袋里,即使它们在充电盒中也是如此,舒适度一直都是人们所追求的,舒适之余,佩戴同样稳固更加令人安心&…...
2020蓝桥杯真题洁净数 C语言/C++
题目描述 小明非常不喜欢数字 2,包括那些数位上包含数字 2 的数。如果一个数的数位不包含数字 2,小明将它称为洁净数。 请问在整数 1 至 n 中,洁净数有多少个? 输入描述 输入的第一行包含一个整数 n(1≤n≤10^6)。 输出描述 输…...
【随笔二】useReducer详解及其应用场景
前言 useReducer 实际上是 useState 的升级版,都是用来存储和更新 state,只是应用的场景不一样。 一般情况下,我们使用 useState 就足够项目需要了,不多当遇到以下场景时,使用useReducer 会更好些 。 状态逻辑复杂&…...
打怪升级之istringstream介绍
istringstream类 istringstream本质不是类,是一个宏,或者说是一个流: typedef basic_istringstream<char> istringstream;istringstream从basic_istringstream的char专用项而来。这一部分让人看得摸不着头脑的原因是因为大量使用了st…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
