使用Masscan扫描器进行信息搜集

📅 2026/8/26 20:24:29
使用Masscan扫描器进行信息搜集
Masscan 是一款极为高效的端口扫描工具以其卓越的扫描速度和大规模扫描能力而著称。该工具不仅支持 TCP 和 UDP 协议的扫描还允许用户根据需求灵活指定多个目标和端口。Masscan 通过采用先进的网络性能优化技术充分利用操作系统的资源和多核处理能力实现了极高的扫描效率和吞吐量。其强大的性能使它能在短时间内扫便互联网的每个角落。使用 Masscan用户可以迅速了解目标主机的服务状态和潜在漏洞并且工具提供多种灵活的输出格式和报告便于后续的分析和处理。源代码编译由于该扫描器的底层采用了Npcap接口实现因此在使用扫描器之前用户需要先下载并安装Npcap库。安装完成后用户需要下载Masscan的源代码可以点击masscan-1.3.2.zip下载版本。我们以下载源代码为例下载好以后将其解压缩至任意位置。其中masscan-1.3.2/vs10目录下为Windows平台下的解决方案读者可以使用Visual Studio打开该项目。在打开后会让读者升级项目此时点击升级即可当升级结束后若直接对项目进行编译则会出现错误提示。此时读者可打开微软针对编译器的说明网站由于笔者使用的是Visual Studio 2013则其对应的_MSC_VER为1800读者只需要记录下这个编号。接着读者可在解决方案管理器内找到misc目录并打开string_s.h头文件打开后定位到第58行并将其中的1900替换为1800并保存文件至此再次点击编译生成即可。当生成结束后会在其bin目录下得到masscan.exe扫描器成品。使用扫描器探测使用Masscan扫描常见的TCP和UDP端口可以在命令中直接指定。但默认情况下只会扫描TCP端口若要扫描UDP端口则需要额外的参数配置。不过Masscan 对于UDP扫描的支持并不如TCP扫描那样全面建议在需要进行深入的UDP扫描时使用Nmap等工具。我们通过使用-p参数来执行扫描常见的TCP端口此处进扫描的端口包括 FTP21、SSH22、Telnet23、SMTP25、DNS53、HTTP80、POP3110、NetBIOS139、IMAP143、HTTPS443、SMB445、RDP3389。使用U来指定扫描UDP端口此处扫描的端口包括DNS53、NTP123、SNMP161在扫描时我们通过使用0.0.0.0/8来指定网段。使用-oJ指定将扫描结果生成为JSON格式的报告当然也可使用-oX指定生成XML报告。masscan -p21,22,23,25,53,80,110,139,143,443,445,3389,U:53,U:123,U:1610.0.0.0/8-oJoutput.json若要扫描整个互联网则需要通过--exclude 255.255.255.255来指明。如下命令所示通过0.0.0.0/0指定扫描全网段并通过-p参数指定仅扫描HTTP80及HTTPS443执行命令后则会对整个互联网中的所有Web服务器进行探测并输出为output_all.json格式的报告。masscan -p80,4430.0.0.0/0--exclude255.255.255.255-oJoutput_all.json运用GeoIP2数据库解析GeoIP2 是由MaxMind提供的一套地理位置数据库和API用于将IP地址映射到地理位置信息。GeoIP2 数据库可以提供关于IP地址的详细地理信息如国家、城市、经纬度、时区、自治系统AS等。其被广泛应用于各类需要地理位置数据的场景如内容定制、安全、广告投放和数据分析等。GeoIP2数据包含两部分内容首先读者需要使用pip install geoip2来安装Python版本的接口其次读者还需要自行下载对应的GeoLite2 database 数据库文件。解析扫描结果在之前我们通过使用Masscan扫描器扫描了世界范围内的所有Web服务器存活状态并将扫描结果存储为了output_all.json格式的JSON文件中接下来我们将通过使用Python解析这个数据库文件并输出解析到的结果。封装parse_scan_results函数该函数接收一个扫描结果并将该扫描结果解析为一个列表嵌套字典的格式其中包含了基本的扫描信息例如主机IP地址、扫描时间、端口号、TTL值等并返回这个列表给调用者。importjsonfromdatetimeimportdatetime,timezoneimportgeoip2.database 解析扫描结果文件并返回一个包含字典的列表。 :param filename: 包含扫描结果的 JSON 文件路径 :return: 一个包含解析结果的列表每个元素是一个字典 defparse_scan_results(filename):results_list[]# 从文件中读取 JSON 数据withopen(filename,r)asfile:datajson.load(file)# 提取所需的信息并保存到列表中forresultindata:ipresult[ip]timestampint(result[timestamp])# 转换时间戳为具体时间readable_timedatetime.fromtimestamp(timestamp,timezone.utc).strftime(%Y-%m-%d %H:%M:%S)forport_infoinresult[ports]:portport_info[port]ttlport_info[ttl]# 将结果保存到字典中result_dict{IP地址:ip,扫描时间:readable_time,端口:port,TTL:ttl}results_list.append(result_dict)returnresults_list封装get_geo_info函数该函数通过使用GeoIP2数据库打开并查询IP地址的详细位置信息并将该信息转换为一个字典格式返回给调用者。 通过 GeoIP2 数据库查询 IP 地址的地理信息。 :param ip_address: 需要查询的 IP 地址 :param db_path: GeoIP2 数据库文件的路径 :return: 包含地理信息的字典 defget_geo_info(ip_address,db_path):try:# 打开 GeoIP2 数据库readergeoip2.database.Reader(db_path)# 查询 IP 地址的地理信息responsereader.city(ip_address)# 提取所需的地理信息geo_info{国家:response.country.name,国家ISO代码:response.country.iso_code,省份:response.subdivisions.most_specific.name,省份ISO代码:response.subdivisions.most_specific.iso_code,城市:response.city.name,邮政编码:response.postal.code,纬度:response.location.latitude,经度:response.location.longitude,时区:response.location.time_zone,精度半径:response.location.accuracy_radius,大洲:response.continent.name,大洲代码:response.continent.code}# 关闭数据库reader.close()returngeo_infoexceptFileNotFoundError:# print(f数据库文件 {db_path} 未找到。)return{}exceptgeoip2.errors.AddressNotFoundError:# print(fIP 地址 {ip_address} 未找到地理信息。)return{}exceptExceptionase:# print(f出现错误: {e})return{}封装combine_scan_geo_info函数用于将结合扫描结果和地理信息生成包含完整信息的列表嵌套字典。封装format_combined_results函数用于 格式化解析后的扫描结果和地理信息并返回一个包含字典的列表。 结合扫描结果和地理信息生成包含完整信息的列表嵌套字典。 :param scan_results: 扫描结果列表 :param db_path: GeoIP2 数据库文件的路径 :return: 包含完整信息的列表每个元素是一个字典 defcombine_scan_geo_info(scan_results,db_path):combined_results[]forresultinscan_results:ipresult[IP地址]geo_infoget_geo_info(ip,db_path)combined_result{**result,**geo_info}combined_results.append(combined_result)returncombined_results 格式化解析后的扫描结果和地理信息返回一个包含字典的列表。 :param results_list: 包含扫描结果和地理信息的列表每个元素是一个字典 :return: 格式化后的结果列表 defformat_combined_results(results_list):formatted_results[]forresultinresults_list:formatted_result{IP地址:result.get(IP地址,),扫描时间:result.get(扫描时间,),端口:result.get(端口,),TTL:result.get(TTL,),国家:result.get(国家,),国家ISO代码:result.get(国家ISO代码,),省份:result.get(省份,),省份ISO代码:result.get(省份ISO代码,),城市:result.get(城市,),邮政编码:result.get(邮政编码,),纬度:result.get(纬度,),经度:result.get(经度,),时区:result.get(时区,),精度半径:result.get(精度半径,),大洲:result.get(大洲,),大洲代码:result.get(大洲代码,)}formatted_results.append(formatted_result)returnformatted_results封装analyze_ip_distribution函数该函数用于分析IP地址的地理分布情况统计每个国家的IP地址数量并返回详细信息。 分析 IP 地址的地理分布情况统计每个国家的 IP 地址数量并返回详细信息。 :param results_list: 包含扫描结果和地理信息的列表每个元素是一个字典 :return: 包含国家、IP 列表和 IP 数量的列表每个元素是一个字典 defanalyze_ip_distribution(results_list):country_distribution{}forresultinresults_list:countryresult.get(国家,未知)ip_addressresult.get(IP地址,)ifcountrynotincountry_distribution:country_distribution[country]{国家:country,IP列表:[],数量:0}country_distribution[country][IP列表].append(ip_address)country_distribution[country][数量]1# 将字典转换为列表country_distribution_listlist(country_distribution.values())returncountry_distribution_list绘制全球IP数量分布通过调用analyze_ip_distribution函数我们还可以进一步分析这个扫描结果获取到不同国家的IP地址信息及所在国家的IP数量等代码如下所示if__name____main__:# 文件名filename./output_all.jsondb_path./GeoLite2-City.mmdb# 解析扫描结果scan_resultsparse_scan_results(filename)# 结合扫描结果和地理信息combined_resultscombine_scan_geo_info(scan_results,db_path)# 格式化结果formatted_resultsformat_combined_results(combined_results)# 分析 IP 地址的地理分布情况ip_distributionanalyze_ip_distribution(formatted_results)# 打印分析结果forcountry_infoinip_distribution:print(f国家:{country_info[国家]}, IP数量:{country_info[数量]}, IP列表:{country_info[IP列表]})运行上述代码则可获取到不同国家的IP分布信息如下图所示因扫描仅进行了一小部分则当前解析结果并不全面仅用于研究代码案例。接着通过使用pyecharts库我们根据IP地址数量及国家分布绘制一个数量分布柱状图实现代码如下所示frompyecharts.chartsimportBarfrompyechartsimportoptionsasoptsif__name____main__:# 文件名filename./output_all.jsondb_path./GeoLite2-City.mmdb# 解析扫描结果scan_resultsparse_scan_results(filename)# 结合扫描结果和地理信息combined_resultscombine_scan_geo_info(scan_results,db_path)# 格式化结果formatted_resultsformat_combined_results(combined_results)# 分析 IP 地址的地理分布情况ip_distributionanalyze_ip_distribution(formatted_results)# 过滤掉国家为美国的数据filtered_ip_distribution[country_infoforcountry_infoinip_distributionifcountry_info[国家]!United States]# 提取国家和IP数量countries[country_info[国家]forcountry_infoinfiltered_ip_distribution]ip_counts[country_info[数量]forcountry_infoinfiltered_ip_distribution]# 创建柱状图barBar()bar.add_xaxis(countries)bar.add_yaxis(IP数量,ip_counts)bar.set_global_opts(title_optsopts.TitleOpts(title全球IP数量分布不包括美国),xaxis_optsopts.AxisOpts(axislabel_optsopts.LabelOpts(rotate45)),yaxis_optsopts.AxisOpts(nameIP数量))# 渲染图表为HTML文件bar.render(ip_distribution.html)由于美国地区的IP地址过多此处为了能展示柱状图效果则忽略美国地区的IP数量这样能更好地展示柱状图分布其运行效果如下图所示绘制全球IP位置分布通过filename传入扫描后的记录信息并调用GeoLite2-City.mmdb城市数据库文件将IP地址解析并组合为一个新的扫描结果通过循环输出给用户。if__name____main__:# 文件名filename./output_all.jsondb_path./GeoLite2-City.mmdb# 解析扫描结果scan_resultsparse_scan_results(filename)# 结合扫描结果和地理信息combined_resultscombine_scan_geo_info(scan_results,db_path)# 格式化结果formatted_resultsformat_combined_results(combined_results)# 打印格式化后的结果forresultinformatted_results:print(result)通过循环的方式依次验证IP地址所对应的数据库信息读者可以获取到包括IP地址、扫描时间、扫描端口、TTL值、国家、国家ISO代码、省份、省份ISO代码、城市、邮政编码、纬度、经度、时区、精度半径、大洲、大洲代码等信息如下图所示KMLKeyhole Markup Language是一种用于表示地理数据的 XML 格式文件。KML 文件通常用于在地理信息系统GIS和地理应用如 Google Earth 和 Google Maps中显示地理数据。我们可以将扫描到的数据进行归纳并调用generate_kml_from_results函数提取出所需要的IP地址及经纬度信息并将其生成为一个独立的KML文件。defretKML(addr,longitude,latitude):# 确保 longitude 和 latitude 为浮点数如果为 None 或无效值则设置为 0.0try:longitudefloat(longitude)except(TypeError,ValueError):longitude0.0try:latitudefloat(latitude)except(TypeError,ValueError):latitude0.0kml(Placemark\nname{}/name\nPoint\ncoordinates{:.6f},{:.6f}/coordinates\n/Point\n/Placemark\n).format(addr,longitude,latitude)returnkmldefgenerate_kml_from_results(results_list,output_file):kmlheader?xml version1.0 encodingUTF-8?\nkml xmlnshttp://www.opengis.net/kml/2.2\nDocument\nkmlfooter/Document\n/kml\nwithopen(output_file,w)asf:f.write(kmlheader)forresultinresults_list:ipresult.get(IP地址,)longituderesult.get(经度,0.0)latituderesult.get(纬度,0.0)kml_placemarkretKML(ip,longitude,latitude)f.write(kml_placemark)f.write(kmlfooter)if__name____main__:# 文件名filename./output_all.jsondb_path./GeoLite2-City.mmdb# 解析扫描结果scan_resultsparse_scan_results(filename)# 结合扫描结果和地理信息combined_resultscombine_scan_geo_info(scan_results,db_path)# 格式化结果formatted_resultsformat_combined_results(combined_results)# 生成 KML 文件output_fileGoogleEarth.kmlgenerate_kml_from_results(formatted_results,output_file)通过将KML文件导入到谷歌地图中我们可以很直观的在地图上进行打点操作打点后每个国家的详细信息都将被呈现如下图所示通过拉近一个国家则可看到每一个打过标记的IP分布位置图如下所示至此本次的技术分享就到此结束了。事实上在获取到IP地址的在线状态后我们可以继续使用Nmap扫描器对其进行操作系统的鉴别。当鉴别到每一个IP地址的操作系统版本后我们就可以推测出这个国家所使用的操作系统比例并以此来衡量每个国家的操作系统普及程度及进一步评估其国家的系统安全系数。