根据做题学习
[i春秋ezgo]
- Go栈扩容的逻辑,这里无需关注。
具体汇编代码
- 输入函数与输出函数
系统学习go reverse
参考文章: https://forum.butian.net/share/1874
Go基础
见 https://forum.butian.net/share/1874
查看Go版本
//一、查看版本号
go version xx.exe
//二、查看地址以及依赖库
go version -m xxx.exe
如果go版本较低可以尝试脚本还原符号表
还原符号表
工具
都是下载好直接用IDA加载脚本就好了,不需要放在插件文件夹里
IDAGolangHelper(idaapi变了,不支持ida8.3)
https://github.com/sibears/IDAGolangHelper
golang_loader_assist
https://rednaga.io/2016/09/21/reversing_go_binaries_like_a_pro/
https://github.com/strazzere/golang_loader_assist/
go_parser(感觉最好用,支持高版本go,ida8.3,但不支持9.0)
https://github.com/0xjiayu/go_parser
IDA加载go_parser.py即可,效果很好,如果有问题注意文件或者项目路径不包含中文试试
go语言逆向的难点
go语言逆向的难点主要分为三点:独特而复杂的数据类型;独特的调用约定和栈结构,多返回值机制;全静态链接构建。
全静态链接构建
Go 语言的编译工具链会全静态链接构建二进制文件,把标准库函数和第三方 package 全部做了静态编译,再加上 Go 二进制文件中还打包进去了 runtime 和 GC(Garbage Collection,垃圾回收) 模块代码,所以即使做了 strip 处理( go build -ldflags "-s -w" ),生成的二进制文件体积仍然很大。在反汇编工具中打开 Go 语言二进制文件,可以看到里面包含动辄几千个函数。使得对 Go 二进制文件的分析,无论是静态逆向还是动态调式分析,都比分析普通的二进制程序要困难很多。
独特的函数调用约定、栈结构和多返回值机制
Go 语言用的是 continue stack 栈管理机制 ,并且 Go 语言函数中 callee 的栈空间由 caller 来维护,callee 的参数、返回值都由 caller 在栈中预留空间,就难以直观看出哪个是参数、哪个是返回值。
具体调用关系: https://forum.butian.net/share/1874
独特而复杂的数据类型
Go 语言内置一些复杂的数据类型,并支持类型的组合与方法绑定,这些复杂数据类型在汇编层面有独特的表示方式和用法。比如 Go 二进制文件中的 string 数据不是传统的以 0x00 结尾的 C-String,而是用 (StartAddress, Length) 两个元素表示一个 string 数据;这样的话,在汇编代码中看,给一个函数传一个 string 类型的参数,其实要传两个值;