带有 golang 目标的 angr

逆向工程 愤怒
2021-07-08 20:55:53

这是一个非常基本的 golang 程序:

package main
import "fmt"

func main() {
    var s1 string
    fmt.Scanln(&s1)

    if s1=="goodpassword" {
        fmt.Println("Good")
    } else {
        fmt.Println("Wrong")
    }
}

我已经编译了这个程序(elf64 linux 二进制文件)。

我已经反汇编了二进制文件,并且找到了 2 个 fmt.Println 调用的地址:

...
0x00490d4f     lea rax, obj.main.statictmp_1    ; wrong
...
0x00490d99     lea rax, obj.main.statictmp_0    ; good
...

现在,我写了这个python程序:

import angr
from angr.state_plugins import SimSystemPosix

p = angr.Project('./mybinary')

sm = p.factory.simulation_manager()
sm.explore(find= 0x00490d99, avoid= 0x00490d4f)

print(sm.found[0].posix.dumps(0))

我不明白为什么 angr 不返回“goodpassword”字符串。我有什么不对,但我不明白是什么......

谢谢你的帮助

1个回答

Go 运行时相当复杂,符号求解器不会按原样运行。您要求angr自己解决所有问题,这对于简单和不复杂的 C 程序可能是可行的,但对于 Go 二进制文件之类的程序则不然。

例如,该fmt.Scanln函数会在您到达之前调用多个 Go 函数libc.readAngr 有 SimProcedures forread但没有 for fmt.Scanln弄清楚fmt.Scanln它必须象征性地执行什么,然后只有它才能发现stdin程序输出之间的依赖关系象征性地执行Scanln绝不是一项简单的任务。

相反,您应该将问题分解为您可以要求angr解决的部分。就像您已经确定了存储用户输入的缓冲区一样,您可以将其标记为符号并指示angr找到“好密码”分支的路径。

关于 Go 逆向的更多资源: