go语言反汇编linux,Go语言逆向去符号信息还原
一、实例
在国内很多朋友都觉得golang的逆向分析很难,其实不然,和其他编程语言相比,go语言的函数太多。但是如果go语言不去符号话,则觉得和.net差不多难度(还是未混淆的)。本文就是要解决golang逆向过程中所遇到去符号化问题。
图1是没有去掉符号信息的反汇编,可以看到GOLANG运行时的各函数名 , 第二张图是去掉符号信息的反汇编,GOLANG运行时的函数名都没了(样本准备,最好是在linux下自己编译一个helloworld用于分析对比)。
图1 go语言没有去掉符号信息的反汇编
图2 go语言去掉符号信息的反汇编
二、分析
这里先感谢https://rednaga.io/2016/09/21/reversing_go_binaries_like_a_pro/链接的作者所提供的的脚本和资料(Reversing GO binaries like a pro)。其提供了golang_loader_assist.py脚本可用于还原符号信息。不过该脚本并不能直接用于windows环境下编译的go程序。在golang_loader_assist.py代码中使用了.gopclntab, .gopclntab是一个非常重要的segments 。在windows环境下去符号化编译go程序逆向分析时不包含该segments。如图3所示:
图3 windows环境下去符号化编译go程序无.gopclntab
图4 linux下没有去除符号信息的go。
图4 含有.gopclntab
因此在他人的肩膀上,对于windows环境go语言的去符号化还原,核心就是要确认.gopclntab的位置:
1、首先旅一下golang_loader_assist.py代码的流程,之后再说windows环境下的go符号还原。
先将golang_loader_assist.py中核心代码贴出,如代码1所示:Line 1: def renamer_init():
Line 2: renamed = 0
Line 3: gopclntab =idaapi.get_segm_by_name('.gopclntab')
Line 4: ifgopclntab is not None:
Line 5: # Skip unimportant header and gotosection size
Line 6: addr = gopclntab.startEA + 16
Line 7: size, addr_size = create_pointer(addr)
Line 8: addr += addr_size
Line 9: # Unsure if this end is correct
Line 10: early_end = addr + (size * addr_size *2)
Line 11: while addr < early_end:
Line 12: func_offset, addr_size =create_pointer(addr)
Line 13: name_offset,addr_size = create_pointer(addr + addr_size)
Line 14: addr += addr_size * 2
Line 15: func_name_addr = Dword(name_offset +gopclntab.startEA + addr_size) +gopclntab.startEA
Line 16: func_name =GetString(func_name_addr)
Line 17: MakeStr(func_name_addr,func_name_addr + len(func_name))
Line 18: appended = clean_func_name =clean_function_name(func_name)
Line 19: debug('Going to remap function at0x%x with %s - cleaned up as %s' % (func_offset, func_name, clean_func_name))
Line 20: ifidaapi.get_func_name(func_offset) is not None:
Line 21: if MakeName(func_offset,clean_func_name):
Line 22: renamed += 1
Line 23: else:
Line 24: error('clean_func_nameerror %s' % clean_func_name)
Line 25: return renamed
代码 1 golang_loader_assist.py中核心代码
如图4所示:.gopclntab的start地址为0813a140,下面为程序单步计算过程。
由line 6可以看到addr = gopclntab.startEA + 16的位置的值是3fcc;
由line 13可知name_offset =3fcc
由line 15可知 name_offset + gopclntab.startEA+ addr_size = 0813a140+3fcc+4=0813e110
Dword(0813e110)=3ffc
func_name_addr=0813e13c
func_name ==(main.main)
图5代码1单步执行结果地址展示
那么如果已知字符串位置,反推.gopclntab是不是也合理呢,答案是一定的。
2、window环境go语言环境去符号化还原:
IDA使用快捷键shif+f12调出字符串窗口搜索runtime或 main一类的关键字,如图6所示:
图6 ida字符串检索结果
随意点开一个字符串,如runtime.memhash_varlen,如图7 所示:
图 7 runtime.memhash_varlen字符串所在地址
runtime.memhash_varlen 的地址是004c1d8c ,图7中鼠标选择部分是该函数所在的地址,其下方20f6c 为该函数名(runtime.memhash_varlen字符串)相对于.gopclntab的偏移地址。
那么由反推.gopclntab的地址为:004c1d8c-20f6c=004a0e20 如图8 所示:
图8 .gopclntab的地址
心细的朋友可能早就发现, .gopclntab位置是包含特征码的啊!!!!!!FB FF FF FF其实就是这么简单。
三、其它提示
a) 修改IDA的segments 新添加的一定要叫.gopclntab,之后便可以使用idapython(ida的插件)
segment name .goclntab
start address (search FB FF FF FF)
end address (.text segment 的尾部)
b)之后IDA加载golang_loader_assist.py,
i. gopclntab =ida_segment.get_segm_by_name('.gopclntab')
if gopclntab is notNone:
ii. # Skip unimportant header andgoto section size
iii. addr = gopclntab.startEA + 8
iv. size, addr_size =create_pointer(addr)
v. addr += addr_size 这里 addr = gopclntab.startEA + 8(也有可能是+16)
c) IDA处理go语言的逆向是f5会失效,原因在于每个函数后面都跟随了runtime_morestack或者runtime_morestack_noctxt函数,因此对这两个函数直接字符串化,就可以使用f5了。
d) runtime_newproc,启动了一个协程,别跟丢。
e) runtime_makechan,go语言比较特殊的channel。
f) golang_loader_assist.py中涉及到IDApython的版本,如果不能直接使用,可将原python文件中的ida_segment .get_segm_by_name替换成idaapi.get_segm_by_name就可以了。其它地方类似将idat_segment,ida_search,ida_funcs,ida_xref换成idaapi)。
四、总结
在很多论坛里很少看到关于go去符号化还原的文章,也经常听周边的人说go语言逆向有多难,可能是被硕大的golang吓到了吧,其实国外的朋友已经解决了该问题,但是由于使用环境差异造成无法复用。
*本文作者Mworld,转载请注明来自FreeBuf.COM
go语言反汇编linux,Go语言逆向去符号信息还原相关推荐
- c语言扫描器,Linux C语言写的超级简单port扫描器
这个本来曾经也写过的,今天无聊复习下 再写一遍.简单的一塌糊涂,写的不咋地大家见谅哦!有空再加强 嘿嘿! #include #include #include #include #include #i ...
- r语言工作路径linux,R语言实用基础知识_工作路径-注释-安装和卸载R包_2019-12-01...
R语言的实用基础知识有很多,都是我在工作和学习中所整理的,有的是看书整理的,也有的是从网络上的各种博客.各种资源获取的,所以我采用日更的方式进行支持整理和更新,希望能够帮到屏幕前的你! 今天是我日更的 ...
- 浅析VS2010反汇编 VS 反汇编方法及常用汇编指令介绍 VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码...
浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...
- linux更改语言脚本,Linux shell脚本入门——shell语言脚本【CentOS】
认识脚本 是使用一种特定的描述性语言,依据一定的格式编写的可执行文件.脚本语言又被称为扩建的语言, 或者动态语言, 是一种编程语言, 用来控制软件应用程序, 脚本通常是以文本 (ASCⅡ) 保存, 只 ...
- linux C语言多线程库pthread中条件变量的正确用法逐步详解
linux C语言多线程库pthread中条件变量的正确用法: 了解pthread常用多线程API和pthread互斥锁,但是对条件变量完全不知道或者不完全了解的人群. 关于条件变量的典型应用,可以参 ...
- linux中c语言结构体详解,Linux C语言结构体-学习笔记
Linux C语言结构体简介 前面学习了c语言的基本语法特性,本节进行更深入的学习. 预处理程序. 编译指令: 预处理, 宏定义, 建立自己的数据类型:结构体,联合体,动态数据结构 c语言表达式工具 ...
- 吴章金: 实例解析 Linux C 语言程序之变量类型
license: "cc-by-nc-nd-4.0" "本文从编译.二进制程序文件和运行角度逐级解析了 Linux C 语言程序中几种变量类型" 吴章金老师&l ...
- C语言实现linux环境UDP协议接收发送数据
C语言实现linux环境UDP协议接收发送数据 说明 上代码 运行结果 说明 闲来无事,写了个C语言的UDP小程序,程序新建了两个线程,分别用来实现UDP数据到发送和接收.需要的直接拿去用. 上代码 ...
- 加分项——C语言实现Linux的pwd命令
加分项--C语言实现Linux的pwd命令 实现要求 1 学习pwd命令 2 研究pwd实现需要的系统调用(man -k; grep),写出伪代码 3 实现mypwd 4 测试mypwd pwd pw ...
最新文章
- OSI七层模型具体解释
- (八)整合spring cloud云服务架构 - commonservice-eureka 项目构建过程
- 【Python】matplotlib基础:数据可视化
- 一夜吸粉200万被封杀,微信都有哪些逆鳞?
- linux用unzip解压.zip文件失败解决方案
- c语言记录五个数组编程,C语言经典编程之数组
- FPGA(8)--频率计检测控制系统
- 微信自定义菜单扩容?
- (day 29 - 二叉树的先序遍历 )剑指 Offer 34. 二叉树中和为某一值的路径
- xshell连接Linxu系统乱码
- OKR工作法阅读笔记(第一天)-序言和前言
- 洋洋背古诗——寒假版
- MIT 6.828 Lab1(从引导扇区开始)
- java-IO流-将文件夹以树形结构打印(打印文件夹目录)问题
- 计算机键盘输入法基础知识,电脑打字入门基础知识
- ubuntu 小新pro14 网卡驱动、键盘、触摸板
- 21级pta《查找表》
- UVM 代码生成器 easier UVM
- EVT, DVT, MVT, PVT常见软件节点是什么意思
- java 通联支付接口_通联支付接口.rar