对 golang 二进制文件进行逆向工程

逆向工程 linux 记忆 静态分析 小精灵
2021-06-15 07:47:28

我自己编译了docker,做了一些修改。我想对二进制文件进行一些静态分析。主要是看代码的哪些部分占用了更多内存,等等。它在 linux (elf) 上。有什么建议我应该使用哪些免费工具?我无权访问 IDA。

我会比以下更具体的东西:

size -A -d mydocker
1个回答

恐怕您要查找内存使用情况的意图可能需要静态和动态分析。运行时事件可能会导致更多或更少的内存使用。我将写下我关于逆向 Go 二进制文件的一般发现,你可以从下面选择你的应用程序特定的解决方案。

Go语言没有可用的反编译工具。尽管根据讨论,您可以从主要基于 DWARF 调试信息的 Go 二进制文件中识别高级结构。

您可以使用具有 Go 运行时支持的objdumpGDB等传统工具安装 Go 工具包后:

echo add-auto-load-safe-path /usr/share/go-1.6/src/runtime/runtime-gdb.py >> ~/.gdbinit

为简单起见,我开始研究函数示例。我用标准构建编译了函数示例。Go 编译器的默认构建包含大量 DWARF 信息。您可以看到objdump源代码-程序集混合在使用 Go 语法导入、包和函数表示方面非常成功。

0000000000401000 <main.main>:

func plusPlus(a, b, c int) int {
    return a + b + c
}

func main() {
  401000:       64 48 8b 0c 25 f8 ff    mov %fs:0xfffffffffffffff8,%rcx
  401007:       ff ff
  401009:       48 8d 44 24 d0          lea    -0x30(%rsp),%rax
  40100e:       48 3b 41 10             cmp    0x10(%rcx),%rax
  401012:       0f 86 f1 02 00 00       jbe    401309 <main.main+0x309>
  401018:       48 81 ec b0 00 00 00    sub    $0xb0,%rsp
    res := plus(1, 2)
  40101f:       48 c7 c3 01 00 00 00    mov    $0x1,%rbx
  401026:       48 c7 c0 02 00 00 00    mov    $0x2,%rax
  40102d:       48 01 c3                add    %rax,%rbx
  401030:       48 89 d8                mov    %rbx,%rax
    fmt.Println("1+2 =", res)
  401033:       48 8d 1d 6e b3 0f 00    lea    0xfb36e(%rip),%rbx        # 4fc3a8 <go.string.*+0x3b0>
...
401159:       e8 82 97 05 00          callq  45a8e0 <fmt.Println>

    res = plusPlus(1,2,3)
  40115e:       48 c7 c3 01 00 00 00    mov    $0x1,%rbx
  401165:       48 c7 c1 02 00 00 00    mov    $0x2,%rcx
  40116c:       48 c7 c0 03 00 00 00    mov    $0x3,%rax
  401173:       48 01 cb                add    %rcx,%rbx
  401176:       48 01 c3                add    %rax,%rbx
  401179:       48 89 d8                mov    %rbx,%rax
    fmt. Println("1+2+3 =", res)
  40117c:       48 8d 1d 2d b2 0f 00    lea    0xfb22d(%rip),%rbx        # 4fc3b0 <go.string.*+0x3b8>

如果您有机会从源代码构建应用程序,我强烈建议您按照 文档中的建议使用 -ldflags "-w" 参数

您可以使用GDB轻松调试和逆向 Go 程序。除非您使用调试信息构建它,否则GDB无法找到用户定义的函数,但是,您可以使用 main 函数来跟踪程序流程。

gdb-peda$ list main.main
9
10 func plusPlus(a, b, c int) int {
11     return a + b + c
12 }
13
14 func main() {
15     res := plus(1, 2)
16     fmt.Println("1+2 =", res)
17
18     res = plusPlus(1,2,3)

我假设您使用调试信息构建它:

void main(void);
void main.init(void);
void main.main(void);
void runtime.main(void);
void runtime.main.func1(void);
void runtime.main.func2(bool *);
0x0000000000401000  main.main
0x0000000000401320  main.init
0x0000000000429a20  runtime.main
0x000000000044aba0  runtime.main.func1
0x000000000044abe0  runtime.main.func2
0x0000000000456520  main

您可以在这篇关于 Go 堆栈实现的博客文章部分的帮助下检查函数并跟踪它们的堆栈使用情况。在要检查和函数的开头设置一个断点runtime.morestack_noctxt堆栈和runtime.mallocinit为堆分配。

另一种非常简单的方法是使用pprof包,您可以在此处找到相关文档