命令行工具的本质:
- 可执行文件
- 和app可执行文件的区别只是在于没有资源文件,没有UI
zhanglingli@bogon Desktop % file Clutch
Clutch: Mach-O universal binary with 3 architectures: [arm_v7:Mach-O executable arm_v7] [arm_v7s:Mach-O executable arm_v7s] [arm64:Mach-O 64-bit executable arm64]
Clutch (for architecture armv7): Mach-O executable arm_v7
Clutch (for architecture armv7s): Mach-O executable arm_v7s
Clutch (for architecture arm64): Mach-O 64-bit executable arm64
zhanglingli@bogon Desktop %
一、开发命令行工具
下面以分析桌面Clutch文件类型为例,开发一个命令行工具
01、创建项目
- 如果命令行工具用在mac电脑上,那么可以直接创建命令行项目
- 如果命令行工具用在iPhone上,那么可以创建iOS项目,然后删除除了
main.m
和info.plist
之外的其他文件
02、编写代码,选择release模式编译
//main.m
#import <Foundation/Foundation.h>
#import <mach-o/loader.h>
#import <mach-o/fat.h>
int main(int argc, char * argv[]) {
@autoreleasepool {
//准备分析的文件路径
NSString *path = @"/Users/zhanglingli/Desktop/Clutch";
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
int length = sizeof(uint32_t);
//读取magic,关于magic请参考mach-o那篇文章
NSData *magicData = [handle readDataOfLength:length];
uint32_t magicNumber;
[magicData getBytes:&magicNumber length:length];
if (magicNumber == FAT_MAGIC || magicNumber == FAT_CIGAM) {
printf("FAT文件 ");
}else if (magicNumber == MH_MAGIC || magicNumber == MH_CIGAM) {
printf("非64bit架构文件 ");
}else if (magicNumber == FAT_MAGIC_64 || magicNumber == FAT_CIGAM_64) {
printf("64bit架构文件 ");
}
printf("magicNumber = 0x%x\n",magicNumber);
[handle closeFile];
}
return 0;
}
03、导出mach-o文件
- 放到bin目录
- 赋予权限
% chmod +x /usr/local/bin/LLZTools
04、执行命令行工具
% LLZTools FAT文件 magicNumber = 0xbebafeca
二、参数说明
/**
* argc: 参数的个数
* argv:存放参数的数组
* argv[0]:当前可执行文件的路径
*/
int main(int argc, char * argv[]) {
}
例:以分析mach-o文件架构类型为例,由用户提供文件路径
int main(int argc, const char * argv[]) {
@autoreleasepool {
if (argc == 1 || argc > 2) {
printf("格式错误");
return 0;
}
//准备分析的文件路径
NSString *path = [NSString stringWithUTF8String:argv[1]];
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
int length = sizeof(uint32_t);
NSData *magicData = [handle readDataOfLength:length];
uint32_t magicNumber;
[magicData getBytes:&magicNumber length:length];
if (magicNumber == FAT_MAGIC || magicNumber == FAT_CIGAM) {
printf("FAT文件 ");
}else if (magicNumber == MH_MAGIC || magicNumber == MH_CIGAM) {
printf("非64bit架构文件 ");
}else if (magicNumber == FAT_MAGIC_64 || magicNumber == FAT_CIGAM_64) {
printf("64bit架构文件 ");
}else{
printf("读取失败");
}
printf("magicNumber = 0x%x\n",magicNumber);
}
return 0;
}
zhanglingli@bogon ~ % chmod +x /usr/local/bin/LLZTools
zhanglingli@bogon ~ % LLZTools
格式错误% zhanglingli@bogon ~ % LLZTools /Users/lingli/Desktop/Clutch
FAT文件 magicNumber = 0xbebafeca
三、权限说明
有时候读取其他文件不成功,我们需要给可执行文件签上一定的权限,让他可以访问其他app的可执行文件。
- 导出可执行文件的权限
% ldid
usage: ldid -S[entitlements.xml] <binary>
ldid -e MobileSafari
ldid -S cat
ldid -Stfp.xml gdb
% ldid -e LZTools > LZTools.entitlements
LZTools.entitlements文件实质是一个xml文件,也就是plist文件,存放着可执行文件的权限信息
Snip20200813_9.png
-
修改可执行文件的权限
我们赋予它SpringBoard可执行文件的权限
- 找出SpringBoard 可执行文件,并导出权限文件
% ldid -e SpringBoard > SpringBoard.entitlements
- 修改LZTools权限
% ldid -SSpringBoard.entitlements LZTools
- 找出SpringBoard 可执行文件,并导出权限文件