twitchyliquid64/golang-asm

GitHub: twitchyliquid64/golang-asm

将 Go 编译器内部的汇编器封装为独立库,支持在 Go 程序中以编程方式构建和汇编 x86-64 指令。

Stars: 210 | Forks: 15

# golang-asm 这是 Go 编译器汇编器的一个镜像,其导入路径已被重写,使其能够作为独立的库来使用。 许可证遵循 Go 项目。 # 状态 可以使用,但你需要深入研究汇编器的 godoc,才能弄清楚该如何设置 `obj.Prog` 的不同参数来生成特定的指令。 # 示例 演示了在 x86-64 上汇编 NOP 和 ADD 指令。 ``` package main import ( "fmt" asm "github.com/twitchyliquid64/golang-asm" "github.com/twitchyliquid64/golang-asm/obj" "github.com/twitchyliquid64/golang-asm/obj/x86" ) func noop(builder *asm.Builder) *obj.Prog { prog := builder.NewProg() prog.As = x86.ANOPL prog.From.Type = obj.TYPE_REG prog.From.Reg = x86.REG_AX return prog } func addImmediateByte(builder *asm.Builder, in int32) *obj.Prog { prog := builder.NewProg() prog.As = x86.AADDB prog.To.Type = obj.TYPE_REG prog.To.Reg = x86.REG_AL prog.From.Type = obj.TYPE_CONST prog.From.Offset = int64(in) return prog } func movImmediateByte(builder *asm.Builder, reg int16, in int32) *obj.Prog { prog := builder.NewProg() prog.As = x86.AMOVB prog.To.Type = obj.TYPE_REG prog.To.Reg = reg prog.From.Type = obj.TYPE_CONST prog.From.Offset = int64(in) return prog } func main() { b, _ := asm.NewBuilder("amd64", 64) b.AddInstruction(noop(b)) b.AddInstruction(movImmediateByte(b, x86.REG_AL, 16)) b.AddInstruction(addImmediateByte(b, 16)) fmt.Printf("Bin: %x\n", b.Assemble()) } ``` # 研究 `obj.Prog` 的参数 我花了一些时间才弄清楚这些,所以我在这里记录一下。 ## 使用这些参考资料 * `obj.Prog` - [godoc](https://godoc.org/github.com/golang/go/src/cmd/internal/obj#Prog) * 一些指令(如 NOP、JMP)是跨平台抽象的,可以在[这里](https://godoc.org/github.com/golang/go/src/cmd/internal/obj#As)找到 * (针对 amd64)`x86 pkg-constants` - [寄存器和指令](https://godoc.org/github.com/golang/go/src/cmd/internal/obj/x86#pkg-constant) ## 指令常量具有命名规则 指令在相关架构的包中被定义为常量,它们带有 'A' 前缀和表示大小的后缀。 例如,用于传输 64 位数据的 MOV 指令是 `AMOVQ`(至少在 amd64 中是这样)。 ## 在 go 源码中搜索特定指令的使用方式 例如,如果我想弄清楚如何生成 64 位的 MOV 指令,我会在 GitHub 上搜索 go 源码中的 `AMOVQ` 或 `x86.AMOVQ`。通常,你会找到几个编译器后端填充 `obj.Prog` 结构体的示例,然后你就可以照着它们做了。
标签:EVTX分析, Golang, 代码生成, 安全编程, 底层开发, 日志审计, 汇编器, 渗透测试工具, 编译器组件