Skip to content

Commit 44d398a

Browse files
committed
add procursus(alt) repo and hide more jailbreak traces
1 parent d0194be commit 44d398a

3 files changed

Lines changed: 283 additions & 12 deletions

File tree

Application/Dopamine/Jailbreak/DOBootstrapper.m

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,11 @@ uint64_t jbrand_current()
886886
URIs: https://roothide.github.io/procursus\n\
887887
Suites: iphoneos-arm64e/%d\n\
888888
Components: main\n\
889+
\n\
890+
Types: deb\n\
891+
URIs: https://github.com/roothide/roothide.github.io/releases/download/%d/\n\
892+
Suites: ./\n\
893+
Components:\n\
889894
"
890895

891896
// #define ALT_SOURCES "\
@@ -908,6 +913,7 @@ uint64_t jbrand_current()
908913
deb https://havoc.app/ ./\n\
909914
deb https://roothide.github.io/ ./\n\
910915
deb https://roothide.github.io/procursus iphoneos-arm64e/%d main\n\
916+
deb https://github.com/roothide/roothide.github.io/releases/download/%d/ ./\n\
911917
\n\
912918
"
913919

@@ -935,7 +941,7 @@ -(int) buildPackageSources:(void (^)(NSError *))completion
935941
{
936942
NSFileManager* fm = NSFileManager.defaultManager;
937943

938-
ASSERT([[NSString stringWithFormat:@(DEFAULT_SOURCES), getCFMajorVersion()] writeToFile:jbrootPrefix(@"/etc/apt/sources.list.d/default.sources") atomically:YES encoding:NSUTF8StringEncoding error:nil]);
944+
ASSERT([[NSString stringWithFormat:@(DEFAULT_SOURCES), getCFMajorVersion(), getCFMajorVersion()] writeToFile:jbrootPrefix(@"/etc/apt/sources.list.d/default.sources") atomically:YES encoding:NSUTF8StringEncoding error:nil]);
939945

940946
// //Users in some regions seem to be unable to access github.io
941947
// if([NSLocale.currentLocale.countryCode isEqualToString:@"CN"]) {
@@ -948,7 +954,7 @@ -(int) buildPackageSources:(void (^)(NSError *))completion
948954
ASSERT([fm createDirectoryAtPath:jbrootPrefix(@"/var/mobile/Library/Application Support/xyz.willy.Zebra") withIntermediateDirectories:YES attributes:attr error:nil]);
949955
}
950956

951-
ASSERT([[NSString stringWithFormat:@(ZEBRA_SOURCES), getCFMajorVersion()] writeToFile:jbrootPrefix(@"/var/mobile/Library/Application Support/xyz.willy.Zebra/sources.list") atomically:YES encoding:NSUTF8StringEncoding error:nil]);
957+
ASSERT([[NSString stringWithFormat:@(ZEBRA_SOURCES), getCFMajorVersion(), getCFMajorVersion()] writeToFile:jbrootPrefix(@"/var/mobile/Library/Application Support/xyz.willy.Zebra/sources.list") atomically:YES encoding:NSUTF8StringEncoding error:nil]);
952958

953959
return 0;
954960
}

BaseBin/roothidehooks/Makefile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ roothidehooks_CFLAGS = -Werror -fobjc-arc -I../.include
1313
roothidehooks_LDFLAGS = -rpath @loader_path/.jbroot/Library/Frameworks -rpath @loader_path/fallback -L../libjailbreak -ljailbreak
1414
roothidehooks_INSTALL_PATH = /basebin
1515

16-
lsd.x_CFLAGS = -fno-objc-arc #lsd using mrc
17-
1816
include $(THEOS_MAKE_PATH)/tweak.mk
1917

2018
after-roothidehooks-all::

BaseBin/roothidehooks/lsd.x

Lines changed: 275 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
#import <Foundation/Foundation.h>
2-
#import <spawn.h>
1+
#include <Foundation/Foundation.h>
2+
3+
#include <spawn.h>
34
#include <roothide.h>
5+
46
#include "common.h"
57

68
extern char **environ;
@@ -78,7 +80,7 @@ static const void *kBlockSchemeTagKey = &kBlockSchemeTagKey;
7880
return result;
7981
}
8082

81-
- (BOOL)canOpenURL:(NSURL*)url publicSchemes:(BOOL)ispublic privateSchemes:(BOOL)isprivate XPCConnection:(NSXPCConnection*)connection error:(NSError*)err
83+
- (BOOL)canOpenURL:(NSURL*)url publicSchemes:(BOOL)ispublic privateSchemes:(BOOL)isprivate XPCConnection:(NSXPCConnection*)connection error:(NSError**)perror
8284
{
8385
BOOL blocked = NO;
8486

@@ -109,7 +111,7 @@ static const void *kBlockSchemeTagKey = &kBlockSchemeTagKey;
109111
return ret;
110112
}
111113

112-
%end
114+
%end //%hook _LSCanOpenURLManager
113115

114116

115117
@interface _LSDOpenClient : NSObject
@@ -229,12 +231,265 @@ static const void *kBlockSchemeTagKey = &kBlockSchemeTagKey;
229231
%orig(url, options, newcallback);
230232
}
231233

232-
%end
234+
%end //%hook _LSDOpenClient
235+
236+
%group UTTypeHooks
237+
238+
@interface UTTypeRecord : NSObject
239+
+ (id)typeRecordWithIdentifier:(id)identifier;
240+
- (unsigned int)tableID;
241+
@end
242+
243+
@interface _UTDeclaredTypeRecord : NSObject
244+
- (id)_initWithContext:(void*)ctx tableID:(unsigned int)tableID unitID:(unsigned int)unitID;
245+
- (BOOL)isDeclared;
246+
- (BOOL)isCoreType;
247+
- (BOOL)isInPublicDomain;
248+
- (id)identifier;
249+
- (id)declaringBundleRecord;
250+
- (unsigned int)unitID;
251+
- (unsigned int)_rawFlags;
252+
@end
253+
254+
@interface LSBundleRecord : NSObject
255+
- (NSURL*)URL;
256+
@end
257+
258+
@interface _LSDReadClient : NSObject
259+
- (NSXPCConnection*)XPCConnection;
260+
@end
261+
262+
static __thread BOOL g_utrHide = NO; // raised by the _LSDReadClient hooks for blacklisted requests
263+
static __thread int g_utrBusy = 0; // >0 while we ourselves touch the DB, to keep our access out of the filters
264+
265+
static BOOL utrFilterActive(void) { return g_utrHide && !g_utrBusy; }
266+
267+
static pid_t utrClientPid(_LSDReadClient* client)
268+
{
269+
NSXPCConnection* conn = [client XPCConnection];
270+
return conn ? conn.processIdentifier : -1;
271+
}
272+
273+
static BOOL utrHideClientBlacklisted(_LSDReadClient* client)
274+
{
275+
pid_t pid = utrClientPid(client);
276+
if(pid>0 && jbclient_blacklist_check_pid(pid)) {
277+
return YES;
278+
}
279+
return NO;
280+
}
281+
282+
// type-units table id; constant for the database. Read once, off the hot path, via a public accessor.
283+
static unsigned int utrTypeTableID(void)
284+
{
285+
static unsigned int tid = 0;
286+
static dispatch_once_t once;
287+
dispatch_once(&once, ^{
288+
// guard this probe's own nested lookup so it is never filtered, independent of the caller.
289+
// g_utrBusy is a counter, so this nests cleanly inside utrUnitIsJailbreak's busy region.
290+
g_utrBusy++;
291+
tid = (unsigned int)[[NSClassFromString(@"UTTypeRecord") typeRecordWithIdentifier:@"public.data"] tableID];
292+
g_utrBusy--;
293+
});
294+
return tid;
295+
}
296+
297+
// YES only when `rec` is a *declared* type whose active declaring bundle is a jailbreak bundle,
298+
// and which is not an Apple core / public-domain type (those are never touched -> #3).
299+
static BOOL utrRecordIsFromJailbreakApp(_UTDeclaredTypeRecord* rec)
300+
{
301+
if (![rec isDeclared]) return NO; // dynamic/undeclared -> already the "absent" shape
302+
if ([rec isCoreType]) return NO; // Apple core type -> never touched (#3)
303+
if ([rec isInPublicDomain]) return NO; // public.* -> never touched (#3)
304+
LSBundleRecord* bundleRec = [rec declaringBundleRecord];
305+
NSURL* url = [bundleRec URL];
306+
if (![url isKindOfClass:[NSURL class]] || !url.isFileURL) return NO;
307+
if (!isJailbreakBundlePath(url.path.fileSystemRepresentation)) return NO;
308+
309+
NSLog(@"[UTType] hide type id=%@ bundle=%@", [rec identifier], url);
310+
return YES;
311+
}
312+
313+
// build a record for an enumerated unitID and decide if it belongs to a jailbreak app.
314+
static BOOL utrUnitIsJailbreak(void* db, intptr_t unitID)
315+
{
316+
BOOL result = NO;
317+
g_utrBusy++; // keep our own nested DB access out of the filters
318+
unsigned int tid = utrTypeTableID();
319+
if (tid) {
320+
void* ctx = db; // _initWithContext: reads *(void**)ctx (offset 0) == db
321+
_UTDeclaredTypeRecord* rec = [[NSClassFromString(@"_UTDeclaredTypeRecord") alloc]
322+
_initWithContext:(void*)&ctx tableID:tid unitID:(unsigned int)unitID];
323+
result = utrRecordIsFromJailbreakApp(rec);
324+
}
325+
g_utrBusy--;
326+
return result;
327+
}
328+
329+
////////////////////////////////////////////////////////////////////////////////////////////////////////
330+
331+
typedef intptr_t (^UTREnumBlock)(intptr_t a2, intptr_t unitID, const void* unitBytes, void* a5);
332+
%hookf(void, _UTEnumerateTypesForTag, void* db, void* tagClass, void* tag, id block)
333+
{
334+
if (!utrFilterActive() || !block) { %orig; return; }
335+
336+
UTREnumBlock orig = (UTREnumBlock)block;
337+
UTREnumBlock wrapper = ^intptr_t(intptr_t a2, intptr_t unitID, const void* unitBytes, void* a5) {
338+
if (utrUnitIsJailbreak(db, unitID)) return 0; // drop -> continue enumeration, nothing recorded
339+
return orig(a2, unitID, unitBytes, a5); // forward to the original callback
340+
};
341+
%orig(db, tagClass, tag, wrapper);
342+
}
343+
344+
%hookf(void, _UTEnumerateTypesForIdentifier, void* db, long identStrId, id block)
345+
{
346+
if (!utrFilterActive() || !block) { %orig; return; }
347+
348+
UTREnumBlock orig = (UTREnumBlock)block;
349+
UTREnumBlock wrapper = ^intptr_t(intptr_t a2, intptr_t unitID, const void* unitBytes, void* a5) {
350+
if (utrUnitIsJailbreak(db, unitID)) return 0;
351+
return orig(a2, unitID, unitBytes, a5);
352+
};
353+
%orig(db, identStrId, wrapper);
354+
}
355+
356+
typedef void (^UTRConformBlock)(intptr_t unitID, const void* unitBytes, intptr_t kind, unsigned char* outStop);
357+
%hookf(void, _UTTypeSearchConformingTypesWithBlock, void* db, long unitID, long flags, long arg4, id block)
358+
{
359+
if (!utrFilterActive() || !block) { %orig; return; }
360+
361+
UTRConformBlock orig = (UTRConformBlock)block;
362+
UTRConformBlock wrapper = ^void(intptr_t uid, const void* unitBytes, intptr_t kind, unsigned char* outStop) {
363+
if (utrUnitIsJailbreak(db, uid)) return; // drop conforming JB type -> outStop stays 0, keep enumerating
364+
orig(uid, unitBytes, kind, outStop); // forward to the original callback
365+
};
366+
%orig(db, unitID, flags, arg4, wrapper);
367+
}
368+
369+
// parents/forward conformance: filters JB parent types out of related-types (degree>0)
370+
// and out of a record's serialized parentTypeIdentifiers/conformsTo list.
371+
// _UTTypeConformsTo's boolean verdict goes through ...Common (not WithBlock), so it is unaffected.
372+
%hookf(void, _UTTypeSearchConformsToTypesWithBlock, void* db, long unitID, long flags, long arg4, id block)
373+
{
374+
if (!utrFilterActive() || !block) { %orig; return; }
375+
376+
UTRConformBlock orig = (UTRConformBlock)block;
377+
UTRConformBlock wrapper = ^void(intptr_t uid, const void* unitBytes, intptr_t kind, unsigned char* outStop) {
378+
if (utrUnitIsJailbreak(db, uid)) return; // drop conforming-to (parent) JB type -> keep enumerating
379+
orig(uid, unitBytes, kind, outStop); // forward to the original callback
380+
};
381+
%orig(db, unitID, flags, arg4, wrapper);
382+
}
233383

234384

385+
%hookf(void, _LSSchemaCacheRead, void* a1, id block)
386+
{
387+
if (utrFilterActive()) return; // force cache miss -> recompute (filtered)
388+
%orig(a1, block);
389+
}
390+
391+
%hookf(void, _LSSchemaCacheWrite, void* a1, id block)
392+
{
393+
if (utrFilterActive()) return; // don't cache the hidden result
394+
%orig(a1, block);
395+
}
396+
397+
%hook _LSDReadClient
398+
- (void)getTypeRecordWithTag:(id)tag ofClass:(id)_class conformingToIdentifier:(id)identifier completionHandler:(void(^)(id))handler
399+
{
400+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
401+
NSLog(@"[UTType] getTypeRecordWithTag:%@ ofClass:%@ conforming:%@ pid=%d", tag, _class, identifier, utrClientPid(self));
402+
g_utrHide = YES;
403+
%orig;
404+
g_utrHide = NO;
405+
}
406+
407+
- (void)getTypeRecordsWithTag:(id)tag ofClass:(id)_class conformingToIdentifier:(id)identifier completionHandler:(void(^)(id))handler
408+
{
409+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
410+
NSLog(@"[UTType] getTypeRecordsWithTag:%@ ofClass:%@ conforming:%@ pid=%d", tag, _class, identifier, utrClientPid(self));
411+
g_utrHide = YES;
412+
%orig;
413+
g_utrHide = NO;
414+
}
415+
416+
- (void)getTypeRecordWithIdentifier:(id)identifier allowUndeclared:(BOOL)allowUndeclared completionHandler:(void(^)(id))handler
417+
{
418+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
419+
NSLog(@"[UTType] getTypeRecordWithIdentifier:%@ allowUndeclared:%d pid=%d", identifier, allowUndeclared, utrClientPid(self));
420+
g_utrHide = YES;
421+
%orig;
422+
g_utrHide = NO;
423+
}
424+
425+
- (void)getTypeRecordsWithIdentifiers:(id)identifiers completionHandler:(void(^)(id))handler
426+
{
427+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
428+
NSLog(@"[UTType] getTypeRecordsWithIdentifiers:%@ pid=%d", identifiers, utrClientPid(self));
429+
g_utrHide = YES;
430+
%orig;
431+
g_utrHide = NO;
432+
}
433+
434+
- (void)getTypeRecordForImportedTypeWithIdentifier:(id)identifier conformingToIdentifier:(id)conforming completionHandler:(void(^)(id))handler
435+
{
436+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
437+
NSLog(@"[UTType] getTypeRecordForImportedTypeWithIdentifier:%@ conforming:%@ pid=%d", identifier, conforming, utrClientPid(self));
438+
g_utrHide = YES;
439+
%orig;
440+
g_utrHide = NO;
441+
}
442+
443+
- (void)getRelatedTypesOfTypeWithIdentifier:(id)identifier maximumDegreeOfSeparation:(NSInteger)degree completionHandler:(void(^)(id, id))handler
444+
{
445+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
446+
NSLog(@"[UTType] getRelatedTypesOfTypeWithIdentifier:%@ degree:%ld pid=%d", identifier, (long)degree, utrClientPid(self));
447+
g_utrHide = YES;
448+
%orig;
449+
g_utrHide = NO;
450+
}
451+
452+
- (void)getWhetherTypeIdentifier:(id)identifier conformsToTypeIdentifier:(id)other completionHandler:(void(^)(id))handler
453+
{
454+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
455+
NSLog(@"[UTType] getWhetherTypeIdentifier:%@ conformsToTypeIdentifier:%@ pid=%d", identifier, other, utrClientPid(self));
456+
g_utrHide = YES;
457+
%orig;
458+
g_utrHide = NO;
459+
}
460+
461+
- (void)getResourceValuesForKeys:(id)keys URL:(id)url preferredLocalizations:(id)locs completionHandler:(void(^)(id, id, id))handler
462+
{
463+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
464+
NSLog(@"[UTType] getResourceValuesForKeys:%@ URL:%@ pid=%d", keys, url, utrClientPid(self));
465+
g_utrHide = YES;
466+
%orig;
467+
g_utrHide = NO;
468+
}
469+
470+
- (void)getBoundIconInfoForDocumentProxy:(id)documentProxy completionHandler:(void(^)(id, id))handler
471+
{
472+
if (!utrHideClientBlacklisted(self)) { %orig; return; }
473+
NSLog(@"[UTType] getBoundIconInfoForDocumentProxy:%@ pid=%d", documentProxy, utrClientPid(self));
474+
g_utrHide = YES;
475+
%orig;
476+
g_utrHide = NO;
477+
}
478+
%end //%hook _LSDReadClient
479+
480+
%end // %group UTTypeHooks
481+
235482
%hook _LSQueryContext
236483

237-
-(NSMutableDictionary*)_resolveQueries:(NSMutableSet*)queries XPCConnection:(NSXPCConnection*)connection error:(NSError*)err
484+
@interface LSPlugInQueryWithUnits : NSObject
485+
-(id)initWithPlugInUnits:(id)units forDatabaseWithUUID:(id)dbUUID;
486+
@end
487+
488+
@interface _LSQueryContext : NSObject
489+
-(NSMutableDictionary*)_resolveQueries:(NSMutableSet*)queries XPCConnection:(NSXPCConnection*)connection error:(NSError**)perror;
490+
@end
491+
492+
-(NSMutableDictionary*)_resolveQueries:(NSMutableSet*)queries XPCConnection:(NSXPCConnection*)connection error:(NSError**)perror
238493
{
239494
NSMutableDictionary* result = %orig;
240495
/*
@@ -317,7 +572,7 @@ static const void *kBlockSchemeTagKey = &kBlockSchemeTagKey;
317572
NSArray* _pluginUnits = [unitsResult valueForKey:@"_pluginUnits"];
318573
NSLog(@"LSPlugInQueryAllUnits: _dbUUID=%@, _pluginUnits count=%ld", _dbUUID, _pluginUnits.count);
319574
id unitQuery = [[NSClassFromString(@"LSPlugInQueryWithUnits") alloc] initWithPlugInUnits:_pluginUnits forDatabaseWithUUID:_dbUUID];
320-
NSMutableDictionary* queriesResult = [self _resolveQueries:[NSSet setWithObject:unitQuery] XPCConnection:connection error:err];
575+
NSMutableDictionary* queriesResult = [self _resolveQueries:[NSSet setWithObject:unitQuery].mutableCopy XPCConnection:connection error:perror];
321576
if(queriesResult)
322577
{
323578
for(id queryKey in queriesResult)
@@ -334,7 +589,7 @@ static const void *kBlockSchemeTagKey = &kBlockSchemeTagKey;
334589
return result;
335590
}
336591

337-
%end
592+
%end //%hook _LSQueryContext
338593

339594

340595
//or -[Copier initWithSourceURL:uniqueIdentifier:destURL:callbackTarget:selector:options:] in transitd
@@ -397,5 +652,17 @@ void lsdInit(void)
397652
MSHookFunction(_LSServer_RebuildApplicationDatabases, (void *)&new_LSServer_RebuildApplicationDatabases, (void **)&orig_LSServer_RebuildApplicationDatabases);
398653
}
399654

655+
void* _LSSchemaCacheRead = MSFindSymbol(coreServicesImage, "__LSSchemaCacheRead");
656+
void* _LSSchemaCacheWrite = MSFindSymbol(coreServicesImage, "__LSSchemaCacheWrite");
657+
void* _UTEnumerateTypesForTag = MSFindSymbol(coreServicesImage, "__UTEnumerateTypesForTag");
658+
void* _UTEnumerateTypesForIdentifier = MSFindSymbol(coreServicesImage, "__UTEnumerateTypesForIdentifier");
659+
void* _UTTypeSearchConformingTypesWithBlock = MSFindSymbol(coreServicesImage, "__UTTypeSearchConformingTypesWithBlock");
660+
void* _UTTypeSearchConformsToTypesWithBlock = MSFindSymbol(coreServicesImage, "__UTTypeSearchConformsToTypesWithBlock");
661+
if(_LSSchemaCacheRead && _LSSchemaCacheWrite && _UTEnumerateTypesForTag && _UTEnumerateTypesForIdentifier && _UTTypeSearchConformingTypesWithBlock && _UTTypeSearchConformsToTypesWithBlock)
662+
{
663+
NSLog(@"UTTypeHooks: installing");
664+
%init(UTTypeHooks, _LSSchemaCacheRead=_LSSchemaCacheRead, _LSSchemaCacheWrite=_LSSchemaCacheWrite, _UTEnumerateTypesForTag=_UTEnumerateTypesForTag, _UTEnumerateTypesForIdentifier=_UTEnumerateTypesForIdentifier, _UTTypeSearchConformingTypesWithBlock=_UTTypeSearchConformingTypesWithBlock, _UTTypeSearchConformsToTypesWithBlock=_UTTypeSearchConformsToTypesWithBlock);
665+
}
666+
400667
%init();
401668
}

0 commit comments

Comments
 (0)