├── .gitignore ├── BenefitPay.plist ├── Icon-orig.png ├── Jailbreak.m ├── LICENSE ├── Makefile ├── README.md ├── Tweak.m ├── headers.h ├── layout └── DEBIAN │ └── control └── prefs ├── BPPRootListController.h ├── BPPRootListController.m ├── Makefile ├── Resources ├── Info.plist ├── Root.plist └── icon.png └── layout └── Library └── PreferenceLoader └── Preferences └── Prefs.plist /.gitignore: -------------------------------------------------------------------------------- 1 | packages/ 2 | .theos/ 3 | .cache/ 4 | compile_commands.json -------------------------------------------------------------------------------- /BenefitPay.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "bh.benefit.bpuser" ); }; } 2 | -------------------------------------------------------------------------------- /Icon-orig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExTBH/BenefitPay-tweak/ea4d6c7816c250d9514fd264f5e110c945537faf/Icon-orig.png -------------------------------------------------------------------------------- /Jailbreak.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | static NSData *makeSynchronousGETRequestWithTimeout(NSURL *url, NSTimeInterval timeout) { 4 | NSURLRequest *request = [NSURLRequest requestWithURL:url]; 5 | dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 6 | 7 | __block NSData *responseData = nil; 8 | NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 9 | responseData = data; 10 | dispatch_semaphore_signal(semaphore); 11 | }]; 12 | 13 | [task resume]; 14 | 15 | dispatch_time_t dispatchTimeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)); 16 | dispatch_semaphore_wait(semaphore, dispatchTimeout); 17 | 18 | return responseData; 19 | } 20 | 21 | // replacement for + (void)load 22 | static void NullLoader() {} 23 | 24 | /* 25 | json format is 26 | { 27 | "versions: [ 28 | { 29 | "version": "2.0.2", 30 | "classes": ["class1","class2"] 31 | } 32 | ] 33 | } 34 | sorted from first supported version at top 35 | and newer version at bottom 36 | */ 37 | void dynamicHooker(NSData* jsonData) { 38 | NSError *error = nil; 39 | NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; 40 | if (error != nil) { 41 | NSLog(@"[ExTLogger] Error Parsing versions JSON %@", error.description); 42 | return; 43 | } 44 | 45 | NSArray *versions = jsonDict[@"versions"]; 46 | 47 | if (versions == nil) { 48 | NSLog(@"[ExTLogger] No versions key found %@", jsonDict.description); 49 | return; 50 | } 51 | 52 | NSString *currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 53 | NSArray *classes = nil; 54 | 55 | for (NSDictionary *version in versions) { 56 | if ([version[@"version"] isEqualToString:currentVersion]) { 57 | classes = version[@"classes"]; 58 | break; 59 | } 60 | } 61 | if (classes == nil) { 62 | NSLog(@"[ExTLogger] Can't find classes to hook [%@] %@",currentVersion, versions); 63 | return; 64 | } 65 | 66 | for (NSString *clazzString in classes) { 67 | Class clz = objc_getMetaClass(clazzString.UTF8String); 68 | MSHookMessageEx(clz, @selector(load), (IMP) NullLoader, NULL); 69 | } 70 | 71 | } 72 | 73 | static void __attribute__((constructor)) init(void) { 74 | NSURL *url = [NSURL URLWithString:@"https://repo.extbh.dev/dev.extbh.benefitpay/versions.json"]; 75 | NSData *resp = makeSynchronousGETRequestWithTimeout(url, 5); 76 | if (resp == nil) { 77 | NSLog(@"[ExTLogger] Can't connent to server"); 78 | return; 79 | } 80 | dynamicHooker(resp); 81 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:13.0 2 | INSTALL_TARGET_PROCESSES = BenefitPay 3 | 4 | 5 | include $(THEOS)/makefiles/common.mk 6 | 7 | TWEAK_NAME = BenefitPay 8 | 9 | BenefitPay_FILES = Tweak.m Jailbreak.m 10 | BenefitPay_CFLAGS = -fobjc-arc 11 | BenefitPay_EXTRA_FRAMEWORKS += Cephei 12 | 13 | include $(THEOS_MAKE_PATH)/tweak.mk 14 | SUBPROJECTS += prefs 15 | include $(THEOS_MAKE_PATH)/aggregate.mk 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BenefitPay-tweak 2 | Benefit is a nice app but ofcouse as a banking app they have to implement jailbreak detection. 3 | In the past detection was simple just use A-Bypass and you good, but now with version 2.0.0 they have integrated [DexProtector](https://licelus.com/products/dexprotector). 4 | So how do we bypass it now? 5 | Well its simple 6 | 1. first Open the app in any disassembler and start analzying the app and see whats happeing 7 | 2. Look at crash logs and identify a potential reason, looking at benefit's crashes it was crashing before the app is ran so it suggested it might be a framework or an [init function](https://stackoverflow.com/a/30703178/16619237) 8 | 3. Before diving in the init funtions and suffering with obfuscated arm stuff, why not finish checking the whole app first? so i went looking in the frameworks. 9 | where i arrived at an obfuscated framework, everything was encrypted every string every method every class, except one thing, the info.plist file, it had the reverse DNS of the framework `com.licel.WbInject` 10 | googling that and we arrive at the homepage of licel where they have DexProtector as a service, with that we know who's the reason. 11 | 4. Now time to break it, first going through the binary, we notice everything is encrypted and done at runtime, there's nothing we can hook 12 | 5. so i was like, what happens if the class can't be initalized? since everything is done at runtime 13 | 6. with that i decided to hook the 3 classes available in the binary and prevent their initalization, to do that we hook the [load method](https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc) 14 | 7. hooking that and opening the app and tada!! it works fine. 15 | 16 | ## Future proofing 17 | But knowing everything is encrpyted, i knew each new update i have to redo these steps and recompile the tweak again so i decided to future proof it this way 18 | first rewrite the hooking code to be done at runtime 19 | then i decided to store a JSON file with each version and their corresponding classes 20 | then write [this](https://github.com/ExTBH/BenefitPay-tweak/blob/77c4e4ea3b071b30bf69b77a143d676d02ef6958/Jailbreak.m#L73C7-L73C7) 21 | and now all i have to do is just update the json whenever a new version is out and all will work fine, and it's been working fine since i wrote it 7 months ago 22 | -------------------------------------------------------------------------------- /Tweak.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import "headers.h" 5 | 6 | static const HBPreferences *tweakPreferences; 7 | 8 | // nedded when hooking an app 9 | @class HBForceCepheiPrefs; 10 | static BOOL override_HBForeCepheiPrefs_forceCepheiPrefsWhichIReallyNeedToAccessAndIKnowWhatImDoingISwear(id self, SEL _cmd){ 11 | return YES; 12 | } 13 | 14 | static void (*orig_AppDelegate_applicationWillEnterForeground)(id, SEL, UIApplication*); 15 | static void override_AppDelegate_applicationWillEnterForeground(id self, SEL _cmd, UIApplication *sharedApplication){ 16 | BOOL isPreventLock; 17 | [tweakPreferences registerBool:&isPreventLock default:YES forKey:@"Lock"]; 18 | if (!isPreventLock){ 19 | orig_AppDelegate_applicationWillEnterForeground(self, _cmd, sharedApplication); 20 | } 21 | 22 | } 23 | 24 | static UIContextMenuConfiguration *new_BPTransactionHistoryDetailCell_contextMenuInteraction$configurationForMenuAtLocation( 25 | BPTransactionHistoryDetailCell *self, 26 | SEL _cmd, 27 | UIContextMenuInteraction *interaction, 28 | CGPoint location) 29 | { 30 | UIAction *copy = [UIAction actionWithTitle:@"Copy" 31 | image:nil 32 | identifier:nil 33 | handler:^(UIAction *handler) { 34 | UIPasteboard.generalPasteboard.string = self.lblDescription.text; 35 | }]; 36 | 37 | UIMenu *menu = [UIMenu menuWithTitle:@"" children:@[copy]]; 38 | 39 | UIContextMenuConfiguration *configuration = [UIContextMenuConfiguration configurationWithIdentifier:nil 40 | previewProvider:nil 41 | actionProvider:^(NSArray *suggestedActions) { 42 | return menu; 43 | }]; 44 | 45 | return configuration; 46 | } 47 | 48 | static void (*orig_BPTransactionHistoryDetailCell_setupCellWithTitle$andDescription)(id, SEL, NSString*, NSString*); 49 | static void override_BPTransactionHistoryDetailCell_setupCellWithTitle$andDescription(BPTransactionHistoryDetailCell *self, SEL _cmd, NSString* title, NSString*description){ 50 | orig_BPTransactionHistoryDetailCell_setupCellWithTitle$andDescription(self, _cmd, title, description); 51 | 52 | BOOL isCopy; 53 | [tweakPreferences registerBool:&isCopy default:YES forKey:@"Copying"]; 54 | 55 | if (isCopy){ 56 | static dispatch_once_t onceToken; 57 | dispatch_once( 58 | &onceToken, 59 | ^{ 60 | class_addMethod([self class], 61 | @selector(contextMenuInteraction:configurationForMenuAtLocation:), 62 | (IMP) &new_BPTransactionHistoryDetailCell_contextMenuInteraction$configurationForMenuAtLocation, 63 | "@@:{name=CGPoint}"); 64 | } 65 | ); 66 | 67 | UIContextMenuInteraction *interaction = [[UIContextMenuInteraction alloc] initWithDelegate:self]; 68 | self.userInteractionEnabled = YES; 69 | [self addInteraction:interaction]; 70 | } 71 | } 72 | 73 | 74 | static UIContextMenuConfiguration *new_BPInboxDetailViewController_contextMenuInteraction$configurationForMenuAtLocation( 75 | BPInboxDetailViewController *self, 76 | SEL _cmd, 77 | UIContextMenuInteraction *interaction, 78 | CGPoint location) 79 | { 80 | UIAction *copy = [UIAction actionWithTitle:@"Copy" 81 | image:nil identifier:nil handler:^(UIAction *handler) { 82 | UIPasteboard.generalPasteboard.string = self.lblMessage.text; 83 | }]; 84 | 85 | UIMenu *menu = [UIMenu menuWithTitle:@"" children:@[copy]]; 86 | 87 | UIContextMenuConfiguration *configuration = [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil 88 | actionProvider:^(NSArray *suggestedActions) { return menu;}]; 89 | return configuration; 90 | } 91 | 92 | 93 | static void (*orig_BPInboxDetailViewController_viewDidLoad)(id, SEL); 94 | static void override_BPInboxDetailViewController_viewDidLoad(BPInboxDetailViewController *self, SEL _cmd){ 95 | orig_BPInboxDetailViewController_viewDidLoad(self, _cmd); 96 | BOOL isCopy; 97 | [tweakPreferences registerBool:&isCopy default:YES forKey:@"Copying"]; 98 | 99 | if (isCopy){ 100 | static dispatch_once_t onceToken; 101 | dispatch_once( 102 | &onceToken, 103 | ^{ 104 | class_addMethod([self class], 105 | @selector(contextMenuInteraction:configurationForMenuAtLocation:), 106 | (IMP) &new_BPInboxDetailViewController_contextMenuInteraction$configurationForMenuAtLocation, 107 | "@@:{name=CGPoint}"); 108 | } 109 | ); 110 | UIContextMenuInteraction *interaction = [[UIContextMenuInteraction alloc] initWithDelegate:self]; 111 | self.lblMessage.userInteractionEnabled = YES; 112 | [self.lblMessage addInteraction:interaction]; 113 | } 114 | } 115 | 116 | // FLEX Will show a return type of '?' because of swift 117 | static UIContextMenuConfiguration *new_TransactionFawriAndFawriPlusSentListingViewModel_ContextMenu( 118 | TransactionFawriAndFawriPlusSentListingViewModel *self, 119 | SEL _cmd, 120 | UITableView *tableView, 121 | NSIndexPath *indexPath, 122 | CGPoint point) 123 | { 124 | BOOL isCopy; 125 | [tweakPreferences registerBool:&isCopy default:YES forKey:@"Copying"]; 126 | if (!isCopy) {return nil;} 127 | 128 | UIAction *copy = [UIAction actionWithTitle:@"Copy" 129 | image:nil identifier:nil handler:^(UIAction *handler) { 130 | TransactionDetailViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 131 | UIPasteboard.generalPasteboard.string = cell.valueLabel.text; 132 | }]; 133 | 134 | UIMenu *menu = [UIMenu menuWithTitle:@"" children:@[copy]]; 135 | 136 | UIContextMenuConfiguration *configuration = [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil 137 | actionProvider:^(NSArray *suggestedActions) { return menu;}]; 138 | return configuration; 139 | } 140 | 141 | 142 | __attribute__((constructor)) static void init(){ 143 | MSHookMessageEx( 144 | objc_getMetaClass("HBForceCepheiPrefs"), 145 | @selector(forceCepheiPrefsWhichIReallyNeedToAccessAndIKnowWhatImDoingISwear), 146 | (IMP) &override_HBForeCepheiPrefs_forceCepheiPrefsWhichIReallyNeedToAccessAndIKnowWhatImDoingISwear, 147 | NULL); 148 | 149 | MSHookMessageEx( 150 | NSClassFromString(@"AppDelegate"), 151 | @selector(applicationWillEnterForeground:), 152 | (IMP) &override_AppDelegate_applicationWillEnterForeground, 153 | (IMP*) &orig_AppDelegate_applicationWillEnterForeground); 154 | 155 | MSHookMessageEx(NSClassFromString(@"BPTransactionHistoryDetailCell"), 156 | @selector(setupCellWithTitle:andDescription:), 157 | (IMP) &override_BPTransactionHistoryDetailCell_setupCellWithTitle$andDescription, 158 | (IMP*) &orig_BPTransactionHistoryDetailCell_setupCellWithTitle$andDescription); 159 | 160 | MSHookMessageEx(NSClassFromString(@"BPInboxDetailViewController"), 161 | @selector(viewDidLoad), 162 | (IMP) &override_BPInboxDetailViewController_viewDidLoad, 163 | (IMP*) &orig_BPInboxDetailViewController_viewDidLoad); 164 | 165 | // beta hooks 166 | Class TransactionsDelegate = NSClassFromString(@"BenefitPay.TransactionFawriAndFawriPlusSentListingViewModel"); 167 | class_addMethod(TransactionsDelegate, 168 | @selector(tableView:contextMenuConfigurationForRowAtIndexPath:point:), 169 | (IMP) &new_TransactionFawriAndFawriPlusSentListingViewModel_ContextMenu, 170 | "@@:@@{name=CGPoint}"); 171 | 172 | MSHookMessageEx( 173 | NSClassFromString(@"BenefitPay.AppDelegate"), 174 | @selector(applicationWillEnterForeground:), 175 | (IMP) &override_AppDelegate_applicationWillEnterForeground, 176 | (IMP*) &orig_AppDelegate_applicationWillEnterForeground); 177 | 178 | tweakPreferences = [[HBPreferences alloc] 179 | initWithIdentifier:@"dev.extbh.benefitpay++.prefs"]; 180 | } -------------------------------------------------------------------------------- /headers.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface AppDelegate : NSObject 4 | - (void)applicationWillEnterForeground:(UIApplication*)sharedApplication; 5 | @end 6 | 7 | @interface BPTransactionHistoryDetailCell : UIView 8 | @property (nonatomic, weak, readwrite) UILabel *lblDescription; 9 | - (void)setupCellWithTitle:(NSString*)title andDescription:(NSString*)desc; 10 | @end 11 | 12 | @interface BPInboxDetailViewController : UIViewController 13 | @property (nonatomic, weak, readwrite) UILabel *lblMessage; 14 | @end 15 | 16 | // Benefit Beta Related 17 | 18 | @interface TransactionDetailViewCell : UITableViewCell 19 | @property (weak, nonatomic) UILabel *valueLabel; 20 | @end 21 | 22 | @interface TransactionFawriAndFawriPlusSentListingViewModel : NSObject 23 | 24 | @end -------------------------------------------------------------------------------- /layout/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: dev.extbh.benefitpay++ 2 | Name: BenefitPay++ 3 | Version: 0.0.6 4 | Architecture: iphoneos-arm 5 | Description: BenefitPay but it's ++ 6 | Maintainer: ExTBH 7 | Author: ExTBH 8 | Section: Tweaks 9 | Depends: mobilesubstrate (>= 0.9.5000), ws.hbang.common (>= 1.17) 10 | Icon: https://raw.githubusercontent.com/ExTBH/BenefitPay-tweak/a3bb0156094bfe5cb82886b445f0ca88fa64c7c6/Icon-orig.png 11 | -------------------------------------------------------------------------------- /prefs/BPPRootListController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | @interface BPPRootListController : HBRootListController 4 | @end 5 | -------------------------------------------------------------------------------- /prefs/BPPRootListController.m: -------------------------------------------------------------------------------- 1 | #import "BPPRootListController.h" 2 | 3 | @implementation BPPRootListController 4 | 5 | - (NSArray *)specifiers { 6 | if (!_specifiers) { 7 | _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; 8 | } 9 | 10 | return _specifiers; 11 | } 12 | @end 13 | 14 | -------------------------------------------------------------------------------- /prefs/Makefile: -------------------------------------------------------------------------------- 1 | INSTALL_TARGET_PROCESSES = Preferences 2 | 3 | 4 | include $(THEOS)/makefiles/common.mk 5 | 6 | BUNDLE_NAME = BPayPrefs 7 | 8 | Prefs_FILES = BPPRootListController.m 9 | Prefs_FRAMEWORKS = UIKit Foundation 10 | Prefs_PRIVATE_FRAMEWORKS = Preferences 11 | Prefs_EXTRA_FRAMEWORKS += CepheiPrefs 12 | Prefs_INSTALL_PATH = /Library/PreferenceBundles 13 | Prefs_CFLAGS = -fobjc-arc 14 | 15 | 16 | include $(THEOS_MAKE_PATH)/bundle.mk 17 | -------------------------------------------------------------------------------- /prefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | Prefs 9 | CFBundleIdentifier 10 | dev.extbh.benefitpay++.prefs 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | NSPrincipalClass 22 | BPPRootListController 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /prefs/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Settings 12 | 13 | 14 | cell 15 | PSSwitchCell 16 | default 17 | 18 | defaults 19 | dev.extbh.benefitpay++.prefs 20 | key 21 | Copying 22 | label 23 | Copy Details 24 | 25 | 26 | cell 27 | PSSwitchCell 28 | default 29 | 30 | defaults 31 | dev.extbh.benefitpay++.prefs 32 | key 33 | Lock 34 | label 35 | Prevent App Lock 36 | 37 | 38 | cell 39 | PSGroupCell 40 | label 41 | Idk Others 42 | footerText 43 | Licensed under the WTFPL By @ExTBH 44 | 45 | 46 | cellClass 47 | HBLinkTableCell 48 | label 49 | Source Code 50 | subtitle 51 | On Github 52 | url 53 | https://github.com/ExTBH/BenefitPay-tweak 54 | 55 | 56 | cellClass 57 | HBTwitterCell 58 | label 59 | Bugs/Features 60 | user 61 | ExTBH 62 | showAvatar 63 | 64 | 65 | 66 | 67 | title 68 | BenefitPay++ 69 | 70 | 71 | -------------------------------------------------------------------------------- /prefs/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExTBH/BenefitPay-tweak/ea4d6c7816c250d9514fd264f5e110c945537faf/prefs/Resources/icon.png -------------------------------------------------------------------------------- /prefs/layout/Library/PreferenceLoader/Preferences/Prefs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | bundle 8 | Prefs 9 | cell 10 | PSLinkCell 11 | detail 12 | BPPRootListController 13 | icon 14 | icon.png 15 | isController 16 | 17 | label 18 | BenefitPay++ 19 | 20 | 21 | 22 | --------------------------------------------------------------------------------