C++ Boost 实现异步端口扫描器

端口扫描是一种用于识别目标系统上哪些网络端口处于开放、关闭或监听状态的网络活动。在计算机网络中,端口是一个虚拟的通信端点,用于在计算机之间传输数据。每个端口都关联着特定类型的网络服务或应用程序。端口扫描通常是网络管理员、安全专业人员用来评估网络安全的一种方法。通过扫描目标系统的端口,可以了解系统上哪些服务在运行、哪些端口是开放的,从而评估系统的安全性。

常见的端口扫描技术包括:

  • TCP端口扫描: 通过发送TCP连接请求来确定目标系统上的端口是否开放。常见的TCP扫描包括全连接扫描(Connect Scan)、半开放扫描(SYN Scan)等。
  • UDP端口扫描: 通过向目标系统发送UDP数据包,观察是否收到相应来判断UDP端口是否开放。UDP扫描较为复杂,因为UDP是一种无连接的协议,难以确定是否因为端口关闭而未响应。
  • NULL、FIN和Xmas Tree扫描: 这些扫描技术利用TCP协议的特殊性质,尝试向目标系统发送非法或异常的TCP数据包,观察目标系统的响应。
  • IDLE扫描: 利用一个第三方系统(通常是僵尸主机)发送探测包,通过观察目标系统的响应来判断端口状态。这种扫描方法更难被目标系统检测到。

本章我们将运用Boost框架实现一个基于TCP的扫描工具,TCP端口扫描是一种常见的网络扫描技术,通过发送TCP连接请求来确定目标系统上的端口是否开放,其本质上是通过调用Socket套接字中的connect()尝试连接对应的端口,如果该端口开放则连接将被建立,由此我们就可以得出该端口是存活的,利用这一特性我们就可以实现批量的端口探测功能。

生成C段地址

C段地址通常指的是IPv4地址中的子网地址,其中C表示了地址的网络前缀的类别。IPv4地址按照其前缀的长度被分为A、B、C、D和E五个类别,每个类别用于不同规模的网络。

在IPv4地址中,每个地址由32位二进制数字组成,通常以点分十进制(Dotted-Decimal Notation)的形式表示,例如,192.168.0.1。IPv4地址的前面的一部分被分配给网络,而后面的部分则分配给主机。

  • A类地址: 以0开头,用于大型网络,例如1.0.0.0到126.0.0.0。
  • B类地址: 以10开头,用于中型网络,例如128.0.0.0到191.255.0.0。
  • C类地址: 以110开头,用于小型网络,例如192.0.0.0到223.255.255.0。

因此,当我们说一个IPv4地址属于C段地址时,通常指的是这个地址的前缀是C类地址的范围,即以192.x.x.x223.x.x.x的范围。例如,192.168.1.1是一个C段地址,因为它的前缀是192。在这样的地址中,最后三个字节通常用于主机标识。

同样我们在实现端口扫描之前需要生成一个C段地址中所有的主机IP,这里我们可以通过Boost库中的字符串拼接功能来实现生成特定主机网段,具体实现细节如下所示;

  • 例如192.168.1.1/100则代表要枚举出这个网段中所有的地址,并将其存储到std::vector<std::string>容器中。
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <vector>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>using namespace std;
using namespace boost;// 传递IP地址范围,自动生成IP地址表
bool CalculationAddress(std::string address, std::vector<std::string> &ref)
{std::vector<std::string> vect;try{// 以/,两个下划线作为切割符号,切割后放入vect容器中boost::split(vect, address, boost::is_any_of("/") || boost::is_any_of("."), boost::token_compress_on);// 将开始和结束地址取出来int start_count = lexical_cast<int>(vect[3]);int end_count = lexical_cast<int>(vect[4]);// IP地址中的C段必须小于255if (end_count <= 255){for (int x = start_count; x <= end_count; x++){std::string this_address = boost::str(boost::format("%s.%s.%s.%s") % vect[0] % vect[1] % vect[2] % x);ref.push_back(this_address);}}else{return false;}}catch (...){return false;}return true;
}int main(int argc, char * argv[])
{// 生成 192.168.1.1/100 这个范围内的地址表std::vector<std::string> address_ref;bool flag = CalculationAddress("192.168.1.1/255", address_ref);if (flag == true){// 输出地址表for (int x = 0; x < address_ref.size(); x++){std::cout << "地址表: " << address_ref[x] << std::endl;}}std::system("pause");return 0;
}

上述函数CalculationAddress通过传入范围192.168.1.1/100即可实现生成1-100以内的所有IP地址字符串,并将其存储到address_ref容器内,输出效果如下图所示;

端口字符串提取

接着我们还需要实现一个提取端口字符串的功能,例如当使用者传入22,23,135,139时,我们将其解析成独立的整数类型,并将其存储到std::vector<int>容器内保存,该功能的实现只需要使用boost::split函数切割并循环将数据放入到整数容器内即可,如下所示;

#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <vector>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>using namespace std;
using namespace boost;// 传递端口字符串,解析为vector容器
bool CalculationPort(std::string port_string, std::vector<int> &ref)
{std::vector<std::string> vect;try{boost::split(vect, port_string, boost::is_any_of(","), boost::token_compress_on);for (int x = 0; x < vect.size(); x++){ref.push_back(lexical_cast<int>(vect[x]));}return true;}catch (...){return false;}return true;
}int main(int argc, char * argv[])
{// 传入字符串端口,自动解析为vector容器std::vector<int> port_ref;bool flag = CalculationPort("22,23,55,135", port_ref);if (flag == true){// 输出地址表for (int x = 0; x < port_ref.size(); x++){std::cout << "端口表: " << port_ref[x] << std::endl;}}std::system("pause");return 0;
}

通过boost中的函数可以很容易实现字符串的切割,运行后可看到字符串被解析成了独立的整数,如下图所示;

异步端口探测

Boost.Asio是一个强大的C++库,提供了异步I/O和网络编程的支持。本文将介绍如何使用Boost.Asio实现异步连接,以及如何设置超时机制,确保连接在规定的时间内建立。Asio是Boost库中的一个模块,用于异步I/O和网络编程。它提供了一种灵活的方式来处理异步操作,使得程序能够更高效地利用系统资源。Boost.Asio支持TCP、UDP、SSL等协议,使得开发者能够轻松实现异步网络通信。

异步连接实现

在本文的代码示例中,我们使用Boost.Asio创建了一个AsyncConnect类,用于执行异步连接。这个类包含了异步连接的主要逻辑,其中使用了tcp::socketdeadline_timer来处理异步操作和超时。

#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <string>
#include <boost/asio.hpp> 
#include <boost/bind.hpp>  
#include <boost/date_time/posix_time/posix_time_types.hpp>  using namespace std;
using boost::asio::ip::tcp;// 异步连接地址与端口
class AsyncConnect
{
public:AsyncConnect(boost::asio::io_service& ios, tcp::socket &s):io_service_(ios), timer_(ios), socket_(s) {}// 异步连接bool aysnc_connect(const tcp::endpoint &ep, int million_seconds){bool connect_success = false;// 异步连接,当连接成功后将触发 connect_handle 函数socket_.async_connect(ep, boost::bind(&AsyncConnect::connect_handle, this, _1, boost::ref(connect_success)));// 设置一个定时器  million_seconds timer_.expires_from_now(boost::posix_time::milliseconds(million_seconds));bool timeout = false;// 异步等待 如果超时则执行 timer_handletimer_.async_wait(boost::bind(&AsyncConnect::timer_handle, this, _1, boost::ref(timeout)));do{// 等待异步操作完成io_service_.run_one();// 判断如果timeout没超时,或者是连接建立了,则不再等待} while (!timeout && !connect_success);timer_.cancel();return connect_success;}private:// 如果连接成功了,则 connect_success = truevoid connect_handle(boost::system::error_code ec, bool &connect_success){if (!ec){connect_success = true;}}// 定时器超时timeout = truevoid timer_handle(boost::system::error_code ec, bool &timeout){if (!ec){socket_.close();timeout = true;}}boost::asio::io_service &io_service_;boost::asio::deadline_timer timer_;tcp::socket &socket_;
};
探测主函数

在主函数中,我们创建了一个AsyncConnect对象,并使用它进行异步连接。这个例子中,我们尝试连接到IP地址为"202.89.233.101",端口号为80的服务器,并设置了连接超时时间为300毫秒。

int main(int argc, char * argv[])
{try{boost::asio::io_service io;tcp::socket socket(io);AsyncConnect hander(io, socket);tcp::endpoint ep(boost::asio::ip::address::from_string("8.141.58.64"), 80);// 传递扫描ep地址结构,以及超时时间if (hander.aysnc_connect(ep, 300)){std::cout << "连通了" << std::endl;io.run();}else{std::cout << "连接失败" << std::endl;}}catch (...){return false;}std::system("pause");return 0;
}

通过本文的示例,我们展示了如何使用Boost.Asio创建异步连接,并设置连接超时。异步连接的实现可以提高程序的性能和效率,特别适用于需要处理大量并发连接的网络应用场景。Boost.Asio的灵活性使得开发者能够更方便地处理异步I/O操作,提高程序的健壮性和可维护性。

当代码被运行时,则自动探测特定地址的特定端口是否开放,如果开放则返回如下图所示;

端口扫描封装

实现端口扫描

首先增加PortScan函数该函数传入地址端口号以及超时时间,自动扫描端口开放状态,这里我们就以扫描192.168.1.1端口从78-100扫描后将结果输出到屏幕上。

// 封装端口扫描函数
bool PortScan(std::string address, int port, int timeout)
{try{boost::asio::io_service io;tcp::socket socket(io);AsyncConnect hander(io, socket);tcp::endpoint ep(boost::asio::ip::address::from_string(address), port);// 传递扫描ep地址结构,以及超时时间if (hander.aysnc_connect(ep, timeout)){io.run();return true;}else{return false;}}catch (...){return false;}
}int main(int argc, char * argv[])
{for (int x = 78; x < 100; x++){bool is_open = PortScan("192.168.1.1", x, 1000);std::cout << "扫描端口: " << x << " 状态: " << is_open << std::endl;}std::system("pause");return 0;
}

运行上述代码即可扫描特定的端口是否开放,输出效果如下图所示;

实现特定端口扫描

实现CalculationPort函数,用户传入一串字符串自动解析为端口号,并调用扫描功能对特定端口进行扫描。

#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <string>
#include <boost/asio.hpp> 
#include <boost/bind.hpp>  
#include <boost/date_time/posix_time/posix_time_types.hpp>#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>using namespace std;
using namespace boost;
using boost::asio::ip::tcp;// 传递端口字符串,解析为vector容器
bool CalculationPort(std::string port_string, std::vector<int> &ref)
{std::vector<std::string> vect;try{boost::split(vect, port_string, boost::is_any_of(","), boost::token_compress_on);for (int x = 0; x < vect.size(); x++){ref.push_back(lexical_cast<int>(vect[x]));}return true;}catch (...){return false;}return true;
}int main(int argc, char * argv[])
{std::string scan_address = "192.168.1.1";std::vector<int> scan_port_list;bool scan_ref = CalculationPort("80,443,445,135,139", scan_port_list);if (scan_ref == true){// 循环取出需要扫描的端口对目标进行扫描for (int x = 0; x < scan_port_list.size(); x++){bool is_open = PortScan(scan_address, scan_port_list[x], 1000);if (is_open == true){std::cout << "扫描地址: " << scan_address << " 扫描端口: " << scan_port_list[x] << " 扫描状态: 端口开放" << std::endl;}else{std::cout << "扫描地址: " << scan_address << " 扫描端口: " << scan_port_list[x] << " 扫描状态: 端口关闭" << std::endl;}}}std::system("pause");return 0;
}

运行上述代码即可扫描地址192.168.1.1下的80,443,445,135,139端口开放状态,如下图所示;

增加参数解析

Boost Program Options 是Boost库中的一个模块,用于处理程序的命令行选项。它提供了一个灵活的框架,使得开发者能够轻松地解析和处理命令行参数。

#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <string>
#include <boost/asio.hpp> 
#include <boost/bind.hpp>  
#include <boost/date_time/posix_time/posix_time_types.hpp>#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>#include <boost/program_options.hpp>using namespace std;
using namespace boost;
using boost::asio::ip::tcp;
namespace opt = boost::program_options;int main(int argc, char * argv[])
{opt::options_description des_cmd("\n Usage: LyShark 端口扫描器 Ver:1.0 \n\n Options");des_cmd.add_options()("address,a", opt::value<std::string>()->default_value("127.0.0.1"), "指定扫描地址")("set_port,s", opt::value<std::string>()->default_value("none"), "设置扫描端口")("help,h", "帮助菜单");opt::variables_map virtual_map;try{opt::store(opt::parse_command_line(argc, argv, des_cmd), virtual_map);}catch (...){ return 0; }// 定义消息opt::notify(virtual_map);// 无参数直接返回if (virtual_map.empty()){return 0;}else if (virtual_map.count("help") || virtual_map.count("h")){std::cout << des_cmd << std::endl;return 0;}else if (virtual_map.count("address") && virtual_map.count("set_port")){std::string address = virtual_map["address"].as<std::string>();std::string set_port = virtual_map["set_port"].as<std::string>();// 判断是不是默认参数if (address == "127.0.0.1" || set_port == "none"){std::cout << des_cmd << std::endl;}else{// 执行扫描流程std::vector<int> scan_port_list;bool scan_ref = CalculationPort(set_port, scan_port_list);if (scan_ref == true){// 循环取出需要扫描的端口对目标进行扫描for (int x = 0; x < scan_port_list.size(); x++){bool is_open = PortScan(address, scan_port_list[x], 1000);if (is_open == true){std::cout << "扫描地址: " << address << " 扫描端口: " << scan_port_list[x] << " 扫描状态: 端口开放" << std::endl;}else{std::cout << "扫描地址: " << address << " 扫描端口: " << scan_port_list[x] << " 扫描状态: 端口关闭" << std::endl;}}}}}else{std::cout << "参数错误" << std::endl;}return 0;std::system("pause");return 0;
}

当有了命令解析功能,我们就可以向程序内传入参数,如下所示;

多线程扫描
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <string>
#include <boost/asio.hpp> 
#include <boost/bind.hpp>  
#include <boost/date_time/posix_time/posix_time_types.hpp>#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>#include <boost/program_options.hpp>#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread_guard.hpp>using namespace std;
using namespace boost;
using boost::asio::ip::tcp;
namespace opt = boost::program_options;boost::mutex io_mutex;// 实现多线程扫描
void MyThread(std::string address, int port)
{bool is_open = PortScan(address, port, 1000);// boost::mutex::scoped_lock lock(io_mutex);boost::lock_guard<boost::mutex> global_mutex(io_mutex);if (is_open == true){std::cout << "扫描地址: " << address << " 扫描端口: " << port << " 扫描状态: 开放" << std::endl;}else{std::cout << "扫描地址: " << address << " 扫描端口: " << port << " 扫描状态: 关闭" << std::endl;}
}int main(int argc, char * argv[])
{opt::options_description des_cmd("\n Usage: LyShark 端口扫描器 Ver:1.0 \n\n Options");des_cmd.add_options()("address,a", opt::value<std::string>()->default_value("127.0.0.1"), "指定扫描地址")("set_port,s", opt::value<std::string>()->default_value("none"), "设置扫描端口")("help,h", "帮助菜单");opt::variables_map virtual_map;try{opt::store(opt::parse_command_line(argc, argv, des_cmd), virtual_map);}catch (...){ return 0; }// 定义消息opt::notify(virtual_map);// 无参数直接返回if (virtual_map.empty()){return 0;}else if (virtual_map.count("help") || virtual_map.count("h")){std::cout << des_cmd << std::endl;return 0;}else if (virtual_map.count("address") && virtual_map.count("set_port")){std::string address = virtual_map["address"].as<std::string>();std::string set_port = virtual_map["set_port"].as<std::string>();// 判断是不是默认参数if (address == "127.0.0.1" || set_port == "none"){std::cout << des_cmd << std::endl;}else{// 执行扫描流程std::vector<int> scan_port_list;bool scan_ref = CalculationPort(set_port, scan_port_list);if (scan_ref == true){boost::thread_group group;// 循环取出需要扫描的端口对目标进行扫描for (int x = 0; x < scan_port_list.size(); x++){group.create_thread(boost::bind(MyThread, address, scan_port_list[x]));}group.join_all();}}}else{std::cout << "参数错误" << std::endl;}return 0;std::system("pause");return 0;
}

运行效果如下图所示,通过使用多线程可提高程序的扫描效率。

完整扫描器代码
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <string>
#include <boost/asio.hpp> 
#include <boost/bind.hpp>  
#include <boost/date_time/posix_time/posix_time_types.hpp>#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>#include <boost/program_options.hpp>#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread_guard.hpp>using namespace std;
using namespace boost;
using boost::asio::ip::tcp;
namespace opt = boost::program_options;boost::mutex io_mutex;void ShowOpt()
{fprintf(stderr,"#                       #                          #       \n""#                       #                          #       \n""#     #    #    #####   ######    ######   # ###   #   ##  \n""#     #    #   #        #     #  #     #   ##      #  #    \n""#     #    #    ####    #     #  #     #   #       ###     \n""#      #####        #   #     #  #    ##   #       #  #    \n""#####      #   #####    #     #   #### #   #       #   ##  \n\n");
}// 异步连接地址与端口
class AsyncConnect
{
public:AsyncConnect(boost::asio::io_service& ios, tcp::socket &s):io_service_(ios), timer_(ios), socket_(s) {}// 异步连接bool aysnc_connect(const tcp::endpoint &ep, int million_seconds){bool connect_success = false;// 异步连接,当连接成功后将触发 connect_handle 函数socket_.async_connect(ep, boost::bind(&AsyncConnect::connect_handle, this, _1, boost::ref(connect_success)));// 设置一个定时器  million_seconds timer_.expires_from_now(boost::posix_time::milliseconds(million_seconds));bool timeout = false;// 异步等待 如果超时则执行 timer_handletimer_.async_wait(boost::bind(&AsyncConnect::timer_handle, this, _1, boost::ref(timeout)));do{// 等待异步操作完成io_service_.run_one();// 判断如果timeout没超时,或者是连接建立了,则不再等待} while (!timeout && !connect_success);timer_.cancel();return connect_success;}private:// 如果连接成功了,则 connect_success = truevoid connect_handle(boost::system::error_code ec, bool &connect_success){if (!ec){connect_success = true;}}// 定时器超时timeout = truevoid timer_handle(boost::system::error_code ec, bool &timeout){if (!ec){socket_.close();timeout = true;}}boost::asio::io_service &io_service_;boost::asio::deadline_timer timer_;tcp::socket &socket_;
};// 封装端口扫描函数
bool PortScan(std::string address, int port, int timeout)
{try{boost::asio::io_service io;tcp::socket socket(io);AsyncConnect acHandler(io, socket);tcp::endpoint ep(boost::asio::ip::address::from_string(address), port);// 传递扫描ep地址结构,以及超时时间if (acHandler.aysnc_connect(ep, timeout)){io.run();return true;}else{return false;}}catch (...){return false;}
}// 传递IP地址范围,自动生成IP地址表
bool CalculationAddress(std::string address, std::vector<std::string> &ref)
{std::vector<std::string> vect;try{// 以/,两个下划线作为切割符号,切割后放入vect容器中boost::split(vect, address, boost::is_any_of("/") || boost::is_any_of("."), boost::token_compress_on);// 将开始和结束地址取出来int start_count = lexical_cast<int>(vect[3]);int end_count = lexical_cast<int>(vect[4]);// IP地址中的C段必须小于255if (end_count <= 255){for (int x = start_count; x <= end_count; x++){std::string this_address = boost::str(boost::format("%s.%s.%s.%s") % vect[0] % vect[1] % vect[2] % x);ref.push_back(this_address);}}else{return false;}}catch (...){return false;}return true;
}// 传递端口字符串,解析为vector容器
bool CalculationPort(std::string port_string, std::vector<int> &ref)
{std::vector<std::string> vect;try{boost::split(vect, port_string, boost::is_any_of(","), boost::token_compress_on);for (int x = 0; x < vect.size(); x++){ref.push_back(lexical_cast<int>(vect[x]));}return true;}catch (...){return false;}return true;
}// 实现多线程扫描
void MyThread(std::string address, int port)
{bool is_open = PortScan(address, port, 1000);// boost::mutex::scoped_lock lock(io_mutex);boost::lock_guard<boost::mutex> global_mutex(io_mutex);if (is_open == true){std::cout << "扫描地址: " << address << " 扫描端口: " << port << " 扫描状态: 开放" << std::endl;}else{std::cout << "扫描地址: " << address << " 扫描端口: " << port << " 扫描状态: 关闭" << std::endl;}
}// 实现全端口线程扫描
void MyThreadB(std::string address, int port)
{bool is_open = PortScan(address, port, 1000);// boost::mutex::scoped_lock lock(io_mutex);boost::lock_guard<boost::mutex> global_mutex(io_mutex);if (is_open == true){std::cout << "扫描地址: " << address << " 扫描端口: " << port << " 扫描状态: 开放" << std::endl;}
}int main(int argc, char * argv[])
{opt::options_description des_cmd("\n Usage: LyShark 端口扫描器 Ver:1.1 \n\n Options");des_cmd.add_options()("address,a", opt::value<std::string>(), "指定扫描地址 192.168.1.1")("c_address,c", opt::value<std::string>(), "设置扫描C地址段 192.168.1.1/24")("set_port,s", opt::value<std::string>(), "设置扫描端口 80,443,135,139")("type,t", opt::value<std::string>(), "对特定主机 扫描 1-65535 全端口")("help,h", "帮助菜单");opt::variables_map virtual_map;try{opt::store(opt::parse_command_line(argc, argv, des_cmd), virtual_map);}catch (...){ return 0; }// 定义消息opt::notify(virtual_map);// 无参数直接返回if (virtual_map.empty()){ShowOpt();std::cout << des_cmd << std::endl;return 0;}else if (virtual_map.count("help") || virtual_map.count("h")){ShowOpt();std::cout << des_cmd << std::endl;return 0;}// 扫描全端口else if (virtual_map.count("address") && virtual_map.count("type")){std::string address = virtual_map["address"].as<std::string>();std::string type = virtual_map["type"].as<std::string>();if (address.length() != 0 && type == "all"){// 执行全端口扫描boost::thread_group group;for (int x = 0; x < 65534; x++){group.create_thread(boost::bind(MyThreadB, address, x));_sleep(50);}group.join_all();}}// 扫描特定端口else if (virtual_map.count("address") && virtual_map.count("set_port")){std::string address = virtual_map["address"].as<std::string>();std::string set_port = virtual_map["set_port"].as<std::string>();// 执行特定端口扫描std::vector<int> scan_port_list;bool scan_ref = CalculationPort(set_port, scan_port_list);if (scan_ref == true){boost::thread_group group;// 循环取出需要扫描的端口对目标进行扫描for (int x = 0; x < scan_port_list.size(); x++){group.create_thread(boost::bind(MyThread, address, scan_port_list[x]));}group.join_all();}}// 扫描特定地址段中的特定端口else if (virtual_map.count("c_address") && virtual_map.count("set_port")){std::string c_address = virtual_map["c_address"].as < std::string >();std::string set_port = virtual_map["set_port"].as<std::string>();// 计算出需要扫描的端口std::vector<int> scan_port_list;bool scan_port_ref = CalculationPort(set_port, scan_port_list);// 计算出需要扫描的地址段std::vector < std::string > scan_address_list;bool scan_address_ref = CalculationAddress(c_address, scan_address_list);if (scan_port_ref == true && scan_address_ref == true){// 分别取出每一个IP地址for (int x = 0; x < scan_address_list.size(); x++){boost::thread_group group;// 对每一个IP地址中的端口段进行扫描for (int y = 0; y < scan_port_list.size(); y++){group.create_thread(boost::bind(MyThreadB, scan_address_list[x], scan_port_list[y]));}group.join_all();}}}else{std::cout << "参数错误" << std::endl;}return 0;
}

至此,一个基于ASIO异步模型的,多线程端口扫描器就这么完成了,总结帮助手册。

  • 扫描全端口: lyscanner.exe --address 192.168.1.1 --type all
  • 扫描整个C段: lyscanner.exe --c_address 192.168.1.1/10 --set_port 22,25
  • 特定端口扫描: lyscanner.exe --address 192.168.1.1 --set_port 22,25,135,139

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

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

相关文章

springboot项目中获取业务功能的导入数据模板文件

场景: 在实际业务场景中,经常会遇到某些管理功能需要数据导入共功能,但既然是导入数据,肯定会有规则限制,有规则就会有数据模板,但这个模板一般是让客户自己下载固定规则模板,而不是让客户自己随便上传模板。下面介绍直接下载模板 一、下载模板示例 1、在项目的…

Mysql查看Binlog文件

前期准备 检查是否开启binlog mysql> SHOW VARIABLES LIKE log_bin; // 或者 mysql> SHOW VARIABLES LIKE log%;ON代表开启&#xff0c;OFF代表关闭。如为OFF需 开启 后才能查看&#xff0c;但只能查看开启之后时间点的。 查看binlog文件有哪些 一般yum安装的mysql…

Program Header Table(转载)

程序头表与段表相互独立&#xff0c;由ELF文件头统一管理。 程序头表负责ELF文件从文件到加载后映像的映射关系&#xff0c;一般只有可执行文件包含。 1. segment和section segment: 程序头表项描述的对象称为segment&#xff0c;即elf文件加载后的数据块&#xff1b; 它提供…

微服务开发中,使用AOP和自定义注解实现对权限的校验

一、背景 微服务开发中&#xff0c;暴露在外网的接口&#xff0c;为了访问的安全&#xff0c;都是需要在http请求中传入登录时颁发的token。这时候&#xff0c;我们需要有专门用来做校验token并解析用户信息的服务。如下图所示&#xff0c;http请求先经过api网关&#xff0c;网…

[点云分割] 欧式距离分割

效果&#xff1a; 代码&#xff1a; #include <iostream> #include <chrono>#include <pcl/ModelCoefficients.h> // 模型系数的定义 #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> // 各种点云数据类型 #include <pcl/sample_c…

java“贪吃蛇”小游戏

基于java实现贪吃蛇小游戏&#xff0c;主要通过绘制不同的图片并以一定速度一帧一帧地在窗体上进行展示。 我是在javaSwing项目下创建了一个包 名字叫做&#xff1a;Snakes包 包下有一个启动类和一个设置代码的主界面两个类 代码主界面&#xff1a; 代码主界面主要讲解的是 …

window文件夹下python脚本实现批量删除无法预览的图片

你是否遇到过下载的图片会发现有些图片会无法预览情况&#xff1f; 有几种原因可能导致一些图片在预览时无法正常显示&#xff1a; 损坏的图片文件&#xff1a; 图片文件可能损坏或者部分损坏&#xff0c;导致无法被正常解析和预览。这种情况可能是因为文件在传输过程中损坏、…

机器学习入门(第二天)——感知机

概述 每个算法都是为了解决一类问题&#xff0c;或者说解决之前的问题所创造出来的&#xff0c;而感知机&#xff0c;在解决一类问题的时候也暴露了很多问题&#xff0c;变相的推动了以后的算法的改进方向。 知识树 苹果表示相对重要的 直观介绍 现在有一盘红豆和绿豆&#…

2014年8月20日 Go生态洞察:Go在OSCON的精彩亮相

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

网络异常检测

随着社交网络、视频流、点对点技术、云计算和 SaaS 的出现&#xff0c;可以肯定地说&#xff0c;现代企业的好坏取决于他们的网络&#xff0c;尤其是在它们提供的带宽和安全性方面。无论是银行保护其数据免遭盗窃&#xff0c;还是商业组织保护其网络免受安全威胁和攻击&#xf…

ChatGLM-6B下载安装

ChatGLM-6B下载安装 项目指向 想把模型下载本地微调 通过官网指引需要先下载git-lfs #Linux 下载安装 curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash sudo apt-get install git-lfs git lfs install如果是docker中的虚拟机…

如何隐藏自己的代码(很酷)

1.引入 幻想当我们成为一名优秀的程序员&#xff0c;有着各大公司想要买我们的代码&#xff0c;但我们并不想要让他们知道我们代码的实现&#xff0c;毕竟一复制便可以解决&#xff0c;这里我们希望有一种方法可以把我们的核心代码给隐藏掉&#xff0c;那我们又应该怎么去实现呢…

官宣!代理IP品牌「一连IP」正式上线

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 今天&#xff0c;企业级代理IP供应商【一连IP】…

通过AX6000路由器,实现外部访问内网的任意主机

概述 这里遇到一个场景,就是需要外部的人员,访问我内网的一台设备,进行内外部的设备联调。 这也是实际环境中,很常见的一种场景。 之前的做法是子设备上运行edge节点,可以直接访问。 但有的设备无法运行edge节点,那么可以参考一下这个方案来实现。 此方案可以摒弃了…

系列九、Entry的key为什么要设计成弱引用

一、Entry的key为什么要设计成弱引用 1.1、四大引用类型 Java中的四种引用 1.2、Entry源码 1.3、为什么设计为弱引用 1.3.1、官网 To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys。 1.3.2、ThreadLocal引用示意…

每日一练 | 华为认证真题练习Day135

1、如果一个以太网数据帧的Length/Tyme0z8100&#xff0c;那么这个数据帧的载荷可能是&#xff1f;&#xff08;多选&#xff09; A. TCP数据段 B. UDP数据 C. ICMP报文 D. ARP报文 2、如图所示&#xff0c;路由器R1上部署了静态NAT命令&#xff0c;当PC访问互联网时&#…

【iOS】知乎日报

文章目录 前言一、首页1.网络的异步请求2.避免同一网络请求执行多次3.下拉刷新与上拉加载的实现下拉刷新上拉加载 二、网页1.webView的实现2.webView的滑动加载3.网页与首页内容的同步更新 三、评论区Masonory实现行高自适应 四、收藏中心通过FMDB实现数据持久化1.创建或打开数…

python中的exec()、eval()以及complie()

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 1.eval函数 函数的作用&#xff1a; 计算指定表达式的值。 也就是说它要执行的python代码只能是单个表达式&#xff08;注意eval不支持任何形式的赋值操作&…

git命令 cherry-pick

参考&#xff1a;https://blog.csdn.net/weixin_42585386/article/details/128256149 https://blog.csdn.net/weixin_44799217/article/details/128279250 merge和cherry-pick的区别&#xff1a; merge&#xff1a;是把某一个代码分支完全合并到当前的代码分支。完全合并的意…

TensorFlow实战教程(一)-TensorFlow环境部署

从本篇文章开始,作者正式开始研究Python深度学习、神经网络及人工智能相关知识。第一篇文章主要讲解神经网络基础概念,同时讲解TensorFlow2.0的安装过程及基础用法,主要结合作者之前的博客和"莫烦大神"的视频介绍,后面随着深入会讲解具体的项目及应用。基础性文章…