├── .DS_Store ├── .idea ├── SearchParttenCode.iml ├── .gitignore ├── vcs.xml ├── xcode.xml └── modules.xml ├── SearchParttenCode ├── .DS_Store ├── Utils.h ├── main.m └── Utils.m ├── SearchParttenCode.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── qiuchenly.xcuserdatad │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcuserdata │ └── qiuchenly.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── SearchParttenCode.xcscheme ├── xcshareddata │ └── xcschemes │ │ └── ReleaseBuild.xcscheme └── project.pbxproj ├── .gitignore └── LICENSE /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiuChenlyOpenSource/SearchHexCodeInFile/HEAD/.DS_Store -------------------------------------------------------------------------------- /.idea/SearchParttenCode.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /SearchParttenCode/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiuChenlyOpenSource/SearchHexCodeInFile/HEAD/SearchParttenCode/.DS_Store -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 基于编辑器的 HTTP 客户端请求 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/xcode.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/xcuserdata/qiuchenly.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.iml 3 | .idea 4 | .vscode 5 | .ruby-lsp 6 | IACPLHttpTransferClient 7 | .dsp_cache 8 | default.profraw 9 | SearchParttenCode.xcodeproj/xcuserdata 10 | SearchParttenCode.xcodeproj/xcshareddata 11 | SearchParttenCode.xcodeproj/project.xcworkspace/xcuserdata -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/project.xcworkspace/xcuserdata/qiuchenly.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiuChenlyOpenSource/SearchHexCodeInFile/HEAD/SearchParttenCode.xcodeproj/project.xcworkspace/xcuserdata/qiuchenly.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/project.xcworkspace/xcuserdata/qiuchenly.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/xcuserdata/qiuchenly.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ReleaseBuild.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 1 11 | 12 | SearchParttenCode.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 3BCEBD8B2AD91AEB0070825E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SearchParttenCode/Utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.h 3 | // SearchParttenCode 4 | // 5 | // Created by qiuchenly on 2023/10/13. 6 | // 7 | 8 | #ifndef Utils_h 9 | #define Utils_h 10 | 11 | 12 | #endif /* Utils_h */ 13 | 14 | BOOL checkSelfInject(char *name); 15 | BOOL checkAppVersion(char *checkVersion); 16 | BOOL checkAppCFBundleVersion(char *checkVersion); 17 | NSString* checkCPUSubType(void); 18 | BOOL isX86(void); 19 | intptr_t getAddress(intptr_t x86,intptr_t arm64); 20 | void NOPAddress(intptr_t address); 21 | void NOPAddressEx(intptr_t address, uint8_t *bytes, uint32_t len); 22 | void initBaseEnv(void); 23 | int ret0(void); 24 | int ret1(void); 25 | uint32_t getArchFileOffset(const uint32_t desiredCpuType, const char *baseName); 26 | NSArray *findOffsetsForHexInFile(NSString *filePath, NSString *searchHex); 27 | NSArray *getArchitecturesInfoForFile(NSString *filePath); 28 | uint32_t getCurrentArchFileOffset(const char* inxForArchImage); 29 | long getRealFileOffset2RAMOffsetA(long codeOffset, long fileOffset); 30 | long getRealFileOffset2RAMOffset(long codeOffset, long fileOffset); 31 | NSArray *findOffsetsForHexInCurrentFile(NSString *searchHex); 32 | NSArray *findOffsetsForWildcardHexInFile(NSString *filePath, NSString *searchHex, NSUInteger matchCount); 33 | 34 | 35 | NSMutableDictionary* hookPtrByMatchMachineCode(const char* hookFile,NSString* intelMachineCode,NSString* arm64MachineCode,int matchCount); 36 | 37 | @interface Utils : NSObject 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/xcuserdata/qiuchenly.xcuserdatad/xcschemes/SearchParttenCode.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 41 | 43 | 49 | 50 | 51 | 52 | 55 | 56 | 59 | 60 | 61 | 62 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/xcshareddata/xcschemes/ReleaseBuild.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /SearchParttenCode/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SearchParttenCode 4 | // 5 | // Created by qiuchenly on 2023/10/13. 6 | // 7 | 8 | #import 9 | #import "Utils.h" 10 | 11 | 12 | int fixPlist(NSString * targetHelper){ 13 | NSLog(@"准备修复Plist信息..."); 14 | NSLog(@"文件: %@", targetHelper); 15 | 16 | NSData *fileData = [NSData dataWithContentsOfFile:targetHelper]; 17 | if (fileData == nil) { 18 | NSLog(@"无法读取文件"); 19 | return -5; 20 | } 21 | 22 | // 在这里处理二进制数据 23 | // 您可以使用NSData的方法来访问和操作二进制数据 24 | // 例如,[fileData bytes]返回指向二进制数据的指针,[fileData length]返回数据的长度 25 | const void *bytes = [fileData bytes]; 26 | NSMutableData *mutableFileData = [NSMutableData dataWithData:fileData]; 27 | const long len = [fileData length]; 28 | 29 | NSLog(@"大小: %li字节",len); 30 | 31 | NSArray *destinationInx = findOffsetsForWildcardHexInFile(targetHelper, @"3C 6B 65 79 3E 53 4D 41 75 74 68 6F 72 69 7A 65 64 43 6C 69 65 6E 74 73 3C 2F 6B 65 79 3E", @""); 32 | 33 | for (NSNumber* inx in destinationInx){ 34 | int start = [inx intValue]; 35 | NSLog(@"开始位置: %i",[inx intValue]); 36 | 37 | const void *startByte = bytes + start; 38 | const void *searchResult = memmem(startByte, len - start, "\x3C\x2F\x61\x72\x72\x61\x79\x3E", 8); 39 | 40 | if (searchResult != NULL) { 41 | NSUInteger endIndex = searchResult - bytes; 42 | NSUInteger length = endIndex - start + 8; 43 | 44 | NSData *subData = [NSData dataWithBytes:startByte length:length]; 45 | 46 | NSString *stringData = [[NSString alloc] initWithData:subData encoding:NSUTF8StringEncoding]; 47 | stringData = [stringData stringByReplacingOccurrencesOfString:@""" withString:@"\""]; 48 | 49 | #ifdef DEBUG 50 | 51 | NSLog(@"%@", stringData); 52 | 53 | #endif 54 | // 使用正则表达式提取特定部分 55 | NSError *error = nil; 56 | 57 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@".*?identifier \"(.*?)\"" options:0 error:&error]; 58 | if (error) { 59 | NSLog(@"Regex error: %@", error.localizedDescription); 60 | } 61 | 62 | NSArray *matches = [regex matchesInString:stringData options:0 range:NSMakeRange(0, stringData.length)]; 63 | 64 | 65 | if([matches count] <=0){ 66 | NSLog(@"此区域已经被修改,或匹配失败,跳过。"); 67 | break; 68 | } 69 | 70 | NSMutableString *reformattedString = [NSMutableString string]; 71 | [reformattedString appendString:@"SMAuthorizedClients\n\n"]; 72 | 73 | for (NSTextCheckingResult *match in matches) { 74 | NSRange matchRange = [match rangeAtIndex:1]; 75 | NSString *stringValue = [stringData substringWithRange:matchRange]; 76 | [reformattedString appendFormat:@"\tidentifier \"%@\"\n", stringValue]; 77 | } 78 | 79 | [reformattedString appendString:@""]; 80 | #ifdef DEBUG 81 | NSLog(@"%@", reformattedString); 82 | #endif 83 | NSData* finalBytes = [reformattedString dataUsingEncoding:NSUTF8StringEncoding]; 84 | 85 | // 获取reformattedData的长度 86 | NSUInteger reformattedLength = [finalBytes length]; 87 | 88 | // 计算剩余空间需要填充的字节数 89 | NSUInteger remainingLength = length - reformattedLength; 90 | 91 | // 替换原始部分 92 | [mutableFileData replaceBytesInRange:NSMakeRange(start, reformattedLength) withBytes:[finalBytes bytes] length:reformattedLength]; 93 | 94 | // 填充剩余空间 95 | if (remainingLength > 0) { 96 | unsigned char paddingBytes[remainingLength]; 97 | memset(paddingBytes, 0x0A, remainingLength); 98 | [mutableFileData replaceBytesInRange:NSMakeRange(start + reformattedLength, remainingLength) withBytes:paddingBytes length:remainingLength]; 99 | } 100 | } else { 101 | NSLog(@"未找到指定字节序列"); 102 | } 103 | } 104 | // 将修改后的数据写回文件 105 | if (![mutableFileData writeToFile:targetHelper atomically:YES]) { 106 | NSLog(@"写入文件失败"); 107 | return -7; 108 | } 109 | NSLog(@"文件修复完成."); 110 | return 0; 111 | } 112 | 113 | int main(int argc, const char * argv[]) { 114 | @autoreleasepool { 115 | const char * target = argv[1]; 116 | if (target == NULL){ 117 | NSLog(@"请提供目标参数!"); 118 | return -3; 119 | } 120 | 121 | NSString *executablePath = [[NSBundle mainBundle] executablePath]; 122 | NSString *executableDirectory = [executablePath stringByDeletingLastPathComponent]; 123 | executableDirectory = [executableDirectory stringByAppendingString:@"/"]; 124 | 125 | NSLog(@"可执行文件所在的目录:%@", executableDirectory); 126 | 127 | /** 128 | 文件内容格式示例 129 | { 130 | "surge": { 131 | "locate": "/Applications/Surge.app/Contents/Library/LaunchServices/com.nssurge.surge-mac.helper", 132 | "arm": "FF C3 02 D1 FA 67 06 A9 F8 5F 07 A9 F6 57 08 A9 F4 4F 09 A9 FD 7B 0A A9 FD 83 02 91 F3 03 00 AA BF 83 1B F8 19 01 00 B0 20 ?? 43 F9 62 12 40 F9 ?? 46 00 94 A2 23 01 D1 01 00 80 52 ?? 3F 00 94 C0 00 00 F0 00 E0 3C 91 E2 43 01 91 01 00 80 52 ?? ?? 00 94 A0 83 5B F8 E2 2B 40 F9 81 00 80 52 ?? ?? 00 94 F5 03 00 AA A0 83 5B F8 ?? 3E 00 94 E0 2B 40 F9 ?? 3E 00 94 C0 00 00 F0 00 60 3D 91 E2 43 01 91 01 00 80 52", 133 | "x86": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 83 EC 58 48 89 FB 4C 8D 7D C0 49 C7 07 00 00 00 00 48 8B 3D ?? ?? 01 00 48 8B 53 20 48 8B 35 ?? ?? 01 00 4C 8B 35 ?? ?? 01 00 41 FF D6 48 89 C7 31 F6 4C 89 FA E8 ?? ?? 01 00 48 8D 3D ?? ?? 01 00 4C 8D 65 C8 31 F6 4C 89 E2 E8 ?? ?? 01 00 49 8B 3F 49 8B 14 24 BE 04 00 00 00 E8 ?? ?? 01 00 89 45 BC 49 8B 3F E8 ?? ?? 01 00 49 8B 3C 24 E8 ?? ?? 01 00 48 8D 3D ?? ?? 01 00 31 F6 4C 89 E2 E8 ?? 2A 01 00" 134 | } 135 | } 136 | */ 137 | NSString *filePath = [executableDirectory stringByAppendingString: @"Patch.json"]; 138 | 139 | // 读取文件内容 140 | NSError *error; 141 | NSString *jsonString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error]; 142 | 143 | if (error) { 144 | NSLog(@"读取文件出错:%@", error); 145 | return -2; 146 | } 147 | 148 | // 解析 JSON 数据 149 | NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; 150 | id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; 151 | 152 | if (error) { 153 | NSLog(@"解析 JSON 数据出错:%@", error); 154 | return -1; 155 | } 156 | 157 | NSDictionary *jsonDict = (NSDictionary *)jsonObject; 158 | 159 | NSDictionary *info = jsonDict[[NSString stringWithUTF8String:target]]; 160 | 161 | if(info == nil) { 162 | NSLog(@"没有找到记录对应的数据! %s", target); 163 | return -4; 164 | } 165 | 166 | NSArray *locateArray = (NSArray *)info[@"locate"]; 167 | 168 | for (NSString *item in locateArray) { 169 | // 部分app可能不存在内部校验,所以有时候并不需要这些操作 170 | if(info[@"x86"] != nil && info[@"arm"] != nil) { 171 | NSMutableDictionary* res = hookPtrByMatchMachineCode([item UTF8String], info[@"x86"], info[@"arm"], 1); 172 | 173 | NSString *targetFile = [executableDirectory stringByAppendingString:info[@"out"]]; 174 | NSError *fileError; 175 | NSString *fileContent = [NSString stringWithContentsOfFile:targetFile encoding:NSUTF8StringEncoding error:&error]; 176 | if (fileContent) { 177 | NSString *keyIntel = info[@"replaceIntel"]; 178 | NSString *keyARM = info[@"replaceARM"]; 179 | 180 | NSString *modifiedContent = [fileContent stringByReplacingOccurrencesOfString:keyIntel withString:res[@"x86"]]; 181 | 182 | modifiedContent = [modifiedContent stringByReplacingOccurrencesOfString:keyARM withString:res[@"arm"]]; 183 | 184 | BOOL success = [modifiedContent writeToFile:targetFile atomically:YES encoding:NSUTF8StringEncoding error:&fileError]; 185 | if (success) { 186 | NSLog(@"成功更新了目标文件中的内容."); 187 | } else { 188 | NSLog(@"更新参数失败! %@", error); 189 | } 190 | } else { 191 | NSLog(@"无法读取待更新参数的文件错误: %@", error); 192 | } 193 | } 194 | 195 | NSString* needFixPlist = info[@"fixPlist"]; 196 | if (needFixPlist!=nil && fixPlist(item) == 0) { 197 | 198 | } 199 | } 200 | } 201 | return 0; 202 | } 203 | -------------------------------------------------------------------------------- /SearchParttenCode/Utils.m: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.m 3 | // SearchParttenCode 4 | // 5 | // Created by qiuchenly on 2023/10/13. 6 | // 7 | 8 | #import 9 | #include "Utils.h" 10 | #include 11 | #import 12 | #import 13 | #import 14 | #import "Utils.h" 15 | #include 16 | #include 17 | #import "mach-o/fat.h" 18 | #import "mach-o/getsect.h" 19 | 20 | @implementation Utils 21 | 22 | NSString *checkCPUSubType(void) { 23 | size_t size; 24 | sysctlbyname("hw.machine", NULL, &size, NULL, 0); 25 | char *machine = malloc(size); 26 | sysctlbyname("hw.machine", machine, &size, NULL, 0); 27 | NSString *machineString = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding]; 28 | free(machine); 29 | NSLog(@"当前CPU类型是 %@", machineString); 30 | return machineString; 31 | } 32 | 33 | 34 | /** 35 | * 是否为X86机器 否则就是arm64机器 36 | */ 37 | BOOL isX86(void) { 38 | return [checkCPUSubType() isEqualToString:@"x86_64"]; 39 | } 40 | 41 | /** 42 | * 获取指向 x86 架构的文件的文件偏移量 43 | * @param desiredCpuType CPU_TYPE_X86 44 | * @param baseName 文件序号 45 | * @return 返回当前架构的代码开始段开始地址 46 | */ 47 | uint32_t getArchFileOffset(const uint32_t desiredCpuType, const char *baseName) { 48 | NSLog(@"==== 得到了 %s", baseName); 49 | NSArray *architecturesInfo = getArchitecturesInfoForFile([NSString stringWithUTF8String:baseName]); 50 | 51 | for (NSDictionary *archInfo in architecturesInfo) { 52 | cpu_type_t cpuType = [archInfo[@"cpuType"] unsignedIntValue]; 53 | uint32_t offset = [archInfo[@"offset"] unsignedIntValue]; 54 | 55 | if (cpuType == desiredCpuType) { 56 | return offset; 57 | } else 58 | continue; 59 | } 60 | return 0; 61 | } 62 | 63 | /** 64 | * 自动获取当前架构的文件相对内存地址偏移 65 | * @param inxForArchImage 镜像名称 66 | * @return 返回当前处理器代码偏移段地址 67 | */ 68 | uint32_t getCurrentArchFileOffset(const char* inxForArchImage) { 69 | const uint32_t desiredCpuType = isX86() ? CPU_TYPE_X86_64 : CPU_TYPE_ARM64; 70 | return getArchFileOffset(desiredCpuType, inxForArchImage); 71 | } 72 | 73 | /** 74 | * 文件偏移Magic头 75 | */ 76 | const long ARCH_FAT_SIZE = 4294967296;//0x100000000 77 | 78 | /** 79 | * 转换文件偏移到内存地址偏移 无0x10000000偏移 80 | * @param codeOffset 81 | * @param fileOffset 82 | * @return 83 | */ 84 | long getRealFileOffset2RAMOffsetA(long codeOffset, long fileOffset) { 85 | return codeOffset - fileOffset; 86 | } 87 | 88 | /** 89 | * 转换文件偏移到内存地址偏移 90 | * @param codeOffset 代码偏移量 91 | * @param fileOffset 文件全局偏移量 92 | * @return long var 93 | */ 94 | long getRealFileOffset2RAMOffset(long codeOffset, long fileOffset) { 95 | return getRealFileOffset2RAMOffsetA(codeOffset, fileOffset) + ARCH_FAT_SIZE; 96 | } 97 | 98 | /** 99 | * 从文件中寻找Hex数据串位置 100 | * @param filePath 文件路径 101 | * @param searchHex 搜索的hex字符串 01 02 03 04 AF 这种数据即可 每个字节用空格空开 102 | * @return 返回数据index 103 | */ 104 | NSArray *findOffsetsForHexInFile(NSString *filePath, NSString *searchHex) { 105 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath]; 106 | NSMutableArray *offsets = [NSMutableArray array]; 107 | 108 | if (fileHandle) { 109 | NSData *fileData = [fileHandle readDataToEndOfFile]; 110 | NSArray *lst = [searchHex componentsSeparatedByString:@" "]; 111 | NSData *searchData = dataFromHexString(searchHex); 112 | 113 | if (searchData) { 114 | NSUInteger searchLength = [searchData length]; 115 | NSUInteger fileLength = [fileData length]; 116 | NSUInteger searchIndex = 0; 117 | 118 | for (NSUInteger i = 0; i < fileLength; i++) { 119 | uint8_t currentByte = ((const uint8_t *) [fileData bytes])[i]; 120 | 121 | if (currentByte == ((const uint8_t *) [searchData bytes])[searchIndex]) { 122 | searchIndex++; 123 | 124 | if (searchIndex == searchLength) { 125 | [offsets addObject:@(i - lst.count + 1)]; 126 | searchIndex = 0; 127 | } 128 | } else { 129 | searchIndex = 0; 130 | } 131 | } 132 | } else { 133 | NSLog(@"Invalid search hex string: %@", searchHex); 134 | } 135 | 136 | [fileHandle closeFile]; 137 | } else { 138 | NSLog(@"Failed to open file at path: %@", filePath); 139 | } 140 | 141 | return [offsets copy]; 142 | } 143 | 144 | NSArray *findOffsetsForHexInCurrentFile(NSString *searchHex) { 145 | return findOffsetsForHexInFile([NSString stringWithUTF8String:_dyld_get_image_name(0)], searchHex); 146 | } 147 | 148 | /** 149 | * 从Mach-O中读取文件架构信息 150 | * @param filePath 文件路径 151 | * @return 返回文件中所有架构列表 只能分析FAT架构文件 Mach-O 64位文件解析不了 会死循环 152 | */ 153 | NSArray *getArchitecturesInfoForFile(NSString *filePath) { 154 | NSMutableArray < NSDictionary * > *architecturesInfo = [NSMutableArray array]; 155 | 156 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath]; 157 | NSData *fileData = [fileHandle readDataOfLength:sizeof(struct fat_header)]; 158 | 159 | if (fileData) { 160 | const struct fat_header *header = (const struct fat_header *) [fileData bytes]; 161 | uint32_t nfat_arch = OSSwapBigToHostInt32(header->nfat_arch); 162 | 163 | NSLog(@"==== nfat_arch = %i = %i",nfat_arch,header->nfat_arch); 164 | 165 | for (uint32_t i = 0; i < nfat_arch; i++) { 166 | NSData *archData = [fileHandle readDataOfLength:sizeof(struct fat_arch)]; 167 | const struct fat_arch *arch = (const struct fat_arch *) [archData bytes]; 168 | 169 | cpu_type_t cpuType = OSSwapBigToHostInt32(arch->cputype); 170 | cpu_subtype_t cpuSubtype = OSSwapBigToHostInt32(arch->cpusubtype); 171 | uint32_t offset = OSSwapBigToHostInt32(arch->offset); 172 | uint32_t size = OSSwapBigToHostInt32(arch->size); 173 | 174 | NSDictionary *archInfo = @{ 175 | @"cpuType": @(cpuType), 176 | @"cpuSubtype": @(cpuSubtype), 177 | @"offset": @(offset), 178 | @"size": @(size) 179 | }; 180 | 181 | [architecturesInfo addObject:archInfo]; 182 | } 183 | } else { 184 | NSLog(@"Failed to read file at path: %@", filePath); 185 | } 186 | 187 | [fileHandle closeFile]; 188 | 189 | return [architecturesInfo copy]; 190 | } 191 | 192 | 193 | /** 194 | * HexString2Data 195 | * @param hexString 196 | * @return 197 | */ 198 | NSData *dataFromHexString(NSString *hexString) { 199 | NSMutableData *data = [NSMutableData new]; 200 | NSCharacterSet *whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 201 | hexString = [[hexString componentsSeparatedByCharactersInSet:whitespace] componentsJoinedByString:@""]; 202 | 203 | for (NSUInteger i = 0; i < [hexString length]; i += 2) { 204 | NSString *byteString = [hexString substringWithRange:NSMakeRange(i, 2)]; 205 | if ([byteString isEqualToString:@"??"]) { 206 | //这里为了适配?? 通配符 直接改成144 0x90 nop 但是这么写在匹配NOP代码的时候可能会出现误判的问题 207 | uint8_t byte = (uint8_t) 144; 208 | [data appendBytes:&byte length:1]; 209 | continue; 210 | } 211 | NSScanner *scanner = [NSScanner scannerWithString:byteString]; 212 | unsigned int byteValue; 213 | [scanner scanHexInt:&byteValue]; 214 | uint8_t byte = (uint8_t) byteValue; 215 | // NSLog(@"byteString = %@, byteValue = %i", byteString,byte); 216 | [data appendBytes:&byte length:1]; 217 | } 218 | // NSLog(@"byteString = %@", [data copy]); 219 | return [data copy]; 220 | } 221 | 222 | NSArray *findOffsetsForWildcardHexInFile(NSString *filePath, NSString *searchHex, NSUInteger matchCount) { 223 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath]; 224 | NSMutableArray *offsets = [NSMutableArray array]; 225 | 226 | if (fileHandle) { 227 | NSData *fileData = [fileHandle readDataToEndOfFile]; 228 | NSData *searchData = dataFromHexString(searchHex); 229 | // NSLog(@"==== fileData = %@,searchData = %@",fileData,searchData); 230 | 231 | if (searchData) { 232 | NSUInteger searchLength = [searchData length]; 233 | NSUInteger fileLength = [fileData length]; 234 | NSUInteger matchCounter = 0; 235 | 236 | for (NSUInteger i = 0; i < fileLength - searchLength + 1; i++) { 237 | BOOL isMatch = YES; 238 | for (NSUInteger j = 0; j < searchLength; j++) { 239 | uint8_t fileByte = ((const uint8_t *)[fileData bytes])[i + j]; 240 | uint8_t searchByte = ((const uint8_t *)[searchData bytes])[j]; 241 | if (searchByte != 0x90 && fileByte != searchByte) { 242 | isMatch = NO; 243 | break; 244 | } 245 | } 246 | if (isMatch) { 247 | [offsets addObject:@(i)]; 248 | matchCounter++; 249 | if (matchCounter >= matchCount) { 250 | break; 251 | } 252 | } 253 | } 254 | } else { 255 | NSLog(@"Invalid search hex string: %@", searchHex); 256 | } 257 | 258 | [fileHandle closeFile]; 259 | } else { 260 | NSLog(@"Failed to open file at path: %@", filePath); 261 | } 262 | 263 | return [offsets copy]; 264 | } 265 | 266 | 267 | /** 268 | * hook机器码匹配通杀函数 269 | * @param hookFile 库名称 270 | * @param intelMachineCode intel机器码 271 | * @param arm64MachineCode arm机器码 272 | * @param matchCount 匹配数量 建议为1 273 | */ 274 | NSMutableDictionary* hookPtrByMatchMachineCode(const char* hookFile,NSString* intelMachineCode,NSString* arm64MachineCode,int matchCount){ 275 | //hook通杀开始 276 | intptr_t fileOffset = getCurrentArchFileOffset(hookFile); 277 | //当前需要检查的架构 278 | NSString *patchImage = [NSString stringWithUTF8String:hookFile]; 279 | 280 | NSMutableDictionary *json = [NSMutableDictionary dictionaryWithDictionary:@{ 281 | @"arm": @"", 282 | @"x86": @"" 283 | }]; 284 | 285 | NSArray *destinationFunction = findOffsetsForWildcardHexInFile(patchImage, intelMachineCode, matchCount); 286 | if (destinationFunction.count > 0) { 287 | for (NSNumber *destination in destinationFunction) { 288 | NSLog(@"==== Intel 通用Hook地址 %llx", destination.longLongValue); 289 | json[@"x86"] = [NSString stringWithFormat:@"%llx", destination.longLongValue]; 290 | } 291 | } 292 | 293 | destinationFunction = findOffsetsForWildcardHexInFile(patchImage, arm64MachineCode, matchCount); 294 | 295 | if (destinationFunction.count > 0) { 296 | for (NSNumber *destination in destinationFunction) { 297 | NSLog(@"==== ARM 通用Hook地址 %llx", destination.longLongValue); 298 | json[@"arm"] = [NSString stringWithFormat:@"%llx", destination.longLongValue]; 299 | } 300 | } else { 301 | NSLog(@"==== 没有匹配到数据"); 302 | } 303 | return json; 304 | } 305 | 306 | @end 307 | -------------------------------------------------------------------------------- /SearchParttenCode.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3BCEBD902AD91AEB0070825E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BCEBD8F2AD91AEB0070825E /* main.m */; }; 11 | 3BCEBDA92AD924990070825E /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BCEBDA82AD924990070825E /* Utils.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 3BCEBD8A2AD91AEB0070825E /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 3BCEBD8C2AD91AEB0070825E /* SearchParttenCode */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SearchParttenCode; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 3BCEBD8F2AD91AEB0070825E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29 | 3BCEBDA82AD924990070825E /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Utils.m; sourceTree = ""; }; 30 | 3BCEBDAA2AD924A80070825E /* Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Utils.h; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 3BCEBD892AD91AEB0070825E /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 3BCEBD832AD91AEB0070825E = { 45 | isa = PBXGroup; 46 | children = ( 47 | 3BCEBD8E2AD91AEB0070825E /* SearchParttenCode */, 48 | 3BCEBD8D2AD91AEB0070825E /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 3BCEBD8D2AD91AEB0070825E /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 3BCEBD8C2AD91AEB0070825E /* SearchParttenCode */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 3BCEBD8E2AD91AEB0070825E /* SearchParttenCode */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 3BCEBD8F2AD91AEB0070825E /* main.m */, 64 | 3BCEBDA82AD924990070825E /* Utils.m */, 65 | 3BCEBDAA2AD924A80070825E /* Utils.h */, 66 | ); 67 | path = SearchParttenCode; 68 | sourceTree = ""; 69 | }; 70 | /* End PBXGroup section */ 71 | 72 | /* Begin PBXNativeTarget section */ 73 | 3BCEBD8B2AD91AEB0070825E /* SearchParttenCode */ = { 74 | isa = PBXNativeTarget; 75 | buildConfigurationList = 3BCEBD932AD91AEB0070825E /* Build configuration list for PBXNativeTarget "SearchParttenCode" */; 76 | buildPhases = ( 77 | 3BCEBD882AD91AEB0070825E /* Sources */, 78 | 3BCEBD892AD91AEB0070825E /* Frameworks */, 79 | 3BCEBD8A2AD91AEB0070825E /* CopyFiles */, 80 | ); 81 | buildRules = ( 82 | ); 83 | dependencies = ( 84 | ); 85 | name = SearchParttenCode; 86 | productName = SearchParttenCode; 87 | productReference = 3BCEBD8C2AD91AEB0070825E /* SearchParttenCode */; 88 | productType = "com.apple.product-type.tool"; 89 | }; 90 | /* End PBXNativeTarget section */ 91 | 92 | /* Begin PBXProject section */ 93 | 3BCEBD842AD91AEB0070825E /* Project object */ = { 94 | isa = PBXProject; 95 | attributes = { 96 | BuildIndependentTargetsInParallel = 1; 97 | LastUpgradeCheck = 1500; 98 | TargetAttributes = { 99 | 3BCEBD8B2AD91AEB0070825E = { 100 | CreatedOnToolsVersion = 15.0; 101 | }; 102 | }; 103 | }; 104 | buildConfigurationList = 3BCEBD872AD91AEB0070825E /* Build configuration list for PBXProject "SearchParttenCode" */; 105 | compatibilityVersion = "Xcode 14.0"; 106 | developmentRegion = en; 107 | hasScannedForEncodings = 0; 108 | knownRegions = ( 109 | en, 110 | Base, 111 | ); 112 | mainGroup = 3BCEBD832AD91AEB0070825E; 113 | productRefGroup = 3BCEBD8D2AD91AEB0070825E /* Products */; 114 | projectDirPath = ""; 115 | projectRoot = ""; 116 | targets = ( 117 | 3BCEBD8B2AD91AEB0070825E /* SearchParttenCode */, 118 | ); 119 | }; 120 | /* End PBXProject section */ 121 | 122 | /* Begin PBXSourcesBuildPhase section */ 123 | 3BCEBD882AD91AEB0070825E /* Sources */ = { 124 | isa = PBXSourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | 3BCEBD902AD91AEB0070825E /* main.m in Sources */, 128 | 3BCEBDA92AD924990070825E /* Utils.m in Sources */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXSourcesBuildPhase section */ 133 | 134 | /* Begin XCBuildConfiguration section */ 135 | 3BCEBD912AD91AEB0070825E /* Debug */ = { 136 | isa = XCBuildConfiguration; 137 | buildSettings = { 138 | ALWAYS_SEARCH_USER_PATHS = NO; 139 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 140 | CLANG_ANALYZER_NONNULL = YES; 141 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 142 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 143 | CLANG_ENABLE_MODULES = YES; 144 | CLANG_ENABLE_OBJC_ARC = YES; 145 | CLANG_ENABLE_OBJC_WEAK = YES; 146 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 147 | CLANG_WARN_BOOL_CONVERSION = YES; 148 | CLANG_WARN_COMMA = YES; 149 | CLANG_WARN_CONSTANT_CONVERSION = YES; 150 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 151 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 152 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 153 | CLANG_WARN_EMPTY_BODY = YES; 154 | CLANG_WARN_ENUM_CONVERSION = YES; 155 | CLANG_WARN_INFINITE_RECURSION = YES; 156 | CLANG_WARN_INT_CONVERSION = YES; 157 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 158 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 159 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 160 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 161 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 162 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 163 | CLANG_WARN_STRICT_PROTOTYPES = YES; 164 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 165 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 166 | CLANG_WARN_UNREACHABLE_CODE = YES; 167 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 168 | COPY_PHASE_STRIP = NO; 169 | DEBUG_INFORMATION_FORMAT = dwarf; 170 | ENABLE_STRICT_OBJC_MSGSEND = YES; 171 | ENABLE_TESTABILITY = YES; 172 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 173 | GCC_C_LANGUAGE_STANDARD = gnu17; 174 | GCC_DYNAMIC_NO_PIC = NO; 175 | GCC_NO_COMMON_BLOCKS = YES; 176 | GCC_OPTIMIZATION_LEVEL = 0; 177 | GCC_PREPROCESSOR_DEFINITIONS = ( 178 | "DEBUG=1", 179 | "$(inherited)", 180 | ); 181 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 182 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 183 | GCC_WARN_UNDECLARED_SELECTOR = YES; 184 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 185 | GCC_WARN_UNUSED_FUNCTION = YES; 186 | GCC_WARN_UNUSED_VARIABLE = YES; 187 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 188 | MACOSX_DEPLOYMENT_TARGET = 14.0; 189 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 190 | MTL_FAST_MATH = YES; 191 | ONLY_ACTIVE_ARCH = YES; 192 | SDKROOT = macosx; 193 | }; 194 | name = Debug; 195 | }; 196 | 3BCEBD922AD91AEB0070825E /* Release */ = { 197 | isa = XCBuildConfiguration; 198 | buildSettings = { 199 | ALWAYS_SEARCH_USER_PATHS = NO; 200 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 201 | CLANG_ANALYZER_NONNULL = YES; 202 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 204 | CLANG_ENABLE_MODULES = YES; 205 | CLANG_ENABLE_OBJC_ARC = YES; 206 | CLANG_ENABLE_OBJC_WEAK = YES; 207 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 208 | CLANG_WARN_BOOL_CONVERSION = YES; 209 | CLANG_WARN_COMMA = YES; 210 | CLANG_WARN_CONSTANT_CONVERSION = YES; 211 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 212 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 213 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 214 | CLANG_WARN_EMPTY_BODY = YES; 215 | CLANG_WARN_ENUM_CONVERSION = YES; 216 | CLANG_WARN_INFINITE_RECURSION = YES; 217 | CLANG_WARN_INT_CONVERSION = YES; 218 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 219 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 220 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 221 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 222 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 223 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 224 | CLANG_WARN_STRICT_PROTOTYPES = YES; 225 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 226 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | COPY_PHASE_STRIP = NO; 230 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 231 | ENABLE_NS_ASSERTIONS = NO; 232 | ENABLE_STRICT_OBJC_MSGSEND = YES; 233 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 234 | GCC_C_LANGUAGE_STANDARD = gnu17; 235 | GCC_NO_COMMON_BLOCKS = YES; 236 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 237 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 238 | GCC_WARN_UNDECLARED_SELECTOR = YES; 239 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 240 | GCC_WARN_UNUSED_FUNCTION = YES; 241 | GCC_WARN_UNUSED_VARIABLE = YES; 242 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 243 | MACOSX_DEPLOYMENT_TARGET = 14.0; 244 | MTL_ENABLE_DEBUG_INFO = NO; 245 | MTL_FAST_MATH = YES; 246 | SDKROOT = macosx; 247 | }; 248 | name = Release; 249 | }; 250 | 3BCEBD942AD91AEB0070825E /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | CODE_SIGN_STYLE = Automatic; 254 | COMPILER_INDEX_STORE_ENABLE = NO; 255 | DEVELOPMENT_TEAM = ""; 256 | ENABLE_HARDENED_RUNTIME = YES; 257 | LIBRARY_SEARCH_PATHS = ( 258 | "$(inherited)", 259 | "$(PROJECT_DIR)/SearchParttenCode", 260 | ); 261 | MACOSX_DEPLOYMENT_TARGET = 14.0; 262 | OTHER_LDFLAGS = "-lc++"; 263 | "OTHER_LDFLAGS[arch=*]" = ""; 264 | PRODUCT_NAME = "$(TARGET_NAME)"; 265 | }; 266 | name = Debug; 267 | }; 268 | 3BCEBD952AD91AEB0070825E /* Release */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | CODE_SIGN_STYLE = Automatic; 272 | COMPILER_INDEX_STORE_ENABLE = NO; 273 | DEVELOPMENT_TEAM = ""; 274 | ENABLE_HARDENED_RUNTIME = YES; 275 | LIBRARY_SEARCH_PATHS = ( 276 | "$(inherited)", 277 | "$(PROJECT_DIR)/SearchParttenCode", 278 | ); 279 | MACOSX_DEPLOYMENT_TARGET = 14.0; 280 | OTHER_LDFLAGS = "-lc++"; 281 | PRODUCT_NAME = "$(TARGET_NAME)"; 282 | }; 283 | name = Release; 284 | }; 285 | /* End XCBuildConfiguration section */ 286 | 287 | /* Begin XCConfigurationList section */ 288 | 3BCEBD872AD91AEB0070825E /* Build configuration list for PBXProject "SearchParttenCode" */ = { 289 | isa = XCConfigurationList; 290 | buildConfigurations = ( 291 | 3BCEBD912AD91AEB0070825E /* Debug */, 292 | 3BCEBD922AD91AEB0070825E /* Release */, 293 | ); 294 | defaultConfigurationIsVisible = 0; 295 | defaultConfigurationName = Release; 296 | }; 297 | 3BCEBD932AD91AEB0070825E /* Build configuration list for PBXNativeTarget "SearchParttenCode" */ = { 298 | isa = XCConfigurationList; 299 | buildConfigurations = ( 300 | 3BCEBD942AD91AEB0070825E /* Debug */, 301 | 3BCEBD952AD91AEB0070825E /* Release */, 302 | ); 303 | defaultConfigurationIsVisible = 0; 304 | defaultConfigurationName = Release; 305 | }; 306 | /* End XCConfigurationList section */ 307 | }; 308 | rootObject = 3BCEBD842AD91AEB0070825E /* Project object */; 309 | } 310 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------