├── .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 |
--------------------------------------------------------------------------------