BypassMarketplace: hook os_eligibility_get_domain_answer

This commit is contained in:
khanhduytran0
2025-12-28 10:10:30 +07:00
parent bfb1c0a946
commit 2248e60627
5 changed files with 82 additions and 32 deletions
+76 -27
View File
@@ -1,32 +1,81 @@
@import Foundation;
%group Hook_managedappdistributiond
// "Not bypassing eligibility for com.apple.mobilesafari:personal (isProfileValidated: false isUPPValidated:false isBeta:false"
// Used in managedappdistributiond. Pseudocode of a validate function in OSEligbility.framework:
#if 0
LSBundleRecord *bundleRecord = ...;
BOOL isProfileValidated = bundleRecord.isProfileValidated;
BOOL isUPPValidated = bundleRecord.isUPPValidated;
BOOL isBeta = bundleRecord.isBeta;
if ( (isProfileValidated == NO) || (isUPPValidated == YES) || (isBeta == YES) ) {
log("Not bypassing eligibility for %s:%s (isProfileValidated: %{bool}d isUPPValidated:%{bool}d isBeta:%{bool}d", bundleRecord.bundleIdentifier.UTF8String, somethingThatSaysPersonal, isProfileValidated, isUPPValidated, isBeta);
return 0;
}
#endif
typedef CF_ENUM(uint64_t, EligibilityDomainType) {
/// Install marketplace-distributed apps
EligibilityDomainTypeHydrogen = 2,
/// Update/restore marketplace-distributed apps
EligibilityDomainTypeHelium = 3,
/// Update/restore web browser engine host apps
EligibilityDomainTypeLithium = 4,
/// Install web browser engine host apps
EligibilityDomainTypeCarbon = 7,
/// Install apps distributed via the web
EligibilityDomainTypeArgon = 19,
/// Update/restore apps distributed via the web
EligibilityDomainTypePotassium = 20,
};
typedef CF_ENUM(uint64_t, EligibilityAnswer) {
EligibilityAnswerEligible = 4,
};
typedef CF_ENUM(uint64_t, EligibilityAnswerSource) {
EligibilityAnswerSourceInvalid = 0,
EligibilityAnswerSourceComputed = 1,
EligibilityAnswerSourceForced = 2,
};
//@interface EligibilityOverride : NSObject
//- (NSMutableDictionary *)overrideMap;
//@end
//@interface EligibilityOverrideData : NSObject
//- (instancetype)initWithAnswer:(EligibilityAnswer)answer context:(id)context;
//@end
// So we just hook these to return values that will bypass eligibility
// for managedappdistributiond
%hook LSBundleRecord
- (BOOL)isProfileValidated {
return YES;
//%group Hook_eligibilityd
// seems to already be YES
//%hook GlobalConfiguration
//- (BOOL)supportsForcedAnswers {
// return YES;
//}
//%end
//%hook EligibilityEngine
//- (EligibilityOverride *)_loadOverridesWithError:(NSError **)error {
// EligibilityOverride *result = %orig;
// if (!result) {
// result = [NSClassFromString(@"EligibilityOverride") new];
// }
// EligibilityOverrideData *overrideData = [[NSClassFromString(@"EligibilityOverrideData") alloc] initWithAnswer:EligibilityAnswerEligible context:nil];
// NSMutableDictionary *overrideMap = result.overrideMap;
// overrideMap[@(EligibilityDomainTypeHydrogen)] = overrideData;
// overrideMap[@(EligibilityDomainTypeHelium)] = overrideData;
// overrideMap[@(EligibilityDomainTypeLithium)] = overrideData;
// overrideMap[@(EligibilityDomainTypeCarbon)] = overrideData;
// overrideMap[@(EligibilityDomainTypeArgon)] = overrideData;
// overrideMap[@(EligibilityDomainTypePotassium)] = overrideData;
// return result;
//}
//%end
//%end
%group Hook_os_eligibility_get_domain_answer
int os_eligibility_get_domain_answer(EligibilityDomainType domain, EligibilityAnswer *answer_ptr, EligibilityAnswerSource *answer_source_ptr, xpc_object_t *status_ptr, xpc_object_t *context_ptr);
%hookf(int, os_eligibility_get_domain_answer, EligibilityDomainType domain, EligibilityAnswer *answer_ptr, EligibilityAnswerSource *answer_source_ptr, xpc_object_t *status_ptr, xpc_object_t *context_ptr) {
switch (domain) {
case EligibilityDomainTypeHydrogen:
case EligibilityDomainTypeHelium:
case EligibilityDomainTypeLithium:
case EligibilityDomainTypeCarbon:
case EligibilityDomainTypeArgon:
case EligibilityDomainTypePotassium:
if (answer_ptr) {
*answer_ptr = EligibilityAnswerEligible;
}
if (answer_source_ptr) {
*answer_source_ptr = EligibilityAnswerSourceForced;
}
return 0;
default:
return %orig(domain, answer_ptr, answer_source_ptr, status_ptr, context_ptr);
}
}
- (BOOL)isUPPValidated {
return NO;
}
- (BOOL)isBeta {
return NO;
}
%end
%end
// for appstorecomponentsd, we hook URL method to replace region code
@@ -52,8 +101,8 @@ if ( (isProfileValidated == NO) || (isUPPValidated == YES) || (isBeta == YES) )
%ctor {
NSString *processName = NSProcessInfo.processInfo.processName;
if ([processName isEqualToString:@"managedappdistributiond"]) {
%init(Hook_managedappdistributiond);
if ([processName isEqualToString:@"managedappdistributiond"] || [processName isEqualToString:@"installd"]) {
%init(Hook_os_eligibility_get_domain_answer);
} else if ([processName isEqualToString:@"appstorecomponentsd"]) {
%init(Hook_appstorecomponentsd);
}
+1 -1
View File
@@ -1,5 +1,5 @@
TARGET := iphone:clang:latest:15.0
INSTALL_TARGET_PROCESSES = appstorecomponentsd managedappdistributiond MobileStorageMounter
INSTALL_TARGET_PROCESSES = appstorecomponentsd installd managedappdistributiond MobileStorageMounter
THEOS_PACKAGE_SCHEME := rootless
include $(THEOS)/makefiles/common.mk
+1
View File
@@ -2,6 +2,7 @@
Filter = {
Executables = (
appstorecomponentsd,
installd,
"managedappdistributiond",
MobileStorageMounter,
);
+2 -2
View File
@@ -1,3 +1,3 @@
#!/bin/sh
# managedappdistributiond does not honor SIGTERM
killall -KILL managedappdistributiond || true
# some daemons do not honor SIGTERM
killall -KILL appstorecomponentsd installd managedappdistributiond || true
+2 -2
View File
@@ -1,3 +1,3 @@
#!/bin/sh
# managedappdistributiond does not honor SIGTERM
killall -KILL managedappdistributiond || true
# some daemons do not honor SIGTERM
killall -KILL appstorecomponentsd installd managedappdistributiond || true