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" + ] } }