分析某款go扫描器之五

2024-05-11 02:20

本文主要是介绍分析某款go扫描器之五,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、概述

前面几篇文章已经把实现的功能都说完了,这篇主要分析下启动函数,并且说明脚本的参数项作用。

项目来源:https://github.com/XinRoom/go-portScan/blob/main/util/file.go

二、cmd/go-portScan.go

1、设置全局变量

这些变量被定义为在整个程序中使用的全局变量,用于存储命令行参数的值


var (ipStr       stringportStr     stringpn          boolpt          boolsT          boolrate        intsV          booltimeout     intrateP       inthostGroup   intiL          stringdevices     boolnexthop     stringhttpx       boolnetLive     boolmaxOpenPort intoCsv        stringoFile       string
)

2、命令行参数的解析

  • func parseFlag(c *cli.Context)

这个函数的作用是解析命令行参数,并将解析后的值存储到全局变量中。它利用了 cli.Context 对象来获取命令行中各个选项的值,并将这些值存储到程序中事先定义好的全局变量中。

// 从命令行参数获取各个选项的值,并存储到对应的全局变量中
func parseFlag(c *cli.Context) {ipStr = c.String("ip")iL = c.String("iL")portStr = c.String("port")nexthop = c.String("nexthop")devices = c.Bool("devices")pn = c.Bool("Pn")rateP = c.Int("rateP")hostGroup = c.Int("hostGroup")pt = c.Bool("PT")rate = c.Int("rate")sT = c.Bool("sT")sV = c.Bool("sV")timeout = c.Int("timeout")httpx = c.Bool("httpx")netLive = c.Bool("netLive")maxOpenPort = c.Int("maxOpenPort")oCsv = c.String("oCsv")oFile = c.String("oFile")
}
  • func run(c *cli.Context) error

这个函数是应用程序的主要执行逻辑,主要负责根据命令行参数执行相应的操作。它首先根据不同的命令行参数进行一些设置,比如忽略特定信号、初始化日志记录器,并根据特定的选项执行相应的操作。例如:

  • 如果设置了 -nohup 选项,则忽略 SIGHUP 和 SIGTERM 信号。
  • 如果设置了 -devices 选项,则调用 syn.GetAllDevs() 函数来列出设备信息。
  • 如果未提供 IP 或端口参数,则显示应用程序的帮助信息并退出。
  • 如果端口参数是 -,则将其替换为默认的端口范围。

接下来的部分代码,根据不同的参数设置,进行了一系列的初始化和配置操作,包括解析 IP 和端口、初始化并发池、进行扫描任务、收集扫描结果等。

总体而言,run 函数是这个程序的核心逻辑部分,负责根据命令行参数配置和执行相应的扫描任务,以及对结果进行处理和输出。

func run(c *cli.Context) error {if c.NumFlags() == 0 {cli.ShowAppHelpAndExit(c, 0)}parseFlag(c)// 执行具体的扫描任务if c.Bool("nohup") {// 忽略SIGHUP和SIGTERM信号signal.Ignore(syscall.SIGHUP)signal.Ignore(syscall.SIGTERM)}myLog := util.NewLogger(oFile, true)// 检查是否需要列出设备信息if devices {if r, err := syn.GetAllDevs(); err != nil {myLog.Fatal(err.Error())} else {myLog.Print(r)}os.Exit(0)}// 检查IP和端口参数,如果参数为空,则显示应用程序帮助信息并退出if ipStr == "" && iL == "" {cli.ShowAppHelpAndExit(c, 0)}if portStr == "-" {portStr = "1-65535"}ipRangeGroup := make([]*iprange.Iter, 0)// ip parsevar firstIp net.IPvar ips []stringif ipStr != "" {ips = strings.Split(ipStr, ",")}if iL != "" {var err errorips, err = util.GetLines(iL)if err != nil {myLog.Fatalf("open file failed: %s", err.Error())}}for _, _ip := range ips {it, startIp, err := iprange.NewIter(_ip)if err != nil {var iprecords []net.IPiprecords, _ = net.LookupIP(_ip)if len(iprecords) > 0 {_ip = iprecords[0].String()} else {myLog.Fatalf("[error] %s is not ip/hostname!\n", _ip)}it, startIp, err = iprange.NewIter(_ip)if err != nil {myLog.Fatalf("[error] %s is not ip!\n", _ip)}}if firstIp == nil {firstIp = startIp}ipRangeGroup = append(ipRangeGroup, it)}// netLivevar wgIpsLive sync.WaitGroup// Pool - ipsLivepoolIpsLive, _ := ants.NewPoolWithFunc(rateP, func(ip interface{}) {_ip := ip.([]net.IP)for _, ip2 := range _ip {if host.IsLive(ip2.String(), pt, time.Duration(tcp.DefaultTcpOption.Timeout)*time.Millisecond) {myLog.Printf("[+] %s is live\n", ip2.String())break}}wgIpsLive.Done()})defer poolIpsLive.Release()if netLive {// 按c段探测for _, ir := range ipRangeGroup { // ip groupfor i := uint64(0); i < ir.TotalNum(); i = i + 256 { // ip indexip := make(net.IP, len(ir.GetIpByIndex(0)))copy(ip, ir.GetIpByIndex(i)) // Note: dup copy []byte when concurrent (GetIpByIndex not to do dup copy)ipLastByte := []byte{1, 2, 254, 253, byte(100 + rand.Intn(20)), byte(200 + rand.Intn(20))}ips2 := make([]net.IP, 6)for j := 0; j < 6; j++ {ips2[j] = make(net.IP, len(ip))ip[3] = ipLastByte[j]copy(ips2[j], ip)}wgIpsLive.Add(1)poolIpsLive.Invoke(ips2)}}wgIpsLive.Wait()return nil}// port parseports, err := port.ShuffleParseAndMergeTopPorts(portStr)if err != nil {myLog.Fatalf("[error] %s is not port!\n", err)}// recvsingle := make(chan struct{})retChan := make(chan port.OpenIpPort, 5000)// ip port num statusipPortNumMap := make(map[string]int) // 记录该IP端口开放数量var ipPortNumRW sync.RWMutex// csv outputvar csvFile *os.Filevar csvWrite *csv.Writerif oCsv != "" {csvFile, err = os.Create(oCsv)if err != nil {myLog.Fatalln("[-]", err)}defer csvFile.Close()csvWrite = csv.NewWriter(csvFile)csvWrite.Write([]string{"IP", "PORT", "SERVICE", "BANNER", "HTTP_TITLE", "HTTP_STATUS", "HTTP_SERVER", "HTTP_TLS", "HTTP_FINGERS"})}go func() {for ret := range retChan {if maxOpenPort > 0 {ipPortNumRW.Lock()if _, ok := ipPortNumMap[ret.Ip.String()]; ok {ipPortNumMap[ret.Ip.String()] += 1}ipPortNumRW.Unlock()}myLog.Println(ret.String())if csvWrite != nil {line := []string{ret.Ip.String(), strconv.Itoa(int(ret.Port)), ret.Service, "", "", "", "", "", ""}line[3] = strings.NewReplacer("\\r", "\r", "\\n", "\n").Replace(strings.Trim(strconv.Quote(string(ret.Banner)), "\""))if ret.HttpInfo != nil {line[4] = ret.HttpInfo.Titleline[5] = strconv.Itoa(ret.HttpInfo.StatusCode)line[6] = ret.HttpInfo.Serverline[7] = ret.HttpInfo.TlsCNline[8] = strings.Join(ret.HttpInfo.Fingers, ",")}csvWrite.Write(line)csvWrite.Flush()csvFile.Sync()}}single <- struct{}{}}()// Initialize the Scannervar s port.Scanneroption := port.Option{Rate:        rate,Timeout:     timeout,NextHop:     nexthop,FingerPrint: sV,Httpx:       httpx,}if sT {// tcpif option.Rate == -1 {option.Rate = tcp.DefaultTcpOption.Rate}if option.Timeout == -1 {option.Timeout = tcp.DefaultTcpOption.Timeout}s, err = tcp.NewTcpScanner(retChan, option)} else {// synif option.Rate == -1 {option.Rate = syn.DefaultSynOption.Rate}if option.Timeout == -1 {option.Timeout = syn.DefaultSynOption.Timeout}s, err = syn.NewSynScanner(firstIp, retChan, option)}if err != nil {fmt.Fprintf(os.Stderr, "[error] Initialize Scanner: %s\n", err)os.Exit(-1)}start := time.Now()var wgPing sync.WaitGroup// port scan funcportScan := func(ip net.IP) {var ipPortNum intvar ipPortNumOk boolif maxOpenPort > 0 {ipPortNumRW.Lock()ipPortNumMap[ip.String()] = 0ipPortNumRW.Unlock()}for _, _port := range ports { // ports.WaitLimiter() // limit rateif maxOpenPort > 0 {ipPortNumRW.RLock()ipPortNum, ipPortNumOk = ipPortNumMap[ip.String()]ipPortNumRW.RUnlock()if ipPortNumOk && ipPortNum >= maxOpenPort {break}}s.Scan(ip, _port)}if maxOpenPort > 0 {ipPortNumRW.Lock()delete(ipPortNumMap, ip.String())ipPortNumRW.Unlock()}}// host group scan funcvar wgHostScan sync.WaitGrouphostScan, _ := ants.NewPoolWithFunc(hostGroup, func(ip interface{}) {_ip := ip.(net.IP)portScan(_ip)wgHostScan.Done()})defer hostScan.Release()// Pool - ping and port scanpoolPing, _ := ants.NewPoolWithFunc(rateP, func(ip interface{}) {_ip := ip.(net.IP)if host.IsLive(_ip.String(), pt, time.Duration(option.Timeout)*time.Millisecond) {wgHostScan.Add(1)hostScan.Invoke(_ip)}wgPing.Done()})defer poolPing.Release()// start scanfor _, ir := range ipRangeGroup { // ip groupshuffle := util.NewShuffle(ir.TotalNum())    // shufflefor i := uint64(0); i < ir.TotalNum(); i++ { // ip indexip := make(net.IP, len(ir.GetIpByIndex(0)))copy(ip, ir.GetIpByIndex(shuffle.Get(i))) // Note: dup copy []byte when concurrent (GetIpByIndex not to do dup copy)if !pn {                                  // pingwgPing.Add(1)_ = poolPing.Invoke(ip)} else {wgHostScan.Add(1)hostScan.Invoke(ip)}}}wgPing.Wait()     // PING组wgHostScan.Wait() // HostGroupSs.Wait()          // 扫描器-等s.Close()         // 扫描器-收<-single          // 接收器-收myLog.Printf("[*] elapsed time: %s\n", time.Since(start))return nil
}
}

3、主函数

  • 1
  • main 函数是整个程序的入口点。
  • cli.App 结构中,通过设置 NameDescription 来定义应用程序的名称和描述。
  • Action: run 指定当执行命令时调用的函数为 run 函数。
  • Flags 列表包含了各种命令行选项,比如 -ip-port 等。每个选项使用 cli.Flag 定义了选项的名称、用法说明、是否必需以及默认值。
  • 这段代码的作用是初始化一个命令行应用程序,并定义了一系列命令行选项。当程序运行时,它会解析命令行参数,并根据这些参数执行相应的操作,其中 err := app.Run(os.Args) 表示运行应用程序,并使用 os.Args 中的参数作为输入参数。如果运行过程中出现错误,则会将错误信息打印到控制台。

func main() {app := &cli.App{Name:        "PortScan",Description: "High-performance port scanner",Action:      run,Flags: []cli.Flag{&cli.StringFlag{Name:     "ip",Usage:    "target ip, eg: \"1.1.1.1/30,1.1.1.1-1.1.1.2,1.1.1.1-2\"",Required: false,Value:    "",},&cli.StringFlag{Name:     "iL",Usage:    "target ip file, eg: \"ips.txt\"",Required: false,Value:    "",},&cli.StringFlag{Name:    "port",Aliases: []string{"p"},Usage:   "eg: \"top1000,5612,65120,-\"",Value:   "top1000",},&cli.BoolFlag{Name:  "Pn",Usage: "no ping probe",Value: false,},&cli.IntFlag{Name:    "rateP",Aliases: []string{"rp"},Usage:   "concurrent num when ping probe each ip",Value:   300,},&cli.IntFlag{Name:    "hostGroup",Aliases: []string{"hp"},Usage:   "host concurrent num",Value:   200,},&cli.BoolFlag{Name:  "PT",Usage: "use TCP-PING mode",Value: false,},&cli.BoolFlag{Name:  "sT",Usage: "TCP-mode(support IPv4 and IPv6)",Value: false,},&cli.IntFlag{Name:    "timeout",Aliases: []string{"to"},Usage:   "TCP-mode SYN-mode timeout. unit is ms.",Value:   800,},&cli.BoolFlag{Name:  "sS",Usage: "Use SYN-mode(Only IPv4)",Value: true,},&cli.StringFlag{Name:    "nexthop",Aliases: []string{"nh"},Usage:   "specified nexthop gw add to pcap dev",Value:   "",},&cli.IntFlag{Name:    "rate",Aliases: []string{"r"},Usage:   fmt.Sprintf("number of packets sent per second. If set -1, TCP-mode is %d, SYN-mode is %d(SYN-mode is restricted by the network adapter, 2000=1M)", tcp.DefaultTcpOption.Rate, syn.DefaultSynOption.Rate),Value:   -1,},&cli.BoolFlag{Name:    "devices",Aliases: []string{"ld"},Usage:   "list devices name",Value:   false,},&cli.BoolFlag{Name:  "sV",Usage: "port service identify",Value: false,},&cli.BoolFlag{Name:  "httpx",Usage: "http server identify",Value: false,},&cli.BoolFlag{Name:  "netLive",Usage: "Detect live C-class networks, eg: -ip 192.168.0.0/16,172.16.0.0/12,10.0.0.0/8",Value: false,},&cli.IntFlag{Name:    "maxOpenPort",Aliases: []string{"mop"},Usage:   "Stop the ip scan, when the number of open-port is maxOpenPort",Value:   0,},&cli.StringFlag{Name:    "oCsv",Aliases: []string{"oC"},Usage:   "output csv file",Value:   "",},&cli.StringFlag{Name:    "oFile",Aliases: []string{"o"},Usage:   "output to file",Value:   "",},&cli.BoolFlag{Name:  "nohup",Usage: "nohup",Value: false,},},}err := app.Run(os.Args)if err != nil {fmt.Println("err:", err)}
}

这篇关于分析某款go扫描器之五的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/978236

相关文章

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

go基础知识归纳总结

无缓冲的 channel 和有缓冲的 channel 的区别? 在 Go 语言中,channel 是用来在 goroutines 之间传递数据的主要机制。它们有两种类型:无缓冲的 channel 和有缓冲的 channel。 无缓冲的 channel 行为:无缓冲的 channel 是一种同步的通信方式,发送和接收必须同时发生。如果一个 goroutine 试图通过无缓冲 channel

如何确定 Go 语言中 HTTP 连接池的最佳参数?

确定 Go 语言中 HTTP 连接池的最佳参数可以通过以下几种方式: 一、分析应用场景和需求 并发请求量: 确定应用程序在特定时间段内可能同时发起的 HTTP 请求数量。如果并发请求量很高,需要设置较大的连接池参数以满足需求。例如,对于一个高并发的 Web 服务,可能同时有数百个请求在处理,此时需要较大的连接池大小。可以通过压力测试工具模拟高并发场景,观察系统在不同并发请求下的性能表现,从而

【软考】希尔排序算法分析

目录 1. c代码2. 运行截图3. 运行解析 1. c代码 #include <stdio.h>#include <stdlib.h> void shellSort(int data[], int n){// 划分的数组,例如8个数则为[4, 2, 1]int *delta;int k;// i控制delta的轮次int i;// 临时变量,换值int temp;in

三相直流无刷电机(BLDC)控制算法实现:BLDC有感启动算法思路分析

一枚从事路径规划算法、运动控制算法、BLDC/FOC电机控制算法、工控、物联网工程师,爱吃土豆。如有需要技术交流或者需要方案帮助、需求:以下为联系方式—V 方案1:通过霍尔传感器IO中断触发换相 1.1 整体执行思路 霍尔传感器U、V、W三相通过IO+EXIT中断的方式进行霍尔传感器数据的读取。将IO口配置为上升沿+下降沿中断触发的方式。当霍尔传感器信号发生发生信号的变化就会触发中断在中断