反-反汇编 & 混淆 #1: 苹果没有遵循自己制定的Mach-O规范?

原文地址:http://reverse.put.as/2012/02/02/anti-disassembly-obfuscation-1-apple-doesnt-follow-their-own-mach-o-specifications/

当想到这个特性时,我非常高兴!因为我喜欢突破束缚,并且写了一个CrackMe来展示这个有趣的特性。

产生问题的原因是:苹果没有遵循自己的文档与标准(Mach-O方面的),但是逆向工具却要遵循。

当逆向修改过Section信息的Mach-O文件时,IDA可能会崩溃、输出错误的反汇编结果、混乱的字符串,

LLDB输出错误的反汇编结果(不是GDB),class-dump 会失败,逆向工程师看到是无意义的Mach-O文件头。

最后,这是一个有趣的混淆手段。^_^

当你使用IDA加载CrackMe时,程序会报这样的错误:负的Section大小或偏移。

当Sections的信息(偏移或者大小)超过文件大小时,otool也会输出错误的结果。

造成这个问题的具体方法是:修改Mach-O的Section信息。在32位下,Section的结构如下:

struct section { /* for 32-bit architectures */
	char		sectname[16];	/* name of this section */
	char		segname[16];	/* segment this section goes in */
	uint32_t	addr;		/* memory address of this section */
	uint32_t	size;		/* size in bytes of this section */
	uint32_t	offset;		/* file offset of this section */
	uint32_t	align;		/* section alignment (power of 2) */
	uint32_t	reloff;		/* file offset of relocation entries */
	uint32_t	nreloc;		/* number of relocation entries */
	uint32_t	flags;		/* flags (section type and attributes)*/
	uint32_t	reserved1;	/* reserved (for offset or index) */
	uint32_t	reserved2;	/* reserved (for count or sizeof) */
};

让我们从最容易引起问题的offset字段说起。根据标准offset的定义如下:指示当前Section在文件中的偏移值。

我的理解是:这个字段用来指示代码或者数据在文件的位置。这么理解没错吧?

既然是一个偏移值,那么理论上Section是没有必要是按照顺序排列的或者按照指定的循序排列(主要是指:没有必要跟Section在Segment中顺序一致)。这就打开了错误之门。

如果我们将offset指向其他地址?比如:IDA需要根据offset指向的地址来读取相应的数据。

我们来做一个测试,修改cstring setion的偏移值,然后使用IDA加载修改后的文件。

喔,现在程序中的字符串被“混淆”了,因为IDA加载了错误的数据。

很有意思,是吗?如果你修改Section信息(将offset改成一个错误的值),然后运行对应的程序,程序的行为还完全正确!

同样,修改 text section的便宜后,程序的中指令应该都错了,但是程序还是可以正常运行。

为什么程序还可以正确运行?这是非常有趣的。我认为主要的原因是:内核只是将文件线性的加载到内存而忽略了offset。

《Mac OS X Internal》812页中对execve()系统调用的说明可以解释问题原因。

exec_mach_imgact()函数(bsd/kern/kern_exec.c)会调用load_machfile()函数,

后者主要用来加载可执行文件,处理具体的Mach-O加载命令等。代码片段如下:

@bsd/kern/kern_exec.c

/*
         * Actually load the image file we previously decided to load.
         */
        lret = load_machfile(imgp, mach_header, thread, map, &load_result);

在load_machfile()内部会调用parse_machfile()函数来解析文件,

@bsd/kern/mach_loader.c

lret = parse_machfile(vp, map, thread, header, file_offset, macho_size,
                              0, result);

在这里我们可以看到有趣的注释:

/*
 * The file size of a mach-o file is limited to 32 bits; this is because
 * this is the limit on the kalloc() of enough bytes for a mach_header and
 * the contents of its sizeofcmds, which is currently constrained to 32
 * bits in the file format itself.  We read into the kernel buffer the
 * commands section, and then parse it in order to parse the mach-o file
 * format load_command segment(s).  We are only interested in a subset of
 * the total set of possible commands.
 */

在实现的下部,我们可以看到处理所有command的循环,其中section command是在segment(LC_SEGMENT/LC_SEGMENT_64)command下处理的。

因为我们需要看下load_segment()的实现。

在load_segment()内,我们发现对于可执行文件合法性的验证只是做到了segment一层,并没有验证section。

这也造成我们没法混淆segment :-))。

当parse_machfile()函数返回时,所有的解析工作已经完成,链接的库被加载,程序的入口函数被调用。

程序的布局与其在文件系统中一致(这就是我前面所说的线性),并且section信息根本没有被使用。

这是一种隐性的约定:可执行文件的格式是正确的。

这种行为(指内核加载可执行文件)正确吗?我认为是错误的。因为内核并没有遵循Mach-O标准,或者是我对标准理解有错误?

这又是一个信任不可信数据的例子,我们应该显式的校验输入数据。

我们应该继续了解真个加载过程,在CrackMe中还有另一个有趣的特性;-)。

我们还可以改变这些section结构的这些字段:flags,size, section和segment的名字,section 的顺序。

这样可以迷惑工具和逆向工程师。这里需要注意的是跟内核遵循同样的隐式约定,忽略如上的字段。

看起来有点怪异,是吧?

我希望你享受如上的分析过程,并且为你带来阅读xnu与dyld源代码的动力。

Have fun,

fG!

更新 1:

如下是本文观点的PoC。代码是32位的、non-fat mach-o文件、控制台程序。如果在Objective-C目标上应用这个特性,

会引起加载错误,因为并不是所有的 section 都可以被混淆。

manglemacho.c.gz

SHA256(manglemacho.c.gz)= d79a612b72130732d7e47b2925fba7fc0b63824622d05f08e7f33641d522a8b5

更新 2:

实际的情况是上section 的所有字段都可以是0,并不会带来什么不利的影响(除了mod_init_func)。

我这样试过,但是没有做笔记。如果不做更深入的混淆,IDA有时还可以聪明得进行反汇编,

原因是入口地址是合法的。我们可以通过修改 size 和 offset 来对IDA进行更深入的迷惑。

通过设置如下工具的第二个参数可以将 section 的所有字段都设置成0.

manglemacho_v0.3.c.gz

SHA256(manglemacho_v0.3.c.gz)= 4b33dc5f43bbb9114e6a8c18dba8894ca44b991cd69a5e5e54bfdcd03607fc9c

-------------------------------------------------

译注:

文章介绍了如何通过修改Mach-O的Section信息来实现反-反汇编,

我们接下来应该思考下如何还原被修改后的Mach-O文件?!

如果修改后的Mach-O程序又包含:完整性校验,反调试,嵌入了断点异常检测等特性呢。

反-反汇编 & 混淆 #1: 苹果没有遵循自己制定的Mach-O规范?

时间: 2024-10-14 18:35:21

反-反汇编 & 混淆 #1: 苹果没有遵循自己制定的Mach-O规范?的相关文章

[译]反-反汇编 & 混淆 #1: 苹果没有遵循自己制定的Mach-O规范?

原文地址:http://reverse.put.as/2012/02/02/anti-disassembly-obfuscation-1-apple-doesnt-follow-their-own-mach-o-specifications/ 当想到这个特性时,我非常高兴!因为我喜欢突破束缚,并且写了一个CrackMe来展示这个有趣的特性. 产生问题的原因是:苹果没有遵循自己的文档与标准(Mach-O方面的),但是逆向工具却要遵循. 当逆向修改过Section信息的Mach-O文件时,IDA可能

android 反编译 混淆过程中注意事项

此文源自组内成员分享的PPT,其他成员的文档由于没有得到授权,暂不公开. 本文命令如果没有特殊注明,均为windows 7环境. 本文只涉及大概的知识点,不涉及具体的细节,需要注意. 反编译 apktool 可反编译资源文件(xml,点九图)以及代码为smali代码 使用命令:apktool d xxx.apk output_filepath dex2jar 反编译dex文件(解压apk获得的classes.dex)为jar 使用命令:dex2jar xxx.dex jd-gui 查看jar文件

【Android 应用开发】 Android APK 反编译 混淆 重编译

反编译工具 : 总结了一下 linux, windows, mac 上的版本, 一起放到 CSDN 上下载; -- CSDN 下载地址 : [email protected]:~/decompiler$ tree -L 2 . ├── linux │   ├── apktool │   ├── dex2jar-0.0.9.15 │   └── jd-gui ├── mac │   ├── apktool │   ├── dex2jar-0.0.9.15 │   └── jd-gui-0.3.5.

安卓应用加固之静态反反汇编技术总结

0x00 前言 对安卓应用的静态保护增加了逆向时对应用的分析难度,可以从以下多个方面进行: 1.应用代码保护 2.资源保护 3.完整性校验 0x01 应用代码保护 所谓应用代码保护主要是对应用的源码进行保护,主要采用的保护手段是:软件混淆技术 软件混淆技术从混淆对象上来看,可以分为代码混淆和数据混淆.从混淆时间来分类,又可以分为:1.代码混淆  2.编译期混淆  3.二进制混淆 以下主要从混淆的不同时间来探讨混淆技术 一.代码混淆 二.模板混淆(编译期混淆) 三.AST混淆(编译期混淆) 四.I

(Unity)Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进展混淆,避免被反编译

Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进行混淆,避免被反编译. 1.打开VS,博主所用版本是Visual Studio 2013. 2.新建一个VC项目,选择类库,取名为JefferyChan,具体步骤如下图: 3.因为要调用Unity中的相关文件,所以这里要引入外部文件.首先在Unity的安装文件夹中找到UnityEngine.dll,我的路径是:D:\Program Files (x86)\Unity\Editor\Data\Managed 如

[C#防止反编译].NET 产品版权保护方案 (.NET源码加密保护)

[C#防止反编译].NET 产品版权保护方案 (.NET源码加密保护) 标签: .net加密产品c#dll工具 2011-03-24 21:06 27009人阅读 评论(13) 收藏 举报 分类: C#/.NET(4)  Decompile(6) 说 明:你希望自己用.net辛辛苦苦做出来的软件被人轻易破解吗?你希望自己花了大量人力物力用.net开发出来的产品被竞争对手轻易获取核心代码吗?这是 一篇比较详尽地介绍如何保护自己的.net源代码的文章,如混淆.加密和强名称等,出于保护原作者的角度,所

苹果式镇压,会奏效吗?

距离苹果新品手机发布越来越近了,外界一片歌舞升平,或等着眼前一亮,或猛烈吐槽,总之,整个消费市场充满着轻松写意,但与之相对应的,则是内部供应链上的剑拔弩张,他们一面殚精竭虑.神经衰弱地思考如何满足苹果巨大的订单以及严苛的品质要求:一面又仔细地盘算,自己在累得跟狗一样之后,还剩下多少利润,更让人感觉无奈的是,作为强势客户,苹果每年都会要求供应商降价,以维持自己的高利润,供应商在面对这种要求时,早期的时候会进行反抗,但临近量产时总能找到平衡点,同样的戏码年复一年地上演,就形成了一种非常微妙的画面:苹

.NET反编译的九大金刚

给大家介绍8款.Net反编译的利器:Reflector.ILspy.de4dot.JustDecompile.dnSpy.dotPeek.NETUnpack.DotNet Id.Simple Assembly Explorer,其中DotNet Id是查壳工具.NETUnpack是脱壳工具.Simple Assembly Explorer是反流程混淆利器(原是一款开源软件,托管在google code上).笔者比较喜欢用Reflector.ILspy.de4dot这3款,长短互补. 1.Refl

java 反编译 android 反编译

1. jad http://varaneckas.com/jad/jad158e.linux.intel.zip  下载jad, 给jad运行权限 ,运行 chmod a+x ./jad ./jad 缺点:不能反编译混淆过的,有很多文件反编译不成功 2. ded http://siis.cse.psu.edu/ded/installation.html 3. jd-gui 都知道这个,直接反编译成java文件,但是没有命令行 4. jd-cmd https://github.com/kwart/