获取iOS任意线程调用堆栈(二)符号化理论:Mach-o文件结构
我们知道Windows下的文件都是PE文件,同样在OS X和iOS中可执行文件是Mach-o格式的。
所以我们如果要进行逆向分析,首先要熟悉Mach-o文件结构。
Mach-o包含三个基本区域:
- 头部(header structure)。
- 加载命令(load command)。
- 段(segment)。可以拥有多个段(segment),每个段可以拥有零个或多个区域(section)。每一个段(segment)都拥有一段虚拟地址映射到进程的地址空间。
- 链接信息。一个完整的用户级Mach-o文件的末端是链接信息。其中包含了动态加载器用来链接可执行文件或者依赖库所需使用的符号表,字符串表等等。
你也可以在这里找到Mach-o的官方资料。
一、我们先使用otool工具来查看Mach-o的头部,看看都包含哪些信息。
头部的的结构如下(32位):
1
2 3 4 5 6 7 8 9 |
struct mach_header{
uint32_t magic; cpu_type_t cputype; cpu_subtype_t cpusubtype; uint32_t filetype; uint32_t ncmds; uint32_t sizeofcmds; uint32_t flags; } |
1.magic,是mach-o文件的魔数,0xfeedface代表的是32位,0xfeedfacf代表64位
2.cputype和cupsubtype代表的是cpu的类型和其子类型,例子中分别是c和9,定义如下:
#define CPU_TYPE_ARM((cpu_type_t) 12)
#define CPU_SUBTYPE_ARM_V7((cpu_subtype_t) 9
即为:armv7
3.接着是filetype,2,代表可执行的文件
#defineMH_EXECUTE 0×2
4.ncmds 指的是加载命令(load commands)的数量,例子中一共23个,编号0-22
5.sizeofcmds 表示23个load commands的总字节大小, load commands区域是紧接着header区域的。
6.最后个flags,例子中是0×00200085,可以按文档分析之。
当然不用工具,直接使用UE看也是一样的。按照定义的结构来就行了。
二、头部之后就是加载命令。加载命令的数目以及总的大小在header中已经给出。
1.cmd 是load command的类型,本文中值=1就是LC_SEGMENT,,LC_SEGMENT的含义是(将文件中的段映射到进程地址空间)
2.cmdsize 代表load command的大小(0×58个字节)。
3.segname 16字节的段名字,当前是__PAGEZERO。
4.vmaddr 段的虚拟内存起始地址
5.vmsize 段的虚拟内存大小
6.fileoff 段在文件中的偏移量
7.filesize 段在文件中的大小
8.maxprot 段页面所需要的最高内存保护(4=r,2=w,1=x)
9.initprot 段页面初始的内存保护
10.nsects 段中包含section的数量
11.flags 其他杂项标志位
三、接下来就是节了:
结构如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 |
struct section {
char sectname[16]; char segname[16]; uint32_t addr; uint32_t size; uint32_t offset; uint32_t align; uint32_t reloff; uint32_t nreloc; uint32_t flags; uint32_t reserved1; uint32_t reserved2; }; |
1.sectname 第一个是__text ,就是主程序代码
2.segname 该section所属的 segment名,第一个是__TEXT
3.addr 该section在内存的启始位置,0xa588。
4.size 该section的大小,0x84a
5.offset 该section的文件偏移,28116 0x6dd4
6.align 字节大小对齐 ,4
7. reloff 重定位入口的文件偏移,0
8.nreloc 需要重定位的入口数量,0
9.flags 包含section的type和attributes
S_REGULAR—This section has no particular type. The standard tools create a __TEXT,__text section of this type.
结构中的最后2项保留用。
段的命名规则是两个下划线紧跟着大写字母(如__TEXT),而section的命名则是两个下划线紧跟着小写字母(__text)。
下面列出段中可能包含的section:
__TEXT段:
__text, __cstring, __picsymbol_stub, __symbol_stub, __const, __litera14, __litera18;
__DATA段
__data, __la_symbol_ptr, __nl_symbol_ptr, __dyld, __const, __mod_init_func, __mod_term_func, __bss, __commom;
__IMPORT段
__jump_table, __pointers;
其中__TEXT段中的__text是实际上的代码部分;__DATA段的__data是实际的初始数据。
可以通过otool –s查看某segment的某个section。
可以通过otool –t直接查看代码段(__TEXT)的反汇编代码:
其它的大家参考官方文档就行了。
转载自:http://www.blogfshare.com/ioss-mach-o.html
获取iOS任意线程调用堆栈(二)符号化理论:Mach-o文件结构相关推荐
- 获取iOS任意线程调用堆栈(三)符号化理论:从Mach-o结构分析类名方法名
下面来讲讲如何从Mach-o文件中分析出类名和方法名,也让我们了解下class-dump的原理. Mach-o结构有两个节:__objc_classname 和 __objc_methname 其中就 ...
- 获取iOS任意线程调用堆栈(四)符号化实战
转载自:http://blog.csdn.net/jasonblog/article/details/49909209 1. 相关API和数据结构 由于我们在上面回溯线程调用栈拿到的是一组地址,所以这 ...
- 获取iOS任意线程调用堆栈(五)完整实现:BSBacktraceLogger
转载自:https://toutiao.io/posts/aveig6/preview BSBacktraceLogger 是一个轻量级的框架,可以获取任意线程的调用栈,开源在我的 GitHub,建议 ...
- 获取iOS任意线程调用堆栈(一)获取任意线程的调用栈地址列表
转载自:http://blog.csdn.net/jasonblog/article/details/49909163 如果要获取当前线程的调用栈,可以直接使用现有API:[NSThread call ...
- 猫猫学iOS之微博国际版的一个关于线程调用的异常修复Main Thread Checker: UI API called on a background thread 异常
问题 优化微博国际版时候,发现控制台打出了这样的异常: Main Thread Checker: UI API called on a background thread: -[UIApplicati ...
- ios跨线程通知_iOS多线程编程指南(三)Run Loop
Run loops是线程相关的的基础框架的一部分.一个run loop就是一个事件处理的循环,用来不停的调度工作以及处理输入事件.使用run loop的目的是让你的线程在有工作的时候忙于工作,而没工作 ...
- logback配置控制打印台异常信息_logback异常输出详细信息(调用堆栈)分析
Logback背景 Logback是一个开源的日志组件,是log4j的作者开发的用来替代log4j的. logback由三个部分组成,logback-core, logback-classic, lo ...
- 使用dbghelp获取调用堆栈--release下的调试方法学
Author : Kevin Lynx 当软件作为release模式被发布给用户时,当程序崩溃时我们很难去查找原因.常见的手法是输出LOG文件,根据LOG文件分析 程序崩溃时的运行情况.我们可以通过S ...
- 获取任意微信公众号二维码方法
[获取任意微信公众号二维码方法] 复制下面链接在浏览器里打开,iOS微信打开会报错. https://open.weixin.qq.com/qr/code?username=PlayerYK 将以上链 ...
最新文章
- firebug中html显示为灰色的原因总结
- 5个教程教你学会写爬虫!(Python)
- mysql字符乱码百度_如何解决MySQL字符集乱码问题
- axure 内部框架内容下滑_Axure教程:转盘抽奖交互原型
- android 集成同一interface不同泛型_C# 基础知识系列- 10 反射和泛型(二)
- 将mysql中的数据库表导出和导入
- python程序启动其他python程序_python中使用fork创建新的进程
- Mac基础知识:Mac日历如何添加提醒事件的教程
- 使用Dism++对电脑优化
- debian or ubuntu下 anjuta配置
- C语言编程入门——HelloWorld!
- [To Selina] 《撒野》读后感
- 反转链表(Java)
- 客户体验管理-运维服务
- 听dalao讲课 7.27
- 每晚泡脚15分钟,5年下来有哪些变化
- 将钞票分解为多张钞票的和
- 线圈绕制中漆包线的简单介绍
- 7.cuBLAS开发指南中文版--cuBLAS中的cublasSetVector()和cublasGetVector()
- HDU 3031 ToBe Or Not To Be(模拟)
热门文章
- python基础学习1-内置函数
- [HDOJ4027]Can you answer these queries?(线段树,特殊成段更新,成段查询)
- 2015年2月12日——不懂点
- 收集一些.NET开发资源站点和部分优秀.NET开源项目 (转)
- 【剑指offer】面试题29:顺时针打印矩阵(Java)
- 计算机操作系统——处理机调度算法
- springboot中获得app_在SpringBoot中读取环境变量
- springboot2整合mysql5_SpringBoot2整合SSM框架详解
- linux vim debugger,Vim 调试:termdebug 入门
- mac怎么合并两个容器_Mac怎么合并文件夹?macz不容错过的苹果mac教程分享