Go渗透测试笔记(一)
GO渗透测试笔记(一)
0X01 基本使用
当在某些极端的情况可以使用
go build -ldflags "-w -s"
进行编译,从二进制文件中剥离调试信息和字符表,从而减少文件的大小,适合在某些极端的情况进行嵌入(大约可以减少 30%)创建使用不同架构上使用的二进制文件—交叉编译
go doc 函数 –>可以查询有关的包,函数的使用方法文档
go get —-> 很多情况下,go程序需要要引入第三方包,可以使用此命令进行导入
即使你使用了 import 导入了相应的包,如
stacktian/ldapauth
,也无法访问。必须先下载实际的包,go get “github.com/stacktian/ldapauth” 下载实际的包,并且放在 $GOPATH/SRC目录下
go 引入了两个工具
dep和mod
来锁定清理依赖项,有助于避免正在进行的依赖项不一致go mod tidy
go mod download 是使用mod时经常使用的两个命令
go fmt –>可以自动格式化源代码,强制使用正确的换行符,缩进和大括号来设置代码样式。—>大部分IDE包含的钩子会在保存文件时自动执行 go fmt,因此无需显式执行该命令
golint 和 go vet命令
go fmt 会更改代码的语法样式,但是golint会报告样式错误,例如缺少注释,不遵循约定的变量命名等,无用的类型等等。
golint时独立工具,需要 go get -u “golang.org/x/lint/golint”进行下载
go vet 也会尝试确定编译器中可能忽略的问题,其中一些可能是合法的错误
GO Playground -> 托管的执行环境,为开发人员提供了稳定的web前端,以快速,测试,执行和共享Go代码段,但是会限制使用系统命令和第三方交互
go 的基本语法
1. 结构体和接口
定义如下方法
1 | package main |
此语言定义Person变量的方法,sayHello(),其他语言将p视为self
与this
的引用。
于此同时,结构体缺少作用域修饰符(如 public ,private 等等),
Go语言中通过大写字母确定作用域,以大写字母开头的类型和字段可以在包外部进行导出并访问,以小写字母开头的类型和字段是私有的,只能在包内部访问
引入接口时
1 | package main |
定义了名为friend
的接口,该接口需要实现一个方法sayHello
,这意味着任何实现了方法sayHello()
类型的都是Friend
,
注意:Friend实际上并未实现这个函数,他只是说,如果你是Friend,则能够使用
sayHello
1 | package main |
2 控制结构
Go 包含的控制结构比其他现代语言要少的多。Go主要的语法条件是if/else
用户输入的时候用fmt.Scanln()
比较合适
1 | package main |
当使用switch结构的时候,Go语言必须使用花括号,与其他现代编程语言不同的是,go不需要包含break
语句。在其他语言中当 case不包含break
的时候,将持续执行,在go
中只会执行一种语句
1 | package main |
Go有一个 type switch
的特殊变体,通过switch
语句进行类型断言,对判断类型接口很有用
1 | package main |
本示例中使用特殊语法(i.type)检查 i 变量的类型,然后进行匹配
最后一个流程控制是for
循环,for循环是 Go用于执行重复代码的结构,Go没有诸如do
或者while
之类的约定
1 | package main |
以下是 for循环的一个轻量级变体,用于遍历集合或者切片/映射
和python 一样,idx用于索引
1 | package main |
3. 并发
go拥有比其他语言更为简单的并发模型,可以使用gorountine
并发执行代码,因其是可以同时运行的函数或者方法,gorountine
被称为轻量级线程,于实际线程相比,创建他们的成本极低
可以通过在被调用的方法或者函数之前使用go
关键字创建gorountine
实现并发
1 | package main |
在函数之前使用了go
关键字,这将意味着程序同时运行f()和main(),换句话说:main()函数的执行将继续,而无需等待f()完成。当我们使用time.Sleep
强制main函数暂停,以便f()可以执行完,如果不暂停main()函数,则该线程很可能在f()执行完毕之前就退出,将看不到其结果。
go 具有一种称为通道
(channel)的数据类型,该数据类型提供了一个机制,通过该机制,gorountine
可以同步执行函数并且这些函数可以互相通信。下面的例子显示使用一个通道时显示不用字符串的长度及其总和的示例
1 | package main |
首先,定义并使用 chan int
类型的变量 c,你可以定义各种类型的通道,具体取决于通道传递的数据类型,你可以在gorountine中
定义各种类型的通道,具体取决于要在通道传递的数据类型,上面的类型是要传递int
类型的数据传长度。因此使用int
类型的传递参数
请注意一个新的运算符,<-
。该运算符只是数据时流入还是流出通道,你可以这样理解他,”将物品放在桶里或者取出一个物品”
结果是5,6,11
,可以理解为是一个栈,将最先放进去放到最底部,取出最后放入的,所以才会出现这种情况。
同时,从通道中取出数据则表明要取出足够的数据,否则会阻塞在这一行
4. 错误处理
与大多数现代编程语言不同,Go 没有try/catch/finally
错误的处理语法。但是,它使用了一种更为简单的方法,鼓励你多去检查哪些容易出现错误的地方,这样他们就不会聚焦在调用链中。
Go使用以下接口声明定义内置错误的类型
1 | type error interface { |
这意味着可以实现了方法Error()的任何数据类型,该方法返回字符串作为一个错误,例如,可以在代码中自定义错误
1 | package main |
你会发现函数和方法至少返回一个值是很普遍的,并且这些值中总会又一个返回值是错误的,在Go中如果返回错误值是nil
,则表明函数未出现任何问题。
go 语言中没有形成统一的错误记录方法,原因之一是,与其他语言不同,Go的内置错误类型没有隐式包含堆栈跟踪以帮助查明错误的上下文或者位置,
5. 处理结构化数据
安全从业人员会预先编好处理结构挂数据或者具有通用编码的数据,如JSON
,xml
最常见的两个包是encoding/xml
和encoding.json
,这两个包都可以组编和结组任意数据结构,这意味着他们可以将字符串转化为结构体,也可以将结构体序列化为字节切片,然后将字节切片反序列化为结构体
1 | package main |
json.Marshal 将struct 编码为JSON
,返回一个字节切片,随后将其打印到标准输出,显示的是Json形式的字节码形式
json.Unmarshal(b,&f) 将其进行解码,生成一个foo结构体实例。处理xml与此过程大致相同