分析某款go端口扫描器之一

2023-11-30 18:36
文章标签 分析 go 端口扫描 某款

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

一、概述

        进来在学go的端口检测部分,但是自己写遇到很多问题,又不知道从何入手,故找来网上佬们写的现成工具,学习一波怎么实现的。分析过程杂乱,没啥思路,勿喷。

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

二、目录结构分析

总体来说,这个工具主要三部分,cmd(主程序)、core(核心框架部分)、util(工具部分),后续的分析也从这三个部分开始讲解

三、util目录

此目录下主要有三个文件,分别为file.go、log.go、shuffle.go,以下逐一分析

1、file.go(逐行读取文件内容)

  • func GetLines(filename string) (out []string, err error)

主要内容为一个GetLines方法,其接收一个文件名作为参数,并返回文件中非空行的内容组成字符串切片和可能的错误,主要作用是逐行读取文件,并将非空行的内容添加到“out"切片中。

func GetLines(filename string) (out []string, err error) {if filename == "" {//先判断文件名是否为空,为空则提示错误return out, errors.New("no filename")}file, err := os.Open(filename)//打开文件if err != nil {return out, err}defer file.Close()//读取完记得关闭scanner := bufio.NewScanner(file)//读取文件的内容scanner.Split(bufio.ScanLines)//一行一行读取分隔for scanner.Scan() {//逐行读取并将文本内容追加到out切片中line := strings.TrimSpace(scanner.Text())if line != "" {out = append(out, line)}}return
}

2、log.go(日志记录)

  • func NewLogger(filename string, std bool) *log.Logger

主要内容为一个 NewLogger方法,它根据提供的参数创建一个新的日志记录器对象。该函数接受一个文件名和一个布尔值参数。

  • filename 参数用于指定日志输出的文件名,如果为空字符串则表示日志将输出到标准输出(stdout)。
  • std 参数是一个布尔值,如果设置为 true,则日志会同时输出到文件和标准输出;如果设置为 false,则只输出到文件。

这个函数的目的是根据参数创建一个日志记录器,可以指定输出到文件还是标准输出,并可以选择是否同时输出到文件和标准输出。

func NewLogger(filename string, std bool) *log.Logger {var out io.Writerif filename == "" {out = os.Stdout //如果传入的filename为空,将out设置为标准输出} else {//如果不为空,则打开这个文件,outFile, _ := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)if std {//如果 std为true,则将输出同时定向到标准输出和文件中,通过 io.MultiWriter 将os.Stdout 和打开的文件合并成一个多写入器out = io.MultiWriter(os.Stdout, outFile)} else {//如果 std 参数为 false,则直接将输出定向到打开的文件中out = outFile}}logger := log.New(out, "", 0)//使用 log.New 方法创建一个新的日志记录器对象 logger,将输出对象 out 作为日志记录器的输出,设置空的前缀,并且不添加任何额外的选项(flag)return logger
}

3、shuffle.go

主要包含3个方法:NewShuffle、Get、IsUint16InList,以及一个结构体Shuffle

  • type Shuffle struct

type Shuffle struct {rl   []uint16 // 乱序序列,存储的是一般轮次的乱序序列rl2  []uint16 // 最后一轮乱序序列(无法整除时使用)n    uint16   // 乱序精度,用来限制乱序序列的长度size uint64    //乱序序列的大小
}
  • func NewShuffle(size uint64) *Shuffle

函数接收一个 size 参数作为生成乱序序列的大小。

// NewShuffle 局部乱序
func NewShuffle(size uint64) *Shuffle {if size == 0 { //如果size为0, 返回nilreturn nil}sf := &Shuffle{size: size}// 创建一个新的 Shuffle 结构体,设置其 size 字段为传入的值if size > 100 {sf.n = 100 //如果size>100,设置乱序精度为100} else {sf.n = uint16(size)//否则设置乱序精度为size 的 uint16 类型。}//通过循环填充 rl 切片,创建一般轮次的乱序序列。//使用 rand 包生成随机数种子,对 rl 进行乱序化操作。//如果 size 无法整除 n,则设置 rl2 切片,并生成最后一轮乱序序列// 通用轮次sf.rl = make([]uint16, sf.n)for i := uint16(0); i < sf.n; i++ {sf.rl[i] = i}// 洗牌方法r := rand.New(rand.NewSource(int64(size)))r.Shuffle(int(sf.n), func(i, j int) {sf.rl[i], sf.rl[j] = sf.rl[j], sf.rl[i]})// 最后一轮无法整除时新建对应长度的rl2t := uint16(size % uint64(sf.n))if t != 0 {sf.rl2 = make([]uint16, t)for i := uint16(0); i < t; i++ {sf.rl2[i] = i}r.Shuffle(int(t), func(i, j int) {sf.rl2[i], sf.rl2[j] = sf.rl2[j], sf.rl2[i]})}return sf
}
  • func (sf *Shuffle) Get(index uint64) uint6

Get 方法接收一个索引 index,用于获取转换后的索引值。首先计算 t 为 index 对 sf.n 取模得到的结果。然后根据索引 index 与 n 的关系,决定使用哪个乱序序列。如果无法整除,则使用 rl2,否则使用 rl

// Get 根据索引获取转换后的索引值
func (sf *Shuffle) Get(index uint64) uint64 {t := index % uint64(sf.n)// 最后一轮无法整除时用rl2if index-t+uint64(sf.n) > sf.size {return index - t + uint64(sf.rl2[uint16(t)])}return index - t + uint64(sf.rl[uint16(t)])
}
  • func IsUint16InList(code uint16, list []uint16) bool

IsUint16InList 函数接收一个 code 和一个 list,用于判断 list 中是否存在 code。

它遍历 list 切片,如果发现存在与 code 相等的元素,则返回 true;如果遍历完 list 后都没有找到,则返回 false。

func IsUint16InList(code uint16, list []uint16) bool {for _, e := range list {if e == code {return true}}return false
}

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



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

相关文章

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

Python 迭代器和生成器概念及场景分析

《Python迭代器和生成器概念及场景分析》yield是Python中实现惰性计算和协程的核心工具,结合send()、throw()、close()等方法,能够构建高效、灵活的数据流和控制流模型,这... 目录迭代器的介绍自定义迭代器省略的迭代器生产器的介绍yield的普通用法yield的高级用法yidle

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序