错误现象
1) 直接运行
/Applications/MobileFonex.app/MobileFonex
Killed: 9

2)gdb调试
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: 50 at address: 0x00043030

背景知识

所有的可执行文件,库文件都需要Apple签名才可以运行在iOS中
内核会在调用execve之前检测Mach-O文件中的LC_CODE_SIGNATURE段是否有效和可信任

iOS内核以及内核扩展 都以 加密的形式 存储在KernelCache文件中
可以在 the iphone wiki上查找解密的key

一般来说,越狱后,Codesigning是禁止的, 可执行的代码页 是可写的

iPhone 上的每个二进制文件都有数字签名
每个内存页都有sha1校验
签名由内核进行检查
访问 标记为可执行的页面时 执行检查
如果签名不合法,进程被内核杀掉

如何检查二进制文件的数字签名

  1. otool -l debugserver | grep LC_CODE_SIGNATURE
  2. cmd LC_CODE_SIGNATURE

或者
grep -b “Apple Code Signing Certification Authority” debugserver

用codesign能显示更详细的签名信息

  1. codesign -dvvvv debugserver
  2. Executable=/private/tmp/x/debugserver
  3. Identifier=debugserver
  4. Format=Mach-O thin (armv7)
  5. CodeDirectory v=20100 size=900 flags=0x0(none) hashes=37+5 location=embedded
  6. CDHash=577b90c4091310762cbd2350e4e32ee919deccf2
  7. Signature size=1599
  8. Authority=iPhone Developer
  9. Signed Time=Feb 9, 2012 11:29:10 PM
  10. Info.plist=not bound
  11. Sealed Resources=none
  12. Internal requirements count=1 size=112

参考资料
https://developer.apple.com/library/mac/#technotes/tn2206/_index.html

Mach-O文件格式

Mach-O 文件分为三个区域: 头部、载入命令区Section和原始段数据.
头部和载入命令区描述文件功能、布局和其他特性;
原始段数据包含由载入命令引用的字节序列。

otools -l 可以查看
Section
sectname __const
segname __TEXT
addr 0x00043908
size 0x000002fc
offset 272648
align 2^2 (4)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0

Load command 7
cmd LC_UUID
cmdsize 24
uuid 5202B55F-F094-2350-9B4C-8E2C83358B11

Load command 8
cmd LC_UNIXTHREAD
cmdsize 84
flavor ARM_THREAD_STATE
count ARM_THREAD_STATE_COUNT
r0 0x00000000 r1 0x00000000 r2 0x00000000 r3 0x00000000
r4 0x00000000 r5 0x00000000 r6 0x00000000 r7 0x00000000
r8 0x00000000 r9 0x00000000 r10 0x00000000 r11 0x00000000
r12 0x00000000 sp 0x00000000 lr 0x00000000 pc 0x00002000
cpsr 0x00000000

可以看到 start 的地址是 0x2000

Load command 9
cmd LC_ENCRYPTION_INFO
cmdsize 20
cryptoff 4096
cryptsize 270336
cryptid 0

Load command 23
cmd LC_CODE_SIGNATURE
cmdsize 16
dataoff 590896
datasize 3040

注意到 LC_ENCRYPTION_INFO的cryptid是0,表示没有加密

http://opensource.apple.com/source/security_systemkeychain/security_systemkeychain-55105/src/cs_dump.cpp
// if the code is not signed, stop here
if (!api.get(kSecCodeInfoIdentifier))
MacOSError::throwMe(errSecCSUnsigned);

https://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html

目标格式
存储目标代码和相关的元数据的文件格式
在内存中建立进程镜像的蓝本
通常由编译器或者汇编器产生

布局
3个主要部分:header, load comands和sections
每个segemtn comand同多个section相关联

header结构可以在 /usr/include/mach-o/loader.h 找到

  1. /*
  2. * The 32-bit mach header appears at the very beginning of the object file for
  3. * 32-bit architectures.
  4. */
  5. struct mach_header {
  6. uint32_t magic; /* mach magic number identifier */
  7. cpu_type_t cputype; /* cpu specifier */
  8. cpu_subtype_t cpusubtype; /* machine specifier */
  9. uint32_t filetype; /* type of file */
  10. uint32_t ncmds; /* number of load commands */
  11. uint32_t sizeofcmds; /* the size of all the load commands */
  12. uint32_t flags; /* flags */
  13. };

可以用 otool -h 命令查看

load commmand直接跟在 header 部分的后面,结构定义如下

  1. /*
  2. * The load commands directly follow the mach_header. The total size of all
  3. * of the commands is given by the sizeofcmds field in the mach_header. All
  4. * load commands must have as their first two fields cmd and cmdsize. The cmd
  5. * field is filled in with a constant for that command type. Each command type
  6. * has a structure specifically for it. The cmdsize field is the size in bytes
  7. * of the particular load command structure plus anything that follows it that
  8. * is a part of the load command (i.e. section structures, strings, etc.). To
  9. * advance to the next load command the cmdsize can be added to the offset or
  10. * pointer of the current load command. The cmdsize for 32-bit architectures
  11. * MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple
  12. * of 8 bytes (these are forever the maximum alignment of any load commands).
  13. * The padded bytes must be zero. All tables in the object file must also
  14. * follow these rules so the file can be memory mapped. Otherwise the pointers
  15. * to these tables will not work well or at all on some machines. With all
  16. * padding zeroed like objects will compare byte for byte.
  17. */
  18. struct load_command {
  19. uint32_t cmd; /* type of load command */
  20. uint32_t cmdsize; /* total size of command in bytes */
  21. };

一个查看Mach-O结构的工具  MachOView

http://sourceforge.net/projects/machoview/files/current/

第3部分是segments, 每个segment含有0个到多个sections
每个section都含有数据或代码
每个secgment都定义了一个虚拟内存的区域, 动态连接器 把这个区域映射到进程的地址空间。

在用户级的完全链接后的Mach-O 文件中,最后一个segement是__LINKEDIT段。
这个segment含有 link edit 信息的表,比如符号表,字符串表,等。

segment通过指定一个in-memory size就可以在运行时要求比实际磁盘中更多的大小
连接器生成的__PAGEZERO段, 有一个虚拟内存大小,而在磁盘上的空间是0. 因为__PAGEZERO不包含数据,所以不需要占用任何磁盘空间

静态链接器 会生成一个 __PAGEZERO段 作为可执行文件的第1个段。这个段位于虚拟内存的0地址, 并没有保护权限设置。这样就可保证程序访问NULL指针时,会立刻crash. 该段的大小是一个 当前的体系结构的完整的虚拟内存页面的大小(对于arm,intel 和powerpc都是4096个字节)

__TEXT段 含有可执行代码和只读的数据。 为了让内核将它 直接从可执行文件映射到共享内存, 静态连接器设置该段的虚拟内存权限为不允许写。当这个段被映射到内存后,可以被所有进程共享。(这主要用在frameworks, bundles和共享库等程序中,也可以为同一个可执行文件的多个进程拷贝使用)

__LINKEDIT段 含有为动态链接库使用的原始数据,比如符号,字符串,重定位表条目等等。

节/Section

一个段可能含有多个节。
__TEXT, __text 可执行机器码
__TEXT, __cstring 常量C字符串

  1. /*
  2. * The segment load command indicates that a part of this file is to be
  3. * mapped into the task's address space. The size of this segment in memory,
  4. * vmsize, maybe equal to or larger than the amount to map from this file,
  5. * filesize. The file is mapped starting at fileoff to the beginning of
  6. * the segment in memory, vmaddr. The rest of the memory of the segment,
  7. * if any, is allocated zero fill on demand. The segment's maximum virtual
  8. * memory protection and initial virtual memory protection are specified
  9. * by the maxprot and initprot fields. If the segment has sections then the
  10. * section structures directly follow the segment command and their size is
  11. * reflected in cmdsize.
  12. */
  13. struct segment_command { /* for 32-bit architectures */
  14. uint32_t cmd; /* LC_SEGMENT */
  15. uint32_t cmdsize; /* includes sizeof section structs */
  16. char segname[16]; /* segment name */
  17. uint32_t vmaddr; /* memory address of this segment */
  18. uint32_t vmsize; /* memory size of this segment */
  19. uint32_t fileoff; /* file offset of this segment */
  20. uint32_t filesize; /* amount to map from the file */
  21. vm_prot_t maxprot; /* maximum VM protection */
  22. vm_prot_t initprot; /* initial VM protection */
  23. uint32_t nsects; /* number of sections in segment */
  24. uint32_t flags; /* flags */
  25. };

要注意segement的cmdsize要包括它拥有的所有的section的结构的大小

fileoff 是从文件偏移的哪里开始映射到 vmaddr
filesize可以比 vmsize小

更在segment_command后面的就是 它所用于的 section数据结构的数组

  1. /*
  2. * A segment is made up of zero or more sections. Non-MH_OBJECT files have
  3. * all of their segments with the proper sections in each, and padded to the
  4. * specified segment alignment when produced by the link editor. The first
  5. * segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header
  6. * and load commands of the object file before its first section. The zero
  7. * fill sections are always last in their segment (in all formats). This
  8. * allows the zeroed segment padding to be mapped into memory where zero fill
  9. * sections might be. The gigabyte zero fill sections, those with the section
  10. * type S_GB_ZEROFILL, can only be in a segment with sections of this type.
  11. * These segments are then placed after all other segments.
  12. *
  13. * The MH_OBJECT format has all of its sections in one segment for
  14. * compactness. There is no padding to a specified segment boundary and the
  15. * mach_header and load commands are not part of the segment.
  16. *
  17. * Sections with the same section name, sectname, going into the same segment,
  18. * segname, are combined by the link editor. The resulting section is aligned
  19. * to the maximum alignment of the combined sections and is the new section's
  20. * alignment. The combined sections are aligned to their original alignment in
  21. * the combined section. Any padded bytes to get the specified alignment are
  22. * zeroed.
  23. *
  24. * The format of the relocation entries referenced by the reloff and nreloc
  25. * fields of the section structure for mach object files is described in the
  26. * header file .
  27. */
  28. struct section { /* for 32-bit architectures */
  29. char sectname[16]; /* name of this section */
  30. char segname[16]; /* segment this section goes in */
  31. uint32_t addr; /* memory address of this section */
  32. uint32_t size; /* size in bytes of this section */
  33. uint32_t offset; /* file offset of this section */
  34. uint32_t align; /* section alignment (power of 2) */
  35. uint32_t reloff; /* file offset of relocation entries */
  36. uint32_t nreloc; /* number of relocation entries */
  37. uint32_t flags; /* flags (section type and attributes)*/
  38. uint32_t reserved1; /* reserved (for offset or index) */
  39. uint32_t reserved2; /* reserved (for count or sizeof) */
  40. };

其中, addr 指定这个section在虚拟内存中的地址
offset 制定这个section在可执行文件中 的偏移
reloff 第1个重定位条目在文件中的偏移

  1. /*
  2. * The linkedit_data_command contains the offsets and sizes of a blob
  3. * of data in the __LINKEDIT segment.
  4. */
  5. struct linkedit_data_command {
  6. uint32_t cmd; /* LC_CODE_SIGNATURE or LC_SEGMENT_SPLIT_INFO */
  7. uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */
  8. uint32_t dataoff; /* file offset of data in __LINKEDIT segment */
  9. uint32_t datasize; /* file size of data in __LINKEDIT segment */
  10. };

可以用 pagestuff mybinary -a 来查看

File Page 144 contains data of code signature
File Page 145 contains data of code signature

签名动作会修改可执行文件
对一个程序进行签名,会修改它的主执行文件。
1)如果你的程序有一个自验证模式,检查到文件被改变,那么你的代码会拒绝运行
2)如果在签名前附加了数据到 可执行文件上,那么签名的过程中,这些附加数据可能会被删除,或者放到其他位置
如果签名后,再次修改可执行文件,或者bundle它们, 代码签名验证引擎 会觉察到这些改变,并做适当的动作。

https://bitbucket.org/ronaldoussoren/macholib
macholib can be used to analyze and edit Mach-O headers, the executable
format used by Mac OS X.

签名后的变化
header部分 load cmd的数目加1, load cmd的size 加 16

__LINKEDIT的load command有变化, vm size 和 file size都增加了

然后在 load command 数组的最后添加了一个
cmd LC_CODE_SIGNATURE
cmdsize 16
dataoff 4176
datasize 5184

https://zhiwei.li/text/2012/02/15/iphone-mach-o文件格式与代码签名/

iPhone Mach-O文件格式与代码签名的更多相关文章

  1. iPhone OS 开发 - 了解并解决代码签名问题

    译者:Jestery 发表时间:2010-04-24浏览量:21082评论数:0挑错数:0 了解并解决代码签名问题 (为保持跟开发环境以及APPLE开发者社区网站结构对应,一些名词未作翻译) 绝大多数 ...

  2. iOS代码签名理解

    前言 做了几年iOS app coder了,对于证书的生成.使用流程烂熟于心,然而对于这套机制的原理却一直不甚理解.近来由于工作需要仔细研究了一下,特将自己的学习经验记录于此,以供大家学习指正. 问题 ...

  3. IOS证书/私钥/代码签名/描述文件

    1.   相关资源 (1)   钥匙串程序(常用工具->钥匙串),用于创建证书请求.安装证书.导出私钥等 (2)   IOS开发中心:https://developer.apple.com/de ...

  4. 密钥库文件格式[keystore]代码

    密钥库文件格式[keystore]代码 格式    :     JKS 扩展名  :      .jks/.ks 描述    :     [Java Keystore]密钥库的Java实现版本,pro ...

  5. SQL Server安全(6/11):执行上下文与代码签名(Execution Context and Code Signing)

    在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切.但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念.这篇文章提供了基础,因此你可以对SQL Se ...

  6. 第六篇 SQL Server安全执行上下文和代码签名

    本篇文章是SQL Server安全系列的第六篇,详细内容请参考原文. SQL Server决定主体是否有必要的执行代码权限的根本途径是其执行上下文规则.这一切都可能复杂一个主体有执行代码的权限,但是却 ...

  7. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  8. Electron 打包Mac安装包代码签名问题解决方案Could not get code signature for running application

    最近一直在做electron应用的打包,集成mac版本的自动更新时出现了问题. Error: Could not get code signature for running application ...

  9. 【译】第六篇 SQL Server安全执行上下文和代码签名

    本篇文章是SQL Server安全系列的第六篇,详细内容请参考原文. SQL Server决定主体是否有必要的执行代码权限的根本途径是其执行上下文规则.这一切都可能复杂一个主体有执行代码的权限,但是却 ...

随机推荐

  1. CSS模块化思想-----命名是个技术活

    CSS模块化思想(一)--------命名是个技术活 引子: 女孩子都喜欢买衣服,而我也不例外,奈何钱包太瘦,买不起高大上的定制,只能买撞衫率极高的休闲衣,不过对于我来说,我还是开心的,毕竟买衣服买的 ...

  2. [SDFZOJ]1069:树上统计

    神题...std丑的不行. 我们可以发现i->i+1的边被覆盖过i×(n-i)次. 因为以1->i为左端点,以i+1->n的为右端点,i->i+1都将被覆盖这么多次. 然后从1 ...

  3. java IO框架分析

    jave.io框架 2010-11-10 22:18:34|  分类: 默认分类|举报|字号 订阅     可从IO的类层次,IO框架的设计模式来论述. 总体来说,IO可以分为字节流和字符流,不同在于 ...

  4. elasticsearch 文档阅读笔记(三)

    文档 elasticsearch是通过document的形式存储数据的,个人理解文档就是一条数据一个对象 我们添加索引文档中不仅包含了数据还包含了元数据 比如我们为一个数据添加索引 文档中不仅有jso ...

  5. 通过Sqoop实现Mysql / Oracle 与HDFS / Hbase互导数据

    通过Sqoop实现Mysql / Oracle 与HDFS / Hbase互导数据\ 下文将重点说明通过Sqoop实现Mysql与HDFS互导数据,Mysql与Hbase,Oracle与Hbase的互 ...

  6. x86、Linux、GNU、GNOME是什么

    一.指令集架构: 指令集架构(英语:Instruction Set Architecture,缩写为ISA),又称指令集或指令集体系,是计算机体系结构中与程序设计有关的部分,包含了基本数据类型,指令集 ...

  7. android中常见的内存泄漏和解决的方法

    android中的内存溢出预计大多数人在写代码的时候都出现过,事实上突然认为工作一年和工作三年的差别是什么呢.事实上干的工作或许都一样,产品汪看到的结果也都一样,那差别就是速度和质量了. 写在前面的一 ...

  8. Java设计模式之从[星际争霸的兵种升级]分析观察者(Observer)模式

    观察者模式定义对象的一种一对多的依赖关系.当一个对象的状态发生改变时.全部依赖于它的对象都会得到通知并被自己主动更新. 一个简单的样例是.在星际争霸的虫族中有一个0基础单位叫做跳狗(Zergling) ...

  9. gephi——怎样上传节点表格而且为节点设定颜色类型

    使用gephi过程中出现两个问题: 一.节点编号不安给定的属性(Nodes)编号,而是莫名其妙地从1w+開始 解决:数据列名中需包括 id.则默觉得节点编号 二.怎样在上传的数据中指定节点颜色 须要一 ...

  10. POJ3463 Sightseeing

    题目大意:求两点间最短路与长度为最短路长度+1的路径的条数之和. 方法1:最短路径+DP 首先求出ST间最短路径,然后根据递归式记忆化搜索(因此还要构造反向图). 我们知道到达终点的路径长度最长为ma ...