brahma-adshonor / gohook

a funny library to hook golang function at runtime
https://www.cnblogs.com/catch/p/10973611.html
MIT License
513 stars 72 forks source link

1.17.* 版本部分函数无法hook的情况 #43

Open 0xlwoe21k opened 2 years ago

0xlwoe21k commented 2 years ago

如下代码所示 hook的函数是http.Client.Do()

使用 go 1.16.9编译的可以hook,使用go 1.17.2编译的无法hook,根据官方文档推测,可能是1.17后函数调用基于寄存器,1.16基本栈导致的,请问作者后续有没有打算适配一下呀?

[root@cslg-centos-72-common centos]# ./go_build_linux_1.16.9
[+] HookFunc hooked: exec
[+] HookFunc hooked: sql
[+] HookFunc hooked: openfile
[+] HookFunc hooked: ssrf
[+] HookFunc hooked: upload

[root@cslg-centos-72-common centos]# ./go_build_linux_1.17.2
[+] HookFunc hooked: exec
[+] HookFunc hooked: sql
[+] HookFunc hooked: openfile
[!] HookFunc  ssrf error:[ both fix/fix2/copy failed, fix:jmp instruction in patching erea overflow, addr:0x635f64, fix2:call instruction is not allowed to move, copy:source addr:635f60, target addr:727380, sizeof source func(62) > sizeof of target func(7) ]
[+] HookFunc hooked: upload
kmalloc commented 2 years ago

有具体的例子吗?

kmalloc commented 2 years ago

你可以尝试把 trampoline 的函数多写些操作 让函数体积大些 这样最后的 copy 方式有可能是可以的

kmalloc commented 2 years ago

image

http.Client.Do 这次生成的代码在前面有一个单字节跳转,距离 trampoline 太远,没法在原函数里面直接修改位移,延长指令则旧函数空间不够,如果 copy 指令,又刚好原函数里面有一个 call 没法 copy,比较不幸。

不过,你可以用 gohook.HookByIndirectJump 来拦截,这个生成的跳转指令短一些,刚好不会覆盖 jbe 那个指令。

err := gohook.HookByIndirectJmp((*http.Client).Do, doHttp, doHttpTrampoline)