一、命令行工具的本质
- 可执行文件
- 跟
APP
内部的可执行文件差不多
二、权限问题
root# TestCL
-sh: /usr/bin/TestCL: Permission denied
赋值权限
root# chmod +x /usr/bin/TestCL
三、MachO识别
3.1、区别Mach-O文件格式
从xnu源码中可以看出
magic number,魔数,用来标识文件类型
FAT文件
#define FAT_MAGIC 0xcafebabe
#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */
struct fat_header {
uint32_t magic; /* FAT_MAGIC */
uint32_t nfat_arch; /* number of structs that follow */
};
非64bit架构文件
/*
* The 32-bit mach header appears at the very beginning of the object file for
* 32-bit architectures.
*/
struct mach_header {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
};
/* Constant for the magic field of the mach_header (32-bit architectures) */
#define MH_MAGIC 0xfeedface /* the mach magic number */
#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
64bit架构文件
/*
* The 64-bit mach header appears at the very beginning of object files for
* 64-bit architectures.
*/
struct mach_header_64 {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
uint32_t reserved; /* reserved */
};
/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
四、命令行工具添加参数
// argc : 参数的个数
// argv : 存放参数的数组
// argv[0] : 是当前可执行文件的路径
int main(int argc, char * argv[]) {
@autoreleasepool {
}
}
五、编写命令行工具
#import <UIKit/UIKit.h>
#import <mach-o/fat.h>
#import <mach-o/loader.h>
// argc : 参数的个数
// argv : 存放参数的数组
// argv[0] : 是当前可执行文件的路径
int main(int argc, char * argv[]) {
@autoreleasepool {
if (argc == 1) {
printf("-l 查看Mach-O信息\n");
return 0;
}
if (strcmp(argv[1], "-l") != 0) {
printf("-l 查看Mach-O信息\n");
return 0;
}
NSString *appPath = @"/var/containers/Bundle/Application/C531D4C7-BE48-4689-9820-B25164C7D9B9/DingTalk.app/DingTalk";
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:appPath];
int length = sizeof(uint32_t);
//读取最前面的4个字节(magic number,魔数,用来标识文件类型)
NSData *magicData = [handle readDataOfLength:length];
// 魔数,用来标识文件类型
uint32_t magicNumber;
[magicData getBytes:&magicNumber length:length];
if (magicNumber == FAT_CIGAM || magicNumber == FAT_MAGIC) {
// 大小端
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);
[handle closeFile];
return 0;
}
}
六、命令行工具添加权限
6.1、利用ldid
添加权限
wenjian % ldid
usage: ldid -S[entitlements.xml] <binary>
ldid -e MobileSafari
ldid -S cat
ldid -Stfp.xml gdb
6.2、获取SpringBoard
权限
SpringBoard
路径:/System/Library/CoreServices/SpringBoard.app/SpringBoard
wenjian % ldid -e SpringBoard > SpringBoard.entitlements
6.3、添加SpringBoard
权限到命令行工具
wenjian % ldid -SSpringBoard.entitlements TestCL
七、运行结果
root# TestCL
-l 查看Mach-O信息
root# TestCL -l
64bit架构文件
magicNumber = 0xfeedfacf