diff --git a/README.md b/README.md
index fcf70f8..2a5ad38 100644
--- a/README.md
+++ b/README.md
@@ -26,27 +26,35 @@
2. Xcode|Clion 集成开发调试环境
3. 特征码搜索
-| App | version | x86 | arm | Download | remark | Author |
-|-----------------|---------|-----|-----|---------------------------------------------|--------------------------------------------------------------------------------------------------------------|---------------------|
-| TablePlus | 6.* | ✔ | ✔ | https://tableplus.com/ | inject_bin="/Applications/TablePlus.app/Contents/Frameworks/Sparkle.framework/Versions/B/Sparkle" | |
-| DevUtils | 1.* | ✔ | ✔ | https://devutils.com/ | | |
-| AirBuddy | 2.* | ✔ | ✔ | https://v2.airbuddy.app/download | inject_bin="/Applications/AirBuddy.app/Contents/Frameworks/LetsMove.framework/Versions/A/LetsMove" | |
-| Navicat Premium | 17.* | ✔ | ✔ | App Store | inject_bin="/Applications/Navicat Premium.app/Contents/Frameworks/EE.framework/Versions/A/EE" | QiuChenlyOpenSource |
-| Paste | 4.1.3 | ✘ | ✔ | App Store | | LeeeMooo |
-| Transmit | 5.* | ✔ | ✔ | https://panic.com/transmit/#download | | |
-| AnyGo | 7.* | ✔ | ✔ | https://itoolab.com/gps-location-changer/ | | |
-| Downie | 4.* | ✔ | ✔ | https://software.charliemonroe.net/downie/ | inject_bin="/Applications/Permute 3.app/Contents/Frameworks/Licensing.framework/Versions/A/Licensing" | |
-| Permute | 3.* | ✔ | ✔ | https://software.charliemonroe.net/permute/ | inject_bin="/Applications/Downie 4.app/Contents/Frameworks/Licensing.framework/Versions/A/Licensing" | |
-| ProxyMan | 5.2 | ✔ | ✔ | https://proxyman.io/ | inject_bin="/Applications/Proxyman.app/Contents/Frameworks/HexFiend.framework/Versions/A/HexFiend" | |
-| Movist Pro | 2.* | ✔ | ✔ | https://movistprime.com/ | inject_bin="/Applications/Movist Pro.app/Contents/Frameworks/MediaKeyTap.framework/Versions/A/MediaKeyTap" | |
-| Surge | 5.7.* | ✔ | ✔ | https://nssurge.com/ | inject_bin="/Applications/Surge.app/Contents/Frameworks/MMMarkdown.framework/Versions/A/MMMarkdown" | |
-| Infuse | 7.7.* | ✔ | ✔ | App Store | inject_bin="/Applications/Infuse.app/Contents/Frameworks/Differentiator.framework/Versions/A/Differentiator" | |
-| MacUpdater | 3. | ✔ | ✔ | https://www.corecode.io/macupdater/#download | inject_bin="/Applications/MacUpdater.app/Contents/Frameworks/Sparkle.framework/Versions/B/Sparkle" | |
+
+ 点击这里展开/收起
+
+| App | version | x86 | arm | Download | remark | Author |
+|-----------------|---------|-----|-----|----------------------------------------------|----------------------------------------------------------------------------------------------------------------------|---------------------|
+| TablePlus | 6.* | ✔ | ✔ | https://tableplus.com/ | inject_bin="/Applications/TablePlus.app/Contents/Frameworks/Sparkle.framework/Versions/B/Sparkle" | |
+| DevUtils | 1.* | ✔ | ✔ | https://devutils.com/ | | |
+| AirBuddy | 2.* | ✔ | ✔ | https://v2.airbuddy.app/download | inject_bin="/Applications/AirBuddy.app/Contents/Frameworks/LetsMove.framework/Versions/A/LetsMove" | |
+| Navicat Premium | 17.* | ✔ | ✔ | App Store | inject_bin="/Applications/Navicat Premium.app/Contents/Frameworks/EE.framework/Versions/A/EE" | QiuChenlyOpenSource |
+| Paste | 4.1.3 | ✘ | ✔ | App Store | | LeeeMooo |
+| Transmit | 5.* | ✔ | ✔ | https://panic.com/transmit/#download | | |
+| AnyGo | 7.* | ✔ | ✔ | https://itoolab.com/gps-location-changer/ | DMCA | |
+| Downie | 4.* | ✔ | ✔ | https://software.charliemonroe.net/downie/ | inject_bin="/Applications/Permute 3.app/Contents/Frameworks/Licensing.framework/Versions/A/Licensing" | |
+| Permute | 3.* | ✔ | ✔ | https://software.charliemonroe.net/permute/ | inject_bin="/Applications/Downie 4.app/Contents/Frameworks/Licensing.framework/Versions/A/Licensing" | |
+| ProxyMan | 5.2 | ✔ | ✔ | https://proxyman.io/ | inject_bin="/Applications/Proxyman.app/Contents/Frameworks/HexFiend.framework/Versions/A/HexFiend" | |
+| Movist Pro | 2.* | ✔ | ✔ | https://movistprime.com/ | inject_bin="/Applications/Movist Pro.app/Contents/Frameworks/MediaKeyTap.framework/Versions/A/MediaKeyTap" | |
+| Surge | 5.7.* | ✔ | ✔ | https://nssurge.com/ | DMCA | |
+| Infuse | 7.7.* | ✔ | ✔ | App Store | inject_bin="/Applications/Infuse.app/Contents/Frameworks/Differentiator.framework/Versions/A/Differentiator" | |
+| MacUpdater | 3. | ✔ | ✔ | https://www.corecode.io/macupdater/#download | inject_bin="/Applications/MacUpdater.app/Contents/Frameworks/Sparkle.framework/Versions/B/Sparkle" | |
+| CleanShotX | 4. | ✔ | ✘ | https://updates.getcleanshot.com/v3/ | DMCA | |
+| ForkLift | 4. | ✔ | ✔ | https://binarynights.com/ | inject_bin="/Applications/ForkLift.app/Contents/Frameworks/UniversalDetector.framework/Versions/A/UniversalDetector" | |
+
+
+
## Usage
-[download latest release](https://github.com/marlkiller/dylib_dobby_hook_private/releases/download/latest/dylib_dobby_hook.tar.gz)
+[download latest release](https://github.com/marlkiller/dylib_dobby_hook/releases/download/latest/dylib_dobby_hook.tar.gz)
```shell
tar -xzvf dylib_dobby_hook.tar.gz
cd script
diff --git a/dylib_dobby_hook.xcodeproj/project.pbxproj b/dylib_dobby_hook.xcodeproj/project.pbxproj
index b41cd82..87888ac 100644
--- a/dylib_dobby_hook.xcodeproj/project.pbxproj
+++ b/dylib_dobby_hook.xcodeproj/project.pbxproj
@@ -27,11 +27,9 @@
B55407272B653DCB005C08E6 /* NavicatPremiumHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B55407262B653DCB005C08E6 /* NavicatPremiumHack.m */; };
B554D7BC2B63F2A300B7EFEA /* DevUtilsHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B554D7BB2B63F2A300B7EFEA /* DevUtilsHack.m */; };
B580D3CA2BE3579300979568 /* LightRoomHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B580D3C72BE3579300979568 /* LightRoomHack.m */; };
- B580D3CB2BE3579300979568 /* AnyGoHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B580D3C82BE3579300979568 /* AnyGoHack.m */; };
- B580D3CC2BE3579300979568 /* SurgeHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B580D3C92BE3579300979568 /* SurgeHack.m */; };
B58160172BE88569001DDB9B /* encryp_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = B58160112BE88569001DDB9B /* encryp_utils.m */; };
B581601B2BE88569001DDB9B /* encryp_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = B58160162BE88569001DDB9B /* encryp_utils.h */; };
- B5CFE84D2BE9F03200CF8D9E /* iMazingHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B5CFE84C2BE9F03200CF8D9E /* iMazingHack.m */; };
+ B5D0C0BB2C4B553500881398 /* ForkLiftHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B5D0C0BA2C4B553500881398 /* ForkLiftHack.m */; };
B5D2ED3F2BC0252D0030CBCA /* DevHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B5D2ED3E2BC0252D0030CBCA /* DevHack.m */; };
B5F06B1D2BEF591E0079E68D /* InfuseHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B5F06B1C2BEF591E0079E68D /* InfuseHack.m */; };
B5FE3B862BA2A571001AE437 /* TransmitHack.m in Sources */ = {isa = PBXBuildFile; fileRef = B5FE3B842BA2A571001AE437 /* TransmitHack.m */; };
@@ -79,11 +77,9 @@
B56968C62BEA4E2A0022FAC6 /* libdylib_dobby_hook.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libdylib_dobby_hook.dylib; sourceTree = ""; };
B56968C72BEA4E4D0022FAC6 /* cmake_debugger.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = cmake_debugger.sh; sourceTree = ""; };
B580D3C72BE3579300979568 /* LightRoomHack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LightRoomHack.m; sourceTree = ""; };
- B580D3C82BE3579300979568 /* AnyGoHack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnyGoHack.m; sourceTree = ""; };
- B580D3C92BE3579300979568 /* SurgeHack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SurgeHack.m; sourceTree = ""; };
B58160112BE88569001DDB9B /* encryp_utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = encryp_utils.m; sourceTree = ""; };
B58160162BE88569001DDB9B /* encryp_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = encryp_utils.h; sourceTree = ""; };
- B5CFE84C2BE9F03200CF8D9E /* iMazingHack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iMazingHack.m; sourceTree = ""; };
+ B5D0C0BA2C4B553500881398 /* ForkLiftHack.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ForkLiftHack.m; sourceTree = ""; };
B5D2ED3E2BC0252D0030CBCA /* DevHack.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DevHack.m; sourceTree = ""; };
B5F06B1C2BEF591E0079E68D /* InfuseHack.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InfuseHack.m; sourceTree = ""; };
B5FE3B842BA2A571001AE437 /* TransmitHack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransmitHack.m; sourceTree = ""; };
@@ -184,12 +180,9 @@
isa = PBXGroup;
children = (
B5F06B1C2BEF591E0079E68D /* InfuseHack.m */,
- B5CFE84C2BE9F03200CF8D9E /* iMazingHack.m */,
38D1AC312B54D1CC00E6CB9E /* AirBuddyHack.m */,
38D1AC2B2B54D03B00E6CB9E /* HackProtocol.h */,
- B580D3C82BE3579300979568 /* AnyGoHack.m */,
B580D3C72BE3579300979568 /* LightRoomHack.m */,
- B580D3C92BE3579300979568 /* SurgeHack.m */,
B5FE3B842BA2A571001AE437 /* TransmitHack.m */,
382A25842B6918DF0083F28C /* PasteHack.m */,
38B83E302B5505B300919735 /* TablePlusHack.m */,
@@ -327,15 +320,12 @@
382A25862B6918DF0083F28C /* PasteHack.m in Sources */,
B554D7BC2B63F2A300B7EFEA /* DevUtilsHack.m in Sources */,
B5F06B1D2BEF591E0079E68D /* InfuseHack.m in Sources */,
- B580D3CC2BE3579300979568 /* SurgeHack.m in Sources */,
B55407272B653DCB005C08E6 /* NavicatPremiumHack.m in Sources */,
3816BBB92B54FF090051CF39 /* MemoryUtils.m in Sources */,
38B83E312B5505B300919735 /* TablePlusHack.m in Sources */,
B580D3CA2BE3579300979568 /* LightRoomHack.m in Sources */,
- B580D3CB2BE3579300979568 /* AnyGoHack.m in Sources */,
B5FECEAE2BC4FC29008916D6 /* common_ret.m in Sources */,
38D1AC2A2B54CA4D00E6CB9E /* Constant.m in Sources */,
- B5CFE84D2BE9F03200CF8D9E /* iMazingHack.m in Sources */,
B502BD5D2BCFB35200DAD97F /* MovistProHack.m in Sources */,
B5FE3B862BA2A571001AE437 /* TransmitHack.m in Sources */,
);
diff --git a/dylib_dobby_hook/apps/ForkLiftHack.m b/dylib_dobby_hook/apps/ForkLiftHack.m
new file mode 100644
index 0000000..81991b2
--- /dev/null
+++ b/dylib_dobby_hook/apps/ForkLiftHack.m
@@ -0,0 +1,79 @@
+//
+// CleanShotXHack.m
+// dylib_dobby_hook
+//
+// Created by voidm on 2024/7/19.
+//
+
+#import
+#import "Constant.h"
+#import "MemoryUtils.h"
+#import
+#import "HackProtocol.h"
+#include
+
+
+@interface ForkLiftHack : NSObject
+
+
+
+@end
+
+
+@implementation ForkLiftHack
+
+
+
+- (NSString *)getAppName {
+ return @"com.binarynights.ForkLift";
+}
+
+- (NSString *)getSupportAppVersion {
+ return @"4.";
+}
+
+
+
+- (BOOL)hack {
+
+
+//
+// ; struct ForkLift.RegistrationData {
+// ; let name: Swift.String
+// ; let quantity: Swift.Int
+// ; let license_type: Swift.Int
+// ; let validityDate: Foundation.Date
+// ; let signature: Swift.String
+// ; let licenseKey: Swift.String?
+// ; }
+//_$s8ForkLift16RegistrationDataVMn: // nominal type descriptor for ForkLift.RegistrationData
+//00000001008327c0 struct __swift_StructDescriptor { ; "RegistrationData", DATA XREF=_$s8ForkLift16RegistrationDataVMa+7
+// struct __swift_ContextDescriptor { // context
+// 0x10051, // flags
+// _$s8ForkLiftMXM-0x1008327c4, // parent context
+// aRegistrationda-0x1008327c8, // name of the type
+// _$s8ForkLift16RegistrationDataVMa-0x1008327cc, // type accessor function pointer
+// _$s8ForkLift16RegistrationDataVMF-0x1008327d0 // fields
+// },
+// 0x6, // number of fields
+// 0x2
+//}
+ // 自定义日期字符串
+ NSDictionary *registrationDataDict = @{
+ @"name": [Constant G_EMAIL_ADDRESS],
+ @"quantity": @520,
+ @"license_type": @1,
+ @"validityDate": @1753025400, // @"2025-07-20 15:30:00",
+ @"signature": @"SignatureExample",
+ @"licenseKey": @"ABC123XYZ"
+ };
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:registrationDataDict options:0 error:nil];
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ [defaults setObject:jsonData forKey:@"registrationData"];
+ [defaults synchronize];
+
+
+ return YES;
+}
+
+@end
diff --git a/dylib_dobby_hook/apps/SurgeHack.m b/dylib_dobby_hook/apps/SurgeHack.m
deleted file mode 100644
index 50f50ac..0000000
--- a/dylib_dobby_hook/apps/SurgeHack.m
+++ /dev/null
@@ -1,799 +0,0 @@
-//
-// SurgeHack.m
-// dylib_dobby_hook
-//
-// Created by 马治武 on 2024/4/4.
-//
-
-#import
-#import "Constant.h"
-#import "dobby.h"
-#import "MemoryUtils.h"
-#import
-#include
-#import "HackProtocol.h"
-#include
-#import
-#import "common_ret.h"
-#include
-#import
-#import "encryp_utils.h"
-
-@interface NSString (MyExtension)
-- (BOOL)sEqualToStringEx:(NSString *)parameter;
-@end
-
-@implementation NSString (MyExtension)
-
-- (BOOL)sEqualToStringEx:(NSString *)parameter {
- return false;
-}
-@end
-
-@interface SurgeHack : NSObject
-
-
-
-@end
-
-
-@implementation SurgeHack
-
-static IMP urlWithStringSeletorIMP;
-static IMP objectForKeyedSubscriptImp;
-static IMP objectForKeyedSubscriptImp2;
-static IMP KD_JSONObjectIMP;
-static IMP initWithBytesNoCopyMethodIMP;
-static IMP dataTaskWithRequestIMP;
-static IMP dataTaskWithRequestIMP2;
-static IMP componentsJoinedByStringIMP;
-static IMP shouldPerformMITMForHostIMP;
-
-static NSString *publicKey = @"-----BEGIN PUBLIC KEY-----\n"
-"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvnU72zbRQFSB7IZ4ob2u\n"
-"4YgjsI6507rjwhR5DzxZBPtxuAuQOJnCM6XqrFy0hUazNDUybmVb+abbQlbmHs9C\n"
-"MGsYLpYKqJLNFCGy+2CRJxCLrTE35pJ36zIVvdj+1qH2KfyfiEjBc6+F6W3E0TwW\n"
-"BMd0ezj1pWYZoCytabmhgvhumWXI0ReOIGLuMrEOAf8zKZBWRRVSW3cLSwq0eQ7u\n"
-"ubi5UD5rvkmcDuL+RUQySi4W8vOpteq3ceZmtZVpUAXvUjnXzg/EX94VVfPCWhd1\n"
-"Ii4P+EBkaV7SuqFgZiczmkcXin5JrkATnIEf5pi71XWadeVZgFSOrkseCQE+Twta\n"
-"9QIDAQAB\n"
-"-----END PUBLIC KEY-----\n";
-
-
-static NSDictionary *policySign;
-// 这里常量不能用 NSNumber, 需要 基本类型
-static const NSInteger enterpriseLicense = 0;
-
-
-- (NSString *)getAppName {
- // >>>>>> 5.7.1 (2758)
- return @"com.nssurge.surge-mac";
-}
-
-- (NSString *)getSupportAppVersion {
- return @"5.7.";
-}
-
-
-
-- (BOOL)hack {
-
- // 程序使用ptrace来进行动态调试保护,使得执行lldb的时候出现Process xxxx exited with status = 45 (0x0000002d)错误。
- // 使用 DobbyHook 替换 ptrace函数。
- DobbyHook((void *)ptrace, (void *)my_ptrace, (void *)&orig_ptrace);
-
- NSString *searchFilePath = [[Constant getCurrentAppPath] stringByAppendingString:@"/Contents/MacOS/Surge"];
- uintptr_t fileOffset =[MemoryUtils getCurrentArchFileOffset: searchFilePath];
-
- // deviceId = [EncryptionUtils generateSurgeDeviceId];
- // NSLog(@">>>>>> deviceId: %@",deviceId);
-
- // NSDictionary *jsonLicense = @{
- // @"deviceID": @"16b8f4bdfd55d29f737427b4ec0c14d7",
- // @"type":@"licensed", // trial:licensed:revoked
- // @"product": @"SURGEMAC5",
- // @"expiresOnDate": @1746350567,
- // @"p": @"QU1oHx8IbxU1PvQQ3340JA=="
- // };
- // 伪造 License , p[1]=1
-// policySign = @{
-// @"policy": @"ewogICJwIiA6ICJtdmlCeW5KRnI3dVZQcGxONVZoTEd3PT0iLAogICJkZXZpY2VJRCIgOiAiMTZiOGY0YmRmZDU1ZDI5ZjczNzQyN2I0ZWMwYzE0ZDciLAogICJwcm9kdWN0IiA6ICJTVVJHRU1BQzUiLAogICJ0eXBlIiA6ICJsaWNlbnNlZCIsCiAgImV4cGlyZXNPbkRhdGUiIDogMTc0NjM1MDU2Nwp9",
-// @"sign": @"a6r7vh1fShggsQgBfghOc6FhXdXsgSrHMhwlwO8HJYMDxch7+H8Q0mAnKdG3yY4J002iTTpgtPcUMctlVWOXLNaHnDEY0lWGnU/oHW5BPBiJ6eqPe/Mf+pqwtG4HTRqGRNUiomru2q7zu4VuYdJFklFffnK7gSLxwxAvV71K8JCkvxb0I+eNuJUSzsRhOJC4HMBmeoq++SBViUANbZhI6u+w5XXVcV3VC0VAfsMrIYItHY8oWE9FjWkB+BnJa6+yXgxfBK89wnsW0gCszAs9Pa1e06QEQ1vHKWmbp8XKP5OwzCLp73vSKyjB4cl9o57qwt9Y+DD1Qsdi1MT0NpWqwA==",
-// @"enterprise":@1
-// };
-
- // 伪造 License , p[1]=3
- policySign = @{
- @"policy": @"ewogICJwIiA6ICJRVTFvSHg4SWJ4VTFQdlFRMzM0MEpBPT0iLAogICJkZXZpY2VJRCIgOiAiMTZiOGY0YmRmZDU1ZDI5ZjczNzQyN2I0ZWMwYzE0ZDciLAogICJwcm9kdWN0IiA6ICJTVVJHRU1BQzUiLAogICJ0eXBlIiA6ICJsaWNlbnNlZCIsCiAgImV4cGlyZXNPbkRhdGUiIDogMTc0NjM1MDU2Nwp9",
- @"sign": @"K7QcxRYpPeIYOUtSHqLr2jfzWKYKlphJen0xUwJLVqwM4Xr/DcDvEgQVyIgV8poF9RnhCg7eruw6wbXzMv9GSfSC/zKm4DUsjPsqtvr4X/+thfUyzVrAJgGUmIGSOR7dFrOvdhbx4h+hsiWR9oYVq+vQfp7xdkF1RD+72QVbhR8PJyBCxja34JklxvDKGDJmsc1FhbkTeXzEBNkSNhD58HRWajIxlAs6sckjbGV/DPrrV8cC3Rok3iytiMcp/KRqtaJYtZk/RMrvxnByszutZ8U9z5ve1mHMdO1BKEnUREtriVZ/kU0I07itV9tpDoJReL9pQiQk93L/WdO9mmtERA==",
- @"enterprise":@(enterpriseLicense)
- };
- // NSLog(@">>>>>> policySign: %@",policySign);
-
- // 写入 license attr 信息
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:policySign options:NSJSONWritingPrettyPrinted error:nil];
- Class KDStorageHelperClass = NSClassFromString(@"KDStorageHelper");
- SEL directoryPathSelector = NSSelectorFromString(@"applicationSupportDirectoryPathWithName:");
- NSString *directoryPath = [KDStorageHelperClass performSelector:directoryPathSelector withObject:@"com.nssurge.surge-mac"];
- const char *directoryUTF8String = [directoryPath UTF8String];
- const void *jsonBytes = [jsonData bytes];
- size_t jsonLength = [jsonData length];
- setxattr(directoryUTF8String, "com.nssurge.surge-mac.nsa.3", jsonBytes, jsonLength, 0, 0);
-
-
- // 伪造 public key
- // - NSData initWithBytesNoCopy:length:freeWhenDone:
- Class NSDataClass = NSClassFromString(@"NSData");
- SEL initWithBytesNoCopySeletor = NSSelectorFromString(@"initWithBytesNoCopy:length:freeWhenDone:");
- Method initWithBytesNoCopyMethod = class_getInstanceMethod(NSDataClass, initWithBytesNoCopySeletor);
- initWithBytesNoCopyMethodIMP = method_getImplementation(initWithBytesNoCopyMethod);
- [MemoryUtils hookInstanceMethod:
- NSDataClass
- originalSelector:initWithBytesNoCopySeletor
- swizzledClass:[self class]
- swizzledSelector:NSSelectorFromString(@"hk_initWithBytesNoCopy:length:freeWhenDone:")
- ];
-
- // hook NSURL['+ URLWithString:']
- Class NSURLControllerClass = NSClassFromString(@"NSURL");
- SEL urlWithStringSeletor = NSSelectorFromString(@"URLWithString:");
- Method urlWithStringSeletorMethod = class_getClassMethod(NSURL.class, urlWithStringSeletor);
- urlWithStringSeletorIMP = method_getImplementation(urlWithStringSeletorMethod);
- [MemoryUtils hookClassMethod:
- NSURLControllerClass
- originalSelector:urlWithStringSeletor
- swizzledClass:[self class]
- swizzledSelector:NSSelectorFromString(@"hk_URLWithString:")
- ];
-
-
- // trigger : expiresOnDate 解析 policy,获取 license/device 信息
- // -[NSDictionary objectForKeyedSubscript:]:
- // Class NSDictionaryClass = NSClassFromString(@"__NSDictionaryI");
- // SEL objectForKeyedSubscriptSeleter = NSSelectorFromString(@"objectForKeyedSubscript:");
- // Method objectForKeyedSubscriptMethod = class_getInstanceMethod(NSDictionaryClass, objectForKeyedSubscriptSeleter);
- // objectForKeyedSubscriptImp = method_getImplementation(objectForKeyedSubscriptMethod);
- // [MemoryUtils hookInstanceMethod:
- // NSDictionaryClass
- // originalSelector:objectForKeyedSubscriptSeleter
- // swizzledClass:[self class]
- // swizzledSelector:NSSelectorFromString(@"hook_objectForKeyedSubscript:")
- // ];
-
- //获取授权凭证 0 未授权, 1 试用 xxx,2 授权, arm : 0000000100173b70
- // -[WindowController trialButtonPressed:] sub_1001c643c() == 0x1:0x0
- // 00000001001c643c push rbp ; CODE XREF=sub_10008aad8+635, sub_1000beb1b+34, -[SGMAppDelegate applicationDidFinishLaunching:]+3108, sub_1001b16ab+64, sub_1001b1820+14, sub_1001b1820+24, sub_1001b1820+33, sub_1001b2827+7, sub_1001b2827+26, sub_1001b2827+64, sub_1001b441b+83
- // 00000001001c643d mov rbp, rsp
- // 00000001001c6440 mov eax, dword [dword_100860ec0] ; dword_100860ec0
- // 00000001001c6446 pop rbp
- // 00000001001c6447 ret
-
-
-//## helper 修复
-//# 通过 dtrace 监控到 surge helper[18720] kill 了 surge [18706] 进程
-//0 243 kill:return 18720 com.nssurge.surge-mac.helper 9 18706 0
-//# 查看 helper 日志 发现 helper 检测了 Framework 下文件签名
-//14156 signing bytes in 3 blob(s) from /Applications/Surge.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Sparkle(x86_64)
-//2024-05-12 15:50:49.107835+0800 0x309f28 Debug 0x0 19297 0 com.nssurge.surge-mac.helper: (Security) [com.apple.securityd:cfloadfile] failed to fetch /Applications/Surge.app/Contents/Frameworks/Sparkle.framework/Versions/Current/./_CodeSignature/CodeRequirements-1 error=-10
-//2024-05-12 15:50:49.107869+0800 0x309f28 Debug 0x0 19297 0 com.nssurge.surge-mac.helper: (Security) [com.apple.securityd:staticCode] SecStaticCode network default: YES
-//2024-05-12 15:50:49.107900+0800 0x309f28 Debug 0x0 19297 0 com.nssurge.surge-mac.helper: (Security) [com.apple.securityd:notarization] Extracting ticket from bundle: /Applications/Surge.app/Contents/Frameworks/Sparkle.framework/Versions/Current/.
-
- // arm: SecCodeCnginfo : 000000010027c7b8
- // 3. 网络不可用(如果校验不通过, 会影响下面的 dns 解析) --> 移除文件签名验证 -> -[SGMScriptManagementViewController viewDidAppear]: intrinsic_movaps(xmm0, *(int128_t *)0x100603550)
- // 00000001005a78b0 db "SecCodeCngInformateWithPckValidimework/Bmework/S", 0 ; DATA XREF=sub_10027f4e8+168
-
- // 00000001006034c0 db "SecCodeCheckValiSecCodeCopySigniSecStaticCodeCreSecStaticCodeChe/Contents/Frameworks/MMMarkdown.framework/MMMarkorks/Bugsnag.fraorks/Sparkle.fra", 0 ; DATA XREF=sub_10030b9a5+33
- // 000000010030b9a5 push rbp ; Objective C Block defined at 0x100747c88, Begin of try block, DATA XREF=0x100747c98
- // 000000010030b9a6 mov rbp, rsp
- // 000000010030b9a9 push r15
- // 000000010030b9ab push r14
- // 000000010030b9ad push r13
- // 000000010030b9af push r12
- // 000000010030b9b1 push rbx
- // 000000010030b9b2 sub rsp, 0xb8
- // 000000010030b9b9 mov edi, 0x14 ; argument "size" for method imp___stubs__malloc
- // 000000010030b9be call imp___stubs__malloc ; malloc
- // 000000010030b9c3 mov rbx, rax
- // 000000010030b9c6 movaps xmm0, xmmword [aSeccodecheckva] ; "SecCodeCheckValiSecCodeCopySigniSecStaticCodeCreSecStaticCodeChe/Contents/Frameworks/MMMarkdown.framework/MMMarkorks/Bugsnag.fraorks/Sparkle.fra"
- // 000000010030b9cd movups xmmword [rax], xmm0
- // 000000010030b9d0 mov dword [rax+0x10], 0x79746964
- // 000000010030b9d7 mov rdi, qword [objc_cls_ref_NSString] ; argument "class" for method imp___stubs__objc_alloc, objc_cls_ref_NSString
- // 000000010030b9de call imp___stubs__objc_alloc ; objc_alloc
- // 000000010030b9e3 mov rsi, qword [0x10082f6d8] ; @selector(initWithBytes:length:encoding:)
-
-#if defined(__arm64__) || defined(__aarch64__)
- NSString *sub_0x10030b9a5Code = @"FF 43 04 D1 E9 23 0A 6D FC 6F 0B A9 FA 67 0C A9 F8 5F 0D A9 F6 57 0E A9 F4 4F 0F A9 FD 7B 10 A9 FD 03 04 91 80 02 80 52 .. .. 09 94 F3 03 00 AA .. .. 00 ..";
-#elif defined(__x86_64__)
- NSString *sub_0x10030b9a5Code = @"55 48 89 E5 41 57 41 56 41 55 41 54 53 48 81 EC .. .. .. .. BF .. .. .. .. E8 .. .. .. .. 48 89 C3 0F 28 05 .. .. .. .. 0F 11 00";
-#endif
- NSArray *sub_0x10030b9a5Offsets =[MemoryUtils searchMachineCodeOffsets:
- searchFilePath
- machineCode:sub_0x10030b9a5Code
- count:(int)1
- ];
- intptr_t _sub_0x10030b9a5 = [MemoryUtils getPtrFromGlobalOffset:0 targetFunctionOffset:(uintptr_t)[sub_0x10030b9a5Offsets[0] unsignedIntegerValue] reduceOffset:(uintptr_t)fileOffset];
-
- // dobby.dylib 动态库 , arm 这里不能写 nil ? EXC_BAD_ACCESS (code=1, address=0x0)
- // 所以全局替换成了静态库 .a
- DobbyHook((void *)_sub_0x10030b9a5, ret, NULL);
-
-
- // hook DNS 解析
-// Class SGDNSRecordIPv4Class = NSClassFromString(@"SGDNSRecordIPv4");
-// SEL addressWithPortSeletor = NSSelectorFromString(@"addressWithPort:");
-// Method addressWithMethod = class_getInstanceMethod(SGDNSRecordIPv4Class, addressWithPortSeletor);
-// addressWithMethodIMP = method_getImplementation(addressWithMethod);
-// [MemoryUtils hookInstanceMethod:
-// SGDNSRecordIPv4Class
-// originalSelector:addressWithPortSeletor
-// swizzledClass:[self class]
-// swizzledSelector:NSSelectorFromString(@"hook_addressWithPort:arg3:arg4:arg5:")
-// ];
-
-
- // 过滤 mac/v3/ac,mac/v3/resource/jsvm,mac/v3/deactivate/,mac/v3/init/,mac/v3/free-trial,mac/v3/resource/module,mac/v3/resource/jsvm,mac/v3/device?deviceID=%@
- // mac/v3/ac
- Class SGRequestHelperClass = NSClassFromString(@"SGRequestHelper");
- SEL dataTaskWithRequestSeletor = NSSelectorFromString(@"dataTaskWithRequest:completionHandler:");
- Method dataTaskWithRequestMethod = class_getInstanceMethod(SGRequestHelperClass, dataTaskWithRequestSeletor);
- dataTaskWithRequestIMP = method_getImplementation(dataTaskWithRequestMethod);
- [MemoryUtils hookInstanceMethod:
- SGRequestHelperClass
- originalSelector:dataTaskWithRequestSeletor
- swizzledClass:[self class]
- swizzledSelector:NSSelectorFromString(@"hook_dataTaskWithRequest:completionHandler:")
- ];
-
- // -[SGHTTPClient dataTaskWithURLRequest:configuration:completionHandler:]
- // mac/v3/xx
- Class SGHTTPClientClass = NSClassFromString(@"SGHTTPClient");
- SEL dataTaskWithRequestSeletor2 = NSSelectorFromString(@"dataTaskWithURLRequest:configuration:completionHandler:");
- Method dataTaskWithRequestMethod2 = class_getInstanceMethod(SGHTTPClientClass, dataTaskWithRequestSeletor2);
- dataTaskWithRequestIMP2 = method_getImplementation(dataTaskWithRequestMethod2);
- [MemoryUtils hookInstanceMethod:
- SGHTTPClientClass
- originalSelector:dataTaskWithRequestSeletor2
- swizzledClass:[self class]
- swizzledSelector:NSSelectorFromString(@"hook_dataTaskWithURLRequest:configuration:completionHandler:")
- ];
-
-
- // 下面俩个 设置菜单会报错,大概是因为没权限调用 Ponte 与 Remote 功能
- [MemoryUtils replaceInstanceMethod:
- NSClassFromString(@"SGPonteManager")
- originalSelector:NSSelectorFromString(@"updatePonteDeviceListWithCompletionHandler:")
- swizzledClass:[self class]
- swizzledSelector:@selector(ret)
- ];
- [MemoryUtils replaceInstanceMethod:
- NSClassFromString(@"SGRemoteNotificationCenter")
- originalSelector:NSSelectorFromString(@"setup")
- swizzledClass:[self class]
- swizzledSelector:@selector(ret)
- ];
-
-
- // 这个判断决定模块(不包括官方内置模块)走本地存储 还是 icloud 存储,得绕过 icloud 存储,不然模块存不了
- // -[NSUbiquitousKeyValueStore defaultStore]
- [MemoryUtils replaceClassMethod:
- NSClassFromString(@"NSUbiquitousKeyValueStore")
- originalSelector:NSSelectorFromString(@"defaultStore")
- swizzledClass:[self class]
- swizzledSelector:@selector(ret0)
- ];
-
- // 过滤 https://76.223.12.1/mac/v3/ac 请求
- // arm: /mac/deviceNasystemVedeviceModevice -> 00000001000e1fe8
- // Message from debugger: Terminated due to signal 9
- // queue = 'com.apple.root.default-qos', stop reason = EXC_GUARD (code=4611686022722355231, subcode=0x8fd4dbfade2dead)
- // triger : -[SGMOverviewViewController viewDidLoad]: >> dispatch_source_set_event_handler(r15, &var_68);
- // 把这个 nop 掉就没必要修复 objectForKeyedSubscript(k) 参数了; mac/v3/ac
- // 00000001003044df push rbp ; DATA XREF=-[SGMOverviewViewController viewDidLoad]+1256
- //#if defined(__arm64__) || defined(__aarch64__)
- // NSString *sub_0x1003044dfCode = @"FF C3 05 D1 FC 6F 11 A9 FA 67 12 A9 F8 5F 13 A9 F6 57 14 A9 F4 4F 15 A9 FD 7B 16 A9 FD 83 05 91 F6 03 00 AA .. .. 00 ..";
- //#elif defined(__x86_64__)
- // NSString *sub_0x1003044dfCode = @"55 48 89 E5 41 57 41 56 41 55 41 54 53 48 81 EC .. .. .. .. 48 89 BD .. .. .. .. 48 8B 05 .. .. .. .. 48 8B 00 48 89 45 .. 48 8B 1D .. .. .. .. 4C 8B 35 .. .. .. .. BF .. .. .. .. E8 .. .. .. .. 49 89 C7 0F 28 05 .. .. .. .. 0F 11 00 48 B8 .. .. .. .. .. .. .. ..";
- //#endif
- // NSArray *sub_0x1003044dfOffsets =[MemoryUtils searchMachineCodeOffsets:
- // searchFilePath
- // machineCode:sub_0x1003044dfCode
- // count:(int)3
- // ];
- //
- // for (NSNumber *sub_0x1003044dIt in sub_0x1003044dfOffsets) {
- // intptr_t _sub_0x1003044df = [MemoryUtils getPtrFromGlobalOffset:0 targetFunctionOffset:(uintptr_t)[sub_0x1003044dIt unsignedIntegerValue] reduceOffset:(uintptr_t)fileOffset];
- // DobbyHook((void *)_sub_0x1003044df, ret1, nil);
- // }
-
-
- // 通过 hook join 函数来伪造 device id
- // NSMutableArray componentsJoinedByString
- Class NSMutableArrayClass = NSClassFromString(@"NSMutableArray");
- SEL componentsJoinedByStringSeletor = NSSelectorFromString(@"componentsJoinedByString:");
- Method componentsJoinedByStringMethod = class_getInstanceMethod(NSMutableArrayClass, componentsJoinedByStringSeletor);
- componentsJoinedByStringIMP = method_getImplementation(componentsJoinedByStringMethod);
- [MemoryUtils hookInstanceMethod:
- NSMutableArrayClass
- originalSelector:componentsJoinedByStringSeletor
- swizzledClass:[self class]
- swizzledSelector:NSSelectorFromString(@"hook_componentsJoinedByString:")
- ];
-
-
-
- // 获取真实的设备 ID
- // deviceId rcx 呢 --> sub_1000b7dbd(0x2, r15, @"Device ID: %@", rcx, 0x0, r9, var_140); arm : 0000000100174278
- // void *fun_device = (void *)_sub_0x1001c6ca6;
- // deviceId = ((NSString* (*)())fun_device)();
- // NSLog(@">>>>>> device id is %@",deviceId);
-
- // hook CCCrypt ; 来获取 p 参数的 key 与 iv
- DobbyHook((void *) CCCrypt,(void *) hk_CCCrypt, (void **) &original_CCCrypt);
-
-
- // 'SGSocket-346', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
- // p 参数第一位如果是 3, 会走这个地方, 导致程序过段时间奔溃或网络不可用
- // 据说正版的第一位是 3, 但是改成 1 好像也没啥问题, 也不会崩溃,要么 hook 下面的, 要么用 1;
-// 000000010000e0fd push rbp ; Objective C Block defined at 0x10073fd58, DATA XREF=0x10073fd68
-// 000000010000e0fe mov rbp, rsp
-// 000000010000e101 push r15
-// 000000010000e103 push r14
-// 000000010000e105 push r13
-// 000000010000e107 push r12
-// 000000010000e109 push rbx
-// 000000010000e10a sub rsp, 0x628
-// 000000010000e111 mov rax, qword [___stack_chk_guard_10073e278] ; ___stack_chk_guard_10073e278
-// rax = [SGDNSPacket queryPacketWithDomain:@"captive.apple.com" identifier:0x0 queryType:0x100];
-
-#if defined(__arm64__) || defined(__aarch64__)
- NSString *sub_0x10000e091Code = @"FA 67 BB A9 F8 5F 01 A9 F6 57 02 A9 F4 4F 03 A9 FD 7B 04 A9 FD 03 01 91 FF 83 18 D1 .. .. 00 ..";
-#elif defined(__x86_64__)
- NSString *sub_0x10000e091Code = @"55 48 89 E5 41 57 41 56 41 55 41 54 53 48 81 EC 28 06 00 00 48 8B 05 .. .. ..";
-#endif
- NSArray *sub_0x10000e091Offsets =[MemoryUtils searchMachineCodeOffsets:
- searchFilePath
- machineCode:sub_0x10000e091Code
- count:(int)3
- ];
-
- for (NSNumber *sub_0x10000e091It in sub_0x10000e091Offsets) {
- intptr_t _sub_0x10000e091 = [MemoryUtils getPtrFromGlobalOffset:0 targetFunctionOffset:(uintptr_t)[sub_0x10000e091It unsignedIntegerValue] reduceOffset:(uintptr_t)fileOffset];
- DobbyHook((void *)_sub_0x10000e091, ret, NULL);
- }
-
-
-
- // TODO: SSL 域名过滤该如何优雅 HOOK ??
-// -[SGHTTPEngine shouldPerformMITMForHost:sourceAddress:isSNI:]:
-//
-// 0000000100049de7 mov r13, qword [0x100837058] ; @selector(isEqualToString:) // __NSCFString
-// if ([rbx isEqualToString:@"api.enterprise.nssurge.com:443"] != 0x0 ||
-// [rbx isEqualToString:@"www.surge-activation.com:443"] != 0x0 ||
-// [rbx isEqualToString:@"www.surge-activation.com"] != 0x0 ||
-// [rbx isEqualToString:@"api.enterprise.nssurge.com"] != 0x0)
- // 它可以在任意地方进行hook 并获取/修改 寄存器的上下文
-// DobbyInstrument((void *) 0x00000001000499d9, shouldPerformMITMForHost_handler);
-
-
-// -[SGJournalRecordContainer _shouldHideRequest:takeoverMode:engineIdentifier:URL:]:
-// r15 hasSuffix:@".surge-activation.com"] != 0x0 || [r15 isEqual:@"enterprise.nssurge.com"] != 0x0
-//
-// 000000010005cdb9 mov r14, qword [0x1008360b8] ; @selector(hasSuffix:), CODE XREF=-[SGJournalRecordContainer _shouldHideRequest:takeoverMode:engineIdentifier:URL:]+642
-// 000000010005cdc0 lea rdx, qword [cfstring__surge_activation_com] ; @".surge-activation.com"
-//
-// 000000010005cdd7 mov rsi, qword [0x100837008] ; @selector(isEqual:)
-// 000000010005cdde lea rdx, qword [cfstring_enterprise_nssurge_com] ; @"enterprise.nssurge.com"
-
-
-
-
- // license 窗口
- // -[SGMLicenseViewController reload]:
- // https://www.surge-activation.com/mac/v3/device?deviceID=ce2500e944650ad7f6e2f580268e5454
- [MemoryUtils hookInstanceMethod:
- NSClassFromString(@"SGMEnterprise")
- originalSelector:NSSelectorFromString(@"settings")
- swizzledClass:[self class]
- swizzledSelector:NSSelectorFromString(@"hk_settings")
- ];
-
-
- // 发送消息提醒
- Method raiseEventMethod = class_getClassMethod(NSClassFromString(@"SGEEventCenter"), NSSelectorFromString(@"raiseEvent:content:type:"));
- IMP raiseEventMethodIMP = method_getImplementation(raiseEventMethod);
- ((void *(*)(id, SEL,id,id,int))raiseEventMethodIMP)(
- NSClassFromString(@"SGEEventCenter"),
- NSSelectorFromString(@"raiseEvent:content:type:"),
- @"WARNNING",
- @"Ref: https://github.com/marlkiller/dylib_dobby_hook",1
- );
-
- return YES;
-}
-
-
-void shouldPerformMITMForHost_handler(void *address, DobbyRegisterContext *ctx) {
- SEL tmp = @selector(sEqualToStringEx:);
-
-#if defined(__arm64__) || defined(__aarch64__)
-#elif defined(__x86_64__)
- intptr_t r12 = (intptr_t)ctx->general.regs.r12;
-// 去 nm 的各种指针, 这样写最好
- ctx->general.regs.r12 = (intptr_t)tmp;
-// *(intptr_t*)&ctx->general.regs.r12 = (intptr_t)tmp;
-
-#endif
-
-}
-// https://github.com/PhD-5/iOSDefectTweak/blob/master/hooks/CCCryptHook.m
-// https://github.com/PhD-5/CCCryptHook/blob/master/hooks/CCCrypt.xm
-static size_t getIVLength(CCAlgorithm alg) {
- switch(alg) {
- case kCCAlgorithmAES128:
- return kCCBlockSizeAES128;
- case kCCAlgorithmDES:
- return kCCBlockSizeDES;
- case kCCAlgorithm3DES:
- return kCCBlockSize3DES;
- case kCCAlgorithmCAST:
- return kCCBlockSizeCAST;
- case kCCAlgorithmRC2:
- return kCCBlockSizeRC2;
- default:
- return 0;
- }
-}
-static CCCryptorStatus (*original_CCCrypt)(
- CCOperation op, /* kCCEncrypt, etc. */
- CCAlgorithm alg, /* kCCAlgorithmAES128, etc. */
- CCOptions options, /* kCCOptionPKCS7Padding, etc. */
- const void *key,
- size_t keyLength,
- const void *iv, /* optional initialization vector */
- const void *dataIn, /* optional per op and alg */
- size_t dataInLength,
- void *dataOut, /* data RETURNED here */
- size_t dataOutAvailable,
- size_t *dataOutMoved);
-
-CCCryptorStatus hk_CCCrypt(
- CCOperation op, /* kCCEncrypt, etc. */
- CCAlgorithm alg, /* kCCAlgorithmAES128, etc. */
- CCOptions options, /* kCCOptionPKCS7Padding, etc. */
- const void *key,
- size_t keyLength,
- const void *iv, /* optional initialization vector */
- const void *dataIn, /* optional per op and alg */
- size_t dataInLength,
- void *dataOut, /* data RETURNED here */
- size_t dataOutAvailable,
- size_t *dataOutMoved)
-{
-// 0x1001c7ce7 <+955>: leaq -0x50(%rbp), %rdi
-// 0x1001c7ceb <+959>: movq %r14, %rsi // deviceId.getBytes()
-// 0x1001c7cee <+962>: movq %rax, %rdx // 32
-// 0x1001c7cf1 <+965>: callq 0x10045fca0 ; // rbp-50 为 key, rbp-40 为 iv ; 这里调用的 sha256 来根据 deviceId 生成key/iv
-// ...
-// 00000001001c7d63 lea rcx, qword [rbp+-0x50] ; argument "key" for method imp___stubs__CCCrypt
-// 00000001001c7d67 mov r8d, 0x20 ; argument "keyLength" for method imp___stubs__CCCrypt
-// 00000001001c7d6d mov edi, 0x1 ; argument "op" for method imp___stubs__CCCrypt
-// 00000001001c7d72 xor esi, esi ; argument "alg" for method imp___stubs__CCCrypt
-// 00000001001c7d74 mov edx, 0x1 ; argument "options" for method imp___stubs__CCCrypt
-// 00000001001c7d79 lea r9, qword [rbp+-0x40] ; argument "iv" for method imp___stubs__CCCrypt
-// 00000001001c7d7d lea r10,
-// 00000001001c7d84 push r10 ; argument "dataOutMoved" for method imp___stubs__CCCrypt
-// 00000001001c7d86 push r13 ; argument "dataOutAvailable" for method imp___stubs__CCCrypt
-// 00000001001c7d88 push qword [qword_100867b70] ; argument "dataOut" for method imp___stubs__CCCrypt,
-// 00000001001c7d8e push rax ; argument "dataInLength" for method imp___stubs__CCCrypt
-// 00000001001c7d8f push r14 ; argument "dataIn" for method imp___stubs__CCCrypt
-// 00000001001c7d91 call imp___stubs__CCCrypt ; CCCrypt
-
- // TODO: 没搞明白 p 参数解密后是什么, 以及干嘛的..
-// https://drafts.misty.moe/surge%E7%A0%B4%E8%A7%A3-89fa88c1794d43f6888e43bd30f91bfe#d777e8afaa1041eaa844910d5b519ecf
-// AES_CBC_256(
-// input: "\x03\x04\x02NSExtension",
-// key: SHA256(deviceID),
-// iv: SHA256(deviceID)[16:32],
-// options: PKCS7Padding)
-// 00000000 03 04 02 4e 53 45 78 74 65 6e 73 69 6f 6e 00 |...NSExtension.|
-//
-// [0] = 3, 为固定header
-// [1] = 4, 控制VMess加密
-// [2] = 2, 控制TCP、SS的端口字节数
-// [3:] = "NSExtension", 控制TE plugin加载
-
- // 似乎 解密后的 dataOut 第一字节不能是 3,不能是 0
- if (keyLength==32) {
- // 0x1001c6921 <+1125>: callq 0x1005df574 ; symbol stub for: CCCrypt
- // 0x1001c6926 <+1130>: addq $0x30, %rsp
- NSData *keyData = [NSData dataWithBytes:key length:keyLength];
- NSString *keyBase64 = [keyData base64EncodedStringWithOptions:0];
- NSString *keyStr = [[NSString alloc] initWithData:keyData encoding:NSUTF8StringEncoding];
- NSLog(@">>>>>> keyBase64 :%@",keyBase64);
- NSLog(@">>>>>> keyStr :%@",keyStr);
-
- const uint8_t *keyBytes = (const uint8_t *)keyData.bytes;
- NSString *keyHex = @"";
- for (int i = 0; i < keyLength; i++) {
- keyHex = [keyHex stringByAppendingFormat:@"%02x ", keyBytes[i]];
- }
- // b7 6a bf 75 99 07 0d 87 1e 59 68 f3 84 4a 79 c0 6a f3 7d 82 af 81 a2 84 39 7e 0a cc f2 83 cb 24
- NSLog(@">>>>>> keyHex: %@", keyHex);
-
- if (iv!=nil) {
- NSData *ivData = [NSData dataWithBytes:iv length:(unsigned int)getIVLength(alg)];
- NSString *ivBase64 = [ivData base64EncodedStringWithOptions:0];
- NSString *ivStr = [[NSString alloc] initWithData:ivData encoding:NSUTF8StringEncoding];
- NSLog(@">>>>>> ivBase64 :%@",ivBase64);
- NSLog(@">>>>>> ivStr :%@",ivStr);
-
- const uint8_t *ivBytes = (const uint8_t *)ivData.bytes;
- NSString *ivHex = @"";
- for (int i = 0; i < getIVLength(alg); i++) {
- ivHex = [ivHex stringByAppendingFormat:@"%02x ", ivBytes[i]];
- }
- // 6a f3 7d 82 af 81 a2 84 39 7e 0a cc f2 83 cb 24
- NSLog(@">>>>>> ivHex: %@", ivHex);
- }
-
- NSData *dataInData = [NSData dataWithBytes:dataIn length:dataInLength];
- NSString *dataInBase64 = [dataInData base64EncodedStringWithOptions:0];
- NSString *dataInStr = [[NSString alloc] initWithData:dataInData encoding:NSUTF8StringEncoding];
- NSLog(@">>>>>> dataInBase64 :%@",dataInBase64);
- NSLog(@">>>>>> dataInStr :%@",dataInStr);
-
- }
- CCCryptorStatus result = original_CCCrypt(op,alg,options,key,keyLength,iv,dataIn,dataInLength,dataOut,dataOutAvailable,dataOutMoved);
-
- if (keyLength==32) {
- NSData *dataOutData = [NSData dataWithBytes:dataOut length:*dataOutMoved];
- NSString *dataOutBase64 = [dataOutData base64EncodedStringWithOptions:0];
- NSString *dataOutStr = [[NSString alloc] initWithData:dataOutData encoding:NSUTF8StringEncoding];
- NSLog(@">>>>>> dataOutBase64 :%@",dataOutBase64);
- NSLog(@">>>>>> dataOutStr :%@",dataOutStr);
-
- // 读取 hex
- unsigned char *dataOutBytes = (unsigned char *)dataOutData.bytes;
- NSString *dataOutHex = @"";
- for (NSUInteger i = 0; i < *dataOutMoved; i++) {
- NSString *byteString = [NSString stringWithFormat:@"%02x ", dataOutBytes[i]];
- dataOutHex = [dataOutHex stringByAppendingString:byteString];
- }
- // 03 04 02 4e 53 45 78 74 65 6e 73 69 6f 6e
- NSLog(@">>>>>> Memory content at address %p: %@", dataOut, dataOutHex);
- // kCCSuccess = 0,
- NSLog(@">>>>>> result: %d",result);
-
- }
- return result;
-}
-
-
-
-
-typedef void (^CompletionHandler1)(NSError *error, NSURLResponse *response, NSData *data);
-typedef void (^CompletionHandler2)(NSData *data, NSURLResponse *response, NSError *error);
-
-// Ref: https://github.com/NyaMisty/Surge4Advanced/blob/master/Tweak.x
-// __auto_type wrapper = ^(NSError *error, NSDictionary *data) {
-// __auto_type resp = [[NSHTTPURLResponse alloc] initWithURL:url statusCode:200 HTTPVersion:@"1.1" headerFields:@{}];
-// NSData *body = [NSJSONSerialization dataWithJSONObject:data options:0 error: &error];
-// completionHandler(body, resp, error);
-// };
-
-//// fake req
-// void (^handler)(NSError *error, NSDictionary *data) = ^(NSError *error, NSDictionary *data){
-// NSDictionary *licInfo = @{
-// @"deviceID": @"deviceID",
-// @"expirationDate": @4070880000, // 2099-01-01 00:00:00
-// @"fusDate": @4070880000,
-// @"type": @"licensed",
-// @"issueDate": [NSNumber numberWithInt:(long)[[NSDate date] timeIntervalSince1970]],
-// @"p": @"p",
-// };
-// NSData *licInfoData = [NSJSONSerialization dataWithJSONObject:licInfo options:0 error: &error];
-// NSString *licInfoStr = [[NSString alloc] initWithData:licInfoData encoding:NSUTF8StringEncoding];
-// NSString *licInfoBase64 = [licInfoData base64EncodedStringWithOptions:0];
-// wrapper(nil, @{
-// @"license": @{
-// @"policy": licInfoBase64,
-// @"sign": @""
-// }
-// });
-// };
-// dispatch_async(dispatch_get_main_queue(), ^{
-// handler(nil, nil);
-// });
-
-// if ([reqUrl hasSuffix:@"ac"]) { // disable refresh req
-// [req setURL:[NSURL URLWithString:@"http://127.0.0.1:65536"]];
-// void (^handler)(NSError *error, NSDictionary *data) = ^(NSError *error, NSDictionary *data){
-// wrapper(nil, @{});
-// };
-// dispatch_async(dispatch_get_main_queue(), ^{
-// handler(nil, nil);
-// });
-// }
-
-// completionHandler:(void (^)(NSError *error, NSURLResponse *response, NSData *data))completionHandler
-//- (void) hook_dataTaskWithURLRequest:(NSMutableURLRequest*)request configuration:arg2
-// completionHandler:(void (^)(NSError *error, NSURLResponse *response, NSData *data))completionHandler{
-- (void) hook_dataTaskWithURLRequest:(NSMutableURLRequest*)request configuration:arg2 completionHandler:(CompletionHandler1)completionHandler{
-
- // Printing description of arg3:
- // <__NSGlobalBlock__: 0x100742fa0>
- // signature: "v32@?0@"NSError"8@"NSHTTPURLResponse"16@"NSData"24"
- // invoke : 0x100108c4a
-
- NSURL *url = [request URL];
- NSString *urlString = [url absoluteString];
- if ([urlString containsString:@"mac/v3/"] && completionHandler) {
- // 在 Objective-C 中,completionHandler 是一种常见的异步编程模式,它通常用于在一个操作完成后执行一些额外的代码或处理结果。
- // po arg2 >> signature: "v32@?0@"NSData"8@"NSURLResponse"16@"NSError"24"
- __auto_type wrapper = ^(NSError *error, NSDictionary *data) {
- __auto_type resp = [[NSHTTPURLResponse alloc] initWithURL:url statusCode:200 HTTPVersion:@"1.1" headerFields:@{}];
- NSData *body = [NSJSONSerialization dataWithJSONObject:data options:0 error: &error];
- completionHandler(error, resp, body);
- };
-
- NSDictionary *respBody;
- NSString *reqBody;
- if ([urlString containsString:@"mac/v3/ac"]) {
- respBody =@{
- @"k":@0
- };
- }else{
- respBody =@{
- @"code":@0
- };
- }
- reqBody = [[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding];
- NSLog(@">>>>>> [hook_dataTaskWithURLRequest] Intercept url: %@, request body: %@, response body: %@",url, reqBody,respBody);
- wrapper(nil,respBody);
- return;
- }
- NSLog(@">>>>>> [hook_dataTaskWithURLRequest] Allow to pass url: %@",url);
- ((void(*)(id, SEL,id,id,id))dataTaskWithRequestIMP2)(self, _cmd,request,arg2,completionHandler);
-}
-
-- (void) hook_dataTaskWithRequest:(NSMutableURLRequest*)request completionHandler:(CompletionHandler2)completionHandler{
-
- // Printing description of arg2:
- // <__NSStackBlock__: 0x7ff7bfefd828>
- // signature: "v32@?0@"NSData"8@"NSURLResponse"16@"NSError"24"
-
- NSURL *url = [request URL];
- NSString *urlString = [url absoluteString];
- if ([urlString containsString:@"mac/v3/"] && completionHandler) {
- // 在 Objective-C 中,completionHandler 是一种常见的异步编程模式,它通常用于在一个操作完成后执行一些额外的代码或处理结果。
- __auto_type wrapper = ^(NSError *error, NSDictionary *data) {
- __auto_type resp = [[NSHTTPURLResponse alloc] initWithURL:url statusCode:200 HTTPVersion:@"1.1" headerFields:@{}];
- NSData *body = [NSJSONSerialization dataWithJSONObject:data options:0 error: &error];
- completionHandler(body, resp,error);
- };
- NSDictionary *respBody;
- NSString *reqBody;
-
- if ([urlString containsString:@"mac/v3/init/"]) {
- // 如果不是 enterprise, 每次软件启动都会校验这个接口
- respBody = policySign;
- } else if ([urlString containsString:@"mac/v3/device"]) {
- respBody =@{
- @"account":[Constant G_EMAIL_ADDRESS],
- @"license":@"🇨🇳 Voidm.Com"
- };
- } else if ([urlString containsString:@"mac/v3/ac"]) {
- respBody =@{
- @"k":@0
- };
- }else if ([urlString containsString:@"mac/v3/resource/jsvm"]) {
- NSString *jsvm = [NSString stringWithContentsOfFile:
- [[Constant getCurrentAppPath] stringByAppendingString:@"/Contents/MacOS/jsvm.js"]
- encoding:NSUTF8StringEncoding error:nil
- ];
- if (!jsvm) {
- NSLog(@">>>>>> /Contents/MacOS/jsvm.js 文件不存在 ???");
- [MemoryUtils exAlart:@"FBI warning" message:@"/Contents/MacOS/jsvm.js 文件不存在 ???"];
- respBody =@{
- @"code": @0
- };
- } else {
- respBody =@{
- @"code": @0,
- @"data": jsvm,
- @"v": @"2024071200000000"
- };
- }
-
- }else if ([urlString containsString:@"mac/v3/resource/module"]) {
- NSData *nsData = [NSData dataWithContentsOfFile:[[Constant getCurrentAppPath] stringByAppendingString:@"/Contents/MacOS/modules.json"]
- options:NSDataReadingMappedIfSafe error:nil];
- if (!nsData) {
- NSLog(@">>>>>> /Contents/MacOS/modules.json 文件不存在 ???");
- [MemoryUtils exAlart:@"FBI warning" message:@"/Contents/MacOS/modules.json 文件不存在 ???"];
- respBody =@{
- @"code": @0
- };
- } else {
- id sections = [NSJSONSerialization JSONObjectWithData:
- nsData options:NSJSONReadingMutableContainers error:nil
- ];
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:@{
- @"v": @"2024071200000000",
- @"sections": sections,
- @"u": @"8fce02ae-b82a-40ce-bda5-9cfbcb50d65f"
- } options:0 error:nil];
- respBody =@{
- @"code":@0,
- @"data": [jsonData base64EncodedStringWithOptions:0]
- };
- }
-
- } else {
- // TODO: 暂时未知, 有没有必要 hook 各个请求的 response data
- respBody =@{
- @"code":@0
- };
- }
- reqBody = [[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding];
- NSLog(@">>>>>> [hook_dataTaskWithRequest] Intercept url: %@, request body: %@, response body: %@",url, reqBody,respBody);
- wrapper(nil,respBody);
- return;
- }
- // pass: https://api.enterprise.nssurge.com/client/refresh
-
- NSLog(@">>>>>> [hook_dataTaskWithRequest] Allow to pass url: %@",url);
- ((void(*)(id, SEL,id,id))dataTaskWithRequestIMP)(self, _cmd,request,completionHandler);
-}
-
-- (NSString *) hook_componentsJoinedByString:arg1{
- if ([arg1 isEqualToString:@"/"] && [[self valueForKeyPath:@"@count"] isEqualToNumber:@6]) {
- NSLog(@">>>>>> device info : %@",self);
- // md5("1/2/3/4/5/6") = 16b8f4bdfd55d29f737427b4ec0c14d7
- return @"1/2/3/4/5/6";
- }
- return ((NSString*(*)(id, SEL, NSString*))componentsJoinedByStringIMP)(self, _cmd, arg1);
-}
-
-
-
-
-// 这里可以伪造 public key,自签名
-- (NSData *) hk_initWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(int)freeWhenDone {
- // 0x1001c6638 <+380>: callq 0x1001c6b0b ; ___lldb_unnamed_symbol7189
- //-> 0x1001c663d <+385>: testb %al, %al
- if (length == 0x1c3) {
- NSLog(@">>>>>> hk_initWithBytesNoCopy input length: %lu", (unsigned long)length);
-
- // NSString *inputString = [[NSString alloc] initWithBytes:bytes length:length encoding:NSUTF8StringEncoding];
- // 替换公钥
- const char *replacementBytes = [publicKey UTF8String];
- NSUInteger replacementLength = [publicKey lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
- memcpy(bytes, replacementBytes, replacementLength);
- length = replacementLength;
- }
- NSData *ret = ((NSData*(*)(id, SEL,void *,NSUInteger,int))initWithBytesNoCopyMethodIMP)(self, _cmd,bytes,length,freeWhenDone);
- return ret;
-}
-
-- (id)hk_settings{
- NSLog(@">>>>>> hk_settings");
-
- // -[SGMLicenseViewController reload]:
- // call sub_1001b1647 ; sub_1001b1647
- id ret = class_createInstance(objc_getClass("SGMEnterpriseSettings"), 0);
- [ret performSelector:NSSelectorFromString(@"setUserID:") withObject:[Constant G_EMAIL_ADDRESS]];
- [ret performSelector:NSSelectorFromString(@"setCompanyName:") withObject:@"Home"];
- [ret performSelector:NSSelectorFromString(@"setCompanyID:") withObject:@"CN"];
- return ret;
-}
-+ (id)hk_URLWithString:arg1{
- id ret = ((id(*)(id, SEL,id))urlWithStringSeletorIMP)(self, _cmd,arg1);
- // >>>>>> hk_URLWithString https://www.surge-activation.com/mac/v3/init/
- if ([arg1 containsString:@"v3"]) {
- NSLog(@">>>>>> hk_URLWithString [v3] %@",arg1);
- }
- return ret;
-}
-
-@end
diff --git a/script/auto_hack.sh b/script/auto_hack.sh
index 4a0b2b8..c395736 100644
--- a/script/auto_hack.sh
+++ b/script/auto_hack.sh
@@ -54,7 +54,7 @@ hack_app "Movist Pro" "/Applications/Movist Pro.app/Contents/Frameworks/MediaKey
hack_app "AirBuddy" "/Applications/AirBuddy.app/Contents/Frameworks/LetsMove.framework/Versions/A/LetsMove"
hack_app "Infuse" "/Applications/Infuse.app/Contents/Frameworks/Differentiator.framework/Versions/A/Differentiator"
hack_app "MacUpdater" "/Applications/MacUpdater.app/Contents/Frameworks/Sparkle.framework/Versions/B/Sparkle"
+hack_app "ForkLift" "/Applications/ForkLift.app/Contents/Frameworks/UniversalDetector.framework/Versions/A/UniversalDetector"
-hack_app "Surge" "/Applications/Surge.app/Contents/Frameworks/MMMarkdown.framework/Versions/A/MMMarkdown" "surge_hack.sh"
diff --git a/tools/mac_patch_helper b/tools/mac_patch_helper
index f415c1d..98c0d70 100755
Binary files a/tools/mac_patch_helper and b/tools/mac_patch_helper differ
diff --git a/tools/patch.json b/tools/patch.json
index 1b5e3d9..6ac3a66 100644
--- a/tools/patch.json
+++ b/tools/patch.json
@@ -13,6 +13,16 @@
"clear_certificate":[
"/Applications/Surge.app/Contents/Library/LaunchServices/com.nssurge.surge-mac.helper"
]
+ },
+ "ForkLift":{
+ "TODO// patch":{
+ "/Applications/ForkLift.app/Contents/Library/LaunchServices/com.binarynights.ForkLiftHelper":{
+
+ }
+ },
+ "clear_certificate":[
+ "/Applications/ForkLift.app/Contents/Library/LaunchServices/com.binarynights.ForkLiftHelper"
+ ]
}
}