首页
社区
课程
招聘
[原创]高版本go语言符号还原
发表于: 2023-6-5 15:05 20134

[原创]高版本go语言符号还原

2023-6-5 15:05
20134

2022.6.8: go version go1.18.3 windows/amd64
高版本适用 1.20

搜索 go.build
图片描述
图片描述
查找交叉引用
图片描述

go.build 在新版本中一定位于 函数名称的第一个。

图片描述

https://go.dev/src/runtime/symtab.go
阅读源码,获取 moduledata 结构

pclntable 一般等于 ftab, 参照上图, ftab 与 pclntable 填充的是 pclntable 的值。

funcnametab 填充的是 函数名称
图片描述
filetab 填充的是 文件名称
图片描述

与函数名称相关的是 ftab 和 pclntable
图片描述

适用于下面的结构体

图片描述
entryoff 为 以代码段为起始位置 的偏移。表示该函数实际的位置。 代码段在windows为 text

funcoff 为 以 pclntable 为起始位置的偏移。

对应着一个 funcInfo 结构体, 里面包含一个 _func 类型,该类型中有我们想要的信息。

意思就是: func 的 _func = pclntable + funcOff
通过上图的信息计算:

发现刚好可以对得上信息
图片描述

第一个函数 go.build

图片描述
第二个函数 internal_cpu_Initialize
图片描述

知道了这些就可以编写简单的脚本来还原go符号名了

ida python 脚本

其中 moduledata_addr 需要手动填充。

还原效果

图片描述

https://github.com/Abyss-emmm/goparse
跳跳糖

 
 
 
// pcHeader holds data used by the pclntab lookups.
type pcHeader struct {
    magic          uint32  // 0xFFFFFFF0
    pad1, pad2     uint8   // 0,0
    minLC          uint8   // min instruction size
    ptrSize        uint8   // size of a ptr in bytes
    nfunc          int     // number of functions in the module
    nfiles         uint    // number of entries in the file tab
    textStart      uintptr // base for function entry PC offsets in this module, equal to moduledata.text
    funcnameOffset uintptr // offset to the funcnametab variable from pcHeader
    cuOffset       uintptr // offset to the cutab variable from pcHeader
    filetabOffset  uintptr // offset to the filetab variable from pcHeader
    pctabOffset    uintptr // offset to the pctab variable from pcHeader
    pclnOffset     uintptr // offset to the pclntab variable from pcHeader
}
 
 
 
type moduledata struct {
    pcHeader     *pcHeader
    funcnametab  []byte
    cutab        []uint32
    filetab      []byte
    pctab        []byte
    pclntable    []byte
    ftab         []functab
    findfunctab  uintptr
    minpc, maxpc uintptr
 
    text, etext           uintptr
    noptrdata, enoptrdata uintptr
    data, edata           uintptr
    bss, ebss             uintptr
    noptrbss, enoptrbss   uintptr
    end, gcdata, gcbss    uintptr
    types, etypes         uintptr
    rodata                uintptr
    gofunc                uintptr // go.func.*
 
    textsectmap []textsect
    typelinks   []int32 // offsets from types
    itablinks   []*itab
 
    ptab []ptabEntry
 
    pluginpath string
    pkghashes  []modulehash
 
    modulename   string
    modulehashes []modulehash
 
    hasmain uint8 // 1 if module contains the main function, 0 otherwise
 
    gcdatamask, gcbssmask bitvector
 
    typemap map[typeOff]*_type // offset to *_rtype in previous module
 
    bad bool // module failed to load and should be ignored
 
    next *moduledata
}
// pcHeader holds data used by the pclntab lookups.
type pcHeader struct {
    magic          uint32  // 0xFFFFFFF0
    pad1, pad2     uint8   // 0,0
    minLC          uint8   // min instruction size
    ptrSize        uint8   // size of a ptr in bytes
    nfunc          int     // number of functions in the module
    nfiles         uint    // number of entries in the file tab
    textStart      uintptr // base for function entry PC offsets in this module, equal to moduledata.text
    funcnameOffset uintptr // offset to the funcnametab variable from pcHeader
    cuOffset       uintptr // offset to the cutab variable from pcHeader
    filetabOffset  uintptr // offset to the filetab variable from pcHeader
    pctabOffset    uintptr // offset to the pctab variable from pcHeader
    pclnOffset     uintptr // offset to the pclntab variable from pcHeader
}
 
 
 
type moduledata struct {
    pcHeader     *pcHeader
    funcnametab  []byte
    cutab        []uint32
    filetab      []byte
    pctab        []byte
    pclntable    []byte
    ftab         []functab
    findfunctab  uintptr
    minpc, maxpc uintptr
 
    text, etext           uintptr
    noptrdata, enoptrdata uintptr
    data, edata           uintptr
    bss, ebss             uintptr
    noptrbss, enoptrbss   uintptr
    end, gcdata, gcbss    uintptr
    types, etypes         uintptr
    rodata                uintptr
    gofunc                uintptr // go.func.*
 
    textsectmap []textsect
    typelinks   []int32 // offsets from types
    itablinks   []*itab
 
    ptab []ptabEntry
 
    pluginpath string
    pkghashes  []modulehash
 
    modulename   string
    modulehashes []modulehash
 
    hasmain uint8 // 1 if module contains the main function, 0 otherwise
 
    gcdatamask, gcbssmask bitvector
 
    typemap map[typeOff]*_type // offset to *_rtype in previous module
 
    bad bool // module failed to load and should be ignored
 
    next *moduledata
}
 
 
 
type functab struct {
    entryoff uint32 // relative to runtime.text
    funcoff  uint32
}
type functab struct {
    entryoff uint32 // relative to runtime.text
    funcoff  uint32
}
 
//src\runtime\symtab.go
type functab struct {
    entry   uintptr
    funcoff uintptr
}
 
type funcInfo struct {
    *_func
    datap *moduledata
}
 
//src\runtime\runtime2.go
type _func struct {
    entry   uintptr // start pc
    nameoff int32   // function name
 
    args        int32  // in/out args size
    deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
 
    pcsp      uint32
    pcfile    uint32
    pcln      uint32
    npcdata   uint32
    cuOffset  uint32  // runtime.cutab offset of this function's CU
    funcID    funcID  // set for certain special runtime functions
    _         [2]byte // pad
    nfuncdata uint8   // must be last
}
//src\runtime\symtab.go
type functab struct {
    entry   uintptr
    funcoff uintptr
}
 
type funcInfo struct {
    *_func
    datap *moduledata

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2023-6-5 17:07 被mingyuexc编辑 ,原因:
收藏
免费 12
支持
分享
最新回复 (10)
雪    币: 3303
活跃值: (30941)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
mark
2023-6-6 09:18
1
雪    币: 174
活跃值: (2771)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
3
mark
2023-6-6 12:37
0
雪    币: 2241
活跃值: (3581)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
vay
4
mark
2023-6-6 14:09
0
雪    币: 3755
活跃值: (3887)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
感谢分享。
2023-6-6 15:24
0
雪    币: 1671
活跃值: (215847)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
tql
2023-6-6 15:40
0
雪    币: 573
活跃值: (1009)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
马卡巴卡
2023-6-7 09:00
0
雪    币: 12664
活跃值: (9472)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9

感谢分享。 

指出里面有两个小错误,不过没什么大影响: 

”entryoff 为 以代码段为起始位置 的偏移。表示该函数实际的位置。 代码段在windows为 text“

猛一看还以为是pe的text,其实不是。这个算是moduledata.text的字段。


另一个是:


type _func struct {

    entry   uintptr // start pc

    nameoff int32   // function name

这个字段entry 我看了下 uint32 ,始终是32位的。这个untptr,在64位就是64位了。

https://go.dev/src/runtime/runtime2.go#:~:text=883-,entryOff%20uint32,-//%20start%20pc%2C%20as


type _func struct {
    entryOff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart  
    nameOff  int32  // function name, as index into moduledata.funcnametab.

这个长度要是错的话,后面肯定是计算错的,可能是你粘贴的老版本的吧。

2023-6-12 11:50
1
雪    币: 690
活跃值: (1601)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
10
Genes 感谢分享。 指出里面有两个小错误,不过没什么大影响: ”entryoff 为 以代码段为起始位置 的偏移。表示该函数实际的位置。 代码段在windows为 text ...
感谢师傅指正,看了下源码确实是更新了,但不影响符号还原。第一个算是没考虑到其他平台,只考虑了windows,就随手写了。
2023-6-12 14:39
0
雪    币: 5921
活跃值: (633)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
从上面截图上看脚本里moduledata_addr的地址应该是:0x5289A0吧?
不知道是不是我理解错了?
2023-6-21 14:01
0
游客
登录 | 注册 方可回帖
返回
//