穆望 发表于 2025-6-1 21:13:23

Go红队开发—格式导出

目录

[*]输出功能

[*]CSV输出

[*]CSV 转 结构体
[*]结构体 转 CSV
[*]端口扫描结果使用CSV格式导出

[*]HTML输出
[*]Sqlite输出

[*]nmap扫描

[*]JSON

[*]map转json
[*]结构体转json
[*]json写入文件
[*]json编解码
[*]json转结构体
[*]json转map
[*]json转string
[*]练习:nmap扫描结果导出json格式



输出功能

在我们使用安全工具的时候基本都会有一个输出功能,同样也很重要,所以下面介绍csv、json、html、sqlite的输出格式。
CSV输出

下载包:go get -u github.com/gocarina/gocsv使用之前先明确我们要csv格式干什么:

[*]首先一些数据可能就是存在csv文件里面,需要我们提取出来的话就需要另外写函数,但是现在有现成的包使用就很方便了
[*]其次我们使用一些安全工具的时候经常会有导出格式为csv格式的,所以在开发过程中也是一个很重要的需求,使用Gocsv包会很方便
同理我们往后的其他格式也一样的需求。
CSV 转 结构体

test.csv文件内容为:

1.在CSV转结构体的时候,我们需要构造一个结构体,用来接收CSV文件中的表头
type Person struct {

    Id   string `csv:"id"`

    Name string `csv:"name"`

    Age  int    `csv:"age"`

}2.解析csv文件
// 解析CSV文件

func anlyzeCSV() {

    file, err := os.OpenFile(

        "test.csv",

        os.O_RDWR|os.O_CREATE,

        0666,

    )

    defer file.Close()

    if err != nil {

        fmt.Println("打开文件失败:", err)

    }



    person := []*Person{}

    if err := gocsv.UnmarshalFile(file, &person); err != nil { //UnmarshalFile将文件解析为结构体

        fmt.Println("解析文件失败:", err)

    }

    fmt.Println("id,name,age")

    for _, p := range person {

        fmt.Println(p.Id, p.Name, p.Age)

    }

}结构体 转 CSV

// 写入CSV文件

func writeCSV() {

    file, err := os.OpenFile("test.csv", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

    if err != nil {

        fmt.Println("打开文件失败:", err)

    }

    defer file.Close()

    person := []*Person{}

    person = append(person, &Person{

        Id:   "1",

        Name: "李四",

        Age:  20,

    })

    err = gocsv.MarshalFile(&person, file) //MarshalFile将数据写入文件

    if err != nil {

        fmt.Println("写入文件失败:", err)

    }

}端口扫描结果使用CSV格式导出

结合之前的端口扫描练习,将结果通过所学的知识CSV格式输出
这里我对之前的练习进行了一个改造,就是让输出美观一点,同时修改了传参与返回值,目的都是为了拿到扫描完成的端口结果。
为了写进csv还创建了一个结构体。
函数中大部分代码其实都是格式的转换,主要功能其实学会了上面基本都能做了。
所以这里我在放代码前说一下我遇到的问题:

[*]csv的表头要修改的话是比较困难,我没有找到一个比较好的办法,就是在写入csv的代码过程中,修改csv表头,我的解决办法是通过开一个新的结构体,通过老结构体的数据传递到新的结构体中就能够修改csv头写进文件里了(这里有大佬知道解决办法可以告诉我一下)
[*]时间格式化有问题,时间格式一定只能用他给出的几种时间:- "2006-01-02 15:04:05":表示 年-月-日 时:分:秒 格式,如果你修改一下2006年改为2002年都是会格式化出错,这一点尝试了几回发现原来是格式时间数字也固定的表达的。
[*]你要写入的结构体的变量名首个字母要大写,一定要大写,否则他会报错,可能这也是一种规范吧,反正不大写就会报错。最后的那个示例代码你可以尝试把HostPort结构体中的ScanTime修改首字母小写scanTime,很好的验证了小写的时候出现的错误,当然我运行的时候没有报错,但是他实际上是他没有吧你的时间写进csv中,也代码出错了,可以观察验证一下确实不能小写只能首字母大写。
[*]自定义格式实现MarshalCSV接口后,在写入的时候会自动调用该函数,你可以在该函数进行一些初始化或者格式化动作等等。
这补充一下时间格式化的代码:
// 格式化时间time.Time类型

func timeFormat(t time.Time) string {

    return t.Format("2006年1月2日") //转为string类型

}


// Parse将string类型转为time.Time类型

func timeParse(t string) time.Time {

    tm, _ := time.Parse("2006-01-02 15:04:05", t)

    return tm

}代码示例:(成功将扫描结果存到csv中保存)

// 稍微改一下代码,return一个port回来,然后输出到csv中func start_WaitGroup_scan_port(host string) ([]int, time.Time) {    var (        wg      sync.WaitGroup        ch      = make(chan int, 1024) // 增加缓冲区,减少阻塞        count   int        workers = 100 // 控制并发数    )    var scanPort = func(hostname string, port int) {        defer wg.Done()        address := fmt.Sprintf("%s:%d", hostname, port)        conn, err := net.DialTimeout("tcp", address, 2*time.Second)        if err == nil {            conn.Close()            ch
页: [1]
查看完整版本: Go红队开发—格式导出