Linux下C/C++(端口扫描技术)

news2024/12/23 11:34:29

随着互联网使用的不断增加,网络攻击也在增加。互联网本质上已经成为现代。因此,了解互联网和使用互联网是非常重要的。网络技术的安全性在当今时代是非常重要和必要的。

在本文中,我们将讨论一个非常重要的主题,即可能破坏计算机设备端口扫描安全的计算机设备的安全性。端口扫描是极其危险的,如果个人/组织及时了解并意识到这种网络攻击,则可以防止端口扫描的发生。

Linux下的开放端口?

侦听端口是应用程序侦听的网络端口。通过使用ss、netstat或lsof等命令查询网络堆栈,可以获得系统上侦听端口的列表。可以使用防火墙打开或关闭(过滤)每个侦听端口。


一般来说,开放端口是接受来自远程位置的传入数据包的网络端口。

例如,如果您运行的web服务器在端口80和443上侦听,并且这些端口在防火墙上是打开的,则任何人(被阻止的ip除外)都可以使用浏览器访问web服务器上托管的网站。在这种情况下,80和443都是开放端口。

开放端口可能会带来安全风险,因为每个开放端口都可能被攻击者用来利用漏洞或执行任何其他类型的攻击。您应该只公开应用程序功能所需的端口,并关闭所有其他端口。

端口扫描基础知识

端口扫描程序发送TCP或UDP网络数据包,并询问端口的当前状态。以下是三种类型的回复:

1.打开,接受:电脑会做出回应,询问是否有什么可以为你做的。
2.关闭,未侦听:计算机响应“此端口当前正在使用,此时不可用。
3.已筛选、已丢弃、已阻止:计算机甚至都懒得响应。

端口扫描通常发生在网络杀伤链的早期,即侦察和入侵期间。攻击者使用端口扫描来检测具有打开和未使用端口的目标,这些端口可以重新用于渗透、命令和控制以及数据泄露,或者发现该计算机上运行的应用程序利用该应用程序中的漏洞。

nmap是目前最流行的开源端口扫描工具之一。Nmap为不同的场景提供了许多不同的端口扫描技术。

使用nmap检查打开的端口

Nmap是一个强大的网络扫描工具,可以扫描单个主机和大型网络。它主要用于安全审计和渗透测试。

如果可用,nmap应该是端口扫描的第一个工具。除了端口扫描,nmap还可以检测Mac地址、操作系统类型、内核版本等。

从控制台发出的以下命令确定哪些端口正在侦听来自网络的TCP连接:


-sT告诉nmap扫描TCP端口,并告诉-p扫描所有65535端口。如果不使用-p-,nmap将只扫描1000个最受欢迎的端口。

要扫描UDP端口,请使用-sU而不是-sT:

nmap -sU -p- 192.168.227.128

有关更多信息,请访问nmap手册页,并阅读该工具的所有其他强大选项。

端口扫描类型有哪些

当我们经过了主机扫描得到了存活主机,有了攻击目标后,我们就需要扫描目标主机的开放端口了。端口扫描技术主要分为三类:开放扫描、隐蔽扫描、半开放扫描。

  • 开放扫描

TCP Connect 扫描 :

实现原理:通过调用socket函数connect()连接到目标计算机 上,完成一次完整的三次握手过程。如果端口处于侦听状态, 那么connect()就能成功返回。否则,这个端口不可用,即没有提供服务。
优点:稳定可靠,不需要特殊的权限
缺点:扫描方式不隐蔽,服务器日志会记录下大量密集的连接和错误记录 ,并容易被防火墙发现和屏蔽

  • 隐蔽扫描

TCP FIN 扫描:

实现原理: 扫描器向目标主机端口发送FIN包。当一个FIN数据包到达一个关闭的端
口,数据包会被丢掉,并且返回一个RST数据包。否则,若是打开的端 口,数据包只是简单的丢掉(不返回RST)。
优点:由于这种技术不包含标准的TCP三次握手协议的任何部分,所以无法被记录下来,从而比SYN扫描隐蔽得多,FIN数据包能够通过只监测SYN
包的包过滤器。
缺点:需要自己构造数据包,要求权限高; 通常适用于UNIX目标主机,但在Windows95/NT环境下,该方法无效。 因为不论目标端口是否打开,操作系统都返回RST包。

TCP Null 扫描 :

实现原理: TCP Xmas和Null扫描是FIN扫描的两个变种。Xmas扫描打开FIN,
URG和PUSH标记,而Null扫描关闭所有标记。 这些组合的目的是为了通过对FIN标记数据包的过滤。
当此类数据包到达一个关闭的端口,数据包会被丢掉,并且返回一个 RST数据包。否则,若是打开的端口,数据包只是简单的丢掉(不返回 RST)。
优点: 隐蔽性好;
缺点: 需要自己构造数据包,要求有超级用户或者授权用户权限; 通常适用于UNIX目标主机,而Windows系统不支持。

  • 半开放扫描

隐蔽性和可靠性介于前两者之间。

TCP SYN 扫描:

实现原理:扫描器向目标主机端口发送SYN包。如果应答是RST包,那么说明端口是关闭的;如果应答中包含SYN和ACK包,说明目标端口处于监听状态,
再传送一个RST包给目标机从而停止建立连接。由于在SYN扫描时,全连接尚未建立,所以这种技术通常被称为半连接扫描。
优点:隐蔽性较全连接扫描好,一般系统对这种半扫描很少记录。
缺点:通常构造SYN数据包需要超级用户或者授权用户访问专门的系统调用。

UDP端口扫描:

向目标端口发送UDP 包。如果得到的应答为“ICMP port Unreachable”(ICMP 端口不可到达),那么目标端口是关闭的。反之,如果没有收到这个应答消息,则目标端口极有可能是开放的。
由于UDP 是无连接的不可靠协议,UDP 扫描的准确性在很大程度上取决于网络及系统资源的使用率等多个因素。

TCP间接扫描:

实现原理:利用第三方的IP(欺骗主机)来隐藏真正扫描者的IP。由于扫描主机会对欺骗主机发送回应信息,所以必须监控欺骗主机的IP行为,从而获得原始扫描的结果。扫描主机通过伪造第三方主机IP地址向目标主机发起SYN扫描,
并通过观察其IP序列号的增长规律获取端口的状态 。
优点:隐蔽性好。
缺点:对第三方主机的要求较高。

我们讨论的扫描是最常见的,但这并不是一个详尽的列表。

shell脚本实现端口扫描

扫描linux机器上的tcp和udp端口的Bash脚本

#!/bin/bash
...
function scan_port {
    host=$1
    port=$2
    timeout 1 bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null && echo "Port $port: Open"
}

function scan_range {
    host=$1
    start_port=$2
    end_port=$3
    for ((port=start_port; port<=end_port; port++)); do
        scan_port $host $port
    done
}

function get_risk_level {
...
}

while getopts ":p:r:h" opt; do
    case $opt in
        p)
            port=$OPTARG
            ;;
        r)
            range=(${OPTARG//:/ })
            start_port=${range[0]}
            end_port=${range[1]}
            ;;
        h)
            echo "Usage: $0 [-p PORT] [-r START_PORT:END_PORT] host"
            exit 1
            ;;
        \?)
            echo "Invalid option: -$OPTARG" >&2
            echo "Usage: $0 [-p PORT] [-r START_PORT:END_PORT] host"
            exit 1
            ;;
        :)
            echo "Option -$OPTARG requires an argument." >&2
            echo "Usage: $0 [-p PORT] [-r START_PORT:END_PORT] host"
            exit 1
            ;;
    esac
done

shift $((OPTIND -1))

host=$1

if [ -z "$host" ]; then
    echo "Error: Host argument missing."
    echo "Usage: $0 [-p PORT] [-r START_PORT:END_PORT] host"
    exit 1
fi

if [ -z "$port" ] && [ -z "$range" ]; then
    echo "Error: Either -p or -r must be specified."
    echo "Usage: $0 [-p PORT] [-r START_PORT:END_PORT] host"
    exit 1
fi

if [ -n "$port" ]; then
...
fi

if [ -n "$range" ]; then
    scan_range $host $start_port $end_port
    for ((port=start_port; port<=end_port; port++)); do
        timeout 1 bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null && echo "Port $port: Open" && risk_level=$(get_risk_level $port) && echo "Risk level: $risk_level"
    done
fi

运行结果:

Linux下C/C++实现(端口扫描技术)

该项目是端口扫描仪的基本实现,它可以帮助网络管理员确保网络中的机器正常运行。

基本上,这个端口扫描仪可以扫描用户给定的ip地址的所有端口。通过向远程主机的端口发送适当的数据包,它可以解析从该主机返回的指示该端口状态的数据包。执行过程中还需要Ip地址。端口扫描仪可以读取的ip格式是用户输入(xxx.xxx.xxx.xxx)、ip文件(类似于此)和ip前缀(xxx.xxx.xxx.xxx/20)。

void parse_args(ps_args_t *ps_args, int argc, char *argv[]);
struct port_queue *init_queue();
int is_empty(struct port_queue *pqueue);
void free_queue(struct port_queue *pqueue);
void clear_queue(struct port_queue *pqueue);
void enqueue(struct port_queue *pqueue, char *ip_addr, int port);
void dequeue(struct port_queue *pqueue, char *ip_addr, int *port);
void connection(int socket, ps_args_t *ps_args);
void get_local_ip(char *source_ip);
u_int16_t cal_checksum(u_int16_t *ptr, int byte_num);
void build_ip_header(struct iphdr *ip_header, char *datagram, u_int8_t protocol, struct sockaddr_in dest_addr);
void build_tcp_header(struct tcphdr *tcp_header, int port, int scan_type);
void build_udp_header(struct udphdr *udp_header, int port);
void build_dns_header(struct DNS_HEADER *dns_header);
results tcp_scan(char *ip_address, int port, int scan_type, int thread);
results udp_scan(char *ip_address, int port, int thread);
void get_service_response(char *message, char *recv_buf, struct sockaddr_in dest_addr);
void check_services(int port, char *result, struct sockaddr_in dest_addr);
void check_http(char *recv_buf, char *result, struct sockaddr_in dest_addr);
void check_ssh(char *recv_buf, char *result, struct sockaddr_in dest_addr);
void check_smtp(char *recv_buf, char *result, struct sockaddr_in dest_addr);
void check_pop(char *recv_buf, char *result, struct sockaddr_in dest_addr);
void check_whois(char *recv_buf, char *result, struct sockaddr_in dest_addr);
void check_imap(char *recv_buf, char *result, struct sockaddr_in dest_addr);

...
int main(int argc, char *argv[]) 
{
...

    memcpy(&scan_name[0], "SYN", 3);
    memcpy(&scan_name[1], "NULL", 4);
    memcpy(&scan_name[2], "FIN", 3);
    memcpy(&scan_name[3], "XMAS", 4);
    memcpy(&scan_name[4], "ACK", 3);
    memcpy(&scan_name[5], "UDP", 3);

    parse_args(&ps_args, argc, argv);

    for (i = 0; i < PORT_NUM; i++) 
    {
        if (ps_args.ports[i] == 1) 
        {
            num_ports++;
        }
    }

    for (i = 0; i < 6; i++) 
    {
        if (ps_args.scan_types[i] == 1) 
        {
            num_scans++;
        }
    }

    int res_size = ps_args.ip_num * num_ports * num_scans;
    result = (results *)malloc(res_size * sizeof(results));
    int res_index = 0;

    get_local_ip(source_ip);

    pqueue = init_queue();  

    // init task queue
    for (i = 0; i < ps_args.ip_num; i++) 
    {
        for (port = 0; port < PORT_NUM; port++) 
        {
            if (ps_args.ports[port] == 1) 
            {
                enqueue(pqueue, ps_args.ip_addr[i], port);
            }
        }
    }
    pthread_mutex_init(&scan_mutex, NULL);
    pthread_mutex_init(&result_mutex, NULL);
...
    for (id = 0; id < ps_args.threads; id++) 
    {
        thread_id[id] = id;
        pthread_create(&thread[id], NULL, thread_func, (void *)&thread_id[id]);
    }

    for (i = 0; i < ps_args.threads; i++)
     {
        thread_res = pthread_join(thread[i], &retval);
        if (thread_res) 
        {
            // printf("pthread_join() failed. Error num: %d. Error: %s. \n", errno, strerror(errno));
            exit(thread_res);
        }
    }
    
...

    if (end.tv_usec < start.tv_usec) 
    {
        usec = end.tv_usec - start.tv_usec + 1000000;
        end.tv_sec--;
    }
    else 
    {
        usec = end.tv_usec - start.tv_usec;
    }
    sec = end.tv_sec - start.tv_sec;
    printf("Scan took %d.%d seconds. \n", sec, usec);

    for (i = 0; i < ps_args.ip_num; i++) 
    {
        printf("IP address: %s\n", ps_args.ip_addr[i]);
        printf("Port\tService Name (if applicable)\tScan Type\tResults\n");
        printf("--------------------------------------------------------------------------------------------------\n");
        print_res(ps_args.ip_addr[i], res_size);
    }
...

    return 0;
}

端口扫描仪可以对一个端口进行多次扫描,支持扫描类型:

TCP SYN
TCP FIN
TCP NULL
TCP XMAS
TCP ACK
UDP

运行结果:





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

总结

端口扫描技术向目标系统的TCP/UDP端口发送探测数据包,记录目标系统的响应,通过分析响应来查看该系统处于监听或运行状态的服务。

最后,端口扫描是网络犯罪分子用来识别计算机开放端口的一种方法。计算机利用许多端口来实现其功能和操作。其中包括打开和关闭端口。计算机网络中的开放端口被网络攻击者利用,通过这种机制进入系统进行端口扫描网络犯罪。

Welcome to follow WeChat official account【程序猿编码

参考:
https://nmap.org/man/zh/
https://www.osgeo.cn/scapy/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/507476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

es 7.x 通过DSL的常用查询语句

一 模拟造数 1.1 模拟数据 添加数据修改数据的请求方式为post http://localhost:9200/student/_doc/101 { "name":"zhangsan", "nickname":"zhangsan","sex":"男","age":30,"createTime":…

InnoDB线程模型

新版本结构演变 MySQL 5.7 版本 将 Undo日志表空间从共享表空间 ibdata 文件中分离出来&#xff0c;可以在安装 MySQL 时由用户自行指定文件大小和数量增加了 temporary 临时表空间&#xff0c;里面存储着临时表或临时查询结果集的数据Buffer Pool 大小可以动态修改&#xff0…

2.3 利用NumPy进行统计分析

2.3 利用NumPy进行统计分析 2.3.1 读/写文件1、二进制的文件读写2、读取文本格式的数据 2.3.2 使用数组进行简单统计分析1、排序2、去重与重复数据3、常用的统计函数 2.3.1 读/写文件 NumPy文件读写主要有二进制的文件读写和文件列表形式的数据读写两种形式 1、二进制的文件读…

代码随想录算法训练营第三十六天 | 重叠区间

435. 无重叠区间 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;贪心算法&#xff0c;依然是判断重叠区间 | LeetCode&#xff1a;435.无重叠区间_哔哩哔哩_bilibili 状态&#xff1a;能做出来&#xff0c;用的“补充(1)”的左边界排序&#xff0c…

SpringCloud —— eureka

目录 1.认识微服务 1.0.学习目标 1.1.单体架构 1.2.分布式架构 1.3.微服务 1.4.SpringCloud 1.5.总结 2.服务拆分和远程调用 2.1.服务拆分原则 2.2.服务拆分示例 2.2.1.导入Sql语句 2.2.2.导入demo工程 2.3.实现远程调用案例 2.3.1.案例需求&#xff1a; 2.3.2.注…

4. Mysql索引优化实战一

一条SQL在MySQL中是如何执行的 1. 示例表举一个大家不容易理解的综合例子 本文是按照自己的理解进行笔记总结&#xff0c;如有不正确的地方&#xff0c;还望大佬多多指点纠正&#xff0c;勿喷。 本节课内容&#xff1a; 索引下推优化详解Mysql优化器索引选择探究索引优化Order…

解决winstore下载mincraft 出现错误提示的问题,以及minecraft.exe出现此应用无法在你的电脑上运行的原因分析。

mincraft 点开显示此应用无法在你的电脑上运行&#xff0c;去C:\XboxGames\Minecraft Launcher\Content下看了下&#xff1a; 但是别人电脑上相同目录下一样的文件能运行&#xff0c;于是选择重装&#xff0c;但是刚开始下载就遇到这个问题&#xff1a; 商店提示这个 点开一…

Neural Network学习笔记2

torch.nn: Containers: 神经网络骨架 Convolution Layers 卷积层 Pooling Layers 池化层 Normalization Layers 正则化层 Non-linear Activations (weighted sum, nonlinearity) 非线性激活 Convolution Layers Conv2d torch.nn.Conv2d(in_channels, out_channels, ke…

Web缓存利用分析(三)

导语&#xff1a;前一篇文章介绍了Server Cache Poisoning在实际应用场景下&#xff0c;产生DOS攻击的利用方式。本篇文章则介绍Web Cache Deception在真实场景下的应用方式和测试情况。 前言 前一篇文章介绍了Server Cache Poisoning在实际应用场景下&#xff0c;产生DOS攻击…

产品经理入门书籍有哪些?

说到入门产品经理&#xff0c;应该看哪些书籍呢&#xff1f;下面咱们就从产品经理的各种能力维度来聊聊&#xff0c;这样更有针对性。 一、夯实产品经理的基础&#xff0c;建立产品思维 首先我们入行&#xff0c;要清楚产品经理具体的工作怎么做&#xff0c;比如&#xff1a;…

分享一个造成azkaban上传文件失败的案例

背景&#xff1a; 当初由于开发的需求&#xff0c;需要将传统方式部署azkaban以容器的方案部署&#xff0c;不但可以满足业务需求&#xff0c;还可以将用于构建的azkaban ECS虚拟机空闲出来&#xff0c;用作k8s节点。 但是在构建azkaban容器实例的时候由于azkaban参数配…

Flink第三章:基本操作(二)

系列文章目录 Flink第一章:环境搭建 Flink第二章:基本操作. Flink第三章:基本操作(二) 文章目录 系列文章目录前言一、物理分区1.shuffle(随机分区)2.Round-Robin(轮询)3.rescale(重缩放分区)4.broadcast(广播)5.Custom(自定义分区) 二、Sink1.写出到文件2.写入到Kafka3.写入到…

leetcode:203.移除链表元素(两种方法详解)

前言&#xff1a;内容包括-题目&#xff0c;代码实现&#xff08;两种方法&#xff09;&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 …

【CSS系列】第五章 · CSS文本属性

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

QT With OpenGL(SSAO)(Screen-Space Ambient Occlusion)

文章目录 在G_Buffer中加入深度信息使用深度信息得到环境遮蔽的结果1. 新建SSAO帧缓存类2.生成法向半球核心3. 生成随机核心转动纹理为什么要生成随机核心转动创建一个小的随机旋转向量纹理 4.使用G_Buffer渲染SSAO纹理传入参数着色器1. 获取当前像素在纹理中的信息2.计算TBN矩…

SpringBoot -- AOP

一直只听过AOP&#xff0c;但是并不知道AOP的原理使用&#xff0c;参考深入浅出SpringBoot2.x学习一下SpringBoot AOP编程 AOP是基于动态代理实现的 静态代理就是代理类中有一个实现类&#xff0c;和实现类相同名称的方法&#xff0c;调用代理的request方法&#xff0c;执行顺…

RF检测器/控制器MS2351可pin对pin兼容AD8314、MAX4003

MS2351M/MS2351D 是一款对数放大器芯片&#xff0c;主要用于接收信号强度指示 (RSSI) 与控制功率放大器&#xff0c;工作频率范围是50MHz&#xff5e;3000MHz&#xff0c;动态范围可达 35dB 到 45dB。可pin对pin兼容AD8314、MAX4003。 MS2351M/MS2351D 是电压响应器件&#xff…

【c语言】结构体详解 | 结构体数组/指针

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c语言系列专栏&#xff1a;c语言之路重点知识整合 &#x…

【ChirpStack 】如何获取 JWT TOKEN

LoRa App Server 提供了两类 API 接口&#xff0c;其中 RESTful JSON API 提供了一个 API console&#xff0c;在AS地址的基础上使用 /api 即可访问&#xff0c;罗列了 API 端点和文档介绍&#xff0c;测试起来非常方便。 本文主要介绍 如何使用 chirpstack 的API 进行测试以及…

商户查询的缓存——基于逻辑过期方式解决缓存击穿问题

//基于逻辑过期方式解决缓存基穿问题 理论上讲都是可以命中的 public Shop queryWithLogincalExpire(Long id){ //1.从redis中查商铺缓存 String jsonShop stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY id); //2.未命中 if(StringUtils.isBlank(j…