作者: 墨阳
免责声明:本文仅供学习研究,严禁从事非法活动,任何后果由使用者本人负责。

0x00 前言

最近开始学习GO语言,希望可以摆脱脚本小子的苦恼,在需要的时候可以根据需要写一些小工具。在做信息搜集的时候无意间发现了一个网站,提供了API接口,于是产生了通过脚本来方便的获取数据的想法。脚本很简单也比较基础,需要的功能百度一下就可以找到实现方法,学习完基本语法就可以来写些小工具啦。由于只用到了一个网站,所以数据肯定是不全面的,后续有需要可以自行添加。

本文中用到的网站是dnsgrep.cn,提供了API查询接口,接口token需要邮箱申请,免费的。

0x01 实现

1、思路

既然是走的网站接口,那么首先需要发送一个请求,获取网站的响应并且解析数据,然后将解析的数据输出出来。首先分析一下网站响应数据的格式。

可以看到,返回的数据时json格式,go语言提供了json.Unmarshal()函数来解析json数据,整理一下json格式,这里如果数据很长可以用在线的json格式美化网站

GET /api/query?q=[ip或者域名]&token=[申请的token值] HTTP/2
Host: www.dnsgrep.cn
Cookie: UM_distinctid=17c89fa6562f0f-061b1aa8d7f106-6373267-1fa400-17c89fa6563847; CNZZDATA1279463756=1182095902-1634402460-%7C1634822243
Sec-Ch-Ua: "Chromium";v="91", " Not;A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Language: zh-CN,zh;q=0.9
Accept-Encoding: gzip, deflate
Connection: close子域名格式:
{"status":200,"data":{"data":[{"domain":"wolai.com","value":"139.196.188.106","type":"A","time":"2021-06-26"},{"domain":"wolai.com","value":"5 mxbiz1.qq.com","type":"MX","time":"2021-06-28"},{"domain":"www.wolai.com","value":"www.wolai.com.w.kunlunca.com","type":"CNAME","time":"2021-06-27"}],"count":16,"type":1}
}ip反查格式:
{"status":200,"data":{"data":[{"domain":"47.98.84.224","value":"47.98.84.224","type":"A","time":"2021-06-25"},{"domain":"a.zhongan.com","value":"47.98.84.224","type":"A","time":"2021-06-25"},{"domain":"zhongan-xflow-nginx.zhongan.com","value":"47.98.84.224","type":"A","time":"2021-06-27"},{"domain":"zhongan.com","value":"47.98.84.224","type":"A","time":"2021-06-27"}],"count":24,"type":2}
}

子域名查询和ip反查的格式是一样的。首先最外层是status、data两个字段,status是int类型,data字段内容又包含了data、count和type字段,内层的data是一个字典的切片,count和type是int类型。下面来构造一下存放解析数据的结构体,这里可以使用结构体嵌套。

//外层的字段
type JsonData struct {Status    int       `json:"status"`Data      Info      `json:"data"`
}
//内层字段
type Info struct {Data    []map[string]string  `json:"data"`Count   intType    int
}

这里建了一个vars的包,用于定义整个程序的全局变量

package varstype JsonData struct {Status    int       `json:"status"`Data      Info      `json:"data"`
}
type Info struct {Data    []map[string]string  `json:"data"`Count   intType    int
}var (//声明一个全局变量V,JsonData类型,用于存放数据V JsonDataTarget string
)

2、函数部分

建一个util包,用于程序调用的函数部分,首先,是对网站接口的请求函数:

func Request(target string) []byte {//start := time.Now()//由于默认的GET方法使用的默认的client没有超时时间,可以自定义一个client来设置超时时间client := &http.Client{Timeout: 5*time.Second}url := "https://www.dnsgrep.cn/api/query?q="+target+"&token=[邮箱申请的token]"resp,err := client.Get(url)if err != nil {fmt.Println("请求链接失败!",err)return nil}else if resp.Status != "200 OK" {                //判断状态码fmt.Println("请求链接失败,状态码不为200!")return nil}defer resp.Body.Close()//读取响应的bodytext,err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Println("读取响应失败!",err)return nil}//end := time.Since(start)//fmt.Printf("请求数据用时:%s",end)return text
}

下面来写解析json数据的函数:

func GetInfo(jsonData []byte) {if jsonData == nil {fmt.Println("获取数据失败!")return}//将json格式反序列化,存放到变量V中err := json.Unmarshal(jsonData, &vars.V)if err != nil {fmt.Println("数据解析失败!", err)return}
}

现在已经获得了网站数据的解析结果,接下来就要将结果显示出来,普通的打印的方式由于数据长度不一致导致每行信息长短不一,不能对齐,不便于查看,这里使用了github.com/liushuochen/gotable三方库来进行表格化输出:

func OutPut()  {fmt.Printf("共检索到%d条数据\n",len(vars.V.Data.Data))//定义一个表格tb,err := gotable.Create("domain","value","type","time")if err != nil{fmt.Println("创建表格失败!",err)os.Exit(0)}//添加行,因为V.Data.Data是一个字典切片,可以直接用tb.AddRows()批量添加tb.AddRows(vars.V.Data.Data)//输出表格tb.PrintTable()
}

如果我们想将结果保存到excel中,可以使用三方库github.com/xuri/excelize/v2来实现:

func WriteExcel()  {f := excelize.NewFile()// 设置表头f.SetCellValue("Sheet1", "A1", "Domain")f.SetCellValue("Sheet1", "B1", "Value")f.SetCellValue("Sheet1", "C1", "Type")f.SetCellValue("Sheet1", "D1", "Time")//遍历数据,写到对应的列中for i,r := range vars.V.Data.Data{num := strconv.Itoa(i+2)                        //num用来控制写到哪行,第一个数据i=0,应该写到第二行f.SetCellValue("Sheet1", "A"+num, r["domain"])f.SetCellValue("Sheet1", "B"+num, r["value"])f.SetCellValue("Sheet1", "C"+num, r["type"])f.SetCellValue("Sheet1", "D"+num, r["time"])}// 根据指定路径保存文件if err := f.SaveAs("Result.xlsx"); err != nil {println(err.Error())}
}

3、主函数部分

上面通过不同函数实现了所需要的功能,接下来就要在主函数中调用:

对于需要输入参数部分,可以使用三方库github.com/urfave/cli来实现

package mainimport ("dnsgrep/util""dnsgrep/vars""fmt""github.com/urfave/cli""os""time"
)func main()  {start := time.Now()//设置参数部分app := &cli.App{Name: "脚本名称",Author: "作者",Version: "2021-11-01",Usage: "简介",Flags: []cli.Flag{            //设定参数的标志&cli.StringFlag{Name: "t",            //参数名称Value: "",            //设置参数的默认值Usage: "target,域名或ip",    //参数介绍,将显示在-h中Destination: &vars.Target,        //将输入的参数赋值给vars包中定义的全局变量Target},},Action: func(c *cli.Context) {//检查是否输入了目标参数,没输入直接退出if c.IsSet("t") == false{fmt.Println("请输入查询目标,-h查看参数!")os.Exit(0)}},}app.Run(os.Args)if vars.Target == "" {os.Exit(0)}//发送请求并将返回值用作GetInfo()函数的输入util.GetInfo(util.Request(vars.Target))util.OutPut()util.WriteExcel()//统计程序运行时间end := time.Since(start)fmt.Printf("共用时:%s",end)
}

4、util包完整代码

package utilimport ("dnsgrep/vars""encoding/json""fmt""github.com/liushuochen/gotable""github.com/xuri/excelize/v2""io/ioutil""net/http""os""strconv""time"
)func Request(target string) []byte {start := time.Now()client := &http.Client{Timeout: 5*time.Second}url := "https://www.dnsgrep.cn/api/query?q="+target+"&token=[申请的token值]"resp,err := client.Get(url)if err != nil {fmt.Println("请求链接失败!",err)return nil}else if resp.Status != "200 OK" {fmt.Println("请求链接失败,状态码不为200!")return nil}defer resp.Body.Close()text,err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Println("读取响应失败!",err)return nil}end := time.Since(start)fmt.Printf("请求数据用时:%s",end)return text
}func GetInfo(jsonData []byte) {if jsonData == nil {fmt.Println("获取数据失败!")return}err := json.Unmarshal(jsonData, &vars.V)if err != nil {fmt.Println("数据解析失败!", err)return}
}func OutPut()  {fmt.Printf("共检索到%d条数据\n",len(vars.V.Data.Data))tb,err := gotable.Create("domain","value","type","time")if err != nil{fmt.Println("创建表格失败!",err)os.Exit(0)}tb.AddRows(vars.V.Data.Data)tb.PrintTable()
}func WriteExcel()  {f := excelize.NewFile()f.SetCellValue("Sheet1", "A1", "Domain")f.SetCellValue("Sheet1", "B1", "Value")f.SetCellValue("Sheet1", "C1", "Type")f.SetCellValue("Sheet1", "D1", "Time")for i,r := range vars.V.Data.Data{num := strconv.Itoa(i+2)f.SetCellValue("Sheet1", "A"+num, r["domain"])f.SetCellValue("Sheet1", "B"+num, r["value"])f.SetCellValue("Sheet1", "C"+num, r["type"])f.SetCellValue("Sheet1", "D"+num, r["time"])}if err := f.SaveAs("Result.xlsx"); err != nil {println(err.Error())}
}

0x03 运行结果

运行一下,看看是不是我们想要的结果

0x04 总结

一个简单的单任务单线程的脚本就写好了。由于查询网站的单一,数据肯定是不全的,那么根据需要,可以自行扩展。下一篇会将这个脚本完善一下,改成多任务的多线程的查询,并简单优化一下使用体验。
项目地址:https://github.com/MoYang233/subdomain-demo/tree/main/subdomain-demo1

0x05 了解更多安全知识

欢迎关注我们的安全公众号,学习更多安全知识!!!
欢迎关注我们的安全公众号,学习更多安全知识!!!
欢迎关注我们的安全公众号,学习更多安全知识!!!

GO工具开发|基于网站API的子域名与IP反查工具(一)相关推荐

  1. GO工具开发|基于网站API的子域名与IP反查工具(二)

    作者:墨阳 免责声明:本文仅供学习研究,严禁从事非法活动,任何后果由使用者本人负责. 0x00 前言 上一篇实现了一个简单的子域名查询和ip反查工具,但是当我们的目标比较多时,一个一个查询体验并不友好 ...

  2. p76 - Python 开发-内外网收集 Socket子域名DNS

    数据来源 本文仅用于信息安全学习,请遵守相关法律法规,严禁用于非法途径.若观众因此作出任何危害网络安全的行为,后果自负,与本人无关. Python 开发相关知识点: 1.开发基础环境配置说明      ...

  3. 第76天:Python开发-内外网收集Socket子域名DNS

    Python开发-内外网收集Socket&子域名&DNS 判断对方是否使用cdn 通过python执行系统命令nslookup返回的结果来进行判断 def cdn(url):#执行系统 ...

  4. 网站存活,ip反查,权重备案查询(方法)

    常用漏洞库: 佩奇漏洞文库: https://www.yuque.com/peiqiwiki/peiqi-poc-wiki http://wiki.peiqi.tech/ 白阁漏洞文库: https: ...

  5. IP反查网站,ip反查接口,旁站查询接口大全,通过IP查域名汇总,域名历史解析记录查询,IP地址查对应机房名称、地址,查IP地址的AS号码...

    IP反查网站,ip反查接口,旁站查询接口大全,通过IP查域名汇总: http://bgp.he.net/,IP地址查对应机房:IP地址在 bgp.he.net 直接能查到IP所属机房或运营商的AS号. ...

  6. IP反查网站/IP反查接口 域名汇总

    IP反查网站,ip反查接口,旁站查询接口大全,通过IP查域名汇总,域名历史解析记录查询,IP地址查对应机房名称.地址,查IP地址的AS号码. IP反查网站,ip反查接口,旁站查询接口大全,通过IP查域 ...

  7. [linux驱动开发] 基于gpiod API的platform总线多个led驱动开发

    gpiod API对platform-led进行驱动开发 修改设备树源码 如何在驱动中获取设备树节点信息 计算设备子节点数量 给私有属性分配内存 对子节点进行遍历 gpiod的获取 根据设备树字节给的 ...

  8. 第76天-Python 开发-内外网收集 Socket子域名

    思维导图 知识点 应急响应补充知识点 挖矿靶机分析 PDF 外加其他 应急响应资源包 提取码:xiao Python 开发相关知识点 1.开发基础环境配置说明 Windows10+Pycharm 2. ...

  9. python安全开发——内外网收集 Socket子域名DNS

    前言: 做渗透测试,第一步就是进行信息收集,对于具体的环境下,需要不同的测试需求,通过自己编写的脚本进行测试会有事半功倍的效果,本文主要介绍了在信息收集的时候,我们可能使用到的库函数. 本人水平有限, ...

最新文章

  1. 【卷积码系列2】(n,k,m)卷积码的生成多项式矩阵系数转网格图描述(不使用MATLAB库函数)
  2. MySQL5.7 semi-sync replication功能增强
  3. 呼叫中心客服交流三大法宝
  4. Android 版权介绍
  5. 以串结构存储c语言版,【数据结构(C语言版)系列四】 串
  6. Scrapy: 爬虫返回403错误
  7. 阿里iconfont矢量图库使用
  8. Webgl开发输入框兼容问题及开发注意的问题
  9. 魔兽争霸无法在这个计算机,win10系统魔兽争霸按F1无法选中自己的英雄的图文办法...
  10. for循环小技巧,遍历数组的时候要使用恰当
  11. supersu二进制更新安装失败_supersu二进制更新失败怎么办 supersu二进制更新失败解决方法...
  12. TAMER——Training an Agent Manually Via Evaluative Reinforcement
  13. 如何在Nginx上 安装SSL证书
  14. Vue2Editor 中文API
  15. bupt信通院上机第一学期实验四(30-37) 指针
  16. 三、实现LED花样流水
  17. 还想朝九晚五?不可能!
  18. 删除的微信聊天记录如何恢复
  19. js 时间戳转成正常时间
  20. 如何在Excel中查找和替换文本和数字

热门文章

  1. EDG为何刷爆你的朋友圈?是什么让年轻人那么激动?作为程序员你关注了么?
  2. 终端改变字体颜色和背景,控制光标,设置屏幕,更改样式与ANSI Esc(\033,\x1B,\e)转义序列用法
  3. C语言概述:什么是C语言?
  4. 字符串匹配 KMP算法 C++
  5. 【ECM技术】ECM(Enhanced Compression Model)帧间技术总结
  6. win2008r2用户账户控制什么意思_UX名词解读“用户体验度量”到底是什么意思?/ZOE的笔记...
  7. 香农费诺编码 c语言实现,对于香农编码、费诺编码和哈夫曼编码,编码方法惟一的是()。...
  8. 服务器个人买能干什么_动态vps是干什么用的?拨号VPS的作用功能是什么?
  9. 持续学习常用6种方法总结:使ML模型适应新数据的同时保持旧数据的性能
  10. XMD RAC(Oracle 9i) 存儲修復處理