GO语言开发GUI安全工具实践(一)

简介: GO语言开发GUI安全工具实践

在实际渗透中,我一直坚信一个思想,如果目标能够渗透进去,而我却没有成功,一定是信息收集的时候,没有收集到关键点。


本文只是一个引子,希望各位师傅们可以有所收获


我们平常少不了的收集手段是端口和目录。而端口我们可以用fofa或者nmap等这些已经灰常好的工具,让我们进行探测。


本文用于一个demo测试,表哥们可以自行改编


本文demo包括:


命令行下工具以及GUI工具,最后介绍一下B/S架构的思考


本人还在学习,所以代码有点菜比,思路最重要,嘤嘤嘤~



让我们早点摆脱脚本小子和ctrl+c ctrl+v工程师的名衔




首先,编写一个工具或者程序首先要有一个思想。



什么是目录探测呢?


第一,要发送请求是不是。


第二,我们要判断响应码是不是200。


第三,可能由于waf的存在,目录不存在响应码也是200,那我们是不是可以在目标站随便输入一个目录,故意让他报错,看他存在的报错信息,是什么,是"页面不存在,跳转"这种字符提示信息。还是提示404。那样是不是我们可以直接在源代码中匹配这些关键词,如果匹配成功我们就判断这个目录不存在。(简单的绕过技巧思路)



那下面我们开始一步一步分析:


import requests
a="https://www.baidu.com"
ret=requests.get(a)
if ret.status_code==200:
print("页面存在"+"响应码:"+str(ret.status_code))
else:
print("不存在")


在Python中我们可以用requests包去发送请求判断响应吗是不是200,如果是我们就判断它页面存在

package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
url := "https://www.baidu.com"
resp, err := http.Get(url)
/*http.Get 是创建HTTP请求的函数,
如果请求没有出错,resp这个结构体中会得到访问的请求
结果
*/
if err != nil {
fmt.Fprintf(os.Stderr, "error:%v\n", err)
//简单一点,可以直接Println("错误")
//把格式字符串输出到指定文件设备中,所以参数比printf多一个文件指针FILE*。
//os.Stderr用于显示错误信息,大多情况下等用于os.Stdout
}
b, err := ioutil.ReadAll(resp.Body)
cunhuo := resp.StatusCode
defer resp.Body.Close()
/*
关键字 defer 用于注册延迟调用。
这些些调用直到 return 前才被执。因此,可以用来做资源清理。
resp.Body字段
包括一个可读的服务器响应流
ioutil.ReadAll函数
从response中读取到全部内容
resp.Body.Close()
关闭resp Boby流
*/
if err != nil {
fmt.Println("Error!")
os.Exit(1)
}
if cunhuo == 200 {
fmt.Println(cunhuo)
fmt.Println("存在此页面")
} else {
fmt.Println("不存在此页面")
}
fmt.Printf("%s", b)
}

同样在Go语言内置包中"io/ioutil". "net/http"也提供了相应的方法来进行判断

提醒:根据Go包中规则,只有大写字母才能被引用,所以我们平常会一直看到大写字母开头的引用


if err != nil相当于Python中的try语句(异常处理机制)



我们现在可以得到一个响应码了,但我们正常的思路是在一个..../x(随机变量)这种方式,去循环请求服务器,不断的改变x的值,去查看什么情况下能够得到200的响应码


这时候我们便需要一个打开一个文件(这个文件作为我们的x的值)


在Python我们只需要写一个循环去请求字典中的值,然后写一个判断便可以了

import requests
a="http://220.249.52.134:49872/"
with open("1.txt","r") as f :
b=f.read().splitlines()
for i in b:
rep=requests.get(a+str(i))
if rep.status_code == 200:
print("存在此页面:"+a+str(i))
else:
print(a+str(i)+"不存在")


而在Go语言中我们同样使用此种思路,读取文件去循环发送请求

package main
import (
"bufio"
"fmt"
"net/http"
"os"
)
func main() {
//author yanmu
url := "http://220.249.52.134:49872/"
file, err := os.Open("1.txt")
//os包是系统标准库里面有操作系统相关的函数和变量,打开一个文件可以使用os.open
if err != nil {
fmt.Printf("文件读书失败")
}
defer func() {
file.Close()
}()
//定义一个立即执行的匿名函数
n := bufio.NewScanner(file)
/*
函数NewScanner返回一个Scanner结构体,这个返回值来自于函数参数file
*/
//fmt.Printf("%T-%d\n"m, n, n)
for n.Scan() {
//n.Scan()相当于其他语言的迭代器iterator,并把迭代器指向的数据存放到新的缓冲区里。新的缓冲区可以用n.Text()得到
//n.Scan()每一次调用都会调入一个新行,并且会自动将其行末的换行符去掉
//n.Scan()是一个bool类型,在这里为true
data := n.Text()
resp, err := http.Get(url + data)
if err != nil {
fmt.Fprintf(os.Stderr, "error:%v\n", err)
}
//b, err := ioutil.ReadAll(resp.Body)
cunhuo := resp.StatusCode
defer resp.Body.Close()
if err != nil {
fmt.Println("Error!")
os.Exit(1)
}
if cunhuo == 200 {
fmt.Println("存在此页面:" + url + data)
} else {
fmt.Println("不存在此页面:" + url + data)
}
//fmt.Printf("%s", b)
}
}

9428b68b4781c15ba16ba1330bbd018b_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


做为一个工具我们希望它有其的灵活性,就像大多数工具一样可以给定相对应的参数

在Python中我们可以使用optparse模块来指定我们的参数


import requests
import optparse
import sys
def main():
parser =optparse.OptionParser('- u <url>')
parser.add_option('-u',dest='a',type='string',help="url")
options,args=parser.parse_args()
if options.a==None:
print(parser.usage)
sys.exit()
else:
url=options.a
a=url
with open("1.txt","r") as f :
b=f.read().splitlines()
for i in b:
rep=requests.get(a+str(i))
if rep.status_code == 200:
print("存在此页面:"+a+str(i))
else:
print(a+str(i)+"不存在")
if __name__ == '__main__':
main()

6b53deffc7f6ab9d4f249e5c34c4b32d_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

在Go语言中我们同样可以运用flag包去接受我们的参数


package main
import (
"bufio"
"flag"
"fmt"
"net/http"
"os"
)
func main() {
var url string
flag.StringVar(&url, "url", "", "请输入一下你的URL")
flag.Parse()
if url == "" {
fmt.Println(`
        ▍ ★∴
   ....▍▍....█▍ ☆ ★∵ ..../
    ◥█▅▅██▅▅██▅▅▅▅▅███◤
    .◥███████████████◤
  ~~~~◥█████████████◤~~~~
雷石安全实验室出品
-h        查看相应步骤
版本       0.0001
`)
os.Exit(1)
}
file, err := os.Open("1.txt")
if err != nil {
fmt.Printf("文件读取失败")
}
defer func() {
file.Close()
}()
n := bufio.NewScanner(file)
//fmt.Printf("%T-%d\n"m, n, n)
//fmt.Printf("%T--\n", n.Scan())
//fmt.Println(n.Scan())
for n.Scan() {
data := n.Text()
resp, err := http.Get(url + data)
if err != nil {
fmt.Fprintf(os.Stderr, "error:%v\n", err)
}
//b, err := ioutil.ReadAll(resp.Body)
cunhuo := resp.StatusCode
defer resp.Body.Close()
if err != nil {
fmt.Println("Error!")
os.Exit(1)
}
if cunhuo == 200 {
fmt.Println("存在此页面:" + url + data)
} else {
fmt.Println("不存在此页面:" + url + data)
}
//fmt.Printf("%s", b)
}
}


我们有了灵活性以后,我们可以希望速度上快一点,不然我们扫完以后可能,就没有以后了(=,=)


在Python中我们可以threading模块去创建多线程


import requests
import threading
import time
import optparse
import sys
def test01(url):
try:
resp = requests.get(url, headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0'})
if resp.status_code == 200:
print('[**' + str(resp.status_code) + '**]' + ":" + url)
else:
print(url+str(resp.status_code))
except:
pass
threadm.release()
def test02(file,url):
for i in file.readlines():
urls = url+i.strip()
threadm.acquire()
t = threading.Thread(target=test01, args=(urls,))
threads.append(t)
t.start()
for t in threads:
t.join()
if __name__ == '__main__':
start = time.time()
threads = []
threadm = threading.BoundedSemaphore(500)
parser = optparse.OptionParser('- u <url>')
parser.add_option('-u', dest='a', type='string', help="url")
options, args = parser.parse_args()
if options.a == None:
print(parser.usage)
sys.exit()
else:
url = options.a
f= open('1.txt',encoding='utf-8')
test02(f,url)
end = time.time()
print(end-start)
f.close()

f0294e6bfe664e7954b9207a3bff4295_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png



package main
import (
"bufio"
"flag"
"fmt"
"net/http"
"os"
"sync"
"time"
)
//channel 通道是一个同步处理的过程
var wg sync.WaitGroup
//time.Time是一个结构体时间点
func testtime(start time.Time) {
fmt.Printf("耗时:%v", time.Since(start))
//func Since(t Time)Duration 表示自从t时刻以后过了多长时间,是一个时间段
}
//开启一个goroutines
func test01(file *os.File, url string, urls chan string) {
n := bufio.NewScanner(file)
for n.Scan() {
var okurl = fmt.Sprintf("%s%s", url, n.Text()) // Sprintf() 是把格式化字符串输出到指定的字符串中,可以用一个变量来接受,然后在打印
urls <- okurl                                  //向urls通道中写入完整的url
}
err := n.Err()
if err != nil {
fmt.Println("Error!")
}
close(urls)
fmt.Println("读取完毕")
}
func main() {
var url string
flag.StringVar(&url, "url", "", "请输入一下你的URL")
flag.Parse()
if url == "" {
fmt.Println(`
        ▍ ★∴
   ....▍▍....█▍ ☆ ★∵ ..../
    ◥█▅▅██▅▅██▅▅▅▅▅███◤
    .◥███████████████◤
  ~~~~◥█████████████◤~~~~
雷石安全实验室出品
-h        查看相应步骤
版本       0.0001test
`)
os.Exit(1)
}
times := time.Now()
urls := make(chan string)
file, err := os.Open("1.txt")
if err != nil {
fmt.Println("字典打开失败: ", err)
return
}
defer testtime(times)
defer file.Close()
go test01(file, url, urls)
//开启多个goroutines
for i := 0; i < 200; i++ {
wg.Add(1)
go gourl(urls)
}
wg.Wait()
}
func gourl(urls chan string) {
for {
/*
Go里面提供了一个关键字select,通过select可以监听channel上的数据流动。
select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。
select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。
*/
select {
case url, ok := <-urls:
if !ok {
wg.Done()
return
}
//Golang通过http.NewRequest实现模拟请求,添加请求头和请求参数:
client := &http.Client{}
request, err := http.NewRequest("HEAD", url, nil)
if err != nil {
continue
}
request.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0")
resp, err := client.Do(request)
if err != nil {
fmt.Println(err)
continue
}
if resp.StatusCode == 200 {
fmt.Printf("%s 状态码: %v\n", url, resp.StatusCode)
} else {
fmt.Printf("%s 状态码: %v\n", url, resp.StatusCode)
}
resp.Body.Close()
/*超时控制
通常我们可以通过select + time.After 来进行超时检查*/
case <-time.After(time.Duration(2) * time.Second):
wg.Done()
return
}
}
}


相关文章
|
1月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
184 4
|
2月前
|
消息中间件 缓存 NoSQL
Redis各类数据结构详细介绍及其在Go语言Gin框架下实践应用
这只是利用Go语言和Gin框架与Redis交互最基础部分展示;根据具体业务需求可能需要更复杂查询、事务处理或订阅发布功能实现更多高级特性应用场景。
255 86
|
3月前
|
数据采集 数据挖掘 测试技术
Go与Python爬虫实战对比:从开发效率到性能瓶颈的深度解析
本文对比了Python与Go在爬虫开发中的特点。Python凭借Scrapy等框架在开发效率和易用性上占优,适合快速开发与中小型项目;而Go凭借高并发和高性能优势,适用于大规模、长期运行的爬虫服务。文章通过代码示例和性能测试,分析了两者在并发能力、错误处理、部署维护等方面的差异,并探讨了未来融合发展的趋势。
294 0
|
1月前
|
JavaScript 前端开发 Java
【GoWails】Go做桌面应用开发?本篇文章带你上手Wails框架!一步步带你玩明白前后端双端的数据绑定!
wails是一个可以让你使用Go和Web技术编写桌面应用的项目 可以将它看作Go的快并且轻量级的Electron替代品。可以使用Go的功能,并结合现代化UI完成桌面应用程序的开发
315 4
|
5月前
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
319 61
|
4月前
|
分布式计算 算法 安全
Go语言泛型-泛型约束与实践
Go语言中的泛型约束用于限制类型参数的范围,提升类型安全性。通过接口定义约束,可实现对数值类型、排序与比较等操作的支持。开发者既可使用标准库提供的预定义约束,如constraints.Ordered和constraints.Comparable,也可自定义约束以满足特定需求。泛型广泛应用于通用数据结构(如栈、队列)、算法实现(如排序、查找)及构建高效可复用的工具库,使代码更简洁灵活。
|
5月前
|
设计模式 人工智能 Go
go 依赖注入实践
依赖注入(DI)是一种软件设计模式,旨在降低代码耦合度,提高代码可测试性和可复用性。其核心思想是将依赖项从外部传入使用对象,而非由其内部创建。通过 DI,模块间关系更清晰,便于维护和扩展。常见实现包括方法注入和接口注入,适用于如 Go 等支持函数式编程和接口抽象的语言。
123 8
|
5月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
5月前
|
开发框架 安全 前端开发
Go Web开发框架实践:模板渲染与静态资源服务
Gin 是一个功能强大的 Go Web 框架,不仅适用于构建 API 服务,还支持 HTML 模板渲染和静态资源托管。它可以帮助开发者快速搭建中小型网站,并提供灵活的模板语法、自定义函数、静态文件映射等功能,同时兼容 Go 的 html/template 引擎,具备高效且安全的页面渲染能力。
|
5月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。

热门文章

最新文章