iOS 安全攻防系列(四):分析二进制软件

       和现代语言一样,Object-C是一种反射式语言,他可以在运行时查看和修改自己 的行为。反射机制允许程序将指令看成数据,也允许在运行的时候对自己进行修改。Object-C 运行司环境不仅可以让一个程序创建和调用临时的方法,还可以实时创建类和方法。Object-C实现了smalltalk 消息队列框架,使得其中的方法实际上并不是传统意义上的呗调用,而是被发送消息。因此,如果你知道该收听哪个电台,就能监听到这些消息,从而了解程序中正在发生什么。另一方面,如果你知道怎么去发送消息,那就可以开始操作你的Object-C软件的运行时环境,使得它的行为发生改变,从而达到你的目的。

首先,先来了解Object-C在运行时是怎么做的,又发生了什么。先来看看下面的列子

@interface SaySomething:NSObject

- (void)say:(NSString *)phrase;

@end

@implementation SaySomething

- (void)say:(NSString *)phrase

{

    printf("%s\n",[phrase UTF8String]);

}

@end

int main(void){


    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

    SaySomething *saySomething = [[SaySomething alloc]init];

    [saySomething say:@"hello world!!"];

    [saySomething release];

    [pool release];

    return  0;

}

没有问题,进行编译

$ clang -arch armv7 -isysroot  `xcrun --sdk iphoneos --show-sdk-path` -o HelloWorld HelloWorld.m -framework Foundation -lobjc


这个是最新的编译器,用的是clang编译器。

$ file HelloWorld

HelloWorld: Mach-O executable arm


当然,这个程序是没法在计算机中运行的,签名后,拷贝到iPhone中才能运行,但是可以在计算机中使用strings 命令查看。

$ strings HelloWorld

hello world!!

UTF8String

say:

alloc

init

release

SaySomething

v12@0:4@8

在苹果操作系统中,可执行文件、动态链接库、扩展文件和核心转储(core dump)文件都是采用了一种名为Mach-O 的文件格式。上面我们用file命令已经查看过。它由三部分组成:头部、一系列的加载指令,以及数据段。在Mach-O 头部中给出了目标体系结构,如:x86-64 或者arm,还给出了一些标志位,以及解析出问价剩下的字段信息。加载指令描诉了问价的结构,以及在加载时在虚拟内存中该如何布局,还包含了一些其他的信息。如(用于动态链接的)符号表的位置和其他要被加载的共享库的名字等。最后,数据段中包含在加载指令中描述的实际要加载到内存中的短,其中包含了实际的代码和其他数据。

用tool命令来显示程序依赖的动态库,也就是程序加载时链接的共享库:

$ otool -L HelloWorld

HelloWorld:

/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1242.12.0)

/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)

/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1242.13.0)

上面红色的那一行就是Object-C库,也就是我们在编译时使用了-lobjc标识链接给应用的。这个库提供了所有Object-C环境的基本功能,如信息、类约定、协议支持、对象管理等。

我们在一开始就介绍,Object-C 是一种反射式语言,它的底层工作都是动态的。那具体是怎么工作的呢,再来看一段代码

objc_msgSend(

                 objc_msgSend(objc_getClass("NSAutoreleasePool"),NSSelectorFromString(@"alloc")),NSSelectorFromString(@"init")

        );

    objc_msgSend(objc_msgSend(objc_msgSend(objc_getClass("SaySomething"),NSSelectorFromString(@"alloc")),NSSelectorFromString(@"init")),NSSelectorFromString(@"say:"),@"hello world");

这说明,所有到say something 类及其方法的映射都必须保存在可执行文件中,让Object-C的反射机制能发挥作用。

在这个例子中调用objc_getClass 方法后想say something 发送了一个消息:alloc、init、say。

在编译好的程序里存在一个到所有类、方法和Object-C其他的组件,用于运行时换进的操作,那如何提取出这个映射的内容呢,这就要用到一个神奇:class-dump,这在我的iOS应用逆向工程(二)有它的介绍和使用说明

$ class-dump HelloWorld

//

//     Generated by class-dump 3.5 (64 bit).

//

//     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.

//


#pragma mark -


//

// File: HelloWorld

// UUID: 8FE08112-5E4D-36E6-8B46-E1654DAF5DB3

//

//                           Arch: armv7

//                 Source version: 0.0.0.0.0

//            Minimum iOS version: 9.2.0

//                    SDK version: 9.2.0

//

// Objective-C Garbage Collection: Unsupported

//


@interface SaySomething : NSObject

{

}


- (void)say:(id)arg1;


@end

这些就是刚刚写的那个程序的头文件,说明被编译进程序的每一个类及其相关的方法、实例变量、属性等。


iOS 应用逆向工程(三) 中介绍过怎么把微信的反编译出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值