Skip to content

Commit

Permalink
Add new libkrw plugin, add libroot, ensure these are installed every …
Browse files Browse the repository at this point in the history
…jailbreak
  • Loading branch information
opa334 committed Feb 4, 2024
1 parent 813c479 commit 9a4bef6
Show file tree
Hide file tree
Showing 20 changed files with 647 additions and 29 deletions.
14 changes: 9 additions & 5 deletions Application/Dopamine.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
8C4ABEB62B52094100B43C9B /* libjailbreak.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CDD08422B4F6DD800A32B61 /* libjailbreak.dylib */; };
8C4ABEB92B520E7B00B43C9B /* libjailbreak.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CDD08422B4F6DD800A32B61 /* libjailbreak.dylib */; platformFilter = ios; };
8C4ABEBE2B52274300B43C9B /* PreferenceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C4ABEBD2B52274300B43C9B /* PreferenceManager.m */; };
8C512B902B5C9F8F00C6F14A /* libjbdrw.deb in Resources */ = {isa = PBXBuildFile; fileRef = 8C512B8A2B5C9DE800C6F14A /* libjbdrw.deb */; };
8C512B912B5C9F9100C6F14A /* sileo.deb in Resources */ = {isa = PBXBuildFile; fileRef = 8C512B8B2B5C9DE800C6F14A /* sileo.deb */; };
8C512B922B5C9F9400C6F14A /* zebra.deb in Resources */ = {isa = PBXBuildFile; fileRef = 8C512B8C2B5C9DE800C6F14A /* zebra.deb */; };
8C71981A2ABF0E82003C6658 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C7198192ABF0E82003C6658 /* AppDelegate.m */; };
Expand All @@ -63,6 +62,8 @@
8CB94F052B59E17A0098BAFD /* basebin.tar in Resources */ = {isa = PBXBuildFile; fileRef = 8CB94F032B59E17A0098BAFD /* basebin.tar */; };
8CC139822B53DE6C00230143 /* NSData+Hex.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CC139812B53DE6C00230143 /* NSData+Hex.m */; };
8CC139832B53E05300230143 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CDD08372B4F682500A32B61 /* IOKit.framework */; };
8CCD8A872B6F16CC004B72B0 /* libkrw-plugin.deb in Resources */ = {isa = PBXBuildFile; fileRef = 8CCD8A852B6F1662004B72B0 /* libkrw-plugin.deb */; };
8CCD8A882B6F16D0004B72B0 /* libroot.deb in Resources */ = {isa = PBXBuildFile; fileRef = 8CCD8A832B6F165A004B72B0 /* libroot.deb */; };
8CDD07AA2B4F619000A32B61 /* kfd.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CDD07A92B4F619000A32B61 /* kfd.h */; settings = {ATTRIBUTES = (Public, ); }; };
8CDD07AF2B4F619000A32B61 /* kfd.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8CDD07A72B4F619000A32B61 /* kfd.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
8CDD08342B4F63E100A32B61 /* kfd.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CDD07B32B4F639100A32B61 /* kfd.m */; };
Expand Down Expand Up @@ -184,7 +185,6 @@
8C46D7262B58A029002899DB /* tar.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = tar.dylib; path = Dopamine/Dependencies/tar.dylib; sourceTree = "<group>"; };
8C4ABEBC2B52274300B43C9B /* PreferenceManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PreferenceManager.h; sourceTree = "<group>"; };
8C4ABEBD2B52274300B43C9B /* PreferenceManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PreferenceManager.m; sourceTree = "<group>"; };
8C512B8A2B5C9DE800C6F14A /* libjbdrw.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libjbdrw.deb; sourceTree = "<group>"; };
8C512B8B2B5C9DE800C6F14A /* sileo.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = sileo.deb; sourceTree = "<group>"; };
8C512B8C2B5C9DE800C6F14A /* zebra.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = zebra.deb; sourceTree = "<group>"; };
8C7198152ABF0E82003C6658 /* Dopamine.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Dopamine.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand All @@ -207,6 +207,8 @@
8CB94F032B59E17A0098BAFD /* basebin.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; name = basebin.tar; path = ../../../BaseBin/basebin.tar; sourceTree = "<group>"; };
8CC139802B53DE6C00230143 /* NSData+Hex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Hex.h"; sourceTree = "<group>"; };
8CC139812B53DE6C00230143 /* NSData+Hex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Hex.m"; sourceTree = "<group>"; };
8CCD8A832B6F165A004B72B0 /* libroot.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libroot.deb; path = ../../../Packages/libroot/libroot.deb; sourceTree = "<group>"; };
8CCD8A852B6F1662004B72B0 /* libkrw-plugin.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libkrw-plugin.deb"; path = "../../../Packages/libkrw-provider/libkrw-plugin.deb"; sourceTree = "<group>"; };
8CDD07A72B4F619000A32B61 /* kfd.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = kfd.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8CDD07A92B4F619000A32B61 /* kfd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kfd.h; sourceTree = "<group>"; };
8CDD07B32B4F639100A32B61 /* kfd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = kfd.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -502,9 +504,10 @@
children = (
8CB94F032B59E17A0098BAFD /* basebin.tar */,
8CB94F022B59E17A0098BAFD /* basebin.tc */,
8C512B8A2B5C9DE800C6F14A /* libjbdrw.deb */,
8C512B8B2B5C9DE800C6F14A /* sileo.deb */,
8C512B8C2B5C9DE800C6F14A /* zebra.deb */,
8CCD8A852B6F1662004B72B0 /* libkrw-plugin.deb */,
8CCD8A832B6F165A004B72B0 /* libroot.deb */,
);
path = Resources;
sourceTree = "<group>";
Expand Down Expand Up @@ -722,9 +725,10 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8C512B922B5C9F9400C6F14A /* zebra.deb in Resources */,
8C512B912B5C9F9100C6F14A /* sileo.deb in Resources */,
8C512B902B5C9F8F00C6F14A /* libjbdrw.deb in Resources */,
8C512B922B5C9F9400C6F14A /* zebra.deb in Resources */,
8CCD8A872B6F16CC004B72B0 /* libkrw-plugin.deb in Resources */,
8CCD8A882B6F16D0004B72B0 /* libroot.deb in Resources */,
8CB94F052B59E17A0098BAFD /* basebin.tar in Resources */,
8CB94F042B59E17A0098BAFD /* basebin.tc in Resources */,
8C7198282ABF0E84003C6658 /* LaunchScreen.storyboard in Resources */,
Expand Down
1 change: 0 additions & 1 deletion Application/Dopamine/Jailbreak/Bootstrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ NS_ASSUME_NONNULL_BEGIN
}

- (void)prepareBootstrapWithCompletion:(void (^)(NSError *))completion;
- (BOOL)needsFinalize;
- (NSError *)finalizeBootstrap;

@end
Expand Down
76 changes: 59 additions & 17 deletions Application/Dopamine/Jailbreak/Bootstrapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#import <dlfcn.h>
#import <sys/stat.h>

#define LIBKRW_DOPAMINE_BUNDLED_VERSION @"2.0.0"
#define LIBROOT_DOPAMINE_BUNDLED_VERSION @"1.0.0"

struct hfs_mount_args {
char *fspec;
uid_t hfs_uid; /* uid that owns hfs files (standard HFS only) */
Expand Down Expand Up @@ -523,31 +526,70 @@ - (void)prepareBootstrapWithCompletion:(void (^)(NSError *))completion
}
}

- (BOOL)needsFinalize
- (int)installPackage:(NSString *)packagePath
{
return exec_cmd_trusted(JBRootPath("/usr/bin/dpkg"), "-i", packagePath.fileSystemRepresentation, NULL);
}

- (int)uninstallPackageWithIdentifier:(NSString *)identifier
{
return exec_cmd_trusted(JBRootPath("/usr/bin/dpkg"), "-r", identifier.UTF8String, NULL);
}

- (NSString *)installedVersionForPackageWithIdentifier:(NSString *)identifier
{
return [[NSFileManager defaultManager] fileExistsAtPath:NSJBRootPath(@"/prep_bootstrap.sh")];
NSString *dpkgStatus = [NSString stringWithContentsOfFile:NSJBRootPath(@"/var/lib/dpkg/status") encoding:NSUTF8StringEncoding error:nil];
NSString *packageStartLine = [NSString stringWithFormat:@"Package: %@", identifier];

NSArray *packageInfos = [dpkgStatus componentsSeparatedByString:@"\n\n"];
for (NSString *packageInfo in packageInfos) {
if ([packageInfo hasPrefix:packageStartLine]) {
__block NSString *version = nil;
[packageInfo enumerateLinesUsingBlock:^(NSString * _Nonnull line, BOOL * _Nonnull stop) {
if ([line hasPrefix:@"Version: "]) {
version = [line substringFromIndex:9];
}
}];
return version;
}
}
return nil;
}

- (NSError *)finalizeBootstrap
{
int r = exec_cmd_trusted(JBRootPath("/bin/sh"), JBRootPath("/prep_bootstrap.sh"), NULL);
if (r != 0) {
return [NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedFinalising userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"prep_bootstrap.sh returned %d\n", r]}];
// Initial setup on first jailbreak
if ([[NSFileManager defaultManager] fileExistsAtPath:NSJBRootPath(@"/prep_bootstrap.sh")]) {
int r = exec_cmd_trusted(JBRootPath("/bin/sh"), JBRootPath("/prep_bootstrap.sh"), NULL);
if (r != 0) {
return [NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedFinalising userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"prep_bootstrap.sh returned %d\n", r]}];
}

NSString *sileoPath = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"sileo.deb"];
NSString *zebraPath = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"zebra.deb"];

if (true) { // TODO: pref (sileo)
int r = [self installPackage:sileoPath];
if (r != 0) return [NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedFinalising userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Failed to install Sileo: %d\n", r]}];
}
if (true) { // TODO: pref (zebra)
int r = [self installPackage:zebraPath];
if (r != 0) return [NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedFinalising userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Failed to install Zebra: %d\n", r]}];
}
}

NSString *sileoPath = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"sileo.deb"];
NSString *zebraPath = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"zebra.deb"];
NSString *krwPath = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"libjbdrw.deb"];

NSArray *toInstall = @[
sileoPath,
zebraPath,
krwPath,
];
NSString *librootInstalledVersion = [self installedVersionForPackageWithIdentifier:@"libroot-dopamine"];
if (!librootInstalledVersion || ![librootInstalledVersion isEqualToString:LIBROOT_DOPAMINE_BUNDLED_VERSION]) {
NSString *librootPath = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"libroot.deb"];
int r = [self installPackage:librootPath];
if (r != 0) return [NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedFinalising userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Failed to install libroot: %d\n", r]}];
}

for (NSString *path in toInstall) {
r = exec_cmd_trusted(JBRootPath("/usr/bin/dpkg"), "-i", path.fileSystemRepresentation, NULL);
if (r != 0) return [NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedFinalising userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Failed to install %@: %d\n", path.lastPathComponent, r]}];
NSString *libkrwDopamineInstalledVersion = [self installedVersionForPackageWithIdentifier:@"libkrw0-dopamine"];
if (!libkrwDopamineInstalledVersion || ![libkrwDopamineInstalledVersion isEqualToString:LIBKRW_DOPAMINE_BUNDLED_VERSION]) {
NSString *libkrwPath = [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"libkrw-plugin.deb"];
int r = [self installPackage:libkrwPath];
if (r != 0) return [NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedFinalising userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Failed to install the libkrw plugin: %d\n", r]}];
}

return nil;
Expand Down
6 changes: 1 addition & 5 deletions Application/Dopamine/Jailbreak/EnvironmentManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,7 @@ - (NSError *)prepareBootstrap

- (NSError *)finalizeBootstrap
{
if (_bootstrapper.needsFinalize) {
printf("Bootstrap needs finalize... Finalizing!\n");
return [_bootstrapper finalizeBootstrap];
}
return nil;
return [_bootstrapper finalizeBootstrap];
}

@end
2 changes: 1 addition & 1 deletion Application/Dopamine/Jailbreak/Jailbreaker.m
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ - (NSError *)createFakeLib

cdhash_t *cdhashes;
uint32_t cdhashesCount;
macho_collect_untrusted_cdhashes(JBRootPath("/basebin/.fakelib/dyld"), NULL, &cdhashes, &cdhashesCount);
macho_collect_untrusted_cdhashes(JBRootPath("/basebin/.fakelib/dyld"), NULL, NULL, &cdhashes, &cdhashesCount);
if (cdhashesCount != 1) return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedInitFakeLib userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Got unexpected number of cdhashes for dyld???: %d", cdhashesCount]}];

trustcache_file_v1 *dyldTCFile = NULL;
Expand Down
Binary file removed Application/Dopamine/Resources/libjbdrw.deb
Binary file not shown.
97 changes: 97 additions & 0 deletions BaseBin/_external/include/libkrw/libkrw_plugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#ifndef LIBKRW_PLUGIN_H
#define LIBKRW_PLUGIN_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>
#include <stdint.h>

/**
* libkrw - Library for kernel read/write
*
* The purpose of this library is to provide a standard interface for common
* kernel memory operations. Subsets of those have historically been exported
* by most jailbreaks, but the provided interfaces are increasingly shifting,
* thus calling for a standard interface.
*
* It is understood that hardly any jailbreak provides the necessary primitives
* to implement ALL of the below functions. Thus, an implementer of this API
* is free to implement any subset of their choosing, even an empty one, and
* simply "stub" the remaining functions to return `ENOTSUP` unconditionally.
*
* All functions imported by this library are expected to return an `int` status
* code, where:
* - The value `0` indicates success.
* - The values `1` through `255` indicate failure and correspond to their
* definitions in <errno.h> (or are reserved, if no such definition exists).
* - All other return values are implementation-defined, but indicate failure.
*
* Notable conditions where values from <errno.h> should be used include:
* - `EPERM` The requested operation requires root, an entitlement, or some
* other form of elevated privileges.
* - `EINVAL` An invalid argument was provided to the function.
* - `EDEVERR` The requested operation is supported in this implementation, but
* could not be completed for some reason.
* - `ENOTSUP` The requested operation is not supported in this implementation.
*
* Further shall be noted that due to the inherently unsafe nature of direct
* kernel memory accesses, functions that take kernel addresses as arguments
* from the caller may panic the kernel, and implementers of this interface may
* choose to defend against that, but are not expected to do so. They ARE
* however expected to defend against causing kernel panics in functions that do
* NOT take kernel addresses as arguments.
**/

typedef int (*krw_kbase_func_t)(uint64_t *addr);
typedef int (*krw_kread_func_t)(uint64_t from, void *to, size_t len);
typedef int (*krw_kwrite_func_t)(void *from, uint64_t to, size_t len);
typedef int (*krw_kmalloc_func_t)(uint64_t *addr, size_t size);
typedef int (*krw_kdealloc_func_t)(uint64_t addr, size_t size);
typedef int (*krw_kcall_func_t)(uint64_t func, size_t argc, const uint64_t *argv, uint64_t *ret);
typedef int (*krw_physread_func_t)(uint64_t from, void *to, size_t len, uint8_t granule);
typedef int (*krw_physwrite_func_t)(void *from, uint64_t to, size_t len, uint8_t granule);

// This struct must only be extended so that old plugins can still load
#define LIBKRW_HANDLERS_VERSION 0
struct krw_handlers_s {
uint64_t version;
krw_kbase_func_t kbase;
krw_kread_func_t kread;
krw_kwrite_func_t kwrite;
krw_kmalloc_func_t kmalloc;
krw_kdealloc_func_t kdealloc;
krw_kcall_func_t kcall;
krw_physread_func_t physread;
krw_physwrite_func_t physwrite;
};

typedef struct krw_handlers_s* krw_handlers_t;

/**
* krw_initializer_t - plugin initialization prototype
*
* Called krw_initializer_t krw_initializer is called when a plugin is opened to
* determine if read/write primitives are available
*
* krw_initializer should set as many of handlers->kread, handlers->kwrite, handlers->kbase,
* handlers->kmalloc, and handlers->kdealloc as possible on success - any not set will
* return unsupported.
*
* Called krw_initializer_t kcall_initializer is called when a plugin is opened to
* determine if read/write primitives are available. It is passed a structure containing
* populated kread/kwrite functions
*
* kcall_initializer should set as many of handlers->kcall, handlers->physread, and
* handlers->physwrite as possible on success. any not set will return unsupported.
*
* Retuns 0 if read/write are supported by this plugin
**/
typedef int (*krw_plugin_initializer_t)(krw_handlers_t handlers);

#ifdef __cplusplus
}
#endif

#endif
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
all:
@$(MAKE) -C BaseBin
@$(MAKE) -C Packages
@$(MAKE) -C Application

clean:
@$(MAKE) -C BaseBin clean
@$(MAKE) -C Packages clean
@$(MAKE) -C Application clean

update: all
Expand Down
2 changes: 2 additions & 0 deletions Packages/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
libkrw-provider/libkrw-plugin.*
libroot/libroot.*
9 changes: 9 additions & 0 deletions Packages/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
all:
@$(MAKE) -C libkrw-provider package
@$(MAKE) -C libroot package

clean:
@$(MAKE) -C libkrw-provider clean
@$(MAKE) -C libroot clean

.PHONY: clean
25 changes: 25 additions & 0 deletions Packages/libkrw-provider/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
TARGET = libkrw-plugin.dylib
CC = clang

CFLAGS = -I../../BaseBin/.include -Isrc -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -arch arm64 -arch arm64e -miphoneos-version-min=15.0 -fobjc-arc -O2
LDFLAGS = -dynamiclib -rpath /var/jb -L. -ljailbreak

all: $(TARGET) sign

sign: $(TARGET)
@ldid -S $^

$(TARGET): $(wildcard src/*.c)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

clean:
@rm -f $(TARGET)
@rm -f libkrw-plugin.deb

package: $(TARGET)
@mkdir -p .package/DEBIAN
@mkdir -p .package/var/jb/usr/lib/libkrw
@cp control .package/DEBIAN/control
@cp libkrw-plugin.dylib .package/var/jb/usr/lib/libkrw/libkrw-plugin.dylib
@dpkg-deb --root-owner-group -Zzstd -b .package ./libkrw-plugin.deb
@rm -rf .package
12 changes: 12 additions & 0 deletions Packages/libkrw-provider/control
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Package: libkrw0-dopamine
Name: libkrw Plug-in (Dopamine)
Author: opa334 <opa334@protonmail.com>
Maintainer: opa334 <opa334@protonmail.com>
Architecture: iphoneos-arm64
Version: 2.0.0
Provides: libkrw0-plugin
Depends: libiosexec1 (>= 1.3.1), libkrw0
Section: Libraries
Priority: standard
Homepage: https://github.com/opa334/Dopamine/tree/main/Packages/libkrw-provider
Description: libkrw Plug-in for Dopamine (Shared Library)
Loading

0 comments on commit 9a4bef6

Please sign in to comment.