IOS逆向学习之命令行工具
Posted GY-93
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IOS逆向学习之命令行工具相关的知识,希望对你有一定的参考价值。
ios逆向学习之命令行工具
1. main函数
- 命令行工具的本质:Mach-O类型的可执行文件,其实跟App内部的可执行文件差不多,区别的是App有界面,有附带的资源文件,但是命令行工具是没有
- 首先我们创建一个IOS平台的app项目,如下:
但是如果我们需要编写一个命令行工具, 我们不需要界面 , 我们可以修改main
函数的实现,直接返回0,这样就不会创建AppDelegate
类和相关界面
然后我们直接编译, 在Product
文件加下生成一个app,我们showFinder
,然后显示包内容,就可以看到一个app的可执行文件, 也就是我们需要的命令行工具:
找到对应的命令行工具,然后通过iFunBox
工具安装到手机的/usr/bin
目录下:
然后我们通过SSH
来连接手机,在终端输入指令看看:
第一次执行该命令行工具的时候,可能没有权限,我们需要赋予执行权限
-
chmod +x
: 赋予某个文件执行权限 -
注意:
- 为什么要用Xcode创建一个IOS项目?
- 因为使用Xcode帮我们创建项目, Xcode会自动帮我们配置该命令行工具的
架构信息
、证书签名(由于本人使用个人账号签名,所以该命令行工具是有期限,只有7天时间)
,一些等等信息,这样命令行工具才能再我们的IOS系统跑起来
- 因为使用Xcode帮我们创建项目, Xcode会自动帮我们配置该命令行工具的
- 为什么要用Xcode创建一个IOS项目?
2. 功能分析
2.1 Mach-O的头文件分析
- 假设我们编写的命令行工具能读取别的app的应用
我们通过MachOView
查看app的Mach-O文件,可以发现app文件的架构是在头部信息的前四个字节来表示的:
我们还可以查看xnu
的源码:
- 注意:有两个值是大小端的问题,根据机器的不同读取方式可能不同
2.2 编写代码读取Mach-O文件类型信息
- 所以这里我们可以读取app的可执行文件前4个字节,来确定app的可执行文件的架构信息,那么我如何读取app的可执行文件信息, 假如我们现在知道某个app的可执行文件路径,那么我们如何读取?
- 通过
NSData
来读取,[NSData dataWithContentsOfFile:neteasemusicPath];
,但是这个方法不太好,因NSData
需要把整个可执行文件载进内存,但是我们只需要读取前4个字节,如果整个文件比较大,那就比较费时了 NSFileHandle
:专门处理文件,一点一点的读取文件,我们可以使用这个类来读取文件
- 通过
#import <UIKit/UIKit.h>
#import<mach-o/fat.h>
#import <mach-o/loader.h>
int main(int argc, char * argv[]) {
//手机上网易云app的路径
NSString *neteasemusicPath = @"/var/containers/Bundle/Application/9F846BAA-F5F1-4C26-B886-210458BCE8CC/neteasemusic.app/neteasemusic";
NSFileHandle *fileHanlde = [NSFileHandle fileHandleForReadingAtPath:neteasemusicPath];
NSLog(@"fileHanlde======%@",fileHanlde);
//首先获取头部文件长度(通过xnu的源码我们可知magic 是uint32_t类型数据)
int length = sizeof(uint32_t);
//读取最前面的4个字节(magic number: 用来标记文件类型)
NSData *data = [fileHanlde readDataOfLength:length];
//得到文件类型
uint32_t magicNumber;
[data getBytes:&magicNumber length:length];
//判断文件类型(由于大端和小端的原因需要比较两个)
if (magicNumber == FAT_MAGIC || magicNumber == FAT_CIGAM) {
printf("FAT文件\\n");
} else if (magicNumber == MH_MAGIC || magicNumber == MH_CIGAM) {
printf("非64bit架构文件\\n");
}else if (magicNumber == MH_MAGIC_64 || magicNumber == MH_CIGAM_64) {
printf("64bit架构文件\\n");
} else {
printf("读取失败\\n");
}
printf("magicNumber = 0x%x \\n",magicNumber);
//关闭
[fileHanlde closeFile];
return 0;
}
2.3 终端的输入参数
argc
: 参数个数argv
: 存放参数的数组argv[0]
: 是存放当前可执行文件的路径
在我们不配置参数的情况下,默认有一个参数, 当前可执行文件的路径:
我们可以设置根据终端设置的参数不一样,执行不同的代码:
//判断终端输入参数
if (argc == 1) {
//表示没有输入参数
printf("-l 产看Mach-o信息\\n");
return 0;
}
//strcmp() : c语言中比较两个字符串是否相等 等于0 就是相等 不等0则不相等
if (strcmp(argv[1], "-l") != 0) {
//表示输入指令不正确
printf("-l 产看Mach-o信息\\n");
return 0;
}
2.4 可执行文件权限
读取别的app的可执行文件,我们上面是读取正常, 但是如果发生文件读取失败,可能是你编写的可执行文件没有权限读访问别的app。我们知道每个app都有沙盒的概念,那么我们让我们编写的命令行工具,具有访问别人app的权限了。
我们需要给我们的可执行文件签名(给可执行文件签上一定的权限,让可执行文件可以访问其它App的可执行文件),签名的方式目前有两种:codesign
、ldid
entitlements
:表示权限
但是codesign
比较麻烦,这里采用ldid
来签名, ldid
在我们安装theos
的时候已经安装了。
2.4.1 ldid导出权限
-
查看
ldid
的指令: -
查看可执行文件权限:
ldid -e xxxx(可执行文件路径) > xxxx.entitlements(权限文件路径)
- 权限文件:
entitlements
、plist
、xml
这三种后缀都是可以的,但是最好还是以entitlements
为后缀 >
: 表示直接覆盖这个文件>>
:表示追加到文件的尾部- 看个人需要是追加还是覆盖
- 权限文件:
2.4.2 签权限
我们如何给可执行文件签一个很高的权限,让其可以访问其它APP, 我们可以找一个权限很高的app,导出其权限,在把该权限签给我们自己的可执行文件。下面我们以SpringBoard
为例
-
SpringBoard
可执行文件所在路径: -
首先我们需要导出
SpringBoard
的权限(ldid -e SpringBoard > SpringBoard.entitlements
):
然后我们把Springboard
的权限签给自己的可执行文件,然后再导出自己的可执行文件权限比对,看看是否签入成功ldid -SSpringBoard.entitlements GYAppTools(把SpringBoard的权限签给GYAppTools)
、ldid -e GYAppTools > GYAppTools.entitlements(导出GYAppTools的权限)
以上是关于IOS逆向学习之命令行工具的主要内容,如果未能解决你的问题,请参考以下文章