[每周一更]-(第75期):Go相关粗浅的防破解方案

2023-12-02 02:28

本文主要是介绍[每周一更]-(第75期):Go相关粗浅的防破解方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

Go作为编译语言,天然存在跨平台的属性,我们在编译完成后,可以再不暴露源代码的情况下,运行在对应的平台中,但是
还是架不住有逆向工程师的反编译、反汇编的情形;(当然我们写的都不希望被别人偷了,以下内容简单做个攻防介绍,起个引导作用,不到之处,多多留言探讨)

  • 反编码(decompilation)是指将机器代码或二进制代码还原为高级语言源代码的过程。虽然一些工具可以进行反编码,但要注意的是,反编码是一个复杂的任务,成功与否取决于多种因素,包括编译器优化、代码混淆和使用的编程语言。
  • 在Go语言中,由于Go是一种静态编译语言,编译器会将Go代码编译为机器码,而不是保留高级语言结构。这使得从Go二进制文件中还原出与原始Go源代码一样的代码非常困难,甚至几乎是不可能的。

逆向工程(反汇编和反编译)

逆向工程(Reverse Engineering)是指将现有的二进制程序或者系统进行分析,还原出其设计或运行机制的一种技术手段

下面是一些逆向工程的常见技术:

  1. 反汇编技术:通过将二进制程序转化为汇编代码,以还原程序的运行过程和指令执行情况。Go语言提供了反汇编工具,可以通过命令行输入“go tool compile -S可执行文件名”来实现反汇编。
  2. 反编译技术:将已经编译好的程序进行还原,得到其源代码。Go语言的反编译工具是“go tool compile -S 源文件名”,生成的代码需要通过代码分析和修改才能重新编译成可执行程序。
  3. 动态调试技术:通过调试器对程序进行分析,观察程序的运行情况和变量值的变化。Go语言的调试器是“dlv”,可以使用命令行对程序进行单步调试。
  4. 内存分析技术:通过对程序运行时的内存进行分析,以了解程序的行为和数据结构。Go语言的内存分析工具是“pprof”,可以对程序进行CPU、内存和goroutine的分析。

1、破解方案

谈到防破解,首先得知道怎么破解,才能更好的防护;

将Go二进制文件转换为与原始源代码结构相同的高级语言源代码是一项非常困难且不可靠的任务。Go是一种静态编译语言,编译器将Go源代码转换为机器码,优化并去除高级语言结构。因此,反向转换机器码到原始源代码是一个复杂的问题。

虽然有一些工具可以进行反汇编和逆向工程,但这些工具通常无法提供与原始Go源代码结构完全相同的高级语言代码。
这是因为编译器进行了各种优化,同时丢失了一些高级语言结构的信息。

以下是一些可能用到的工具:

IDA Pro: IDA Pro是一款反汇编和逆向工程工具,但它通常只能提供汇编级别的代码,并不能还原为原始的高级语言源代码。

Ghidra: Ghidra是一款开源的逆向工程工具,它提供反汇编和分析二进制文件的功能。与IDA Pro类似,Ghidra也更倾向于提供汇编级别的代码。

汇编代码还原: 逆向工程师可能会尝试还原机器码为汇编代码,但这通常只是一个近似的过程,并不会得到原始的高级语言源代码。

2、防破解方式

防破解一直是个很常见的需求,特别是不能做成服务的、或者需要二进制私部署的场景,Go 的编译特性天然就比脚本类语言更好防逆向,脚本类代码是藏不住的。

当然防破解这个事情主要看投入产出比。Go 在这里的优势主要是省心,同时提高了破解的技术门槛。多数时候,写一个时间戳检查、或者 MAC 比对就很够用了。

举例:比如你可以分离功能逻辑和校验逻辑,校验失败并不会立即触发异常,而是会正常执行功能逻辑,但附加一个随机延迟的取消机制,使得功能完成之前就异常退出。

上述逻辑用 Go 代码写出来大概就是 contextWithCancel 几行代码的事情。这样产生的程序无论静态反编译还是静态调试都会很令人迷惑,静态方面难以定位校验逻辑,动态方面上下文切换缺少规律,实际运行表现又是难以稳定复现的,大幅增加了逆向难度。

除此之外还可以配合 burrowers/garble 之类的自动化混淆工具。

以下是常规的增加破解难度的方式:

  1. 删除调试符号

正常情况,我们go代码,部署完成,如果出现报错和日志等,会有暴露目录内容的风险;

go build -ldflags "-s -w" [<your/package] (go version > 1.7 )
  1. 删除trace文件信息

    放到自己的.bash_profile或.zshrc中即可

     ACTUAL_GOPATH="~/Programming/go"export GOPATH='/tmp/go'export GOROOT_FINAL=$GOPATH[ ! -d $GOPATH ] && ln -s "$ACTUAL_GOPATH" "$GOPATH"[[ ! $PATH =~ $GOPATH ]] && export PATH=$PATH:$GOPATH/bin
    
  • https://github.com/golang/go/issues/13809
  1. 代码混淆:
  • 使用工具对Go代码进行混淆,使代码更难以理解。例如,可以使用诸如gobfuscate等工具。
  1. 静态编译: 使用静态编译将依赖项嵌入到二进制文件中,以减少对外部文件的依赖。这可以增加分析和替换的难度。

  2. 加密关键部分:

  • 使用加密算法:使用加密库对关键代码进行加密。运行时在解密后执行这些代码。
  • 例如,您可以使用Go的crypto包进行加密和解密操作。
  1. 代码分割:
  • 模块化代码:将代码组织成模块,然后使用Go的动态导入或插件系统进行加载。
  • 使用Go的plugin包可以实现动态加载。
  1. 使用硬编码密钥:
    将密钥硬编码:在代码中直接将密钥硬编码,而不是存储在配置文件或其他地方
package mainvar encryptionKey = []byte{0x01, 0x02, 0x03, 0x04, 0x05}
  1. 防调试技术:
    使用防调试技术,防止二进制文件在调试器中运行。这可以增加对抗性,使得破解变得更加困难。
    使用runtime/debug包:通过runtime/debug包的ReadBuildInfo函数检查二进制文件是否被构建,从而检测是否在调试模式下运行。
package mainimport ("fmt""runtime/debug"
)func main() {if info := debug.ReadBuildInfo(); info != nil {fmt.Println("Debug information found:", info)// Take appropriate action if running in debug mode}
}
  1. 使用代码签名: 对二进制文件进行数字签名,以确保它的完整性和来源。这可以防止恶意篡改和替换。

  2. 运行时检测: 在运行时检测二进制文件是否被修改。这可以通过计算文件哈希值等方式来实现。

  3. 虚拟化技术: 使用虚拟化技术将关键代码片段放在虚拟机中执行,增加攻击者分析的难度。

  4. 动态链接库: 将一些关键逻辑放入动态链接库,并在运行时动态加载。这可以减少整个二进制文件的复杂性。

参考

  • 分享一些 Go 在全栈开发中的经验

  • 想成为逆向工程师么?

  • 逆向工程介绍

  • 减小 Go 代码编译后的二进制体积-upx

  • Golang二进制文件混淆保护

这篇关于[每周一更]-(第75期):Go相关粗浅的防破解方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/443610

相关文章

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本

使用Go实现文件复制的完整流程

《使用Go实现文件复制的完整流程》本案例将实现一个实用的文件操作工具:将一个文件的内容完整复制到另一个文件中,这是文件处理中的常见任务,比如配置文件备份、日志迁移、用户上传文件转存等,文中通过代码示例... 目录案例说明涉及China编程知识点示例代码代码解析示例运行练习扩展小结案例说明我们将通过标准库 os

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.

SpringBoot3.X 整合 MinIO 存储原生方案

《SpringBoot3.X整合MinIO存储原生方案》本文详细介绍了SpringBoot3.X整合MinIO的原生方案,从环境搭建到核心功能实现,涵盖了文件上传、下载、删除等常用操作,并补充了... 目录SpringBoot3.X整合MinIO存储原生方案:从环境搭建到实战开发一、前言:为什么选择MinI

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

go中的时间处理过程

《go中的时间处理过程》:本文主要介绍go中的时间处理过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 获取当前时间2 获取当前时间戳3 获取当前时间的字符串格式4 相互转化4.1 时间戳转时间字符串 (int64 > string)4.2 时间字符串转时间