go语言逆向-基础basic

news2024/11/27 16:33:49

文章目录

  • go 编译命令 ldflags -w -s的作用和问题
      • 使用 `file` 命令查看文件类型
  • go 语言逆向参考
  • go ID
  • 版本
  • GOROOT和GOPATH
      • GOROOT
      • GOPATH
      • GOROOT和GOPATH的关系
      • 示例
  • go build和 go mod
  • pclntab (Program Counter Line Table 程序计数器行数映射表)
  • Moduledata
  • 程序启动

go 编译命令 ldflags -w -s的作用和问题

https://blog.csdn.net/Kevin_Gates/article/details/130107710
-ldflags 参数可以用来向编译器传递额外的参数。其中,-w 和 -s 是两个常用的参数。

  • w:去掉 dwarf 调试信息。会减小可执行文件的大小。
  • s:去掉符号表信息。会进一步减小可执行文件的大小。

在编译可执行文件时使用了 -ldflags "-w -s" 参数后,你可以通过以下几种方式来检查生成的可执行文件是否去掉了调试信息和符号表信息。

使用 file 命令查看文件类型

file 命令可以显示可执行文件的基本信息,如果去掉了调试信息,file 的输出中应该不会提到调试符号(debugging symbols)。
在这里插入图片描述

go 语言逆向参考

https://www.cnblogs.com/lordtianqiyi/articles/16315905.html
https://forum.butian.net/share/1874
https://jiayu0x.com/2020/09/28/go-binary-reverse-engineering-tips-and-example/
【技术推荐】正向角度看Go逆向
Golang逆向资料

Go 语言设计与实现

go ID

Build ID 是 Go 二进制文件中的元信息之一

llk@ubuntu:~/Desktop/go-reverse/basic$ go tool buildid basic
-VH5aOSX9mVrJNbHxruF/FwnNtemK3U4RER9TE7_8/5x300ikDrpjLHazn79N3/ftLrOMaMAByiPF3chfMM

无论是gccgo还是go编译的,file或者readelf -n都能看到BuildID

版本

一、查看版本号
go version xx.exe
二、查看地址以及依赖库
go version -m xxx.exe

GOROOT和GOPATH

  • GOROOT: 主要是Go语言工具链所在的位置,通常不需要手动修改。
  • GOPATH: 用于管理和组织用户的Go项目,可以根据需要设置和修改,方便管理不同的工作空间。

GOROOT

  • 定义: GOROOT是Go语言的安装目录。它指向Go工具链、标准库源码和编译器等内容所在的目录。
  • 默认值: 通常在安装Go时,GOROOT会自动设置为安装路径。例如,如果你通过官方安装包安装Go,GOROOT可能会是 /usr/local/go(在类Unix系统上)或 C:\Go(在Windows上)。
  • 作用:
    • 存放Go编译器和工具链。
    • 包含标准库源码。
    • Go工具使用GOROOT来找到编译器、链接器等工具,以及标准库的源码。

GOPATH

  • 定义: GOPATH是Go项目的工作目录。它指向开发者的工作空间,可以包含多个目录。
  • 默认值: 如果没有设置GOPATH,默认值通常是用户的主目录下的go目录(如$HOME/go)。
  • 结构: GOPATH目录通常包含三个子目录:
    • src: 存放源代码。
    • pkg: 存放已编译的包对象文件。
    • bin: 存放编译后生成的可执行文件。
  • 作用:
    • 用于存储和组织用户的Go代码。
    • go get 命令会下载依赖包到GOPATHsrc目录中。
    • 编译时,Go工具会从GOPATH中查找包的源码。

GOROOT和GOPATH的关系

  • GOROOT 是Go工具链的安装目录,包含标准库。
  • GOPATH 是用户工作空间的目录,包含用户的代码和第三方库。

示例

假设你在$HOME/go_projects下开发一个项目:

  1. 你可以设置GOPATH$HOME/go_projects

    export GOPATH=$HOME/go_projects
    
  2. 你的项目目录结构可能如下:

    $HOME/go_projects/
        src/
            github.com/
                yourusername/
                    yourproject/
                        main.go
        pkg/
        bin/
    
  3. 编译你的项目:

    cd $HOME/go_projects/src/github.com/yourusername/yourproject
    go build
    

编译后的可执行文件将会出现在$HOME/go_projects/bin目录中。

go build和 go mod

go build命令用来启动编译,它可以将Go语言程序与相关依赖编译成一个可执行文件,其语法格式如下。
go build fileName  -o 可执行程序名
其中 fileName 为所需要的参数,可以是一个或者多个 Go 源文件名(当有多个参数时需要使用空格将两个相邻的参数隔开),也可以省略不写。
使用 go build 命令进行编译时,不同参数的执行结果也是不同的。

编译go程序也是编译与链接的一个流程

在这里插入图片描述
golang包管理工具----go mod

一个 Module 中可以包含多个不同的 Package,而每个 Package 中可以包含多个目录和很多的源码文件。

Module :moduledata 里面有pclntab 全名是 Program Counter Line Table

pclntab (Program Counter Line Table 程序计数器行数映射表)

对应到源码为pcHeader结构体,源码路径在src/runtime/symtab.go

// pcHeader 包含 pclntab 查找使用的数据。
type pcHeader struct {
        magic          uint32  // 0xFFFFFFF1: 用于识别 pcHeader 结构的魔数。
        pad1, pad2     uint8   // 0,0: 对齐结构在内存中的填充字节。
        minLC          uint8   // 架构的最小指令大小。
        ptrSize        uint8   // 指针的字节大小(取决于 32 位或 64 位架构)。
        nfunc          int     // 模块中的函数数量。
        nfiles         uint    // 文件表中的条目数量(模块中的源文件数量)。
        textStart      uintptr // 功能入口 PC 偏移的基地址,等于 moduledata.text。
        funcnameOffset uintptr // 从 pcHeader 开始到 funcnametab 变量的偏移量,包含函数名。
        cuOffset       uintptr // 从 pcHeader 开始到 cutab 变量的偏移量,用于编译单元信息。
        filetabOffset  uintptr // 从 pcHeader 开始到 filetab 变量的偏移量,包含文件名。
        pctabOffset    uintptr // 从 pcHeader 开始到 pctab 变量的偏移量,用于 PC 数据表。
        pclnOffset     uintptr // 从 pcHeader 开始到 pclntab 变量的偏移量,用于 PC 到行号的映射。
}

在这里插入图片描述

  1. cu_offset:

    • cu_offset 是编译单元(Compilation Unit)的偏移量。
    • gopclntab 中,编译单元是一个大块,包含了函数信息、行号表等。
    • cu_offset 指的是当前函数在编译单元中的偏移位置。
  2. pctab:

    • pctab 是一个表格,存储了程序计数器(PC)和行号(line number)之间的映射关系。
    • 这种映射关系使得在运行时可以根据PC值找到源代码中的行号,帮助调试和错误处理。
  3. runtime_pclntab:

    • runtime_pclntab 是整个gopclntab的起始点或基地址。
    • 这是一个全局表格,包含了所有函数的PC和函数信息的映射。
  4. dq offset cu_offset - offset runtime_pclntab:

    • 这表示当前函数的 cu_offset 减去全局 runtime_pclntab 的偏移量,得到一个具体的偏移值。
    • 这个偏移值用来定位当前函数在整个 gopclntab 结构中的位置。
  5. dq offset pctab - offset runtime_pclntab:

    • 这表示当前函数的 pctab 减去全局 runtime_pclntab 的偏移量。
    • 这个偏移值用来定位 pctab 在整个 gopclntab 结构中的位置。

函数表
函数地址偏移是和函数表第一个函数地址的偏移
在这里插入图片描述
源码文件表
在这里插入图片描述

Moduledata

Module 是比 Package 更高层次的概念,具体表现在一个 Module 中可以包含多个不同的 Package,而每个 Package 中可以包含多个目录和很多的源码文件。

相应地,Moduledata 在 Go 二进制文件中也是一个更高层次的数据结构,它包含很多其他结构的索引信息

根据 Moduledata 的定义,源码路径在src/runtime/symtab.go

type moduledata struct {
        sys.NotInHeap // 仅用于静态数据

        // 指向pcHeader结构的指针,包含程序计数器的头信息
        pcHeader     *pcHeader
        funcnametab  []byte      // 函数名称表
        cutab        []uint32    // 编译单元表
        filetab      []byte      // 文件表
        pctab        []byte      // 程序计数器表
        pclntable    []byte      // PC到行号的映射表
        ftab         []functab   // 函数表
        findfunctab  uintptr     // findfunctab函数的起始地址
        minpc, maxpc uintptr     // 代码段的起始和结束地址

        text, etext           uintptr // 代码段的起始和结束地址
        noptrdata, enoptrdata uintptr // 不包含指针的数据段的起始和结束地址
        data, edata           uintptr // 数据段的起始和结束地址
        bss, ebss             uintptr // BSS段的起始和结束地址
        noptrbss, enoptrbss   uintptr // 不包含指针的BSS段的起始和结束地址
        covctrs, ecovctrs     uintptr // 覆盖计数器的起始和结束地址
        end, gcdata, gcbss    uintptr // 结束地址,GC数据,GC BSS
        types, etypes         uintptr // 类型信息的起始和结束地址
        rodata                uintptr // 只读数据段的起始地址
        gofunc                uintptr // go.func.*

        textsectmap []textsect // 文本段映射
        typelinks   []int32    // 类型链接信息,存储类型偏移
        itablinks   []*itab    // 接口表链接

        ptab []ptabEntry // P 表

        pluginpath string       // 插件路径
        pkghashes  []modulehash // 包哈希信息

        // 这个切片记录了启动程序所需的初始化任务。由链接器构建。
        inittasks []*initTask

        modulename   string       // 模块名
        modulehashes []modulehash // 模块哈希信息

        hasmain uint8 // 如果模块包含main函数,则值为1,否则为0

        gcdatamask, gcbssmask bitvector // GC数据和BSS段的位向量

        typemap map[typeOff]*_type // 前一个模块中从偏移量到*_rtype的映射

        bad bool // 模块加载失败,应被忽略

        next *moduledata // 指向下一个模块的指针
}

Moduledata 是可以串成链表的形式的,而一个完整的可执行 Go 二进制文件中,只有一个 firstmoduledata 包含如上完整的字段

在这里插入图片描述

程序启动

Golang 程序启动过程

rt0_amd64_linux->rt0_amd64->runtime_rt0_go
rt0_go 代码比较长,可分为两个部分,第一部分是系统参数获取和运行时检查。第二部分是 go 程序启动的核心,总体启动流程如下
在这里插入图片描述
执行 runtime.main, 主要进行了
1.启动系统后台监控sysmon 线程
2.执行 runtime 包内 init
3.启动gc
4.用户包依赖 init 的执行
5.执行用户main.mian 方法

  1. rt0_go函数

    • 当程序启动时,Go运行时的入口点是rt0_go函数。这个函数负责初始化运行时环境。
  2. schedinit:初始化运行时组件

    • rt0_go调用runtime_schedinit_0来初始化调度器、内存分配器和垃圾回收器等等。
    • 调度器初始化:初始化调度器,准备管理Goroutines的创建、调度和执行。
    • 内存分配器初始化:初始化堆内存管理,为Goroutines和程序数据分配内存。
    • 垃圾回收器初始化:初始化垃圾回收器,自动管理内存的分配和回收。
  3. newproc:创建主Goroutine

    • rt0_go调用runtime_newproc_0创建主Goroutine。主Goroutine的入口函数是runtime.main,而不是用户的main函数。
    • 创建Goroutinenewproc函数负责创建一个新的Goroutine,并将其加入调度器的队列中。这个Goroutine的入口函数是runtime.main
  4. mstart:启动调度器的调度循环

    • rt0_go调用runtime_mstart启动主线程。主线程会执行runtime.main函数。
    • 调度循环mstart函数启动调度器的调度循环,开始执行队列中的Goroutines。第一个执行的Goroutine是入口方法为runtime.main的G。
  5. runtime.main:执行初始化和用户main函数

    • runtime.main函数首先执行一些必要的初始化操作,例如设置全局变量、初始化标准库等。
    • 然后,runtime.main调用用户的main函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2248524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RL78/G15 Fast Prototyping Board Arduino IDE 平台开发过程

这是一篇基于RL78/G15 Fast Prototyping Board的Arduino IDE开发记录 RL78/G15 Fast Prototyping Board硬件简介(背景)基础测试(方法说明/操作说明)开发环境搭建(方法说明/操作说明代码结果)Arduino IDE RL…

Servlet细节

目录 1 Servlet 是否符合线程安全? 2 Servlet对象的创建时间? 3 Servlet 绑定url 的写法 3.1 一个Servlet 可以绑定多个url 3.2 在web.xml 配置文件中 url-pattern写法 1 Servlet 是否符合线程安全? 答案:不安全 判断一个线程…

使用UE5.5的Animator Kit变形器

UE5.5版本更新了AnimatorKit内置插件,其中包含了一些内置变形器,可以辅助我们的动画制作。 操作步骤 首先打开UE5.5,新建第三人称模板场景以便测试,并开启AnimatorKit组件。 新建Sequence,放入测试角色 点击角色右…

【前端】ES6基础

1.开发工具 vscode地址 :https://code.visualstudio.com/download, 下载对应系统的版本windows一般都是64位的 安装可以自选目录,也可以使用默认目录 插件: 输入 Chinese,中文插件 安装: open in browser,直接右键文件…

蓝桥杯模拟题不知名题目

题目:p是一个质数&#xff0c;但p是n的约数。将p称为是n的质因数。求2024最大质因数。 #include<iostream> #include<algorithm> using namespace std; bool fun(int x) {for(int i 2 ; i * i < x ; i){if(x % i 0)return false;}return true; } int main() …

Android 13 编译Android Studio版本的Launcher3

Android 13 Aosp源码 源码版本 Android Studio版本 Launcher3QuickStepLib (主要代码) Launcher3ResLib(主要资源) Launcher3IconLoaderLib(图片加载&#xff0c;冲突资源单独新建) 需要值得注意的是&#xff1a; SystemUISharedLib.jar 有kotlin和java下的&#xff0c;在 Lau…

VMware ubuntu创建共享文件夹与Windows互传文件

1.如图1所示&#xff0c;点击虚拟机&#xff0c;点击设置&#xff1b; 图1 2.如图2所示&#xff0c;点击选项&#xff0c;点击共享文件夹&#xff0c;如图3所示&#xff0c;点击总是启用&#xff0c;点击添加&#xff1b; 图2 图3 3.如图4所示&#xff0c;出现命名共享文件夹…

零地址挂页

零地址 如果我们有比较好的C编程基础&#xff0c;我们就会知道&#xff0c;我们在代码中定义了一个零地址或者空指针&#xff0c;那么它实际上会指向虚拟内存的零地址&#xff0c;多数操作系统&#xff0c;包括Win&#xff0c;在进程创建的时候&#xff0c;都会空出前64k的空间…

oneplus6线刷、trwp、magisk(apatch)、LSPosed、Shamiko、Hide My Applist

oneplus6线刷android10.0.1 oneplus6线刷包(官方android10.0.1)下载、线刷教程&#xff1a; OnePlus6-brick-enchilada_22_K_52_210716_repack-HOS-10_0_11-zip 启用开发者模式 设置 / 连续点击6次版本号 : 启用开发者模式设置/开发者模式/{打开 usb调试, 打开 网络adb调试,…

树---索引的进化--从二叉搜索树到B+Tree的光荣进化(未完)

平衡二叉树 1. 索引平衡二叉树&#xff08;AVL树&#xff09;是一种自平衡的二叉搜索树&#xff0c;它通过在插入和删除节点时自动调整树的结构&#xff0c;保持树的平衡&#xff0c;从而保证了树的高度始终保持在O(log n)的范围内&#xff0c;这对于提高搜索、插入和删除操作…

FileZilla 报错解决

一、错误:严重错误: 无法连接到服务器 解决方法&#xff1a;FileZilla站点的用户名密码要和linux用户名密码保持一致&#xff0c;出现这个报错大概率是用户名和密码不一致导致的。 二、错误&#xff1a;文件传输失败 解决方法&#xff1a;检查linux下的文件夹是否有可执行权限…

替代Postman ,17.3K star!

现在&#xff0c;许多人都朝着全栈工程师的方向发展&#xff0c;API 接口的编写和调试已成为许多开发人员必备的技能之一。 工欲善其事&#xff0c;必先利其器。拥有一款优秀的 API 工具对于任何工程师来说都是极为重要的&#xff0c;它能够帮助我们高效地完成各种开发任务。 …

Flutter 3.24.5安装配置——2024年11月26日

目录 1️⃣前置安装使用环境配置步骤安装Flutter SDK安装Android SDK修改文件默认安装位置&#xff08;.gradle, AVD&#xff09;开始项目 2️⃣执行结果&#x1fab2;Bug找不到**.jar文件 &#x1f517;参考链接 1️⃣前置安装 使用环境 Windows 11IDEA 2024.2.3Flutter 3.2…

Perforce SAST专家详解:自动驾驶汽车的安全与技术挑战,Klocwork、Helix QAC等静态代码分析成必备合规性工具

自动驾驶汽车安全吗&#xff1f;现代汽车的软件包含1亿多行代码&#xff0c;支持许多不同的功能&#xff0c;如巡航控制、速度辅助和泊车摄像头。而且&#xff0c;这些嵌入式系统中的代码只会越来越复杂。 随着未来汽车的互联程度越来越高&#xff0c;这一趋势还将继续。汽车越…

(计算机组成原理)期末复习

第一章 计算机的基本组成&#xff1a;硬件软件&#xff08;程序&#xff09;计算机系统 软件有系统软件&#xff08;系统管理工具&#xff09;&#xff0c;应用软件 计算机硬件&#xff1a;包括主机和外设&#xff0c;主机包括CPU和内存&#xff0c;***CPU由运算器和控制器所组…

UEFI 中的 Protocol

Protocol 在 UEFI 内核中的表示 typedef VOID *EFI_HANDLE;EFI_HANDLE是指向某种对象的指针&#xff0c;UEFI 用它来表示某个对象。 UEFI 扫描总线后&#xff0c;会为每个设备建立一个 Controller 对象&#xff0c;用于控制设备&#xff0c;所有该设备的驱动以 Protocol 的形式…

量子安全与经典密码学:一些现实方面的讨论

量子安全与经典密码学 背景&#xff1a;量子安全与经典密码学量子计算对传统密码学的威胁 安全性分析经典密码学的数学复杂性假设**量子密码学的物理不可克隆性假设** **性能与实现难度**后量子算法在经典计算机上的运行效率**量子通信设备的技术要求与成本** **可扩展性与适用…

【大模型】LLaMA-Factory的环境配置、微调模型与测试

前言 【一些闲扯】 时常和朋友闲聊&#xff0c;时代发展这么快&#xff0c;在时代的洪流下&#xff0c;我们个人能抓住些什么呢。我问了大模型&#xff0c;文心一言是这样回答的&#xff1a; 在快速发展的时代背景下&#xff0c;个人确实面临着诸多挑战&#xff0c;但同时也充满…

PostgreSQL的学习心得和知识总结(一百五十八)|在线调优工具pgtune的实现原理和源码解析

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

汽车渲染领域:Blender 和 UE5 哪款更适用?两者区别?

在汽车渲染领域&#xff0c;选择合适的工具对于实现高质量的视觉效果至关重要。Blender和UE5&#xff08;Unreal Engine 5&#xff09;作为两大主流3D软件&#xff0c;各自在渲染动画方面有着显著的差异。本文将从核心定位与用途、工作流程、渲染技术和灵活性、后期处理与合成四…