├── .gitattributes ├── .gitignore ├── ChOma-main ├── .gitignore ├── .vscode │ └── settings.json ├── Makefile ├── README.md ├── cert.p12 ├── external │ └── ios │ │ ├── entitlements.plist │ │ └── libcrypto.a ├── src │ ├── Base64.c │ ├── Base64.h │ ├── BufferedStream.c │ ├── BufferedStream.h │ ├── CSBlob.c │ ├── CSBlob.h │ ├── CodeDirectory.c │ ├── CodeDirectory.h │ ├── FAT.c │ ├── FAT.h │ ├── FileStream.c │ ├── FileStream.h │ ├── Host.c │ ├── Host.h │ ├── MachO.c │ ├── MachO.h │ ├── MachOByteOrder.h │ ├── MachOLoadCommand.c │ ├── MachOLoadCommand.h │ ├── MemoryStream.c │ ├── MemoryStream.h │ ├── PatchFinder.c │ ├── PatchFinder.h │ ├── SignOSSL.c │ ├── SignOSSL.h │ ├── Util.c │ └── Util.h └── tests │ ├── choma_cli │ └── main.c │ ├── ct_bypass │ ├── AppStoreCodeDirectory.h │ ├── DecryptedSignature.h │ ├── PrivateKey.h │ ├── TemplateSignatureBlob.h │ └── main.c │ ├── fat_create │ └── main.c │ └── kpf │ └── main.c ├── LICENSE ├── README.md ├── bootstrap.entitlements ├── bootstrap ├── .gitignore ├── .vscode │ └── settings.json ├── Makefile ├── assert.h ├── autosign.m ├── bootstrap.c ├── common.c ├── common.h ├── common.m ├── control ├── dobby.h ├── envbuf.c ├── envbuf.h ├── exechook.c ├── fishhook.c ├── fishhook.h ├── fixfork.c ├── fixsuid.c ├── interpose.c ├── layout │ └── DEBIAN │ │ └── preinst ├── libdobby.a ├── libproc.h ├── libproc_private.h ├── platformhook.m ├── prefshook.m ├── prefshook.rtf ├── sandbox.h └── syscall.S ├── bootstrapd ├── .gitignore ├── .vscode │ └── settings.json ├── Makefile ├── assert.h ├── bootstrapd.h ├── common.h ├── control ├── entitlements.plist ├── envbuf.c ├── envbuf.h ├── ipc.h ├── ipc.m ├── jiter.m ├── libbsd.h ├── libbsd.m ├── libproc.h ├── libproc_private.h ├── main.m ├── openssh.m ├── usreboot.m ├── varClean.m └── xpc │ ├── XPC.apinotes │ ├── activity.h │ ├── availability.h │ ├── base.h │ ├── connection.h │ ├── debug.h │ ├── endpoint.h │ ├── module.modulemap │ ├── private.h │ └── xpc.h ├── copy.sh ├── devtest ├── .gitignore ├── Makefile ├── control ├── entitlements.plist └── main.m ├── entitlements ├── com.apple.mobilemail.extra ├── com.apple.mobilemail.strip ├── com.apple.mobilesafari.extra ├── com.apple.mobilesafari.strip ├── com.apple.mobileslideshow.extra └── com.apple.mobileslideshow.photo-picker.extra ├── fastPathSign ├── .gitignore ├── Makefile ├── roothide.xml └── src │ ├── Templates │ ├── AppStoreCodeDirectory.h │ ├── DecryptedSignature.h │ ├── PrivateKey.h │ └── SignatureBlob.h │ ├── codesign.h │ ├── codesign.m │ ├── codesign.o │ ├── coretrust_bug.c │ ├── coretrust_bug.h │ ├── coretrust_bug.o │ ├── external │ ├── .gitignore │ ├── include │ │ └── choma │ └── lib │ │ ├── libchoma.a │ │ └── libcrypto.a │ ├── main.m │ └── main.o ├── ldid ├── .github │ └── workflows │ │ └── build.yml ├── .gitignore ├── COPYING ├── Makefile ├── README.md ├── _ldid ├── docs │ ├── ldid.1 │ ├── ldid.zh_CN.1 │ └── ldid.zh_TW.1 ├── ldid.cpp ├── ldid.hpp ├── libcrypto.a ├── libplist-2.0.a ├── machine.h └── roothide.xml ├── nickchan.entitlements ├── preload ├── .gitignore ├── Makefile ├── control ├── entitlements.plist ├── layout │ └── DEBIAN │ │ └── postinst ├── prelib.m ├── preload.m └── sandbox.h ├── rebuild.sh ├── rebuildapp ├── .gitignore ├── .vscode │ └── settings.json ├── Makefile ├── Templates │ ├── AppStoreCodeDirectory.h │ ├── DecryptedSignature.h │ ├── PrivateKey.h │ └── SignatureBlob.h ├── choma ├── control ├── entitlements.plist ├── layout │ └── basebin │ │ └── rebuildapps.sh ├── libchoma.a ├── libcrypto.a ├── libplist-2.0.a ├── main.m └── realstore.cpp ├── test.sh └── uicache ├── .gitignore ├── .vscode └── settings.json ├── Makefile ├── choma ├── control ├── entitlements.plist ├── exepatch.c ├── libchoma.a └── main.m /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | installdeb2 3 | -------------------------------------------------------------------------------- /ChOma-main/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all 2 | * 3 | 4 | # Unignore all with extensions 5 | !*.* 6 | 7 | # Unignore Makefile 8 | !Makefile 9 | 10 | # Unignore all dirs 11 | !*/ 12 | 13 | # Ignore build/ 14 | build/ 15 | output/ 16 | data/ 17 | 18 | # Ignore .DS_Store 19 | .DS_Store 20 | 21 | # Ignore .vscode/ 22 | .vscode/* 23 | !.vscode/settings.json 24 | 25 | # Ignore nocommit-* files and dirs 26 | nocommit-* 27 | 28 | # Ignore Python scripts 29 | *.py 30 | 31 | # Miscellaneous 32 | ca.key 33 | *.tipa 34 | *.zip 35 | *.ipa 36 | *.app 37 | Payload/ -------------------------------------------------------------------------------- /ChOma-main/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.default.compilerPath": "/usr/bin/clang", 3 | "clangd.fallbackFlags": [ 4 | "-I${workspaceFolder}/src/external", 5 | "-I${workspaceFolder}/output/include", 6 | "-I/opt/homebrew/Cellar/openssl@3/3.1.3/include", 7 | ], 8 | "files.associations": { 9 | "*.ejs": "html", 10 | "codedirectory.h": "c", 11 | "templatesignatureblob.h": "c", 12 | "loader.h": "c", 13 | "__hash_table": "c", 14 | "__split_buffer": "c", 15 | "array": "c", 16 | "bitset": "c", 17 | "initializer_list": "c", 18 | "span": "c", 19 | "string": "c", 20 | "string_view": "c", 21 | "unordered_map": "c", 22 | "vector": "c", 23 | "macho.h": "c", 24 | "host.h": "c" 25 | } 26 | } -------------------------------------------------------------------------------- /ChOma-main/Makefile: -------------------------------------------------------------------------------- 1 | CC := clang 2 | CFLAGS := -Wall -Werror $(shell pkg-config --cflags libcrypto) -fPIC -Wno-pointer-to-int-cast -Wno-unused-command-line-argument -Wno-deprecated-declarations -Wno-unused-variable -framework CoreFoundation 3 | DEBUG ?= 0 4 | ifeq ($(DEBUG), 1) 5 | CFLAGS += -fsanitize=address -static-libsan 6 | endif 7 | 8 | LIB_NAME := libchoma 9 | 10 | ifeq ($(TARGET), ios) 11 | BUILD_DIR := build/ios 12 | OUTPUT_DIR := output/ios 13 | CFLAGS += -arch arm64 -arch arm64e -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -miphoneos-version-min=14.0 external/ios/libcrypto.a 14 | else 15 | BUILD_DIR := build 16 | OUTPUT_DIR := output 17 | CFLAGS += $(shell pkg-config --libs libcrypto) 18 | endif 19 | 20 | SRC_DIR := src 21 | 22 | HEADER_OUTPUT_DIR := $(OUTPUT_DIR)/include 23 | TESTS_SRC_DIR := tests 24 | TESTS_BUILD_DIR := $(BUILD_DIR)/tests 25 | TESTS_OUTPUT_DIR := $(OUTPUT_DIR)/tests 26 | 27 | LIB_DIR := $(OUTPUT_DIR)/lib 28 | TESTS_DIR := build/tests 29 | 30 | STATIC_LIB := $(LIB_DIR)/$(LIB_NAME).a 31 | DYNAMIC_LIB := $(LIB_DIR)/$(LIB_NAME).dylib 32 | 33 | SRC_FILES := $(wildcard $(SRC_DIR)/*.c) 34 | OBJ_FILES := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRC_FILES)) 35 | 36 | TESTS_SUBDIRS := $(wildcard $(TESTS_SRC_DIR)/*) 37 | TESTS_BINARIES := $(patsubst $(TESTS_SRC_DIR)/%,$(TESTS_OUTPUT_DIR)/%,$(TESTS_SUBDIRS)) 38 | 39 | CHOMA_HEADERS_SRC_DIR := $(SRC_DIR) 40 | CHOMA_HEADERS_DST_DIR := $(HEADER_OUTPUT_DIR)/choma 41 | 42 | CHOMA_HEADERS := $(shell find $(CHOMA_HEADERS_SRC_DIR) -type f -name "*.h") 43 | 44 | all: $(STATIC_LIB) $(DYNAMIC_LIB) copy-choma-headers clean-test $(TESTS_BINARIES) 45 | 46 | $(STATIC_LIB): $(OBJ_FILES) 47 | @mkdir -p $(LIB_DIR) 48 | ar rcs $@ $^ 49 | 50 | $(DYNAMIC_LIB): $(OBJ_FILES) 51 | @mkdir -p $(LIB_DIR) 52 | $(CC) $(CFLAGS) -shared -o $@ $^ 53 | 54 | $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c 55 | @mkdir -p $(dir $@) 56 | $(CC) $(CFLAGS) -c $< -o $@ 57 | 58 | ifeq ($(TARGET), ios) 59 | $(TESTS_OUTPUT_DIR)/%: $(TESTS_SRC_DIR)/% 60 | @mkdir -p $(dir $@) 61 | @rm -rf $@ 62 | $(CC) $(CFLAGS) -I$(OUTPUT_DIR)/include -o $@ $ 2 | 3 | 4 | 5 | platform-application 6 | 7 | com.apple.private.security.no-container 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ChOma-main/external/ios/libcrypto.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/ChOma-main/external/ios/libcrypto.a -------------------------------------------------------------------------------- /ChOma-main/src/Base64.c: -------------------------------------------------------------------------------- 1 | #include "Base64.h" 2 | 3 | // https://stackoverflow.com/a/6782480 4 | static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 5 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 6 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 7 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 8 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 9 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 10 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', 11 | '4', '5', '6', '7', '8', '9', '+', '/'}; 12 | static int mod_table[] = {0, 2, 1}; 13 | 14 | 15 | char *base64_encode(const unsigned char *data, 16 | size_t input_length, 17 | size_t *output_length) { 18 | 19 | *output_length = 4 * ((input_length + 2) / 3); 20 | 21 | char *encoded_data = malloc(*output_length); 22 | if (encoded_data == NULL) return NULL; 23 | 24 | for (int i = 0, j = 0; i < input_length;) { 25 | 26 | uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0; 27 | uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0; 28 | uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0; 29 | 30 | uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; 31 | 32 | encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F]; 33 | encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F]; 34 | encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F]; 35 | encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F]; 36 | } 37 | 38 | for (int i = 0; i < mod_table[input_length % 3]; i++) 39 | encoded_data[*output_length - 1 - i] = '='; 40 | 41 | return encoded_data; 42 | } -------------------------------------------------------------------------------- /ChOma-main/src/Base64.h: -------------------------------------------------------------------------------- 1 | #ifndef BASE64_H 2 | #define BASE64_H 3 | 4 | #include 5 | #include 6 | 7 | char *base64_encode(const unsigned char *data, 8 | size_t input_length, 9 | size_t *output_length); 10 | 11 | #endif // BASE64_H -------------------------------------------------------------------------------- /ChOma-main/src/BufferedStream.h: -------------------------------------------------------------------------------- 1 | #ifndef BUFFERED_STREAM_H 2 | #define BUFFERED_STREAM_H 3 | 4 | #include "MemoryStream.h" 5 | #include 6 | 7 | #define BUFFERED_STREAM_FLAG_AUTO_EXPAND (1 << 0) 8 | 9 | typedef struct BufferedStreamContext { 10 | uint8_t *buffer; 11 | size_t bufferSize; 12 | uint32_t subBufferStart; 13 | size_t subBufferSize; 14 | } BufferedStreamContext; 15 | 16 | MemoryStream *buffered_stream_init_from_buffer_nocopy(void *buffer, size_t bufferSize, uint32_t flags); 17 | MemoryStream *buffered_stream_init_from_buffer(void *buffer, size_t bufferSize, uint32_t flags); 18 | 19 | #endif // BUFFERED_STREAM_H -------------------------------------------------------------------------------- /ChOma-main/src/CSBlob.h: -------------------------------------------------------------------------------- 1 | #ifndef CS_BLOB_H 2 | #define CS_BLOB_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "FAT.h" 10 | #include "MachO.h" 11 | #include "MemoryStream.h" 12 | 13 | // Blob index 14 | typedef struct __BlobIndex { 15 | uint32_t type; 16 | uint32_t offset; 17 | } CS_BlobIndex; 18 | 19 | // CMS superblob 20 | typedef struct __SuperBlob { 21 | uint32_t magic; 22 | uint32_t length; 23 | uint32_t count; 24 | CS_BlobIndex index[]; 25 | } CS_SuperBlob; 26 | 27 | typedef struct __GenericBlob { 28 | uint32_t magic; /* magic number */ 29 | uint32_t length; /* total length of blob */ 30 | char data[]; 31 | } CS_GenericBlob; 32 | 33 | // CMS blob magic types 34 | enum { 35 | CSMAGIC_REQUIREMENT = 0xfade0c00, 36 | CSMAGIC_REQUIREMENTS = 0xfade0c01, 37 | CSMAGIC_CODEDIRECTORY = 0xfade0c02, 38 | CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0, 39 | CSMAGIC_EMBEDDED_SIGNATURE_OLD = 0xfade0b02, 40 | CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171, 41 | CSMAGIC_EMBEDDED_DER_ENTITLEMENTS = 0xfade7172, 42 | CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1, 43 | CSMAGIC_BLOBWRAPPER = 0xfade0b01, 44 | CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT = 0xfade8181, 45 | } CS_BlobMagic; 46 | 47 | enum { 48 | CSSLOT_CODEDIRECTORY = 0, 49 | CSSLOT_INFOSLOT = 1, 50 | CSSLOT_REQUIREMENTS = 2, 51 | CSSLOT_RESOURCEDIR = 3, 52 | CSSLOT_APPLICATION = 4, 53 | CSSLOT_ENTITLEMENTS = 5, 54 | CSSLOT_DER_ENTITLEMENTS = 7, 55 | CSSLOT_LAUNCH_CONSTRAINT_SELF = 8, 56 | CSSLOT_LAUNCH_CONSTRAINT_PARENT = 9, 57 | CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE = 10, 58 | CSSLOT_LIBRARY_CONSTRAINT = 11, 59 | 60 | CSSLOT_ALTERNATE_CODEDIRECTORIES = 0x1000, /* first alternate CodeDirectory, if any */ 61 | CSSLOT_ALTERNATE_CODEDIRECTORY_MAX = 5, /* max number of alternate CD slots */ 62 | CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT = CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX, /* one past the last */ 63 | 64 | CSSLOT_SIGNATURESLOT = 0x10000, 65 | CSSLOT_IDENTIFICATIONSLOT = 0x10001, 66 | CSSLOT_TICKETSLOT = 0x10002, 67 | } CS_SlotType; 68 | 69 | typedef struct s_CS_DecodedBlob { 70 | struct s_CS_DecodedBlob *next; 71 | uint32_t type; 72 | MemoryStream *stream; 73 | } CS_DecodedBlob; 74 | 75 | typedef struct s_CS_DecodedSuperBlob { 76 | uint32_t magic; 77 | struct s_CS_DecodedBlob *firstBlob; 78 | } CS_DecodedSuperBlob; 79 | 80 | // Convert blob magic to readable blob type string 81 | const char *cs_blob_magic_to_string(uint32_t magic); 82 | const char *cs_slot_type_to_string(uint32_t slotType); 83 | 84 | // Extract Code Signature to file 85 | int macho_extract_cs_to_file(MachO *macho, CS_SuperBlob *superblob); 86 | 87 | int macho_find_code_signature_bounds(MachO *macho, uint32_t *offsetOut, uint32_t *sizeOut); 88 | 89 | CS_SuperBlob *macho_read_code_signature(MachO *macho); 90 | 91 | int macho_replace_code_signature(MachO *macho, CS_SuperBlob *superblob); 92 | 93 | int update_load_commands(MachO *macho, CS_SuperBlob *superblob, uint64_t originalSize); 94 | 95 | CS_DecodedBlob *csd_blob_init(uint32_t type, CS_GenericBlob *blobData); 96 | int csd_blob_read(CS_DecodedBlob *blob, uint64_t offset, size_t size, void *outBuf); 97 | int csd_blob_write(CS_DecodedBlob *blob, uint64_t offset, size_t size, const void *inBuf); 98 | int csd_blob_insert(CS_DecodedBlob *blob, uint64_t offset, size_t size, const void *inBuf); 99 | int csd_blob_delete(CS_DecodedBlob *blob, uint64_t offset, size_t size); 100 | int csd_blob_read_string(CS_DecodedBlob *blob, uint64_t offset, char **outString); 101 | int csd_blob_write_string(CS_DecodedBlob *blob, uint64_t offset, const char *string); 102 | int csd_blob_get_size(CS_DecodedBlob *blob); 103 | uint32_t csd_blob_get_type(CS_DecodedBlob *blob); 104 | void csd_blob_set_type(CS_DecodedBlob *blob, uint32_t type); 105 | void csd_blob_free(CS_DecodedBlob *blob); 106 | 107 | CS_DecodedSuperBlob *csd_superblob_decode(CS_SuperBlob *superblob); 108 | CS_SuperBlob *csd_superblob_encode(CS_DecodedSuperBlob *decodedSuperblob); 109 | CS_DecodedBlob *csd_superblob_find_blob(CS_DecodedSuperBlob *superblob, uint32_t type, uint32_t *indexOut); 110 | int csd_superblob_insert_blob_after_blob(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *blobToInsert, CS_DecodedBlob *afterBlob); 111 | int csd_superblob_insert_blob_at_index(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *blobToInsert, uint32_t atIndex); 112 | int csd_superblob_append_blob(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *blobToAppend); 113 | int csd_superblob_remove_blob(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *blobToRemove); // <- Important: When calling this, caller is responsible for freeing blobToRemove 114 | int csd_superblob_remove_blob_at_index(CS_DecodedSuperBlob *superblob, uint32_t atIndex); 115 | int csd_superblob_print_content(CS_DecodedSuperBlob *decodedSuperblob, MachO *macho, bool printAllSlots, bool verifySlots); 116 | void csd_superblob_free(CS_DecodedSuperBlob *decodedSuperblob); 117 | 118 | 119 | #endif // CS_BLOB_H -------------------------------------------------------------------------------- /ChOma-main/src/CodeDirectory.h: -------------------------------------------------------------------------------- 1 | #ifndef CODE_DIRECTORY_H 2 | #define CODE_DIRECTORY_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "MachO.h" 9 | #include "CSBlob.h" 10 | #include "FAT.h" 11 | #include "MachOByteOrder.h" 12 | #include "MachOLoadCommand.h" 13 | #include "MemoryStream.h" 14 | 15 | 16 | // Code directory blob header 17 | typedef struct __CodeDirectory { 18 | uint32_t magic; 19 | uint32_t length; 20 | uint32_t version; 21 | uint32_t flags; 22 | uint32_t hashOffset; 23 | uint32_t identOffset; 24 | uint32_t nSpecialSlots; 25 | uint32_t nCodeSlots; 26 | uint32_t codeLimit; 27 | uint8_t hashSize; 28 | uint8_t hashType; 29 | uint8_t spare1; 30 | uint8_t pageSize; 31 | uint32_t spare2; 32 | uint32_t scatterOffset; 33 | uint32_t teamOffset; 34 | } CS_CodeDirectory; 35 | 36 | enum CS_HashType { 37 | CS_HASHTYPE_SHA160_160 = 1, 38 | CS_HASHTYPE_SHA256_256 = 2, 39 | CS_HASHTYPE_SHA256_160 = 3, 40 | CS_HASHTYPE_SHA384_384 = 4, 41 | }; 42 | 43 | char *csd_code_directory_copy_identity(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut); 44 | char *csd_code_directory_copy_team_id(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut); 45 | int csd_code_directory_set_team_id(CS_DecodedBlob *codeDirBlob, char *newTeamID); 46 | uint32_t csd_code_directory_get_flags(CS_DecodedBlob *codeDirBlob); 47 | void csd_code_directory_set_flags(CS_DecodedBlob *codeDirBlob, uint32_t flags); 48 | uint8_t csd_code_directory_get_hash_type(CS_DecodedBlob *codeDirBlob); 49 | void csd_code_directory_set_hash_type(CS_DecodedBlob *codeDirBlob, uint8_t hashType); 50 | int csd_code_directory_print_content(CS_DecodedSuperBlob *decodedSuperblob, CS_DecodedBlob *codeDirBlob, MachO *macho, bool printSlots, bool verifySlots); 51 | void csd_code_directory_update(CS_DecodedBlob *codeDirBlob, MachO *macho); 52 | void csd_code_directory_alloc(CS_DecodedBlob *codeDirBlob, MachO *macho); 53 | 54 | #endif // CODE_DIRECTORY_H -------------------------------------------------------------------------------- /ChOma-main/src/FAT.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "FAT.h" 6 | #include "MachO.h" 7 | #include "MachOByteOrder.h" 8 | 9 | #include "FileStream.h" 10 | #include "MemoryStream.h" 11 | 12 | #define LOG(...) 13 | 14 | int fat_read_at_offset(FAT *fat, uint64_t offset, size_t size, void *outBuf) 15 | { 16 | return memory_stream_read(fat->stream, offset, size, outBuf); 17 | } 18 | 19 | MemoryStream *fat_get_stream(FAT *fat) 20 | { 21 | return fat->stream; 22 | } 23 | 24 | int fat_parse_slices(FAT *fat) 25 | { 26 | // Get size of file 27 | size_t fileSize = memory_stream_get_size(fat->stream); 28 | if (fileSize == MEMORY_STREAM_SIZE_INVALID) { 29 | printf("Error: Failed to parse fat slices, memory_stream_get_size returned MEMORY_STREAM_SIZE_INVALID\n"); 30 | return -1; 31 | } 32 | 33 | // Read the FAT header 34 | struct fat_header fatHeader; 35 | fat_read_at_offset(fat, 0, sizeof(fatHeader), &fatHeader); 36 | FAT_HEADER_APPLY_BYTE_ORDER(&fatHeader, BIG_TO_HOST_APPLIER); 37 | 38 | // Check if the file is a FAT file 39 | if (fatHeader.magic == FAT_MAGIC || fatHeader.magic == FAT_MAGIC_64) { 40 | LOG("FAT header found! Magic: 0x%x.\n", fatHeader.magic); 41 | bool is64 = fatHeader.magic == FAT_MAGIC_64; 42 | 43 | // Sanity check the number of machOs 44 | if (fatHeader.nfat_arch > 5 || fatHeader.nfat_arch < 1) { 45 | printf("Error: invalid number of MachO slices (%d), this likely means you are not using an iOS MachO.\n", fatHeader.nfat_arch); 46 | return -1; 47 | } 48 | 49 | fat->slicesCount = fatHeader.nfat_arch; 50 | fat->slices = malloc(sizeof(MachO*) * fat->slicesCount); 51 | memset(fat->slices, 0, sizeof(MachO*) * fat->slicesCount); 52 | 53 | // Iterate over all machOs 54 | for (uint32_t i = 0; i < fatHeader.nfat_arch; i++) { 55 | struct fat_arch_64 arch64 = {0}; 56 | if (is64) { 57 | // Read the arch descriptor 58 | fat_read_at_offset(fat, sizeof(struct fat_header) + i * sizeof(arch64), sizeof(arch64), &arch64); 59 | FAT_ARCH_64_APPLY_BYTE_ORDER(&arch64, BIG_TO_HOST_APPLIER); 60 | } 61 | else { 62 | // Read the FAT arch structure 63 | struct fat_arch arch = {0}; 64 | fat_read_at_offset(fat, sizeof(struct fat_header) + i * sizeof(arch), sizeof(arch), &arch); 65 | FAT_ARCH_APPLY_BYTE_ORDER(&arch, BIG_TO_HOST_APPLIER); 66 | 67 | // Convert fat_arch to fat_arch_64 68 | arch64 = (struct fat_arch_64){ 69 | .cputype = arch.cputype, 70 | .cpusubtype = arch.cpusubtype, 71 | .offset = (uint64_t)arch.offset, 72 | .size = (uint64_t)arch.size, 73 | .align = arch.align, 74 | .reserved = 0, 75 | }; 76 | } 77 | 78 | MemoryStream *machOStream = memory_stream_softclone(fat->stream); 79 | int r = memory_stream_trim(machOStream, arch64.offset, fileSize - (arch64.offset + arch64.size)); 80 | if (r == 0) { 81 | fat->slices[i] = macho_init(machOStream, arch64); 82 | } 83 | } 84 | } else { 85 | // Not FAT? Parse single slice 86 | 87 | fat->slicesCount = 1; 88 | fat->slices = malloc(sizeof(MachO) * fat->slicesCount); 89 | memset(fat->slices, 0, sizeof(MachO) * fat->slicesCount); 90 | 91 | MemoryStream *machOStream = memory_stream_softclone(fat->stream); 92 | 93 | struct mach_header_64 machHeader; 94 | memory_stream_read(machOStream, 0, sizeof(machHeader), &machHeader); 95 | MACH_HEADER_APPLY_BYTE_ORDER(&machHeader, LITTLE_TO_HOST_APPLIER); 96 | 97 | struct fat_arch_64 singleArch = {0}; 98 | singleArch.cpusubtype = machHeader.cpusubtype; 99 | singleArch.cputype = machHeader.cputype; 100 | singleArch.offset = 0; 101 | singleArch.size = fileSize; 102 | singleArch.align = 0x4000; 103 | 104 | MachO *singleSlice = macho_init(machOStream, singleArch); 105 | if (!singleSlice) return -1; 106 | fat->slices[0] = singleSlice; 107 | } 108 | LOG("Found %u MachO slices.\n", fat->slicesCount); 109 | return 0; 110 | } 111 | 112 | MachO *fat_find_slice(FAT *fat, cpu_type_t cputype, cpu_subtype_t cpusubtype) 113 | { 114 | for (uint32_t i = 0; i < fat->slicesCount; i++) { 115 | MachO *curMacho = fat->slices[i]; 116 | if (curMacho) { 117 | if (curMacho->machHeader.cputype == cputype && curMacho->machHeader.cpusubtype == cpusubtype) { 118 | return curMacho; 119 | } 120 | } 121 | } 122 | return NULL; 123 | } 124 | 125 | void fat_free(FAT *fat) 126 | { 127 | if (fat->slices != NULL) { 128 | for (int i = 0; i < fat->slicesCount; i++) { 129 | if (fat->slices[i]) { 130 | macho_free(fat->slices[i]); 131 | } 132 | } 133 | free(fat->slices); 134 | } 135 | memory_stream_free(fat->stream); 136 | free(fat); 137 | } 138 | 139 | FAT *fat_init_from_memory_stream(MemoryStream *stream) 140 | { 141 | FAT *fat = malloc(sizeof(FAT)); 142 | if (!fat) return NULL; 143 | memset(fat, 0, sizeof(FAT)); 144 | 145 | fat->stream = stream; 146 | 147 | if (fat_parse_slices(fat) != 0) goto fail; 148 | 149 | size_t size = memory_stream_get_size(fat->stream); 150 | LOG("File size 0x%zx bytes, MachO slice count %u.\n", size, fat->slicesCount); 151 | return fat; 152 | 153 | fail: 154 | fat_free(fat); 155 | return NULL; 156 | } 157 | 158 | FAT *fat_init_from_path(const char *filePath) 159 | { 160 | MemoryStream *stream = file_stream_init_from_path(filePath, 0, FILE_STREAM_SIZE_AUTO, 0); 161 | if (stream) { 162 | return fat_init_from_memory_stream(stream);; 163 | } 164 | return NULL; 165 | } 166 | 167 | FAT *fat_create_for_macho_array(char *firstInputPath, MachO **machoArray, int machoArrayCount) { 168 | FAT *fat = fat_init_from_path(firstInputPath); 169 | for (int i = 1; i < machoArrayCount; i++) { 170 | if (fat_add_macho(fat, machoArray[i]) != 0) { 171 | printf("Error: failed to add MachO to FAT.\n"); 172 | fat_free(fat); 173 | return NULL; 174 | } 175 | } 176 | return fat; 177 | } 178 | 179 | int fat_add_macho(FAT *fat, MachO *macho) 180 | { 181 | fat->slicesCount++; 182 | fat->slices = realloc(fat->slices, sizeof(MachO*) * fat->slicesCount); 183 | if (!fat->slices) return -1; 184 | fat->slices[fat->slicesCount - 1] = macho; 185 | return 0; 186 | } -------------------------------------------------------------------------------- /ChOma-main/src/FAT.h: -------------------------------------------------------------------------------- 1 | #ifndef MACHO_H 2 | #define MACHO_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "MemoryStream.h" 12 | typedef struct MachO MachO; 13 | 14 | // A FAT structure can either represent a FAT file with multiple slices, in which the slices will be loaded into the slices attribute 15 | // Or a single slice MachO, in which case it serves as a compatibility layer and the single slice will also be loaded into the slices attribute 16 | typedef struct FAT 17 | { 18 | MemoryStream *stream; 19 | MachO **slices; 20 | uint32_t slicesCount; 21 | int fileDescriptor; 22 | } FAT; 23 | 24 | int fat_read_at_offset(FAT *fat, uint64_t offset, size_t size, void *outBuf); 25 | 26 | MemoryStream *fat_get_stream(FAT *fat); 27 | 28 | // Initialise a FAT structure from a memory stream 29 | FAT *fat_init_from_memory_stream(MemoryStream *stream); 30 | 31 | // Initialise a FAT structure using the path to the file 32 | FAT *fat_init_from_path(const char *filePath); 33 | 34 | // Find macho with cputype and cpusubtype in FAT, returns NULL if not found 35 | MachO *fat_find_slice(FAT *fat, cpu_type_t cputype, cpu_subtype_t cpusubtype); 36 | 37 | // Create a FAT structure from an array of MachO structures 38 | FAT *fat_create_for_macho_array(char *firstInputPath, MachO **machoArray, int machoArrayCount); 39 | 40 | // Add a MachO to the FAT structure 41 | int fat_add_macho(FAT *fat, MachO *macho); 42 | 43 | // Free all elements of the FAT structure 44 | void fat_free(FAT *fat); 45 | 46 | #endif // MACHO_H -------------------------------------------------------------------------------- /ChOma-main/src/FileStream.h: -------------------------------------------------------------------------------- 1 | #ifndef FILE_STREAM_H 2 | #define FILE_STREAM_H 3 | 4 | #include "MemoryStream.h" 5 | 6 | #define FILE_STREAM_SIZE_AUTO 0 7 | #define FILE_STREAM_FLAG_WRITABLE (1 << 0) 8 | #define FILE_STREAM_FLAG_AUTO_EXPAND (1 << 1) 9 | 10 | typedef struct FileStreamContext { 11 | int fd; 12 | size_t fileSize; 13 | uint32_t bufferStart; 14 | size_t bufferSize; 15 | } FileStreamContext; 16 | 17 | MemoryStream *file_stream_init_from_file_descriptor_nodup(int fd, uint32_t bufferStart, size_t bufferSize, uint32_t flags); 18 | MemoryStream *file_stream_init_from_file_descriptor(int fd, uint32_t bufferStart, size_t bufferSize, uint32_t flags); 19 | MemoryStream *file_stream_init_from_path(const char *path, uint32_t bufferStart, size_t bufferSize, uint32_t flags); 20 | 21 | #endif // FILE_STREAM_H -------------------------------------------------------------------------------- /ChOma-main/src/Host.c: -------------------------------------------------------------------------------- 1 | #include "Host.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "MachO.h" 9 | 10 | #define CPU_SUBTYPE_ARM64E_ABI_V2 0x80000000 11 | 12 | int host_get_cpu_information(cpu_type_t *cputype, cpu_subtype_t *cpusubtype) 13 | { 14 | size_t len; 15 | 16 | // Query for cputype 17 | len = sizeof(cputype); 18 | if (sysctlbyname("hw.cputype", cputype, &len, NULL, 0) == -1) { printf("ERROR: no cputype.\n"); return -1; } 19 | 20 | // Query for cpusubtype 21 | len = sizeof(cpusubtype); 22 | if (sysctlbyname("hw.cpusubtype", cpusubtype, &len, NULL, 0) == -1) { printf("ERROR: no cpusubtype.\n"); return -1; } 23 | 24 | return 0; 25 | } 26 | 27 | MachO *fat_find_preferred_slice(FAT *fat) 28 | { 29 | cpu_type_t cputype; 30 | cpu_subtype_t cpusubtype; 31 | if (host_get_cpu_information(&cputype, &cpusubtype) != 0) { return NULL; } 32 | 33 | MachO *preferredMacho = NULL; 34 | 35 | // If you intend on supporting non darwin, implement platform specific logic here using #ifdef's 36 | if (cputype == CPU_TYPE_ARM64) { 37 | if (cpusubtype == CPU_SUBTYPE_ARM64E) { 38 | // If this is an arm64e device, first try to find a new ABI arm64e slice 39 | // TODO: Gate this behind iOS 14+? 40 | preferredMacho = fat_find_slice(fat, cputype, (CPU_SUBTYPE_ARM64E | CPU_SUBTYPE_ARM64E_ABI_V2)); 41 | if (!preferredMacho) { 42 | // If that's not found, try to find an old ABI arm64e slice 43 | preferredMacho = fat_find_slice(fat, cputype, CPU_SUBTYPE_ARM64E); 44 | 45 | //the new kernel cannot execute an old ABI arm64e executable 46 | if(preferredMacho && preferredMacho->machHeader.filetype == MH_EXECUTE) { 47 | preferredMacho = NULL; 48 | } 49 | } 50 | } 51 | 52 | if (!preferredMacho) { 53 | // If not arm64e device or no arm64e slice found, try to find regular arm64 slice 54 | 55 | // On iOS 15+, the Kernel prefers an arm64v8 slice to an arm64 slice, so check that first 56 | // TODO: Gate this behind iOS 15+? 57 | preferredMacho = fat_find_slice(fat, cputype, CPU_SUBTYPE_ARM64_V8); 58 | if (!preferredMacho) { 59 | // If that's not found, finally check for a regular arm64 slice 60 | preferredMacho = fat_find_slice(fat, cputype, CPU_SUBTYPE_ARM64_ALL); 61 | } 62 | } 63 | } 64 | 65 | if (!preferredMacho) { 66 | printf("Error: failed to find a valid, preferred macho.\n"); 67 | } 68 | return preferredMacho; 69 | } -------------------------------------------------------------------------------- /ChOma-main/src/Host.h: -------------------------------------------------------------------------------- 1 | #ifndef HOST_H 2 | #define HOST_H 3 | 4 | #include "FAT.h" 5 | 6 | // Retrieve the preferred MachO slice from a FAT 7 | // Preferred slice as in the slice that the kernel would use when loading the file 8 | MachO *fat_find_preferred_slice(FAT *fat); 9 | 10 | #endif // HOST_H -------------------------------------------------------------------------------- /ChOma-main/src/MachO.h: -------------------------------------------------------------------------------- 1 | #ifndef MACHO_SLICE_H 2 | #define MACHO_SLICE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "MemoryStream.h" 8 | #include "FAT.h" 9 | 10 | typedef struct MachOSegment 11 | { 12 | struct segment_command_64 command; 13 | struct section_64 sections[]; 14 | } __attribute__((__packed__)) MachOSegment; 15 | 16 | typedef struct FilesetMachO { 17 | char *entry_id; 18 | uint64_t vmaddr; 19 | uint64_t fileoff; 20 | struct FAT *underlyingMachO; 21 | } FilesetMachO; 22 | 23 | typedef struct MachO { 24 | MemoryStream *stream; 25 | bool isSupported; 26 | struct mach_header_64 machHeader; 27 | struct fat_arch_64 archDescriptor; 28 | 29 | uint32_t filesetCount; 30 | FilesetMachO *filesetMachos; 31 | 32 | uint32_t segmentCount; 33 | MachOSegment **segments; 34 | } MachO; 35 | 36 | // Read data from a MachO at a specified offset 37 | int macho_read_at_offset(MachO *macho, uint64_t offset, size_t size, void *outBuf); 38 | 39 | // Write data from a MachO at a specified offset, auto expands, only works if opened via macho_init_for_writing 40 | int macho_write_at_offset(MachO *macho, uint64_t offset, size_t size, void *inBuf); 41 | 42 | MemoryStream *macho_get_stream(MachO *macho); 43 | uint32_t macho_get_filetype(MachO *macho); 44 | 45 | // Perform translation between file offsets and virtual addresses 46 | int macho_translate_fileoff_to_vmaddr(MachO *macho, uint64_t fileoff, uint64_t *vmaddrOut, MachOSegment **segmentOut); 47 | int macho_translate_vmaddr_to_fileoff(MachO *macho, uint64_t vmaddr, uint64_t *fileoffOut, MachOSegment **segmentOut); 48 | 49 | // Read data from a MachO at a specified virtual address 50 | int macho_read_at_vmaddr(MachO *macho, uint64_t vmaddr, size_t size, void *outBuf); 51 | 52 | int macho_enumerate_load_commands(MachO *macho, void (^enumeratorBlock)(struct load_command loadCommand, uint64_t offset, void *cmd, bool *stop)); 53 | 54 | // Initialise a MachO object from a MemoryStream and it's corresponding FAT arch descriptor 55 | MachO *macho_init(MemoryStream *stream, struct fat_arch_64 archDescriptor); 56 | 57 | // Initialize a single slice macho for writing to it 58 | MachO *macho_init_for_writing(const char *filePath); 59 | 60 | // Create an array of MachO objects from an array of paths 61 | MachO **macho_array_create_for_paths(char **inputPaths, int inputPathsCount); 62 | 63 | void macho_free(MachO *macho); 64 | 65 | #endif // MACHO_SLICE_H -------------------------------------------------------------------------------- /ChOma-main/src/MachOByteOrder.h: -------------------------------------------------------------------------------- 1 | #ifndef MACHO_BYTE_ORDER_H 2 | #define MACHO_BYTE_ORDER_H 3 | 4 | #include 5 | #include 6 | 7 | // 8-bit integers needed for CodeDirectory 8 | #define BIG_TO_HOST(n) _Generic((n), \ 9 | int8_t: n, \ 10 | uint8_t: n, \ 11 | int16_t: OSSwapBigToHostInt16(n), \ 12 | uint16_t: OSSwapBigToHostInt16(n), \ 13 | int32_t: OSSwapBigToHostInt32(n), \ 14 | uint32_t: OSSwapBigToHostInt32(n), \ 15 | int64_t: OSSwapBigToHostInt64(n), \ 16 | uint64_t: OSSwapBigToHostInt64(n) \ 17 | ) 18 | 19 | #define HOST_TO_BIG(n) _Generic((n), \ 20 | int8_t: n, \ 21 | uint8_t: n, \ 22 | uint16_t: OSSwapHostToBigInt16(n), \ 23 | int16_t: OSSwapHostToBigInt16(n), \ 24 | int32_t: OSSwapHostToBigInt32(n), \ 25 | uint32_t: OSSwapHostToBigInt32(n), \ 26 | int64_t: OSSwapHostToBigInt64(n), \ 27 | uint64_t: OSSwapHostToBigInt64(n) \ 28 | ) 29 | 30 | #define LITTLE_TO_HOST(n) _Generic((n), \ 31 | int8_t: n, \ 32 | uint8_t: n, \ 33 | int16_t: OSSwapLittleToHostInt16(n), \ 34 | uint16_t: OSSwapLittleToHostInt16(n), \ 35 | int32_t: OSSwapLittleToHostInt32(n), \ 36 | uint32_t: OSSwapLittleToHostInt32(n), \ 37 | int64_t: OSSwapLittleToHostInt64(n), \ 38 | uint64_t: OSSwapLittleToHostInt64(n) \ 39 | ) 40 | 41 | #define HOST_TO_LITTLE(n) _Generic((n), \ 42 | int8_t: n, \ 43 | uint8_t: n, \ 44 | int16_t: OSSwapHostToLittleInt16(n), \ 45 | uint16_t: OSSwapHostToLittleInt16(n), \ 46 | int32_t: OSSwapHostToLittleInt32(n), \ 47 | uint32_t: OSSwapHostToLittleInt32(n), \ 48 | int64_t: OSSwapHostToLittleInt64(n), \ 49 | uint64_t: OSSwapHostToLittleInt64(n) \ 50 | ) 51 | 52 | #define HOST_TO_LITTLE_APPLIER(instance, member) \ 53 | (instance)->member = HOST_TO_LITTLE((instance)->member) 54 | 55 | #define HOST_TO_BIG_APPLIER(instance, member) \ 56 | (instance)->member = HOST_TO_BIG((instance)->member) 57 | 58 | #define LITTLE_TO_HOST_APPLIER(instance, member) \ 59 | (instance)->member = LITTLE_TO_HOST((instance)->member) 60 | 61 | #define BIG_TO_HOST_APPLIER(instance, member) \ 62 | (instance)->member = BIG_TO_HOST((instance)->member) 63 | 64 | #define FAT_HEADER_APPLY_BYTE_ORDER(fh, applier) \ 65 | applier(fh, magic); \ 66 | applier(fh, nfat_arch); 67 | 68 | #define FAT_ARCH_APPLY_BYTE_ORDER(arch, applier) \ 69 | applier(arch, cputype); \ 70 | applier(arch, cpusubtype); \ 71 | applier(arch, offset); \ 72 | applier(arch, size); \ 73 | applier(arch, align); \ 74 | 75 | #define FAT_ARCH_64_APPLY_BYTE_ORDER(arch, applier) \ 76 | applier(arch, cputype); \ 77 | applier(arch, cpusubtype); \ 78 | applier(arch, offset); \ 79 | applier(arch, size); \ 80 | applier(arch, align); \ 81 | applier(arch, reserved); \ 82 | 83 | #define MACH_HEADER_APPLY_BYTE_ORDER(mh, applier) \ 84 | applier(mh, magic); \ 85 | applier(mh, cputype); \ 86 | applier(mh, cpusubtype); \ 87 | applier(mh, filetype); \ 88 | applier(mh, ncmds); \ 89 | applier(mh, sizeofcmds); \ 90 | applier(mh, reserved); 91 | 92 | #define LOAD_COMMAND_APPLY_BYTE_ORDER(lc, applier) \ 93 | applier(lc, cmd); \ 94 | applier(lc, cmdsize); 95 | 96 | #define LINKEDIT_DATA_COMMAND_APPLY_BYTE_ORDER(lc, applier) \ 97 | applier(lc, cmd); \ 98 | applier(lc, cmdsize); \ 99 | applier(lc, dataoff); \ 100 | applier(lc, datasize); 101 | 102 | #define BLOB_INDEX_APPLY_BYTE_ORDER(bi, applier) \ 103 | applier(bi, type); \ 104 | applier(bi, offset); 105 | 106 | #define SUPERBLOB_APPLY_BYTE_ORDER(sb, applier) \ 107 | applier(sb, magic); \ 108 | applier(sb, length); \ 109 | applier(sb, count); 110 | 111 | #define GENERIC_BLOB_APPLY_BYTE_ORDER(gb, applier) \ 112 | applier(gb, magic); \ 113 | applier(gb, length); 114 | 115 | #define CODE_DIRECTORY_APPLY_BYTE_ORDER(cd, applier) \ 116 | applier(cd, magic); \ 117 | applier(cd, length); \ 118 | applier(cd, version); \ 119 | applier(cd, flags); \ 120 | applier(cd, hashOffset); \ 121 | applier(cd, identOffset); \ 122 | applier(cd, nSpecialSlots); \ 123 | applier(cd, nCodeSlots); \ 124 | applier(cd, codeLimit); \ 125 | applier(cd, hashSize); \ 126 | applier(cd, hashType); \ 127 | applier(cd, spare1); \ 128 | applier(cd, pageSize); \ 129 | applier(cd, spare2); \ 130 | applier(cd, scatterOffset); \ 131 | applier(cd, teamOffset); 132 | 133 | #define SEGMENT_COMMAND_64_APPLY_BYTE_ORDER(sc64, applier) \ 134 | applier(sc64, cmd); \ 135 | applier(sc64, cmdsize); \ 136 | applier(sc64, fileoff); \ 137 | applier(sc64, filesize); \ 138 | applier(sc64, vmaddr); \ 139 | applier(sc64, vmsize); \ 140 | applier(sc64, flags); \ 141 | applier(sc64, initprot); \ 142 | applier(sc64, maxprot); \ 143 | applier(sc64, nsects); 144 | 145 | #define SECTION_64_APPLY_BYTE_ORDER(sc64, applier) \ 146 | applier(sc64, addr); \ 147 | applier(sc64, align); \ 148 | applier(sc64, flags); \ 149 | applier(sc64, nreloc); \ 150 | applier(sc64, offset); \ 151 | applier(sc64, reserved1); \ 152 | applier(sc64, reserved2); \ 153 | applier(sc64, reserved3); \ 154 | applier(sc64, size); 155 | 156 | #define FILESET_ENTRY_COMMAND_APPLY_BYTE_ORDER(fse, applier) \ 157 | applier(fse, cmd); \ 158 | applier(fse, cmdsize); \ 159 | applier(fse, vmaddr); \ 160 | applier(fse, fileoff); \ 161 | applier(fse, entry_id.offset); \ 162 | applier(fse, reserved); \ 163 | 164 | #endif // MACHO_BYTE_ORDER_H -------------------------------------------------------------------------------- /ChOma-main/src/MachOLoadCommand.h: -------------------------------------------------------------------------------- 1 | #ifndef MACHO_LOAD_COMMAND_H 2 | #define MACHO_LOAD_COMMAND_H 3 | 4 | #include 5 | #include "MachO.h" 6 | #include "CSBlob.h" 7 | #include "FileStream.h" 8 | #include "MachOByteOrder.h" 9 | 10 | // Convert load command to load command name 11 | char *load_command_to_string(int loadCommand); 12 | void update_segment_command_64(MachO *macho, const char *segmentName, uint64_t vmaddr, uint64_t vmsize, uint64_t fileoff, uint64_t filesize); 13 | void update_lc_code_signature(MachO *macho, uint64_t size); 14 | int update_load_commands_for_coretrust_bypass(MachO *macho, CS_SuperBlob *superblob, uint64_t originalCodeSignatureSize, uint64_t originalMachOSize); 15 | 16 | #endif // MACHO_LOAD_COMMAND_H -------------------------------------------------------------------------------- /ChOma-main/src/MemoryStream.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_STREAM_H 2 | #define MEMORY_STREAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define MEMORY_STREAM_FLAG_OWNS_DATA (1 << 0) 13 | #define MEMORY_STREAM_FLAG_MUTABLE (1 << 1) 14 | #define MEMORY_STREAM_FLAG_AUTO_EXPAND (1 << 2) 15 | 16 | #define MEMORY_STREAM_SIZE_INVALID (size_t)-1 17 | 18 | // A generic memory IO interface that is used throughout this project 19 | // Can be backed by anything, just the functions have to be implemented 20 | typedef struct s_MemoryStream { 21 | void *context; 22 | uint32_t flags; 23 | 24 | int (*read)(struct s_MemoryStream *stream, uint64_t offset, size_t size, void *outBuf); 25 | int (*write)(struct s_MemoryStream *stream, uint64_t offset, size_t size, const void *inBuf); 26 | int (*getSize)(struct s_MemoryStream *stream, size_t *sizeOut); 27 | uint8_t *(*getRawPtr)(struct s_MemoryStream *stream); 28 | 29 | int (*trim)(struct s_MemoryStream *stream, size_t trimAtStart, size_t trimAtEnd); 30 | int (*expand)(struct s_MemoryStream *stream, size_t expandAtStart, size_t expandAtEnd); 31 | 32 | struct s_MemoryStream *(*hardclone)(struct s_MemoryStream *stream); 33 | struct s_MemoryStream *(*softclone)(struct s_MemoryStream *stream); 34 | void (*free)(struct s_MemoryStream *stream); 35 | } MemoryStream; 36 | 37 | int memory_stream_read(MemoryStream *stream, uint64_t offset, size_t size, void *outBuf); 38 | int memory_stream_write(MemoryStream *stream, uint64_t offset, size_t size, const void *inBuf); 39 | 40 | int memory_stream_insert(MemoryStream *stream, uint64_t offset, size_t size, const void *inBuf); 41 | int memory_stream_delete(MemoryStream *stream, uint64_t offset, size_t size); 42 | 43 | int memory_stream_read_string(MemoryStream *stream, uint64_t offset, char **outString); 44 | int memory_stream_write_string(MemoryStream *stream, uint64_t offset, const char *string); 45 | 46 | size_t memory_stream_get_size(MemoryStream *stream); 47 | uint8_t *memory_stream_get_raw_pointer(MemoryStream *stream); 48 | uint32_t memory_stream_get_flags(MemoryStream *stream); 49 | 50 | MemoryStream *memory_stream_softclone(MemoryStream *stream); 51 | MemoryStream *memory_stream_hardclone(MemoryStream *stream); 52 | int memory_stream_trim(MemoryStream *stream, size_t trimAtStart, size_t trimAtEnd); 53 | int memory_stream_expand(MemoryStream *stream, size_t expandAtStart, size_t expandAtEnd); 54 | 55 | void memory_stream_free(MemoryStream *stream); 56 | 57 | int memory_stream_copy_data(MemoryStream *originStream, uint64_t originOffset, MemoryStream *targetStream, uint64_t targetOffset, size_t size); 58 | int memory_stream_find_memory(MemoryStream *stream, uint64_t searchOffset, size_t searchSize, void *bytes, void *mask, size_t nbytes, uint16_t alignment, uint64_t *foundOffsetOut); 59 | 60 | #endif // MEMORY_STREAM_H -------------------------------------------------------------------------------- /ChOma-main/src/PatchFinder.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MachO.h" 3 | 4 | #define METRIC_TYPE_PATTERN 1 5 | #define METRIC_TYPE_STRING 2 6 | #define METRIC_TYPE_XREF 3 7 | 8 | typedef struct s_PFSection { 9 | MachO *macho; 10 | uint64_t fileoff; 11 | uint64_t vmaddr; 12 | uint64_t size; 13 | uint8_t *cache; 14 | bool ownsCache; 15 | } PFSection; 16 | 17 | PFSection *pf_section_init_from_macho(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName); 18 | int pf_section_read_at_relative_offset(PFSection *section, uint64_t rel, size_t size, void *outBuf); 19 | int pf_section_read_at_address(PFSection *section, uint64_t vmaddr, void *outBuf, size_t size); 20 | uint32_t pf_section_read32(PFSection *section, uint64_t vmaddr); 21 | int pf_section_set_cached(PFSection *section, bool cached); 22 | void pf_section_free(PFSection *section); 23 | 24 | 25 | typedef struct s_MetricShared { 26 | uint32_t type; 27 | } MetricShared; 28 | 29 | 30 | typedef enum { 31 | BYTE_PATTERN_ALIGN_8_BIT, 32 | BYTE_PATTERN_ALIGN_16_BIT, 33 | BYTE_PATTERN_ALIGN_32_BIT, 34 | BYTE_PATTERN_ALIGN_64_BIT, 35 | } BytePatternAlignment; 36 | 37 | typedef struct s_PFBytePatternMetric { 38 | MetricShared shared; 39 | 40 | void *bytes; 41 | void *mask; 42 | size_t nbytes; 43 | BytePatternAlignment alignment; 44 | } PFBytePatternMetric; 45 | 46 | typedef struct s_PFStringMetric { 47 | MetricShared shared; 48 | 49 | char *string; 50 | } PFStringMetric; 51 | 52 | PFBytePatternMetric *pf_create_byte_pattern_metric(void *bytes, void *mask, size_t nbytes, BytePatternAlignment alignment); 53 | void pf_byte_pattern_metric_free(PFBytePatternMetric *metric); 54 | 55 | PFStringMetric *pf_create_string_metric(const char *string); 56 | void pf_string_metric_free(PFStringMetric *metric); 57 | 58 | 59 | void pf_section_run_metric(PFSection *section, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop)); 60 | -------------------------------------------------------------------------------- /ChOma-main/src/SignOSSL.c: -------------------------------------------------------------------------------- 1 | #include "SignOSSL.h" 2 | 3 | unsigned char *signWithRSA(unsigned char *inputData, size_t inputDataLength, unsigned char *key, size_t key_len, size_t *outputDataLength) 4 | { 5 | // Create EVP_PKEY from private key data 6 | FILE *privateKeyFile = fmemopen(key, key_len, "r"); 7 | if (!privateKeyFile) return NULL; 8 | EVP_PKEY *privateKey = PEM_read_PrivateKey(privateKeyFile, NULL, NULL, NULL); 9 | fclose(privateKeyFile); 10 | if (!privateKey) { 11 | fprintf(stderr, "Error: failed to read private key file.\n"); 12 | } 13 | 14 | // Get the RSA key from the private key 15 | RSA *rsaKey = EVP_PKEY_get1_RSA(privateKey); 16 | if (!rsaKey) { 17 | printf("Error: failed to get RSA key from private key.\n"); 18 | } 19 | 20 | // Determine the size of the RSA key in bytes 21 | int keySize = RSA_size(rsaKey); 22 | 23 | // Allocate memory for the signature 24 | unsigned char *signature = (unsigned char *)malloc(keySize); 25 | if (!signature) { 26 | printf("Error: failed to allocate memory.\n"); 27 | } 28 | 29 | // Sign the data 30 | int signatureLength = RSA_private_encrypt(inputDataLength, inputData, signature, rsaKey, RSA_PKCS1_PADDING); 31 | if (signatureLength == -1) { 32 | printf("Error: failed to sign the data.\n"); 33 | } 34 | 35 | RSA_free(rsaKey); 36 | EVP_PKEY_free(privateKey); 37 | 38 | *outputDataLength = signatureLength; 39 | return signature; 40 | } 41 | -------------------------------------------------------------------------------- /ChOma-main/src/SignOSSL.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGN_OSSL_H 2 | #define SIGN_OSSL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | unsigned char *signWithRSA(unsigned char *inputData, size_t inputDataLength, unsigned char *key, size_t key_len, size_t *outputDataLength); 13 | 14 | #endif // SIGN_OSSL_H 15 | 16 | // 0xA422 -------------------------------------------------------------------------------- /ChOma-main/src/Util.c: -------------------------------------------------------------------------------- 1 | #include "Util.h" 2 | #include 3 | 4 | int memcmp_masked(const void *str1, const void *str2, unsigned char* mask, size_t n) 5 | { 6 | const unsigned char* p = (const unsigned char*)str1; 7 | const unsigned char* q = (const unsigned char*)str2; 8 | 9 | if (p == q) return 0; 10 | for (int i = 0; i < n; i++) { 11 | unsigned char cMask = 0xFF; 12 | if (mask) { 13 | cMask = mask[i]; 14 | } 15 | if((p[i] & cMask) != (q[i] & cMask)) { 16 | // we do not care about 1 / -1 17 | return -1; 18 | } 19 | } 20 | 21 | return 0; 22 | } 23 | 24 | uint64_t align_to_size(int size, int alignment) 25 | { 26 | return (size + alignment - 1) & ~(alignment - 1); 27 | } 28 | 29 | int count_digits(int64_t num) 30 | { 31 | if (num == 0) { 32 | return 1; 33 | } 34 | int digits = 0; 35 | if (num < 0) { 36 | num = -num; 37 | digits++; 38 | } 39 | while (num != 0) { 40 | num = num / 10; 41 | digits++; 42 | } 43 | return digits; 44 | } 45 | 46 | void print_hash(uint8_t *hash, size_t size) 47 | { 48 | for (int j = 0; j < size; j++) { 49 | printf("%02x", hash[j]); 50 | } 51 | } -------------------------------------------------------------------------------- /ChOma-main/src/Util.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int memcmp_masked(const void *str1, const void *str2, unsigned char* mask, size_t n); 5 | uint64_t align_to_size(int size, int alignment); 6 | int count_digits(int64_t num); 7 | void print_hash(uint8_t *hash, size_t size); -------------------------------------------------------------------------------- /ChOma-main/tests/choma_cli/main.c: -------------------------------------------------------------------------------- 1 | #include "choma/FileStream.h" 2 | #include 3 | #include 4 | 5 | char *get_argument_value(int argc, char *argv[], const char *flag) 6 | { 7 | for (int i = 0; i < argc; i++) { 8 | if (!strcmp(argv[i], flag)) { 9 | if (i+1 < argc) { 10 | return argv[i+1]; 11 | } 12 | } 13 | } 14 | return NULL; 15 | } 16 | 17 | bool argument_exists(int argc, char *argv[], const char *flag) 18 | { 19 | for (int i = 0; i < argc; i++) { 20 | if (!strcmp(argv[i], flag)) { 21 | return true; 22 | } 23 | } 24 | return false; 25 | } 26 | 27 | void print_usage(char *executablePath) { 28 | printf("Options:\n"); 29 | printf("\t-i: Path to input file\n"); 30 | printf("\t-c: Parse the CMS superblob blob of a MachO\n"); 31 | printf("\t-e: Extract the Code Signature from a MachO\n"); 32 | printf("\t-s: Print all page hash code slots in a CodeDirectory blob\n"); 33 | printf("\t-v: Verify that the CodeDirectory hashes are correct\n"); 34 | printf("\t-f: Parse an MH_FILESET MachO and output it's sub-files\n"); 35 | printf("\t-h: Print this message\n"); 36 | printf("Examples:\n"); 37 | printf("\t%s -i -c\n", executablePath); 38 | printf("\t%s -i -c -s -v\n", executablePath); 39 | printf("\t%s -i -f\n", executablePath); 40 | exit(-1); 41 | } 42 | 43 | int main(int argc, char *argv[]) { 44 | 45 | if (argument_exists(argc, argv, "-h")) { 46 | print_usage(argv[0]); 47 | return 0; 48 | } 49 | 50 | if (argc < 2) { 51 | print_usage(argv[0]); 52 | return -1; 53 | } 54 | 55 | char *inputPath = get_argument_value(argc, argv, "-i"); 56 | if (!inputPath) { 57 | printf("Error: no input file specified.\n"); 58 | print_usage(argv[0]); 59 | return -1; 60 | } 61 | 62 | if (!argument_exists(argc, argv, "-c") && !argument_exists(argc, argv, "-f")) { 63 | printf("Error: no action specified.\n"); 64 | print_usage(argv[0]); 65 | return -1; 66 | } 67 | 68 | // Initialise the FAT structure 69 | printf("Initialising FAT structure from %s.\n", inputPath); 70 | FAT *fat = fat_init_from_path(inputPath); 71 | if (!fat) return -1; 72 | 73 | for (int i = 0; i < fat->slicesCount; i++) { 74 | MachO *slice = fat->slices[i]; 75 | printf("Slice %d (arch %x/%x, macho %x/%x):\n", i, slice->archDescriptor.cputype, slice->archDescriptor.cpusubtype, slice->machHeader.cputype, slice->machHeader.cpusubtype); 76 | if (argument_exists(argc, argv, "-c")) { 77 | CS_SuperBlob *superblob = macho_read_code_signature(slice); 78 | CS_DecodedSuperBlob *decodedSuperBlob = csd_superblob_decode(superblob); 79 | csd_superblob_print_content(decodedSuperBlob, slice, argument_exists(argc, argv, "-s"), argument_exists(argc, argv, "-v")); 80 | if (argument_exists(argc, argv, "-e")) { 81 | macho_extract_cs_to_file(slice, superblob); 82 | } 83 | } 84 | if (argument_exists(argc, argv, "-f")) { 85 | for (uint32_t i = 0; i < slice->segmentCount; i++) { 86 | MachOSegment *segment = slice->segments[i]; 87 | printf("(0x%08llx-0x%08llx)->(0x%09llx-0x%09llx) | %s\n", segment->command.fileoff, segment->command.fileoff + segment->command.filesize, segment->command.vmaddr, segment->command.vmaddr + segment->command.vmsize, segment->command.segname); 88 | for (int j = 0; j < segment->command.nsects; j++) { 89 | struct section_64 *section = &segment->sections[j]; 90 | printf("(0x%08x-0x%08llx)->(0x%09llx-0x%09llx) | %s.%s\n", section->offset, section->offset + section->size, section->addr, section->addr + section->size, section->segname, section->sectname); 91 | } 92 | } 93 | for (uint32_t i = 0; i < slice->filesetCount; i++) { 94 | MachO *filesetMachoSlice = slice->filesetMachos[i].underlyingMachO->slices[0]; 95 | char *entry_id = slice->filesetMachos[i].entry_id; 96 | for (int j = 0; j < filesetMachoSlice->segmentCount; j++) { 97 | MachOSegment *segment = filesetMachoSlice->segments[j]; 98 | printf("(0x%08llx-0x%08llx)->(0x%09llx-0x%09llx) | %s.%s\n", segment->command.fileoff, segment->command.fileoff + segment->command.filesize, segment->command.vmaddr, segment->command.vmaddr + segment->command.vmsize, entry_id, segment->command.segname); 99 | for (int k = 0; k < segment->command.nsects; k++) { 100 | struct section_64 *section = &segment->sections[k]; 101 | printf("(0x%08x-0x%08llx)->(0x%09llx-0x%09llx) | %s.%s.%s\n", section->offset, section->offset + section->size, section->addr, section->addr + section->size, entry_id, section->segname, section->sectname); 102 | } 103 | } 104 | } 105 | } 106 | } 107 | 108 | fat_free(fat); 109 | 110 | return 0; 111 | 112 | } -------------------------------------------------------------------------------- /ChOma-main/tests/ct_bypass/DecryptedSignature.h: -------------------------------------------------------------------------------- 1 | unsigned char DecryptedSignature[] = { 2 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 3 | 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0xe2, 0x34, 0xf9, 0x25, 0x65, 4 | 0xa4, 0x33, 0xb7, 0x13, 0x67, 0xc8, 0x63, 0x93, 0xdc, 0x41, 0xaa, 0xc4, 5 | 0x0e, 0x76, 0xa0, 0x80, 0x29, 0x8b, 0x38, 0x9e, 0xc5, 0x6d, 0xd6, 0xba, 6 | 0xef, 0xbf, 0x0d 7 | }; 8 | unsigned int DecryptedSignature_len = 51; 9 | -------------------------------------------------------------------------------- /ChOma-main/tests/fat_create/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define ARM64_ALIGNMENT 0xE 15 | 16 | char *get_argument_value(int argc, char *argv[], const char *flag) 17 | { 18 | for (int i = 0; i < argc; i++) { 19 | if (!strcmp(argv[i], flag)) { 20 | if (i+1 < argc) { 21 | return argv[i+1]; 22 | } 23 | } 24 | } 25 | return NULL; 26 | } 27 | 28 | bool argument_exists(int argc, char *argv[], const char *flag) 29 | { 30 | for (int i = 0; i < argc; i++) { 31 | if (!strcmp(argv[i], flag)) { 32 | return true; 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | void print_usage(char *executablePath) { 39 | printf("Options:\n"); 40 | printf("\t-o: Path to output file\n"); 41 | printf("\t-r: Replace output file if it already exists\n"); 42 | printf("\t-h: Print this message\n"); 43 | printf("Examples:\n"); 44 | printf("\t%s -o ...\n", executablePath); 45 | exit(-1); 46 | } 47 | 48 | char **get_input_paths(int argc, char *argv[], int *inputPathsCount) { 49 | char **inputPaths = malloc(sizeof(char *) * argc); 50 | int count = 0; 51 | for (int i = 1; i < argc; i++) { 52 | // Make sure this isn't a flag or the output path 53 | if (argv[i][0] != '-' && strcmp(argv[i], get_argument_value(argc, argv, "-o"))) { 54 | inputPaths[count] = argv[i]; 55 | count++; 56 | } 57 | } 58 | if (count == 0) { 59 | free(inputPaths); 60 | return NULL; 61 | } 62 | *inputPathsCount = count; 63 | return inputPaths; 64 | } 65 | 66 | int main(int argc, char *argv[]) { 67 | if (argument_exists(argc, argv, "-h")) { 68 | print_usage(argv[0]); 69 | return -1; 70 | } 71 | 72 | char *outputPath = get_argument_value(argc, argv, "-o"); 73 | if (!outputPath) { 74 | printf("Error: no output file specified.\n"); 75 | print_usage(argv[0]); 76 | return -1; 77 | } 78 | 79 | // Get the input paths 80 | int inputPathsCount = 0; 81 | char **inputPaths = get_input_paths(argc, argv, &inputPathsCount); 82 | if (!inputPaths) { 83 | printf("Error: no input files specified.\n"); 84 | print_usage(argv[0]); 85 | return -1; 86 | } 87 | 88 | // Create the output FAT 89 | struct stat st; 90 | if (stat(outputPath, &st) == 0) { 91 | if (argument_exists(argc, argv, "-r")) { 92 | if (remove(outputPath) != 0) { 93 | printf("Error: failed to remove output file.\n"); 94 | return -1; 95 | } 96 | } else { 97 | printf("Error: output file already exists.\n"); 98 | return -1; 99 | } 100 | } 101 | 102 | FILE *outputFile = fopen(outputPath, "w"); 103 | if (!outputFile) { 104 | printf("Error: failed to create output file.\n"); 105 | return -1; 106 | } 107 | fclose(outputFile); 108 | 109 | // Create an array of MachO objects 110 | MachO **machoArray = macho_array_create_for_paths(inputPaths, inputPathsCount); 111 | if (!machoArray) { 112 | printf("Error: failed to create FAT array.\n"); 113 | return -1; 114 | } 115 | 116 | // Create the FAT object 117 | FAT *fat = fat_create_for_macho_array(inputPaths[0], machoArray, inputPathsCount); 118 | printf("Created FAT with %u slices.\n", fat->slicesCount); 119 | 120 | // Write the FAT to the output file 121 | struct fat_header fatHeader; 122 | fatHeader.magic = FAT_MAGIC; 123 | fatHeader.nfat_arch = fat->slicesCount; 124 | FAT_HEADER_APPLY_BYTE_ORDER(&fatHeader, HOST_TO_BIG_APPLIER); 125 | uint64_t alignment = pow(2, ARM64_ALIGNMENT); 126 | uint64_t paddingSize = alignment - sizeof(struct fat_header) - (sizeof(struct fat_arch) * fat->slicesCount); 127 | MemoryStream *stream = file_stream_init_from_path(outputPath, 0, FILE_STREAM_SIZE_AUTO, FILE_STREAM_FLAG_WRITABLE | FILE_STREAM_FLAG_AUTO_EXPAND); 128 | memory_stream_write(stream, 0, sizeof(struct fat_header), &fatHeader); 129 | 130 | uint64_t lastSliceEnd = alignment; 131 | for (int i = 0; i < fat->slicesCount; i++) { 132 | struct fat_arch archDescriptor; 133 | archDescriptor.cpusubtype = fat->slices[i]->archDescriptor.cpusubtype; 134 | archDescriptor.cputype = fat->slices[i]->archDescriptor.cputype; 135 | archDescriptor.size = fat->slices[i]->archDescriptor.size; 136 | archDescriptor.offset = align_to_size(lastSliceEnd, alignment); 137 | archDescriptor.align = ARM64_ALIGNMENT; 138 | FAT_ARCH_APPLY_BYTE_ORDER(&archDescriptor, HOST_TO_BIG_APPLIER); 139 | printf("Writing to offset 0x%lx\n", sizeof(struct fat_header) + (sizeof(struct fat_arch) * i)); 140 | memory_stream_write(stream, sizeof(struct fat_header) + (sizeof(struct fat_arch) * i), sizeof(struct fat_arch), &archDescriptor); 141 | lastSliceEnd += align_to_size(memory_stream_get_size(fat->slices[i]->stream), alignment); 142 | } 143 | uint8_t *padding = malloc(paddingSize); 144 | memset(padding, 0, paddingSize); 145 | memory_stream_write(stream, sizeof(struct fat_header) + (sizeof(struct fat_arch) * fat->slicesCount), paddingSize, padding); 146 | free(padding); 147 | 148 | uint64_t offset = alignment; 149 | for (int i = 0; i < fat->slicesCount; i++) { 150 | MachO *macho = fat->slices[i]; 151 | int size = memory_stream_get_size(macho->stream); 152 | void *data = malloc(size); 153 | memory_stream_read(macho->stream, 0, size, data); 154 | memory_stream_write(stream, offset, size, data); 155 | free(data); 156 | uint64_t alignedSize = i == fat->slicesCount - 1 ? size : align_to_size(size, alignment);; 157 | printf("Slice %d: 0x%x bytes, aligned to 0x%llx bytes.\n", i, size, alignedSize); 158 | padding = malloc(alignedSize - size); 159 | memset(padding, 0, alignedSize - size); 160 | memory_stream_write(stream, offset + size, alignedSize - size, padding); 161 | free(padding); 162 | offset += alignedSize; 163 | } 164 | 165 | if (fat) fat_free(fat); 166 | if (machoArray) free(machoArray); 167 | if (stream) memory_stream_free(stream); 168 | if (inputPaths) free(inputPaths); 169 | 170 | return 0; 171 | } -------------------------------------------------------------------------------- /ChOma-main/tests/kpf/main.c: -------------------------------------------------------------------------------- 1 | #include "choma/FAT.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | // 1. Direct branch (b) 11 | // 2. Direct function call (bl) 12 | // 3. Indirect function call (adr / adrp, add) 13 | 14 | int main(int argc, char *argv[]) { 15 | if (argc != 2) return -1; 16 | 17 | int fd = open(argv[1], O_RDONLY); 18 | if (fd < 0) return -1; 19 | 20 | struct stat stat_buf; 21 | fstat(fd, &stat_buf); 22 | 23 | void *mapping = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 24 | if (mapping == MAP_FAILED) return -1; 25 | 26 | MemoryStream *stream = buffered_stream_init_from_buffer(mapping, stat_buf.st_size, 0); 27 | if (!stream) return -1; 28 | 29 | FAT *fat = fat_init_from_memory_stream(stream); 30 | if (!fat) return -1; 31 | 32 | //FAT *fat = fat_init_from_path(argv[1]); 33 | //printf("fat: %p\n", fat); 34 | //if (!fat) return -1; 35 | 36 | MachO *macho = fat_find_preferred_slice(fat); 37 | if (macho) { 38 | uint32_t inst = 0xD503237F; 39 | uint32_t mask = 0xFFFFFFFF; 40 | 41 | clock_t t; 42 | t = clock(); 43 | 44 | PFSection *kernelTextSection = pf_section_init_from_macho(macho, "com.apple.kernel", "__TEXT_EXEC", "__text"); 45 | pf_section_set_cached(kernelTextSection, true); 46 | 47 | PFSection *kernelStringSection = pf_section_init_from_macho(macho, "com.apple.kernel", "__TEXT", "__cstring"); 48 | pf_section_set_cached(kernelStringSection, true); 49 | 50 | PFBytePatternMetric *pacibspMetric = pf_create_byte_pattern_metric(&inst, &mask, sizeof(inst), BYTE_PATTERN_ALIGN_32_BIT); 51 | pf_section_run_metric(kernelTextSection, pacibspMetric, ^(uint64_t vmaddr, bool *stop) { 52 | printf("PACIBSP: 0x%llx (%x)\n", vmaddr, pf_section_read32(kernelTextSection, vmaddr+4)); 53 | }); 54 | pf_byte_pattern_metric_free(pacibspMetric); 55 | 56 | PFStringMetric *stringMetric = pf_create_string_metric("trust_cache_init"); 57 | pf_section_run_metric(kernelStringSection, stringMetric, ^(uint64_t vmaddr, bool *stop) { 58 | printf("trust_cache_init: 0x%llx\n", vmaddr); 59 | }); 60 | pf_string_metric_free(stringMetric); 61 | 62 | t = clock() - t; 63 | double time_taken = ((double)t)/CLOCKS_PER_SEC; 64 | printf("KPF finished in %lf seconds\n", time_taken); 65 | 66 | pf_section_free(kernelTextSection); 67 | } 68 | 69 | fat_free(fat); 70 | return 0; 71 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 RootHide 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bootstrap-basebin 2 | base binaries for Bootstrap 3 | -------------------------------------------------------------------------------- /bootstrap.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | platform-application 14 | 15 | get-task-allow 16 | 17 | com.apple.private.persona-mgmt 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /bootstrap/.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | packages/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /bootstrap/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "stdio.h": "c", 4 | "stdlib.h": "c", 5 | "ASSERT.h": "c", 6 | "syslog.h": "c", 7 | "fishhook.h": "c", 8 | "util.h": "c", 9 | "common.h": "c", 10 | "unistd.h": "c", 11 | "loader.h": "c", 12 | "mach.h": "c", 13 | "dyld.h": "c", 14 | "syslimits.h": "c", 15 | "*.cccc": "c", 16 | "varargs.h": "c", 17 | "vadefs.h": "c", 18 | "fcntl.h": "c", 19 | "stat.h": "c", 20 | "dlfcn.h": "c", 21 | "sandbox.h": "c", 22 | "libbsd.h": "c", 23 | "stdarg.h": "c", 24 | "errno.h": "c", 25 | "string.h": "c", 26 | "spawn.h": "c", 27 | "paths.h": "c", 28 | "iosfwd": "cpp", 29 | "machine.h": "c", 30 | "byte_order.h": "c", 31 | "__config": "c", 32 | "filesystem": "c", 33 | "stdbool.h": "c", 34 | "__locale": "c", 35 | "locale": "c", 36 | "signal.h": "c", 37 | "utsname.h": "c", 38 | "param.h": "c", 39 | "pwd.h": "c", 40 | "libproc.h": "c", 41 | "libproc_private.h": "c" 42 | } 43 | } -------------------------------------------------------------------------------- /bootstrap/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:15.0 2 | 3 | THEOS_PACKAGE_SCHEME = roothide 4 | 5 | FINALPACKAGE ?= 1 6 | DEBUG ?= 0 7 | 8 | include $(THEOS)/makefiles/common.mk 9 | 10 | LIBRARY_NAME = bootstrap 11 | 12 | bootstrap_FILES = $(wildcard *.c *.x *.m *.S) ../bootstrapd/ipc.m ../bootstrapd/libbsd.m 13 | bootstrap_CFLAGS = -fobjc-arc -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-value -Wno-format-invalid-specifier 14 | bootstrap_LDFLAGS = -L./ -ldobby -lc++ 15 | bootstrap_INSTALL_PATH = /basebin 16 | 17 | include $(THEOS_MAKE_PATH)/library.mk 18 | 19 | clean:: 20 | rm -rf ./packages/* 21 | 22 | ifneq ($(DEBUG), 1) 23 | before-package:: 24 | strip -N ./.theos/_/basebin/bootstrap.dylib 25 | ldid -S ./.theos/_/basebin/bootstrap.dylib 26 | endif 27 | -------------------------------------------------------------------------------- /bootstrap/assert.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SIGABRT 6 5 | #define OS_REASON_SIGNAL 2 6 | #define OS_REASON_DYLD 6 7 | #define DYLD_EXIT_REASON_OTHER 9 8 | 9 | void abort_with_payload(uint32_t reason_namespace, uint64_t reason_code, 10 | void *payload, uint32_t payload_size, 11 | const char *reason_string, uint64_t reason_flags) 12 | __attribute__((noreturn, cold)); 13 | 14 | #define ASSERT(e) (__builtin_expect(!(e), 0) ?\ 15 | ((void)fprintf(stderr, "%s:%d: failed ASSERTion `%s'\n", __FILE_NAME__, __LINE__, #e),\ 16 | abort_with_payload(OS_REASON_DYLD,DYLD_EXIT_REASON_OTHER,NULL,0, #e, 0)) : (void)0) 17 | -------------------------------------------------------------------------------- /bootstrap/common.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | bool stringStartsWith(const char *str, const char* prefix) 4 | { 5 | if (!str || !prefix) { 6 | return false; 7 | } 8 | 9 | size_t str_len = strlen(str); 10 | size_t prefix_len = strlen(prefix); 11 | 12 | if (str_len < prefix_len) { 13 | return false; 14 | } 15 | 16 | return !strncmp(str, prefix, prefix_len); 17 | } 18 | 19 | bool stringEndsWith(const char* str, const char* suffix) 20 | { 21 | if (!str || !suffix) { 22 | return false; 23 | } 24 | 25 | size_t str_len = strlen(str); 26 | size_t suffix_len = strlen(suffix); 27 | 28 | if (str_len < suffix_len) { 29 | return false; 30 | } 31 | 32 | return !strcmp(str + str_len - suffix_len, suffix); 33 | } 34 | -------------------------------------------------------------------------------- /bootstrap/common.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "assert.h" 8 | 9 | extern char** environ; 10 | 11 | extern char** NXArgv; // __NSGetArgv() not working on ctor 12 | extern int NXArgc; 13 | 14 | #define EXPORT __attribute__ ((visibility ("default"))) 15 | 16 | #ifdef DEBUG 17 | void bootstrapLog(const char* format, ...); 18 | #define SYSLOG bootstrapLog 19 | #else 20 | #define SYSLOG(...) 21 | #endif 22 | 23 | bool stringStartsWith(const char *str, const char* prefix); 24 | bool stringEndsWith(const char* str, const char* suffix); 25 | 26 | void fixsuid(); 27 | 28 | pid_t __getppid(); 29 | 30 | int requireJIT(); 31 | 32 | extern struct mach_header_64* _dyld_get_prog_image_header(); 33 | extern intptr_t _dyld_get_image_slide(struct mach_header_64* mh); 34 | 35 | 36 | extern int posix_spawn_hook(pid_t *restrict pid, const char *restrict file, 37 | const posix_spawn_file_actions_t *restrict file_actions, 38 | const posix_spawnattr_t *restrict attrp, 39 | char *const argv[restrict], 40 | char *const envp[restrict]); 41 | 42 | -------------------------------------------------------------------------------- /bootstrap/common.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "../bootstrapd/libbsd.h" 7 | 8 | void bootstrapLog(const char* format, ...) 9 | { 10 | va_list ap; 11 | va_start(ap, format); 12 | NSString* log = [[NSString alloc] initWithFormat:@(format) arguments:ap]; 13 | va_end(ap); 14 | 15 | // fprintf(stderr, "%s\n", log.UTF8String); 16 | // fflush(stderr); 17 | 18 | openlog("bootstrap",LOG_PID,LOG_AUTH); 19 | syslog(LOG_DEBUG, "%s", log.UTF8String); 20 | closelog(); 21 | } 22 | 23 | @interface LSApplicationWorkspace : NSObject 24 | +(instancetype)defaultWorkspace; 25 | -(BOOL)openApplicationWithBundleID:(id)arg1 ; 26 | -(id)pluginsWithIdentifiers:(id)arg1 protocols:(id)arg2 version:(id)arg3 ; 27 | -(id)pluginsWithIdentifiers:(id)arg1 protocols:(id)arg2 version:(id)arg3 applyFilter:(/*^block*/id)arg4 ; 28 | -(id)pluginsWithIdentifiers:(id)arg1 protocols:(id)arg2 version:(id)arg3 withFilter:(/*^block*/id)arg4 ; 29 | -(void)enumeratePluginsMatchingQuery:(id)arg1 withBlock:(/*^block*/id)arg2 ; 30 | -(id)pluginsMatchingQuery:(id)arg1 applyFilter:(/*^block*/id)arg2 ; 31 | @end 32 | 33 | #include 34 | void launchBootstrapApp() 35 | { 36 | dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_NOW); 37 | Class class_LSApplicationWorkspace = NSClassFromString(@"LSApplicationWorkspace"); 38 | [[class_LSApplicationWorkspace defaultWorkspace] openApplicationWithBundleID:@"com.roothide.Bootstrap"]; 39 | } 40 | 41 | void varCleanInit() 42 | { 43 | SYSLOG("varClean: init..."); 44 | 45 | if([NSHomeDirectory().stringByStandardizingPath hasPrefix:@"/var/mobile/Containers/"]) { 46 | return; 47 | } 48 | 49 | dispatch_async(dispatch_get_main_queue(), ^{ 50 | static NSOperationQueue* queue; 51 | 52 | queue = [NSOperationQueue new]; 53 | queue.maxConcurrentOperationCount = 1; 54 | 55 | [NSNotificationCenter.defaultCenter addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil 56 | queue:queue usingBlock:^(NSNotification* note) { 57 | SYSLOG("varClean UIApplicationDidEnterBackgroundNotification %@", note); 58 | bsd_varClean(); 59 | }]; 60 | 61 | [NSNotificationCenter.defaultCenter addObserverForName:UIApplicationWillTerminateNotification object:nil 62 | queue:queue usingBlock:^(NSNotification* note) { 63 | SYSLOG("varClean UIApplicationWillTerminateNotification %@", note); 64 | bsd_varClean(); 65 | }]; 66 | 67 | SYSLOG("varClean init in main queue"); 68 | }); 69 | } 70 | 71 | bool isTrollStoredApp() 72 | { 73 | return [NSFileManager.defaultManager fileExistsAtPath:[NSString stringWithFormat:@"%@/../_TrollStore", NSBundle.mainBundle.bundlePath]]; 74 | } 75 | -------------------------------------------------------------------------------- /bootstrap/control: -------------------------------------------------------------------------------- 1 | Package: com.roothide.bootstrap.dylib 2 | Name: bootstrap 3 | Version: 0.0.1 4 | Architecture: iphoneos-arm 5 | Description: An awesome library of some sort!! 6 | Maintainer: roothide 7 | Author: roothide 8 | Section: System 9 | Tag: role::developer 10 | -------------------------------------------------------------------------------- /bootstrap/dobby.h: -------------------------------------------------------------------------------- 1 | #ifndef dobby_h 2 | #define dobby_h 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | typedef uintptr_t addr_t; 12 | typedef uint32_t addr32_t; 13 | typedef uint64_t addr64_t; 14 | 15 | typedef void *dobby_dummy_func_t; 16 | typedef void *asm_func_t; 17 | 18 | #if defined(__arm__) 19 | typedef struct { 20 | uint32_t dummy_0; 21 | uint32_t dummy_1; 22 | 23 | uint32_t dummy_2; 24 | uint32_t sp; 25 | 26 | union { 27 | uint32_t r[13]; 28 | struct { 29 | uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12; 30 | } regs; 31 | } general; 32 | 33 | uint32_t lr; 34 | } DobbyRegisterContext; 35 | #elif defined(__arm64__) || defined(__aarch64__) 36 | #define ARM64_TMP_REG_NDX_0 17 37 | 38 | typedef union _FPReg { 39 | __int128_t q; 40 | struct { 41 | double d1; 42 | double d2; 43 | } d; 44 | struct { 45 | float f1; 46 | float f2; 47 | float f3; 48 | float f4; 49 | } f; 50 | } FPReg; 51 | 52 | // register context 53 | typedef struct { 54 | uint64_t dmmpy_0; // dummy placeholder 55 | uint64_t sp; 56 | 57 | uint64_t dmmpy_1; // dummy placeholder 58 | union { 59 | uint64_t x[29]; 60 | struct { 61 | uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, 62 | x23, x24, x25, x26, x27, x28; 63 | } regs; 64 | } general; 65 | 66 | uint64_t fp; 67 | uint64_t lr; 68 | 69 | union { 70 | FPReg q[32]; 71 | struct { 72 | FPReg q0, q1, q2, q3, q4, q5, q6, q7; 73 | // [!!! READ ME !!!] 74 | // for Arm64, can't access q8 - q31, unless you enable full floating-point register pack 75 | FPReg q8, q9, q10, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24, q25, q26, q27, q28, q29, 76 | q30, q31; 77 | } regs; 78 | } floating; 79 | } DobbyRegisterContext; 80 | #elif defined(_M_IX86) || defined(__i386__) 81 | typedef struct _RegisterContext { 82 | uint32_t dummy_0; 83 | uint32_t esp; 84 | 85 | uint32_t dummy_1; 86 | uint32_t flags; 87 | 88 | union { 89 | struct { 90 | uint32_t eax, ebx, ecx, edx, ebp, esp, edi, esi; 91 | } regs; 92 | } general; 93 | 94 | } DobbyRegisterContext; 95 | #elif defined(_M_X64) || defined(__x86_64__) 96 | typedef struct { 97 | uint64_t dummy_0; 98 | uint64_t rsp; 99 | 100 | union { 101 | struct { 102 | uint64_t rax, rbx, rcx, rdx, rbp, rsp, rdi, rsi, r8, r9, r10, r11, r12, r13, r14, r15; 103 | } regs; 104 | } general; 105 | 106 | uint64_t dummy_1; 107 | uint64_t flags; 108 | } DobbyRegisterContext; 109 | #endif 110 | 111 | #define install_hook_name(name, fn_ret_t, fn_args_t...) \ 112 | static fn_ret_t fake_##name(fn_args_t); \ 113 | static fn_ret_t (*orig_##name)(fn_args_t); \ 114 | /* __attribute__((constructor)) */ static void install_hook_##name(void *sym_addr) { \ 115 | DobbyHook(sym_addr, (dobby_dummy_func_t)fake_##name, (dobby_dummy_func_t *)&orig_##name); \ 116 | return; \ 117 | } \ 118 | fn_ret_t fake_##name(fn_args_t) 119 | 120 | // memory code patch 121 | int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size); 122 | 123 | // function inline hook 124 | int DobbyHook(void *address, dobby_dummy_func_t replace_func, dobby_dummy_func_t *origin_func); 125 | 126 | // dynamic binary instruction instrument 127 | // for Arm64, can't access q8 - q31, unless enable full floating-point register pack 128 | typedef void (*dobby_instrument_callback_t)(void *address, DobbyRegisterContext *ctx); 129 | int DobbyInstrument(void *address, dobby_instrument_callback_t pre_handler); 130 | 131 | // destroy and restore code patch 132 | int DobbyDestroy(void *address); 133 | 134 | const char *DobbyGetVersion(); 135 | 136 | // symbol resolver 137 | void *DobbySymbolResolver(const char *image_name, const char *symbol_name); 138 | 139 | // import table replace 140 | int DobbyImportTableReplace(char *image_name, char *symbol_name, dobby_dummy_func_t fake_func, 141 | dobby_dummy_func_t *orig_func); 142 | 143 | // for arm, Arm64, try use b xxx instead of ldr absolute indirect branch 144 | // for x86, x64, always use absolute indirect jump 145 | void dobby_enable_near_branch_trampoline(); 146 | void dobby_disable_near_branch_trampoline(); 147 | 148 | #ifdef __cplusplus 149 | } 150 | #endif 151 | 152 | #endif 153 | -------------------------------------------------------------------------------- /bootstrap/envbuf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int envbuf_len(const char *envp[]) 5 | { 6 | if (envp == NULL) return 1; 7 | 8 | int k = 0; 9 | const char *env = envp[k++]; 10 | while (env != NULL) { 11 | env = envp[k++]; 12 | } 13 | return k; 14 | } 15 | 16 | char **envbuf_mutcopy(const char *envp[]) 17 | { 18 | if (envp == NULL) return NULL; //opa said don't comment this 19 | 20 | int len = envbuf_len(envp); 21 | char **envcopy = malloc(len * sizeof(char *)); 22 | 23 | for (int i = 0; i < len-1; i++) { 24 | envcopy[i] = strdup(envp[i]); 25 | } 26 | envcopy[len-1] = NULL; 27 | 28 | return envcopy; 29 | } 30 | 31 | void envbuf_free(char *envp[]) 32 | { 33 | if (envp == NULL) return; 34 | 35 | int len = envbuf_len((const char**)envp); 36 | for (int i = 0; i < len-1; i++) { 37 | free(envp[i]); 38 | } 39 | free(envp); 40 | } 41 | 42 | int envbuf_find(const char *envp[], const char *name) 43 | { 44 | if (envp) { 45 | unsigned long nameLen = strlen(name); 46 | int k = 0; 47 | const char *env = envp[k++]; 48 | while (env != NULL) { 49 | unsigned long envLen = strlen(env); 50 | if (envLen > nameLen) { 51 | if (!strncmp(env, name, nameLen)) { 52 | if (env[nameLen] == '=') { 53 | return k-1; 54 | } 55 | } 56 | } 57 | env = envp[k++]; 58 | } 59 | } 60 | return -1; 61 | } 62 | 63 | const char *envbuf_getenv(const char *envp[], const char *name) 64 | { 65 | if (envp) { 66 | unsigned long nameLen = strlen(name); 67 | int envIndex = envbuf_find(envp, name); 68 | if (envIndex >= 0) { 69 | return &envp[envIndex][nameLen+1]; 70 | } 71 | } 72 | return NULL; 73 | } 74 | 75 | void envbuf_setenv(char **envpp[], const char *name, const char *value, int override) 76 | { 77 | if (envpp) { 78 | char **envp = *envpp; 79 | if (!envp) { 80 | // treat NULL as [NULL] 81 | envp = malloc(sizeof(const char *)); 82 | envp[0] = NULL; 83 | } 84 | 85 | char *envToSet = malloc(strlen(name)+strlen(value)+2); 86 | strcpy(envToSet, name); 87 | strcat(envToSet, "="); 88 | strcat(envToSet, value); 89 | 90 | int existingEnvIndex = envbuf_find((const char **)envp, name); 91 | if (existingEnvIndex >= 0) { 92 | if(!override) { 93 | free(envToSet); 94 | return; 95 | } 96 | // if already exists: deallocate old variable, then replace pointer 97 | free(envp[existingEnvIndex]); 98 | envp[existingEnvIndex] = envToSet; 99 | } 100 | else { 101 | // if doesn't exist yet: increase env buffer size, place at end 102 | int prevLen = envbuf_len((const char **)envp); 103 | *envpp = realloc(envp, (prevLen+1)*sizeof(const char *)); 104 | envp = *envpp; 105 | envp[prevLen-1] = envToSet; 106 | envp[prevLen] = NULL; 107 | } 108 | } 109 | } 110 | 111 | void envbuf_unsetenv(char **envpp[], const char *name) 112 | { 113 | if (envpp) { 114 | char **envp = *envpp; 115 | if (!envp) return; 116 | 117 | int existingEnvIndex = envbuf_find((const char **)envp, name); 118 | if (existingEnvIndex >= 0) { 119 | free(envp[existingEnvIndex]); 120 | int prevLen = envbuf_len((const char **)envp); 121 | for (int i = existingEnvIndex; i < (prevLen-1); i++) { 122 | envp[i] = envp[i+1]; 123 | } 124 | *envpp = realloc(envp, (prevLen-1)*sizeof(const char *)); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /bootstrap/envbuf.h: -------------------------------------------------------------------------------- 1 | int envbuf_len(const char *envp[]); 2 | char **envbuf_mutcopy(const char *envp[]); 3 | void envbuf_free(char *envp[]); 4 | int envbuf_find(const char *envp[], const char *name); 5 | const char *envbuf_getenv(const char *envp[], const char *name); 6 | void envbuf_setenv(char **envpp[], const char *name, const char *value, int overwrite); 7 | void envbuf_unsetenv(char **envpp[], const char *name); -------------------------------------------------------------------------------- /bootstrap/exechook.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "common.h" 16 | #include "envbuf.h" 17 | 18 | 19 | // Derived from posix_spawnp in Apple libc 20 | int resolvePath(const char *file, const char *searchPath, int (^attemptHandler)(char *path)) 21 | { 22 | const char *env_path; 23 | char *bp; 24 | char *cur; 25 | char *p; 26 | char **memp; 27 | int lp; 28 | int ln; 29 | int cnt; 30 | int err = 0; 31 | int eacces = 0; 32 | struct stat sb; 33 | char path_buf[PATH_MAX]; 34 | 35 | env_path = searchPath; 36 | if (!env_path) { 37 | env_path = getenv("PATH"); 38 | if (!env_path) { 39 | env_path = _PATH_DEFPATH; 40 | } 41 | } 42 | 43 | /* If it's an absolute or relative path name, it's easy. */ 44 | if (index(file, '/')) { 45 | bp = (char *)file; 46 | cur = NULL; 47 | goto retry; 48 | } 49 | bp = path_buf; 50 | 51 | /* If it's an empty path name, fail in the usual POSIX way. */ 52 | if (*file == '\0') 53 | return (ENOENT); 54 | 55 | if ((cur = alloca(strlen(env_path) + 1)) == NULL) 56 | return ENOMEM; 57 | strcpy(cur, env_path); 58 | while ((p = strsep(&cur, ":")) != NULL) { 59 | /* 60 | * It's a SHELL path -- double, leading and trailing colons 61 | * mean the current directory. 62 | */ 63 | if (*p == '\0') { 64 | p = "."; 65 | lp = 1; 66 | } else { 67 | lp = strlen(p); 68 | } 69 | ln = strlen(file); 70 | 71 | /* 72 | * If the path is too long complain. This is a possible 73 | * security issue; given a way to make the path too long 74 | * the user may spawn the wrong program. 75 | */ 76 | if (lp + ln + 2 > sizeof(path_buf)) { 77 | err = ENAMETOOLONG; 78 | goto done; 79 | } 80 | bcopy(p, path_buf, lp); 81 | path_buf[lp] = '/'; 82 | bcopy(file, path_buf + lp + 1, ln); 83 | path_buf[lp + ln + 1] = '\0'; 84 | 85 | retry: err = attemptHandler(bp); 86 | switch (err) { 87 | case E2BIG: 88 | case ENOMEM: 89 | case ETXTBSY: 90 | goto done; 91 | case ELOOP: 92 | case ENAMETOOLONG: 93 | case ENOENT: 94 | case ENOTDIR: 95 | break; 96 | case ENOEXEC: 97 | goto done; 98 | default: 99 | /* 100 | * EACCES may be for an inaccessible directory or 101 | * a non-executable file. Call stat() to decide 102 | * which. This also handles ambiguities for EFAULT 103 | * and EIO, and undocumented errors like ESTALE. 104 | * We hope that the race for a stat() is unimportant. 105 | */ 106 | if (stat(bp, &sb) != 0) 107 | break; 108 | if (err == EACCES) { 109 | eacces = 1; 110 | continue; 111 | } 112 | goto done; 113 | } 114 | } 115 | if (eacces) 116 | err = EACCES; 117 | else 118 | err = ENOENT; 119 | done: 120 | return (err); 121 | } 122 | 123 | void enumeratePathString(const char *pathsString, void (^enumBlock)(const char *pathString, bool *stop)) 124 | { 125 | char *pathsCopy = strdup(pathsString); 126 | char *pathString = strtok(pathsCopy, ":"); 127 | while (pathString != NULL) { 128 | bool stop = false; 129 | enumBlock(pathString, &stop); 130 | if (stop) break; 131 | pathString = strtok(NULL, ":"); 132 | } 133 | free(pathsCopy); 134 | } 135 | 136 | // extern const char* bootstrapath; 137 | int posix_spawn_hook(pid_t *restrict pid, const char *restrict path, 138 | const posix_spawn_file_actions_t *restrict file_actions, 139 | const posix_spawnattr_t *restrict attrp, 140 | char *const argv[restrict], 141 | char *const envp[restrict]) 142 | { 143 | const char* preload = envbuf_getenv((const char **)envp, "DYLD_INSERT_LIBRARIES"); 144 | char **envc = envbuf_mutcopy((const char **)envp); 145 | 146 | bool isBootstrapApp = stringEndsWith(path, "/Bootstrap.app/Bootstrap"); 147 | 148 | const char* bootstrapath = jbroot("/basebin/bootstrap.dylib"); 149 | if(!isBootstrapApp) if(!preload || !strstr(preload, "/basebin/bootstrap.dylib")) 150 | { 151 | int newlen = strlen(bootstrapath)+1; 152 | if(preload && *preload) newlen += strlen(preload); 153 | 154 | char newpreload[newlen]; 155 | strcpy(newpreload, bootstrapath); 156 | 157 | if(preload && *preload) { 158 | strcat(newpreload, ":"); 159 | strcat(newpreload, preload); 160 | } 161 | 162 | envbuf_setenv(&envc, "DYLD_INSERT_LIBRARIES", newpreload, 1); 163 | } 164 | 165 | int retval = posix_spawn(pid, path, file_actions, attrp, argv, envc); 166 | envbuf_free(envc); 167 | return retval; 168 | } 169 | -------------------------------------------------------------------------------- /bootstrap/fishhook.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #ifndef fishhook_h 25 | #define fishhook_h 26 | 27 | #include 28 | #include 29 | 30 | #if !defined(FISHHOOK_EXPORT) 31 | #define FISHHOOK_VISIBILITY __attribute__((visibility("hidden"))) 32 | #else 33 | #define FISHHOOK_VISIBILITY __attribute__((visibility("default"))) 34 | #endif 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif //__cplusplus 39 | 40 | /* 41 | * A structure representing a particular intended rebinding from a symbol 42 | * name to its replacement 43 | */ 44 | struct rebinding { 45 | const char *name; 46 | void *replacement; 47 | void **replaced; 48 | }; 49 | 50 | /* 51 | * For each rebinding in rebindings, rebinds references to external, indirect 52 | * symbols with the specified name to instead point at replacement for each 53 | * image in the calling process as well as for all future images that are loaded 54 | * by the process. If rebind_functions is called more than once, the symbols to 55 | * rebind are added to the existing list of rebindings, and if a given symbol 56 | * is rebound more than once, the later rebinding will take precedence. 57 | */ 58 | FISHHOOK_VISIBILITY 59 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); 60 | 61 | /* 62 | * Rebinds as above, but only in the specified image. The header should point 63 | * to the mach-o header, the slide should be the slide offset. Others as above. 64 | */ 65 | FISHHOOK_VISIBILITY 66 | int rebind_symbols_image(void *header, 67 | intptr_t slide, 68 | struct rebinding rebindings[], 69 | size_t rebindings_nel); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif //__cplusplus 74 | 75 | #endif //fishhook_h 76 | 77 | -------------------------------------------------------------------------------- /bootstrap/fixsuid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "common.h" 11 | 12 | enum { 13 | PERSONA_INVALID = 0, 14 | PERSONA_GUEST = 1, 15 | PERSONA_MANAGED = 2, 16 | PERSONA_PRIV = 3, 17 | PERSONA_SYSTEM = 4, 18 | PERSONA_DEFAULT = 5, 19 | PERSONA_SYSTEM_PROXY = 6, 20 | PERSONA_SYS_EXT = 7, 21 | PERSONA_ENTERPRISE = 8, 22 | 23 | PERSONA_TYPE_MAX = PERSONA_ENTERPRISE, 24 | }; 25 | 26 | #define PERSONA_INFO_V1 1 27 | #define PERSONA_INFO_V2 2 28 | 29 | struct kpersona_info { 30 | /* v1 fields */ 31 | uint32_t persona_info_version; 32 | 33 | uid_t persona_id; 34 | int persona_type; 35 | gid_t persona_gid; /* unused */ 36 | uint32_t persona_ngroups; /* unused */ 37 | gid_t persona_groups[NGROUPS]; /* unused */ 38 | uid_t persona_gmuid; /* unused */ 39 | char persona_name[MAXLOGNAME + 1]; 40 | 41 | /* v2 fields */ 42 | uid_t persona_uid; 43 | } __attribute__((packed)); 44 | 45 | extern int kpersona_find_by_type(int persona_type, uid_t *id, size_t *idlen); 46 | extern int kpersona_getpath(uid_t id, char path[MAXPATHLEN]); 47 | extern int kpersona_pidinfo(pid_t id, struct kpersona_info *info); 48 | extern int kpersona_info(uid_t id, struct kpersona_info *info); 49 | extern int kpersona_find(const char *name, uid_t uid, uid_t *id, size_t *idlen); 50 | extern int kpersona_alloc(struct kpersona_info *info, uid_t *id); 51 | 52 | 53 | int available_persona_id() 54 | { 55 | struct kpersona_info info={PERSONA_INFO_V1}; 56 | ASSERT(kpersona_pidinfo(getpid(), &info) == 0); 57 | 58 | int current_persona_id = info.persona_id; 59 | 60 | for(int t=1; t<=PERSONA_TYPE_MAX; t++) 61 | { 62 | uid_t personas[128]={0}; 63 | size_t npersonas = 128; 64 | 65 | if(kpersona_find_by_type(t, personas, &npersonas) <= 0) 66 | continue; 67 | 68 | for(int i=0; i 84 | 85 | void fixsuid() 86 | { 87 | if(getenv("UIDFIX")) { 88 | uid_t uid = atoi(getenv("UIDFIX")); 89 | setreuid(uid, geteuid()); 90 | unsetenv("UIDFIX"); 91 | } 92 | if(getenv("GIDFIX")) { 93 | uid_t gid = atoi(getenv("GIDFIX")); 94 | setregid(gid, getegid()); 95 | unsetenv("GIDFIX"); 96 | } 97 | 98 | char path[PATH_MAX]={0}; 99 | uint32_t bufsize=sizeof(path); 100 | ASSERT(_NSGetExecutablePath(path, &bufsize) == 0); 101 | 102 | struct stat st; 103 | ASSERT(stat(path, &st) == 0); 104 | 105 | if (!S_ISREG(st.st_mode) || !(st.st_mode & (S_ISUID | S_ISGID))) 106 | return; 107 | 108 | if( ((st.st_mode&S_ISUID)==0 || st.st_uid==geteuid()) 109 | && ((st.st_mode&S_ISGID)==0 || st.st_gid==getegid()) ) 110 | return; 111 | 112 | 113 | char uidbuf[32], gidbuf[32]; 114 | snprintf(uidbuf, sizeof(uidbuf), "%d", geteuid()); 115 | snprintf(gidbuf, sizeof(gidbuf), "%d", getegid()); 116 | setenv("UIDFIX", uidbuf, 1); 117 | setenv("GIDFIX", gidbuf, 1); 118 | 119 | posix_spawnattr_t attr; 120 | posix_spawnattr_init(&attr); 121 | 122 | int persona_id = available_persona_id(); 123 | ASSERT(persona_id != 0); 124 | 125 | posix_spawnattr_set_persona_np(&attr, persona_id, POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE); 126 | if(st.st_mode & S_ISUID) posix_spawnattr_set_persona_uid_np(&attr, st.st_uid); 127 | if(st.st_mode & S_ISGID) posix_spawnattr_set_persona_gid_np(&attr, st.st_gid); 128 | 129 | posix_spawn_file_actions_t action; 130 | posix_spawn_file_actions_init(&action); 131 | 132 | pid_t pid=0; 133 | int ret = posix_spawn_hook(&pid, path, &action, &attr, NXArgv, environ); 134 | 135 | ASSERT(ret==0 && pid>0); 136 | 137 | int status=0; 138 | while(waitpid(pid, &status, 0) != -1) 139 | { 140 | if (WIFSIGNALED(status)) { 141 | kill(getpid(), -WTERMSIG(status)); 142 | } else if (WIFEXITED(status)) { 143 | exit(WEXITSTATUS(status)); 144 | } 145 | //keep waiting?return status; 146 | }; 147 | 148 | exit(-1); 149 | } 150 | 151 | void runAsRoot(const char* path, char* argv[]) 152 | { 153 | posix_spawnattr_t attr; 154 | posix_spawnattr_init(&attr); 155 | 156 | int persona_id = available_persona_id(); 157 | ASSERT(persona_id != 0); 158 | 159 | posix_spawnattr_set_persona_np(&attr, persona_id, POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE); 160 | posix_spawnattr_set_persona_uid_np(&attr, 0); 161 | posix_spawnattr_set_persona_gid_np(&attr, 0); 162 | 163 | posix_spawn_file_actions_t action; 164 | posix_spawn_file_actions_init(&action); 165 | 166 | pid_t pid=0; 167 | int ret = posix_spawn_hook(&pid, path, &action, &attr, argv, environ); 168 | 169 | ASSERT(ret==0 && pid>0); 170 | 171 | int status=0; 172 | while(waitpid(pid, &status, 0) != -1) 173 | { 174 | if (WIFSIGNALED(status)) { 175 | kill(getpid(), -WTERMSIG(status)); 176 | } else if (WIFEXITED(status)) { 177 | exit(WEXITSTATUS(status)); 178 | } 179 | //keep waiting?return status; 180 | }; 181 | 182 | exit(-1); 183 | } 184 | 185 | -------------------------------------------------------------------------------- /bootstrap/layout/DEBIAN/preinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # rm -f /basebin/bootstrap.dylib || true 4 | -------------------------------------------------------------------------------- /bootstrap/libdobby.a: -------------------------------------------------------------------------------- 1 | ../../../Dobby-master/build/iphoneos/universal/libdobby.a -------------------------------------------------------------------------------- /bootstrap/libproc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, 2007, 2010 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _LIBPROC_H_ 24 | #define _LIBPROC_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | /* 38 | * This header file contains private interfaces to obtain process information. 39 | * These interfaces are subject to change in future releases. 40 | */ 41 | 42 | /*! 43 | @define PROC_LISTPIDSPATH_PATH_IS_VOLUME 44 | @discussion This flag indicates that all processes that hold open 45 | file references on the volume associated with the specified 46 | path should be returned. 47 | */ 48 | #define PROC_LISTPIDSPATH_PATH_IS_VOLUME 1 49 | 50 | 51 | /*! 52 | @define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 53 | @discussion This flag indicates that file references that were opened 54 | with the O_EVTONLY flag should be excluded from the matching 55 | criteria. 56 | */ 57 | #define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 2 58 | 59 | __BEGIN_DECLS 60 | 61 | 62 | /*! 63 | @function proc_listpidspath 64 | @discussion A function which will search through the current 65 | processes looking for open file references which match 66 | a specified path or volume. 67 | @param type types of processes to be searched (see proc_listpids) 68 | @param typeinfo adjunct information for type 69 | @param path file or volume path 70 | @param pathflags flags to control which files should be considered 71 | during the process search. 72 | @param buffer a C array of int-sized values to be filled with 73 | process identifiers that hold an open file reference 74 | matching the specified path or volume. Pass NULL to 75 | obtain the minimum buffer size needed to hold the 76 | currently active processes. 77 | @param buffersize the size (in bytes) of the provided buffer. 78 | @result the number of bytes of data returned in the provided buffer; 79 | -1 if an error was encountered; 80 | */ 81 | int proc_listpidspath(uint32_t type, 82 | uint32_t typeinfo, 83 | const char *path, 84 | uint32_t pathflags, 85 | void *buffer, 86 | int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 87 | 88 | int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 89 | int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); 90 | int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); 91 | int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); 92 | int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 93 | int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 94 | int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); 95 | int proc_name(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 96 | int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 97 | int proc_kmsgbuf(void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 98 | int proc_pidpath(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 99 | int proc_libversion(int *major, int * minor) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 100 | 101 | /* 102 | * Return resource usage information for the given pid, which can be a live process or a zombie. 103 | * 104 | * Returns 0 on success; or -1 on failure, with errno set to indicate the specific error. 105 | */ 106 | int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); 107 | 108 | /* 109 | * A process can use the following api to set its own process control 110 | * state on resoure starvation. The argument can have one of the PROC_SETPC_XX values 111 | */ 112 | #define PROC_SETPC_NONE 0 113 | #define PROC_SETPC_THROTTLEMEM 1 114 | #define PROC_SETPC_SUSPEND 2 115 | #define PROC_SETPC_TERMINATE 3 116 | 117 | int proc_setpcontrol(const int control) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); 118 | int proc_setpcontrol(const int control); 119 | 120 | int proc_track_dirty(pid_t pid, uint32_t flags); 121 | int proc_set_dirty(pid_t pid, bool dirty); 122 | int proc_get_dirty(pid_t pid, uint32_t *flags); 123 | 124 | int proc_terminate(pid_t pid, int *sig); 125 | 126 | __END_DECLS 127 | 128 | #endif /*_LIBPROC_H_ */ 129 | -------------------------------------------------------------------------------- /bootstrap/libproc_private.h: -------------------------------------------------------------------------------- 1 | struct proc_bsdinfo { 2 | uint32_t pbi_flags; /* 64bit; emulated etc */ 3 | uint32_t pbi_status; 4 | uint32_t pbi_xstatus; 5 | uint32_t pbi_pid; 6 | uint32_t pbi_ppid; 7 | uid_t pbi_uid; 8 | gid_t pbi_gid; 9 | uid_t pbi_ruid; 10 | gid_t pbi_rgid; 11 | uid_t pbi_svuid; 12 | gid_t pbi_svgid; 13 | uint32_t rfu_1; /* reserved */ 14 | char pbi_comm[MAXCOMLEN]; 15 | char pbi_name[2 * MAXCOMLEN]; /* empty if no name is registered */ 16 | uint32_t pbi_nfiles; 17 | uint32_t pbi_pgid; 18 | uint32_t pbi_pjobc; 19 | uint32_t e_tdev; /* controlling tty dev */ 20 | uint32_t e_tpgid; /* tty process group id */ 21 | int32_t pbi_nice; 22 | uint64_t pbi_start_tvsec; 23 | uint64_t pbi_start_tvusec; 24 | }; 25 | 26 | #define PROC_PIDTBSDINFO 3 27 | #define PROC_PIDTBSDINFO_SIZE (sizeof(struct proc_bsdinfo)) -------------------------------------------------------------------------------- /bootstrap/platformhook.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "common.h" 5 | #include "fishhook.h" 6 | #include "dobby.h" 7 | 8 | bool os_variant_has_internal_content(); 9 | bool (*orig_os_variant_has_internal_content)(); 10 | bool new_os_variant_has_internal_content() 11 | { 12 | return true; 13 | } 14 | 15 | #define CS_OPS_STATUS 0 /* return status */ 16 | #define CS_VALID 0x00000001 /* dynamically valid */ 17 | #define CS_PLATFORM_BINARY 0x04000000 /* this is a platform binary */ 18 | #define CS_PLATFORM_PATH 0x08000000 /* platform binary by the fact of path (osx only) */ 19 | int csops(pid_t pid, uint32_t ops, void* useraddr, user_size_t usersize); 20 | int csops_audittoken(pid_t pid, unsigned int ops, void * useraddr, size_t usersize, audit_token_t * token); 21 | int (*orig_csops_audittoken)(pid_t pid, unsigned int ops, void * useraddr, size_t usersize, audit_token_t * token); 22 | int new_csops_audittoken(pid_t pid, unsigned int ops, void * useraddr, size_t usersize, audit_token_t * token) 23 | { 24 | int ret = orig_csops_audittoken(pid, ops, useraddr, usersize, token); 25 | if(ret==-1) ret = csops(getpid(), ops, useraddr, usersize); 26 | 27 | SYSLOG("csops_audittoken(%d): %d : %d %08X %lx %p", ops, ret, pid, useraddr ? *(uint32_t*)useraddr : 0, usersize, token); 28 | 29 | if(ops==CS_OPS_STATUS) { 30 | *(uint32_t*)useraddr |= CS_VALID; 31 | *(uint32_t*)useraddr |= CS_PLATFORM_BINARY; 32 | *(uint32_t*)useraddr &= ~CS_PLATFORM_PATH; 33 | } 34 | 35 | return ret; 36 | } 37 | 38 | void init_platformHook() 39 | { 40 | SYSLOG("init_platformHook %d", getpid()); 41 | 42 | if(requireJIT()!=0) return; 43 | 44 | DobbyHook(csops_audittoken, new_csops_audittoken, (void**)&orig_csops_audittoken); 45 | // DobbyHook(os_variant_has_internal_content, new_os_variant_has_internal_content, (void**)&orig_os_variant_has_internal_content); 46 | } 47 | 48 | 49 | #include 50 | int (*orig__xpc_activate_endpoint)(const char *name, int type, void* handle, uint64_t flags, mach_port_t* p_port, bool* non_launching); 51 | int new__xpc_activate_endpoint(const char *name, int type, void* handle, uint64_t flags, mach_port_t* p_port, bool* p_non_launching) 52 | { 53 | SYSLOG("_xpc_activate_endpoint name=%s type=%d handle=%p flags=%llx", name, type, handle, flags); 54 | 55 | int ret = orig__xpc_activate_endpoint(name, type, handle, flags, p_port, p_non_launching); 56 | SYSLOG("_xpc_activate_endpoint ret=%d port=%x non-launching=%d", ret, *p_port, *p_non_launching); 57 | 58 | if(ret != 0) { 59 | mach_port_t port = MACH_PORT_NULL; 60 | kern_return_t kr = bootstrap_check_in(bootstrap_port, name, &port); 61 | SYSLOG("bootstrap_check_in port=%x kr=%x,%s", port, kr, bootstrap_strerror(kr)); 62 | if(kr == KERN_SUCCESS) { 63 | *p_non_launching = false; 64 | *p_port = port; 65 | ret = 0; 66 | } 67 | } 68 | 69 | return ret; 70 | } 71 | 72 | void init_xpchook() 73 | { 74 | SYSLOG("init_xpchook %d", getpid()); 75 | 76 | if(requireJIT()!=0) return; 77 | 78 | if(dlopen("/usr/lib/system/libxpc.dylib", RTLD_NOW)==NULL) { 79 | SYSLOG("dlopen libxpc.dylib failed"); 80 | return; 81 | } 82 | 83 | void* _xpc_activate_endpoint = DobbySymbolResolver("/usr/lib/system/libxpc.dylib", "__xpc_activate_endpoint"); 84 | SYSLOG("_xpc_activate_endpoint=%p", _xpc_activate_endpoint); 85 | 86 | DobbyHook(_xpc_activate_endpoint, (void *)new__xpc_activate_endpoint, (void **)&orig__xpc_activate_endpoint); 87 | } 88 | -------------------------------------------------------------------------------- /bootstrap/sandbox.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | enum sandbox_filter_type { 4 | SANDBOX_FILTER_NONE, 5 | SANDBOX_FILTER_PATH, 6 | SANDBOX_FILTER_GLOBAL_NAME, 7 | SANDBOX_FILTER_LOCAL_NAME, 8 | SANDBOX_FILTER_APPLEEVENT_DESTINATION, 9 | SANDBOX_FILTER_RIGHT_NAME, 10 | SANDBOX_FILTER_PREFERENCE_DOMAIN, 11 | SANDBOX_FILTER_KEXT_BUNDLE_ID, 12 | SANDBOX_FILTER_INFO_TYPE, 13 | SANDBOX_FILTER_NOTIFICATION, 14 | // ? 15 | // ? 16 | SANDBOX_FILTER_XPC_SERVICE_NAME = 12, 17 | SANDBOX_FILTER_IOKIT_CONNECTION, 18 | // ? 19 | // ? 20 | // ? 21 | // ? 22 | }; 23 | 24 | enum sandbox_extension_flags { 25 | FS_EXT_DEFAULTS = 0, 26 | FS_EXT_FOR_PATH = (1 << 0), 27 | FS_EXT_FOR_FILE = (1 << 1), 28 | FS_EXT_READ = (1 << 2), 29 | FS_EXT_WRITE = (1 << 3), 30 | FS_EXT_PREFER_FILEID = (1 << 4), 31 | }; 32 | 33 | enum sandbox_extension_types { 34 | EXTENSION_TYPE_FILE, 35 | EXTENSION_TYPE_MACH, 36 | EXTENSION_TYPE_IOKIT_REGISTRY_ENTRY, 37 | EXTENSION_TYPE_GENERIC, 38 | EXTENSION_TYPE_POSIX, 39 | EXTENSION_TYPE_PREFERENCE, 40 | EXTENSION_TYPE_SYSCTL, 41 | EXTENSION_TYPE_MAX /* last */ 42 | }; 43 | 44 | #define EXTENSION_FLAG_INVALID (1 << 0) 45 | #define EXTENSION_FLAG_CANONICAL (1 << 1) 46 | #define EXTENSION_FLAG_PREFIXMATCH (1 << 2) /* Not for paths. */ 47 | #define EXTENSION_FLAG_PATHLITERAL (1 << 3) /* Only for paths. */ 48 | #define EXTENSION_FLAG_NO_REPORT (1 << 4) 49 | #define EXTENSION_FLAG_BIND_PID (1 << 16) 50 | #define EXTENSION_FLAG_BIND_PIDVERSION (1 << 17) 51 | 52 | #define MAX_TOKEN_SIZE 2048 53 | 54 | struct syscall_extension_issue_args { 55 | uint64_t extension_class; 56 | uint64_t extension_type; 57 | uint64_t extension_data; 58 | uint64_t extension_flags; 59 | uint64_t extension_token; /* out */ 60 | int64_t extension_pid; 61 | int64_t extension_pid_version; 62 | }; 63 | 64 | extern const char *APP_SANDBOX_IOKIT_CLIENT; 65 | extern const char *APP_SANDBOX_MACH; 66 | extern const char *APP_SANDBOX_READ; 67 | extern const char *APP_SANDBOX_READ_WRITE; 68 | 69 | extern const char *IOS_SANDBOX_APPLICATION_GROUP; 70 | extern const char *IOS_SANDBOX_CONTAINER; 71 | 72 | extern const enum sandbox_filter_type SANDBOX_CHECK_ALLOW_APPROVAL; 73 | extern const enum sandbox_filter_type SANDBOX_CHECK_CANONICAL; 74 | extern const enum sandbox_filter_type SANDBOX_CHECK_NOFOLLOW; 75 | extern const enum sandbox_filter_type SANDBOX_CHECK_NO_APPROVAL; 76 | extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT; 77 | 78 | extern const uint32_t SANDBOX_EXTENSION_CANONICAL; 79 | extern const uint32_t SANDBOX_EXTENSION_DEFAULT; 80 | extern const uint32_t SANDBOX_EXTENSION_MAGIC; 81 | extern const uint32_t SANDBOX_EXTENSION_NOFOLLOW; 82 | extern const uint32_t SANDBOX_EXTENSION_NO_REPORT; 83 | extern const uint32_t SANDBOX_EXTENSION_NO_STORAGE_CLASS; 84 | extern const uint32_t SANDBOX_EXTENSION_PREFIXMATCH; 85 | extern const uint32_t SANDBOX_EXTENSION_UNRESOLVED; 86 | 87 | int sandbox_init(const char *profile, uint64_t flags, char **errorbuf); 88 | int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); 89 | int sandbox_init_with_extensions(const char *profile, uint64_t flags, const char *const extensions[], char **errorbuf); 90 | 91 | int sandbox_check(pid_t, const char *operation, enum sandbox_filter_type, ...); 92 | int sandbox_check_by_audit_token(audit_token_t, const char *operation, enum sandbox_filter_type, ...); 93 | int sandbox_check_by_uniqueid(uid_t, pid_t, const char *operation, enum sandbox_filter_type, ...); 94 | 95 | int64_t sandbox_extension_consume(const char *extension_token); 96 | char *sandbox_extension_issue_file(const char *extension_class, const char *path, uint32_t flags); 97 | char *sandbox_extension_issue_file_to_process(const char *extension_class, const char *path, uint32_t flags, audit_token_t); 98 | char *sandbox_extension_issue_file_to_process_by_pid(const char *extension_class, const char *path, uint32_t flags, pid_t); 99 | char *sandbox_extension_issue_file_to_self(const char *extension_class, const char *path, uint32_t flags); 100 | char *sandbox_extension_issue_generic(const char *extension_class, uint32_t flags); 101 | char *sandbox_extension_issue_generic_to_process(const char *extension_class, uint32_t flags, audit_token_t); 102 | char *sandbox_extension_issue_generic_to_process_by_pid(const char *extension_class, uint32_t flags, pid_t); 103 | char *sandbox_extension_issue_iokit_registry_entry_class(const char *extension_class, const char *registry_entry_class, uint32_t flags); 104 | char *sandbox_extension_issue_iokit_registry_entry_class_to_process(const char *extension_class, const char *registry_entry_class, uint32_t flags, audit_token_t); 105 | char *sandbox_extension_issue_iokit_registry_entry_class_to_process_by_pid(const char *extension_class, const char *registry_entry_class, uint32_t flags, pid_t); 106 | char *sandbox_extension_issue_iokit_user_client_class(const char *extension_class, const char *registry_entry_class, uint32_t flags); 107 | char *sandbox_extension_issue_mach(const char *extension_class, const char *name, uint32_t flags); 108 | char *sandbox_extension_issue_mach_to_process(const char *extension_class, const char *name, uint32_t flags, audit_token_t); 109 | char *sandbox_extension_issue_mach_to_process_by_pid(const char *extension_class, const char *name, uint32_t flags, pid_t); 110 | char *sandbox_extension_issue_posix_ipc(const char *extension_class, const char *name, uint32_t flags); 111 | 112 | void sandbox_extension_reap(void); 113 | int sandbox_extension_release(int64_t extension_handle); 114 | int sandbox_extension_release_file(int64_t extension_handle, const char *path); 115 | int sandbox_extension_update_file(int64_t extension_handle, const char *path); 116 | 117 | int __sandbox_ms(const char *policyname, int call, void *arg); -------------------------------------------------------------------------------- /bootstrap/syscall.S: -------------------------------------------------------------------------------- 1 | .text 2 | 3 | .align 4 4 | 5 | .global _ffsys_fork 6 | _ffsys_fork: 7 | #ifdef __arm64e__ 8 | pacibsp 9 | #endif 10 | stp x29, x30, [SP, #-0x10]! 11 | mov x29, sp 12 | mov x16, #2 13 | svc 0x80 14 | b.cs _ffsys_fork_err 15 | cbz x1, _ffsys_fork_end 16 | mov w0, #0 17 | adrp x9, __current_pid@GOTPAGE 18 | ldr x9, [x9, __current_pid@GOTPAGEOFF] 19 | str w0, [x9] 20 | b _ffsys_fork_end 21 | 22 | _ffsys_fork_err: 23 | bl _cerror 24 | mov w0, #-1 25 | 26 | _ffsys_fork_end: 27 | mov sp, x29 28 | ldp x29, x30, [SP],#0x10 29 | #ifdef __arm64e__ 30 | retab 31 | #else 32 | ret 33 | #endif 34 | 35 | .global _ffsys_getpid 36 | _ffsys_getpid: 37 | mov x16, #20 38 | svc 0x80 39 | ret 40 | 41 | .global _ffsys_read 42 | _ffsys_read: 43 | mov x16, #3 44 | svc 0x80 45 | b.cc _ffsys_read_end 46 | #ifdef __arm64e__ 47 | pacibsp 48 | #endif 49 | stp x29, x30, [SP, #-0x10]! 50 | mov x29, sp 51 | bl _cerror 52 | mov sp, x29 53 | ldp x29, x30, [SP],#0x10 54 | #ifdef __arm64e__ 55 | retab 56 | #else 57 | ret 58 | #endif 59 | 60 | _ffsys_read_end: 61 | ret 62 | 63 | .global _ffsys_write 64 | _ffsys_write: 65 | mov x16, #4 66 | svc 0x80 67 | b.cc _ffsys_write_end 68 | #ifdef __arm64e__ 69 | pacibsp 70 | #endif 71 | stp x29, x30, [SP, #-0x10]! 72 | mov x29, sp 73 | bl _cerror 74 | mov sp, x29 75 | ldp x29, x30, [SP],#0x10 76 | #ifdef __arm64e__ 77 | retab 78 | #else 79 | ret 80 | #endif 81 | 82 | _ffsys_write_end: 83 | ret 84 | 85 | .global _ffsys_close 86 | _ffsys_close: 87 | mov x16, #6 88 | svc 0x80 89 | b.cc _ffsys_close_end 90 | #ifdef __arm64e__ 91 | pacibsp 92 | #endif 93 | stp x29, x30, [SP, #-0x10]! 94 | mov x29, sp 95 | bl _cerror 96 | mov sp, x29 97 | ldp x29, x30, [SP],#0x10 98 | #ifdef __arm64e__ 99 | retab 100 | #else 101 | ret 102 | #endif 103 | 104 | _ffsys_close_end: 105 | ret 106 | -------------------------------------------------------------------------------- /bootstrapd/.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | packages/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /bootstrapd/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "ios": "cpp", 4 | "algorithm": "cpp", 5 | "streambuf": "cpp", 6 | "__bit_reference": "cpp", 7 | "__bits": "cpp", 8 | "__config": "cpp", 9 | "__debug": "cpp", 10 | "__errc": "cpp", 11 | "__hash_table": "cpp", 12 | "__locale": "cpp", 13 | "__mutex_base": "cpp", 14 | "__node_handle": "cpp", 15 | "__nullptr": "cpp", 16 | "__split_buffer": "cpp", 17 | "__string": "cpp", 18 | "__threading_support": "cpp", 19 | "__tree": "cpp", 20 | "__tuple": "cpp", 21 | "array": "cpp", 22 | "atomic": "cpp", 23 | "bitset": "cpp", 24 | "cctype": "cpp", 25 | "chrono": "cpp", 26 | "clocale": "cpp", 27 | "cmath": "cpp", 28 | "compare": "cpp", 29 | "complex": "cpp", 30 | "concepts": "cpp", 31 | "cstdarg": "cpp", 32 | "cstddef": "cpp", 33 | "cstdint": "cpp", 34 | "cstdio": "cpp", 35 | "cstdlib": "cpp", 36 | "cstring": "cpp", 37 | "ctime": "cpp", 38 | "cwchar": "cpp", 39 | "cwctype": "cpp", 40 | "deque": "cpp", 41 | "exception": "cpp", 42 | "fstream": "cpp", 43 | "initializer_list": "cpp", 44 | "iomanip": "cpp", 45 | "iosfwd": "cpp", 46 | "iostream": "cpp", 47 | "istream": "cpp", 48 | "limits": "cpp", 49 | "locale": "cpp", 50 | "memory": "cpp", 51 | "mutex": "cpp", 52 | "new": "cpp", 53 | "optional": "cpp", 54 | "ostream": "cpp", 55 | "ratio": "cpp", 56 | "set": "cpp", 57 | "sstream": "cpp", 58 | "stack": "cpp", 59 | "stdexcept": "cpp", 60 | "string": "cpp", 61 | "string_view": "cpp", 62 | "system_error": "cpp", 63 | "tuple": "cpp", 64 | "type_traits": "cpp", 65 | "typeinfo": "cpp", 66 | "unordered_map": "cpp", 67 | "variant": "cpp", 68 | "vector": "cpp", 69 | "filesystem": "cpp", 70 | "types.h": "c" 71 | } 72 | } -------------------------------------------------------------------------------- /bootstrapd/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:15.0 2 | 3 | THEOS_PACKAGE_SCHEME = roothide 4 | 5 | FINALPACKAGE ?= 1 6 | DEBUG ?= 0 7 | 8 | include $(THEOS)/makefiles/common.mk 9 | 10 | TOOL_NAME = bootstrapd 11 | 12 | #-fvisibility=hidden 13 | 14 | bootstrapd_FILES = $(wildcard *.c *.m *.mm *.cpp) 15 | bootstrapd_CFLAGS = -DBOOTSTRAPD -I./ -fobjc-arc -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-function -Wno-unneeded-internal-declaration 16 | bootstrapd_LDFLAGS = -lbsm 17 | bootstrapd_CODESIGN_FLAGS = -Sentitlements.plist 18 | bootstrapd_INSTALL_PATH = /basebin/ 19 | 20 | include $(THEOS_MAKE_PATH)/tool.mk 21 | 22 | clean:: 23 | rm -rf ./packages/* 24 | 25 | after-install:: 26 | install.exec '$(THEOS_PACKAGE_INSTALL_PREFIX)/basebin/$(TOOL_NAME)' server -f 27 | -------------------------------------------------------------------------------- /bootstrapd/assert.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SIGABRT 6 5 | #define OS_REASON_SIGNAL 2 6 | #define OS_REASON_DYLD 6 7 | #define DYLD_EXIT_REASON_OTHER 9 8 | 9 | void abort_with_payload(uint32_t reason_namespace, uint64_t reason_code, 10 | void *payload, uint32_t payload_size, 11 | const char *reason_string, uint64_t reason_flags) 12 | __attribute__((noreturn, cold)); 13 | 14 | #define ASSERT(e) (__builtin_expect(!(e), 0) ?\ 15 | ((void)fprintf(stderr, "%s:%d: failed ASSERTion `%s'\n", __FILE_NAME__, __LINE__, #e),\ 16 | abort_with_payload(OS_REASON_DYLD,DYLD_EXIT_REASON_OTHER,NULL,0, #e, 0)) : (void)0) 17 | -------------------------------------------------------------------------------- /bootstrapd/bootstrapd.h: -------------------------------------------------------------------------------- 1 | 2 | enum bootstrapReq 3 | { 4 | BSD_REQ_NONE, 5 | BSD_REQ_CHECK_SERVER, 6 | BSD_REQ_STOP_SERVER, 7 | BSD_REQ_GET_SBTOKEN, 8 | BSD_REQ_ENABLE_JIT, 9 | BSD_REQ_ENABLE_JIT2, 10 | BSD_REQ_SSH_CHECK, 11 | BSD_REQ_SSH_START, 12 | BSD_REQ_SSH_STOP, 13 | BSD_REQ_VAR_CLEAN, 14 | BSD_REQ_MAX_REQ 15 | }; 16 | -------------------------------------------------------------------------------- /bootstrapd/common.h: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic ignored "-Wformat-invalid-specifier" 2 | 3 | #ifdef BOOTSTRAPD 4 | 5 | #define SYSLOG(...) NSLog(@ __VA_ARGS__) 6 | 7 | #elif DEBUG==1 8 | 9 | #include 10 | extern int ipc_log_enabled; 11 | #define SYSLOG(...) do if(ipc_log_enabled) {\ 12 | openlog("bootstrap",LOG_PID,LOG_AUTH);\ 13 | syslog(LOG_DEBUG, __VA_ARGS__);closelog();\ 14 | } while(0) 15 | 16 | #define printf SYSLOG 17 | #define perror(x) SYSLOG("%s : %s", x, strerror(errno)) 18 | 19 | #else 20 | 21 | #define SYSLOG(...) 22 | #define printf(...) 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /bootstrapd/control: -------------------------------------------------------------------------------- 1 | Package: com.roothide.bootstrapd 2 | Name: bootstrapd 3 | Version: 0.0.1 4 | Architecture: iphoneos-arm 5 | Description: An awesome tool of some sort!! 6 | Maintainer: roothide 7 | Author: roothide 8 | Section: System 9 | Tag: role::hacker 10 | -------------------------------------------------------------------------------- /bootstrapd/entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | 8 | get-task-allow 9 | 10 | 11 | com.apple.private.security.container-required 12 | 13 | com.apple.private.security.no-container 14 | 15 | com.apple.private.security.no-sandbox 16 | 17 | 18 | com.apple.private.security.storage.AppBundles 19 | 20 | com.apple.private.security.storage.AppDataContainers 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /bootstrapd/envbuf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int envbuf_len(const char *envp[]) 5 | { 6 | if (envp == NULL) return 1; 7 | 8 | int k = 0; 9 | const char *env = envp[k++]; 10 | while (env != NULL) { 11 | env = envp[k++]; 12 | } 13 | return k; 14 | } 15 | 16 | char **envbuf_mutcopy(const char *envp[]) 17 | { 18 | if (envp == NULL) return NULL; //opa said don't comment this 19 | 20 | int len = envbuf_len(envp); 21 | char **envcopy = malloc(len * sizeof(char *)); 22 | 23 | for (int i = 0; i < len-1; i++) { 24 | envcopy[i] = strdup(envp[i]); 25 | } 26 | envcopy[len-1] = NULL; 27 | 28 | return envcopy; 29 | } 30 | 31 | void envbuf_free(char *envp[]) 32 | { 33 | if (envp == NULL) return; 34 | 35 | int len = envbuf_len((const char**)envp); 36 | for (int i = 0; i < len-1; i++) { 37 | free(envp[i]); 38 | } 39 | free(envp); 40 | } 41 | 42 | int envbuf_find(const char *envp[], const char *name) 43 | { 44 | if (envp) { 45 | unsigned long nameLen = strlen(name); 46 | int k = 0; 47 | const char *env = envp[k++]; 48 | while (env != NULL) { 49 | unsigned long envLen = strlen(env); 50 | if (envLen > nameLen) { 51 | if (!strncmp(env, name, nameLen)) { 52 | if (env[nameLen] == '=') { 53 | return k-1; 54 | } 55 | } 56 | } 57 | env = envp[k++]; 58 | } 59 | } 60 | return -1; 61 | } 62 | 63 | const char *envbuf_getenv(const char *envp[], const char *name) 64 | { 65 | if (envp) { 66 | unsigned long nameLen = strlen(name); 67 | int envIndex = envbuf_find(envp, name); 68 | if (envIndex >= 0) { 69 | return &envp[envIndex][nameLen+1]; 70 | } 71 | } 72 | return NULL; 73 | } 74 | 75 | void envbuf_setenv(char **envpp[], const char *name, const char *value, int override) 76 | { 77 | if (envpp) { 78 | char **envp = *envpp; 79 | if (!envp) { 80 | // treat NULL as [NULL] 81 | envp = malloc(sizeof(const char *)); 82 | envp[0] = NULL; 83 | } 84 | 85 | char *envToSet = malloc(strlen(name)+strlen(value)+2); 86 | strcpy(envToSet, name); 87 | strcat(envToSet, "="); 88 | strcat(envToSet, value); 89 | 90 | int existingEnvIndex = envbuf_find((const char **)envp, name); 91 | if (existingEnvIndex >= 0) { 92 | if(!override) { 93 | free(envToSet); 94 | return; 95 | } 96 | // if already exists: deallocate old variable, then replace pointer 97 | free(envp[existingEnvIndex]); 98 | envp[existingEnvIndex] = envToSet; 99 | } 100 | else { 101 | // if doesn't exist yet: increase env buffer size, place at end 102 | int prevLen = envbuf_len((const char **)envp); 103 | *envpp = realloc(envp, (prevLen+1)*sizeof(const char *)); 104 | envp = *envpp; 105 | envp[prevLen-1] = envToSet; 106 | envp[prevLen] = NULL; 107 | } 108 | } 109 | } 110 | 111 | void envbuf_unsetenv(char **envpp[], const char *name) 112 | { 113 | if (envpp) { 114 | char **envp = *envpp; 115 | if (!envp) return; 116 | 117 | int existingEnvIndex = envbuf_find((const char **)envp, name); 118 | if (existingEnvIndex >= 0) { 119 | free(envp[existingEnvIndex]); 120 | int prevLen = envbuf_len((const char **)envp); 121 | for (int i = existingEnvIndex; i < (prevLen-1); i++) { 122 | envp[i] = envp[i+1]; 123 | } 124 | *envpp = realloc(envp, (prevLen-1)*sizeof(const char *)); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /bootstrapd/envbuf.h: -------------------------------------------------------------------------------- 1 | int envbuf_len(const char *envp[]); 2 | char **envbuf_mutcopy(const char *envp[]); 3 | void envbuf_free(char *envp[]); 4 | int envbuf_find(const char *envp[], const char *name); 5 | const char *envbuf_getenv(const char *envp[], const char *name); 6 | void envbuf_setenv(char **envpp[], const char *name, const char *value, int overwrite); 7 | void envbuf_unsetenv(char **envpp[], const char *name); -------------------------------------------------------------------------------- /bootstrapd/ipc.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int connect_to_server(); 4 | 5 | int run_ipc_server(int (*callback)(int socket, pid_t pid, int reqId, NSDictionary* msg)); 6 | int set_stop_server(); 7 | 8 | int request(int socket, int reqId, NSDictionary* msg); 9 | int reply(int socket, NSDictionary* msg); 10 | NSDictionary* reponse(int socket); 11 | -------------------------------------------------------------------------------- /bootstrapd/jiter.m: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include "common.h" 6 | #include "libproc.h" 7 | #include "libproc_private.h" 8 | 9 | 10 | /* Status values. */ 11 | #define SIDL 1 /* Process being created by fork. */ 12 | #define SRUN 2 /* Currently runnable. */ 13 | #define SSLEEP 3 /* Sleeping on an address. */ 14 | #define SSTOP 4 /* Process debugging or suspension. */ 15 | #define SZOMB 5 /* Awaiting collection by parent. */ 16 | 17 | int proc_paused(pid_t pid, bool* paused) 18 | { 19 | *paused = false; 20 | 21 | struct proc_bsdinfo procInfo={0}; 22 | int ret = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &procInfo, sizeof(procInfo)); 23 | if(ret != sizeof(procInfo)) { 24 | SYSLOG("bsdinfo failed, %d,%s\n", errno, strerror(errno)); 25 | return -1; 26 | } 27 | 28 | if(procInfo.pbi_status == SSTOP) 29 | { 30 | SYSLOG("%d pstat=%x flag=%x xstat=%x\n", ret, procInfo.pbi_status, procInfo.pbi_flags, procInfo.pbi_xstatus); 31 | *paused = true; 32 | } 33 | else if(procInfo.pbi_status != SRUN) { 34 | SYSLOG("unexcept %d pstat=%x\n", ret, procInfo.pbi_status); 35 | return -1; 36 | } 37 | 38 | return 0; 39 | } 40 | 41 | 42 | #define PT_DETACH 11 /* stop tracing a process */ 43 | #define PT_ATTACHEXC 14 /* attach to running process with signal exception */ 44 | int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data); 45 | 46 | #include 47 | 48 | int enableJIT(pid_t pid) 49 | { 50 | int ret = ptrace(PT_ATTACHEXC, pid, NULL, 0); 51 | SYSLOG("attach=%d", ret); 52 | if(ret != 0) return ret; 53 | 54 | //don't SIGCONT here, otherwise kernel may send exception msg to this process and the traced process keep waiting, kill(pid, SIGCONT); 55 | 56 | bool paused=false; 57 | for(int i=0; i<1000*50; i++) 58 | { 59 | ret = proc_paused(pid, &paused); 60 | SYSLOG("paused=%d, %d", ret, paused); 61 | 62 | if(ret != 0) return ret; 63 | 64 | if(paused) break; 65 | 66 | usleep(10); 67 | } 68 | 69 | if(!paused) { 70 | SYSLOG("*** ptrace: wait process timeout"); 71 | } 72 | 73 | ret = ptrace(PT_DETACH, pid, NULL, 0); 74 | SYSLOG("detach=%d, %s", ret, ret==0?"":strerror(errno)); 75 | 76 | return ret; 77 | } 78 | -------------------------------------------------------------------------------- /bootstrapd/libbsd.h: -------------------------------------------------------------------------------- 1 | 2 | int bsd_enableJIT(); 3 | int bsd_enableJIT2(pid_t pid); 4 | 5 | const char* bsd_getsbtoken(); 6 | 7 | int bsd_opensshcheck(); 8 | int bsd_opensshctl(bool run); 9 | 10 | int bsd_checkServer(); 11 | int bsd_stopServer(); 12 | 13 | int bsd_varClean(); 14 | -------------------------------------------------------------------------------- /bootstrapd/libbsd.m: -------------------------------------------------------------------------------- 1 | 2 | #include "../bootstrapd/ipc.h" 3 | #include "../bootstrapd/bootstrapd.h" 4 | #include "../bootstrapd/common.h" 5 | 6 | int bsd_enableJIT() 7 | { 8 | int result=-1; 9 | 10 | int sd = connect_to_server(); 11 | if(sd <= 0) return -1; 12 | int req = request(sd, BSD_REQ_ENABLE_JIT, nil); 13 | SYSLOG("request=%d", req); 14 | if(req == 0) { 15 | NSDictionary* rep = reponse(sd); 16 | SYSLOG("reponse=%@", rep); 17 | NSNumber* resultObj = rep[@"result"]; 18 | if(resultObj) result = resultObj.intValue; 19 | } 20 | close(sd); 21 | 22 | return result; 23 | } 24 | 25 | extern int ipc_log_enabled; 26 | int bsd_enableJIT2(pid_t pid) 27 | { 28 | ipc_log_enabled=0; 29 | 30 | int result=-1; 31 | 32 | int sd = connect_to_server(); 33 | if(sd <= 0) return -1; 34 | int req = request(sd, BSD_REQ_ENABLE_JIT2, @{@"pid":@(pid)}); 35 | SYSLOG("request=%d", req); 36 | if(req == 0) { 37 | NSDictionary* rep = reponse(sd); 38 | SYSLOG("reponse=%@", rep); 39 | NSNumber* resultObj = rep[@"result"]; 40 | if(resultObj) result = resultObj.intValue; 41 | } 42 | close(sd); 43 | 44 | ipc_log_enabled=1; 45 | 46 | return result; 47 | } 48 | 49 | const char* bsd_getsbtoken() 50 | { 51 | const char* result=nil; 52 | 53 | int sd = connect_to_server(); 54 | if(sd <= 0) return NULL; 55 | int req = request(sd, BSD_REQ_GET_SBTOKEN, nil); 56 | SYSLOG("request=%d", req); 57 | if(req == 0) { 58 | NSDictionary* rep = reponse(sd); 59 | result = [rep[@"sbtoken"] UTF8String]; 60 | SYSLOG("reponse=%@", rep); 61 | } 62 | close(sd); 63 | 64 | return result; 65 | } 66 | 67 | int bsd_opensshctl(bool run) 68 | { 69 | int result = -1; 70 | 71 | int sd = connect_to_server(); 72 | if(sd <= 0) return -1; 73 | int req = request(sd, run ? BSD_REQ_SSH_START : BSD_REQ_SSH_STOP, nil); 74 | SYSLOG("request=%d", req); 75 | if(req == 0) { 76 | NSDictionary* rep = reponse(sd); 77 | SYSLOG("reponse=%@", rep); 78 | NSNumber* resultObj = rep[@"result"]; 79 | if(resultObj) result = resultObj.intValue; 80 | } 81 | close(sd); 82 | 83 | return result; 84 | } 85 | 86 | int bsd_opensshcheck() 87 | { 88 | int result = -1; 89 | 90 | int sd = connect_to_server(); 91 | if(sd <= 0) return -1; 92 | int req = request(sd, BSD_REQ_SSH_CHECK, nil); 93 | SYSLOG("request=%d", req); 94 | if(req == 0) { 95 | NSDictionary* rep = reponse(sd); 96 | SYSLOG("reponse=%@", rep); 97 | NSNumber* resultObj = rep[@"result"]; 98 | if(resultObj) result = resultObj.intValue; 99 | } 100 | close(sd); 101 | 102 | return result; 103 | } 104 | 105 | int bsd_stopServer() 106 | { 107 | int result = -1; 108 | 109 | int sd = connect_to_server(); 110 | if(sd <= 0) return -1; 111 | int req = request(sd, BSD_REQ_STOP_SERVER, nil); 112 | SYSLOG("request=%d", req); 113 | if(req == 0) { 114 | NSDictionary* rep = reponse(sd); 115 | SYSLOG("reponse=%@", rep); 116 | NSNumber* resultObj = rep[@"result"]; 117 | if(resultObj) result = resultObj.intValue; 118 | } 119 | close(sd); 120 | 121 | return result; 122 | } 123 | 124 | int bsd_checkServer() 125 | { 126 | int result = -1; 127 | 128 | int sd = connect_to_server(); 129 | if(sd <= 0) return -1; 130 | int req = request(sd, BSD_REQ_CHECK_SERVER, nil); 131 | SYSLOG("request=%d", req); 132 | if(req == 0) { 133 | NSDictionary* rep = reponse(sd); 134 | SYSLOG("reponse=%@", rep); 135 | NSNumber* resultObj = rep[@"result"]; 136 | if(resultObj) result = resultObj.intValue; 137 | } 138 | close(sd); 139 | 140 | return result; 141 | } 142 | 143 | int bsd_varClean() 144 | { 145 | int result = -1; 146 | 147 | int sd = connect_to_server(); 148 | if(sd <= 0) return -1; 149 | int req = request(sd, BSD_REQ_VAR_CLEAN, @{@"bundleIdentifier":NSBundle.mainBundle.bundleIdentifier}); 150 | SYSLOG("request=%d", req); 151 | if(req == 0) { 152 | NSDictionary* rep = reponse(sd); 153 | SYSLOG("reponse=%@", rep); 154 | NSNumber* resultObj = rep[@"result"]; 155 | if(resultObj) result = resultObj.intValue; 156 | } 157 | close(sd); 158 | 159 | return result; 160 | } 161 | -------------------------------------------------------------------------------- /bootstrapd/libproc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, 2007, 2010 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _LIBPROC_H_ 24 | #define _LIBPROC_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | /* 38 | * This header file contains private interfaces to obtain process information. 39 | * These interfaces are subject to change in future releases. 40 | */ 41 | 42 | /*! 43 | @define PROC_LISTPIDSPATH_PATH_IS_VOLUME 44 | @discussion This flag indicates that all processes that hold open 45 | file references on the volume associated with the specified 46 | path should be returned. 47 | */ 48 | #define PROC_LISTPIDSPATH_PATH_IS_VOLUME 1 49 | 50 | 51 | /*! 52 | @define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 53 | @discussion This flag indicates that file references that were opened 54 | with the O_EVTONLY flag should be excluded from the matching 55 | criteria. 56 | */ 57 | #define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 2 58 | 59 | __BEGIN_DECLS 60 | 61 | 62 | /*! 63 | @function proc_listpidspath 64 | @discussion A function which will search through the current 65 | processes looking for open file references which match 66 | a specified path or volume. 67 | @param type types of processes to be searched (see proc_listpids) 68 | @param typeinfo adjunct information for type 69 | @param path file or volume path 70 | @param pathflags flags to control which files should be considered 71 | during the process search. 72 | @param buffer a C array of int-sized values to be filled with 73 | process identifiers that hold an open file reference 74 | matching the specified path or volume. Pass NULL to 75 | obtain the minimum buffer size needed to hold the 76 | currently active processes. 77 | @param buffersize the size (in bytes) of the provided buffer. 78 | @result the number of bytes of data returned in the provided buffer; 79 | -1 if an error was encountered; 80 | */ 81 | int proc_listpidspath(uint32_t type, 82 | uint32_t typeinfo, 83 | const char *path, 84 | uint32_t pathflags, 85 | void *buffer, 86 | int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 87 | 88 | int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 89 | int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); 90 | int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); 91 | int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); 92 | int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 93 | int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 94 | int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); 95 | int proc_name(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 96 | int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 97 | int proc_kmsgbuf(void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 98 | int proc_pidpath(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 99 | int proc_libversion(int *major, int * minor) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); 100 | 101 | /* 102 | * Return resource usage information for the given pid, which can be a live process or a zombie. 103 | * 104 | * Returns 0 on success; or -1 on failure, with errno set to indicate the specific error. 105 | */ 106 | int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); 107 | 108 | /* 109 | * A process can use the following api to set its own process control 110 | * state on resoure starvation. The argument can have one of the PROC_SETPC_XX values 111 | */ 112 | #define PROC_SETPC_NONE 0 113 | #define PROC_SETPC_THROTTLEMEM 1 114 | #define PROC_SETPC_SUSPEND 2 115 | #define PROC_SETPC_TERMINATE 3 116 | 117 | int proc_setpcontrol(const int control) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); 118 | int proc_setpcontrol(const int control); 119 | 120 | int proc_track_dirty(pid_t pid, uint32_t flags); 121 | int proc_set_dirty(pid_t pid, bool dirty); 122 | int proc_get_dirty(pid_t pid, uint32_t *flags); 123 | 124 | int proc_terminate(pid_t pid, int *sig); 125 | 126 | __END_DECLS 127 | 128 | #endif /*_LIBPROC_H_ */ 129 | -------------------------------------------------------------------------------- /bootstrapd/libproc_private.h: -------------------------------------------------------------------------------- 1 | struct proc_bsdinfo { 2 | uint32_t pbi_flags; /* 64bit; emulated etc */ 3 | uint32_t pbi_status; 4 | uint32_t pbi_xstatus; 5 | uint32_t pbi_pid; 6 | uint32_t pbi_ppid; 7 | uid_t pbi_uid; 8 | gid_t pbi_gid; 9 | uid_t pbi_ruid; 10 | gid_t pbi_rgid; 11 | uid_t pbi_svuid; 12 | gid_t pbi_svgid; 13 | uint32_t rfu_1; /* reserved */ 14 | char pbi_comm[MAXCOMLEN]; 15 | char pbi_name[2 * MAXCOMLEN]; /* empty if no name is registered */ 16 | uint32_t pbi_nfiles; 17 | uint32_t pbi_pgid; 18 | uint32_t pbi_pjobc; 19 | uint32_t e_tdev; /* controlling tty dev */ 20 | uint32_t e_tpgid; /* tty process group id */ 21 | int32_t pbi_nice; 22 | uint64_t pbi_start_tvsec; 23 | uint64_t pbi_start_tvusec; 24 | }; 25 | 26 | #define PROC_PIDTBSDINFO 3 27 | #define PROC_PIDTBSDINFO_SIZE (sizeof(struct proc_bsdinfo)) -------------------------------------------------------------------------------- /bootstrapd/usreboot.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #undef CFSTR 14 | #define CFSTR(x) @ x 15 | #undef xpc_release 16 | #define xpc_release(x) //error: ARC forbids explicit message send of 'release' 17 | 18 | 19 | int userspaceReboot(void) 20 | { 21 | kern_return_t ret = 0; 22 | xpc_object_t xdict = xpc_dictionary_create(NULL, NULL, 0); 23 | xpc_dictionary_set_uint64(xdict, "cmd", 5); 24 | ret = unlink("/private/var/mobile/Library/MemoryMaintenance/mmaintenanced"); 25 | if (ret && errno != ENOENT) { 26 | NSLog(CFSTR("could not delete mmaintenanced last reboot file")); 27 | return -1; 28 | } 29 | xpc_connection_t connection = xpc_connection_create_mach_service("com.apple.mmaintenanced", NULL, 0); 30 | 31 | if (xpc_get_type(connection) == XPC_TYPE_ERROR) { 32 | char* desc = xpc_copy_description(connection); 33 | NSLog(CFSTR("%s"),desc); 34 | free(desc); 35 | xpc_release(connection); 36 | return -1; 37 | } 38 | xpc_connection_set_event_handler(connection, ^(xpc_object_t random) {}); 39 | xpc_connection_activate(connection); 40 | char* desc = xpc_copy_description(connection); 41 | puts(desc); 42 | NSLog(CFSTR("mmaintenanced connection created")); 43 | xpc_object_t reply = xpc_connection_send_message_with_reply_sync(connection, xdict); 44 | if (reply) { 45 | char* desc = xpc_copy_description(reply); 46 | NSLog(CFSTR("%s"),desc); 47 | free(desc); 48 | ret = 0; 49 | } else { 50 | NSLog(CFSTR("no reply received from mmaintenanced")); 51 | ret = -1; 52 | } 53 | 54 | 55 | xpc_connection_cancel(connection); 56 | xpc_release(connection); 57 | xpc_release(reply); 58 | xpc_release(xdict); 59 | return ret; 60 | } -------------------------------------------------------------------------------- /bootstrapd/varClean.m: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | char* varCleanPatterns[][4] = { 6 | {"","Library/Preferences",".plist",(char*)true}, 7 | {"","Library/SplashBoard/Snapshots","",(char*)true}, 8 | {"","Library/Saved Application State",".savedState",(char*)true}, 9 | 10 | {"","Library/Caches","",(char*)false}, 11 | {"","Library/WebKit","",(char*)false}, 12 | {"","Library/Cookies",".binarycookies",(char*)false}, 13 | {"","Library/HTTPStorages","",(char*)false}, 14 | {"","Library/Application Support/Containers","",(char*)false}, 15 | }; 16 | 17 | dispatch_queue_t varCleanQueue = nil; 18 | NSMutableDictionary* varCleanDict = nil; 19 | 20 | void doVarClean(const char* bundleIdentifier, bool all) 21 | { 22 | //if the user has enabled URLSchemes, this means the user does not need to hide the "jailbreak" 23 | if(access(jbroot("/var/mobile/.allow_url_schemes"), F_OK)==0) { 24 | return; 25 | } 26 | 27 | NSLog(@"varClean: doVarClean(%d) %s", all, bundleIdentifier); 28 | 29 | for(int i=0; i 5 | 6 | // Certain parts of the project use all the project's headers but have to build 7 | // against newer OSX SDKs than ebuild uses -- liblaunch_host being the example. 8 | // So we need to define these. 9 | #ifndef __MAC_10_13 10 | #define __MAC_10_13 101300 11 | #define __AVAILABILITY_INTERNAL__MAC_10_13 \ 12 | __attribute__((availability(macosx, introduced=10.13))) 13 | #endif // __MAC_10_13 14 | 15 | #ifndef __MAC_10_12 16 | #define __MAC_10_12 101200 17 | #define __AVAILABILITY_INTERNAL__MAC_10_12 \ 18 | __attribute__((availability(macosx, introduced=10.12))) 19 | #endif // __MAC_10_12 20 | 21 | #ifndef __MAC_10_11 22 | #define __MAC_10_11 101100 23 | #define __AVAILABILITY_INTERNAL__MAC_10_11 \ 24 | __attribute__((availability(macosx, introduced=10.11))) 25 | #endif // __MAC_10_11 26 | 27 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_11 28 | #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_11 29 | #endif // __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_11 30 | 31 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_11 32 | #define __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_11 33 | #endif // __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_11 34 | 35 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_4_DEP__MAC_10_11 36 | #define __AVAILABILITY_INTERNAL__MAC_10_4_DEP__MAC_10_11 37 | #endif // __AVAILABILITY_INTERNAL__MAC_10_4_DEP__MAC_10_11 38 | 39 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_5_DEP__MAC_10_11 40 | #define __AVAILABILITY_INTERNAL__MAC_10_5_DEP__MAC_10_11 41 | #endif // __AVAILABILITY_INTERNAL__MAC_10_5_DEP__MAC_10_11 42 | 43 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_6_DEP__MAC_10_11 44 | #define __AVAILABILITY_INTERNAL__MAC_10_6_DEP__MAC_10_11 45 | #endif // __AVAILABILITY_INTERNAL__MAC_10_6_DEP__MAC_10_11 46 | 47 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_7_DEP__MAC_10_11 48 | #define __AVAILABILITY_INTERNAL__MAC_10_7_DEP__MAC_10_11 49 | #endif // __AVAILABILITY_INTERNAL__MAC_10_7_DEP__MAC_10_11 50 | 51 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_8_DEP__MAC_10_11 52 | #define __AVAILABILITY_INTERNAL__MAC_10_8_DEP__MAC_10_11 53 | #endif // __AVAILABILITY_INTERNAL__MAC_10_8_DEP__MAC_10_11 54 | 55 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_9_DEP__MAC_10_11 56 | #define __AVAILABILITY_INTERNAL__MAC_10_9_DEP__MAC_10_11 57 | #endif // __AVAILABILITY_INTERNAL__MAC_10_9_DEP__MAC_10_11 58 | 59 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_10_DEP__MAC_10_11 60 | #define __AVAILABILITY_INTERNAL__MAC_10_10_DEP__MAC_10_11 61 | #endif // __AVAILABILITY_INTERNAL__MAC_10_10_DEP__MAC_10_11 62 | 63 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_11_DEP__MAC_10_11 64 | #define __AVAILABILITY_INTERNAL__MAC_10_11_DEP__MAC_10_11 65 | #endif // __AVAILABILITY_INTERNAL__MAC_10_11_DEP__MAC_10_11 66 | 67 | #ifndef __AVAILABILITY_INTERNAL__MAC_10_6_DEP__MAC_10_13 68 | #define __AVAILABILITY_INTERNAL__MAC_10_6_DEP__MAC_10_13 69 | #endif // __AVAILABILITY_INTERNAL__MAC_10_6_DEP__MAC_10_13 70 | 71 | #if __has_include() 72 | #include 73 | #else // __has_include() 74 | #ifndef IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED 75 | #define IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED 999999 76 | #endif // IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED 77 | #endif // __has_include() 78 | 79 | #ifndef __WATCHOS_UNAVAILABLE 80 | #define __WATCHOS_UNAVAILABLE 81 | #endif 82 | 83 | #ifndef __TVOS_UNAVAILABLE 84 | #define __TVOS_UNAVAILABLE 85 | #endif 86 | 87 | // simulator host-side bits build against SDKs not having __*_AVAILABLE() yet 88 | #ifndef __OSX_AVAILABLE 89 | #define __OSX_AVAILABLE(...) 90 | #endif 91 | 92 | #ifndef __IOS_AVAILABLE 93 | #define __IOS_AVAILABLE(...) 94 | #endif 95 | 96 | #ifndef __TVOS_AVAILABLE 97 | #define __TVOS_AVAILABLE(...) 98 | #endif 99 | 100 | #ifndef __WATCHOS_AVAILABLE 101 | #define __WATCHOS_AVAILABLE(...) 102 | #endif 103 | 104 | #ifndef __API_AVAILABLE 105 | #define __API_AVAILABLE(...) 106 | #endif 107 | 108 | #endif // __XPC_AVAILABILITY_H__ 109 | -------------------------------------------------------------------------------- /bootstrapd/xpc/base.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2011 Apple Inc. All rights reserved. 2 | 3 | #ifndef __XPC_BASE_H__ 4 | #define __XPC_BASE_H__ 5 | 6 | #include 7 | 8 | __BEGIN_DECLS 9 | 10 | #if !defined(__has_include) 11 | #define __has_include(x) 0 12 | #endif // !defined(__has_include) 13 | 14 | #if !defined(__has_attribute) 15 | #define __has_attribute(x) 0 16 | #endif // !defined(__has_attribute) 17 | 18 | #if !defined(__has_feature) 19 | #define __has_feature(x) 0 20 | #endif // !defined(__has_feature) 21 | 22 | #if !defined(__has_extension) 23 | #define __has_extension(x) 0 24 | #endif // !defined(__has_extension) 25 | 26 | #if __has_include() 27 | #include 28 | #else // __has_include() 29 | #include 30 | #endif // __has_include() 31 | 32 | #if XPC_SERVICE_MAIN_IN_LIBXPC 33 | #define XPC_HOSTING_OLD_MAIN 1 34 | #else // XPC_SERVICE_MAIN_IN_LIBXPC 35 | #define XPC_HOSTING_OLD_MAIN 0 36 | #endif // XPC_SERVICE_MAIN_IN_LIBXPC 37 | 38 | #ifndef __XPC_INDIRECT__ 39 | #error "Please #include instead of this file directly." 40 | #endif // __XPC_INDIRECT__ 41 | 42 | #pragma mark Attribute Shims 43 | #ifdef __GNUC__ 44 | #define XPC_CONSTRUCTOR __attribute__((constructor)) 45 | #define XPC_NORETURN __attribute__((__noreturn__)) 46 | #define XPC_NOTHROW __attribute__((__nothrow__)) 47 | #define XPC_NONNULL1 __attribute__((__nonnull__(1))) 48 | #define XPC_NONNULL2 __attribute__((__nonnull__(2))) 49 | #define XPC_NONNULL3 __attribute__((__nonnull__(3))) 50 | #define XPC_NONNULL4 __attribute__((__nonnull__(4))) 51 | #define XPC_NONNULL5 __attribute__((__nonnull__(5))) 52 | #define XPC_NONNULL6 __attribute__((__nonnull__(6))) 53 | #define XPC_NONNULL7 __attribute__((__nonnull__(7))) 54 | #define XPC_NONNULL8 __attribute__((__nonnull__(8))) 55 | #define XPC_NONNULL9 __attribute__((__nonnull__(9))) 56 | #define XPC_NONNULL10 __attribute__((__nonnull__(10))) 57 | #define XPC_NONNULL11 __attribute__((__nonnull__(11))) 58 | #define XPC_NONNULL_ALL __attribute__((__nonnull__)) 59 | #define XPC_SENTINEL __attribute__((__sentinel__)) 60 | #define XPC_PURE __attribute__((__pure__)) 61 | #define XPC_WARN_RESULT __attribute__((__warn_unused_result__)) 62 | #define XPC_MALLOC __attribute__((__malloc__)) 63 | #define XPC_UNUSED __attribute__((__unused__)) 64 | #define XPC_USED __attribute__((__used__)) 65 | #define XPC_PACKED __attribute__((__packed__)) 66 | #define XPC_PRINTF(m, n) __attribute__((format(printf, m, n))) 67 | #define XPC_INLINE static __inline__ __attribute__((__always_inline__)) 68 | #define XPC_NOINLINE __attribute__((noinline)) 69 | #define XPC_NOIMPL __attribute__((unavailable)) 70 | 71 | #if __has_attribute(noescape) 72 | #define XPC_NOESCAPE __attribute__((__noescape__)) 73 | #else 74 | #define XPC_NOESCAPE 75 | #endif 76 | 77 | #if __has_extension(attribute_unavailable_with_message) 78 | #define XPC_UNAVAILABLE(m) __attribute__((unavailable(m))) 79 | #else // __has_extension(attribute_unavailable_with_message) 80 | #define XPC_UNAVAILABLE(m) XPC_NOIMPL 81 | #endif // __has_extension(attribute_unavailable_with_message) 82 | 83 | #define XPC_EXPORT extern __attribute__((visibility("default"))) 84 | #define XPC_NOEXPORT __attribute__((visibility("hidden"))) 85 | #define XPC_WEAKIMPORT extern __attribute__((weak_import)) 86 | #define XPC_DEBUGGER_EXCL XPC_NOEXPORT XPC_USED 87 | #define XPC_TRANSPARENT_UNION __attribute__((transparent_union)) 88 | #if __clang__ 89 | #define XPC_DEPRECATED(m) __attribute__((deprecated(m))) 90 | #else // __clang__ 91 | #define XPC_DEPRECATED(m) __attribute__((deprecated)) 92 | #endif // __clang 93 | 94 | #if __XPC_TEST__ 95 | #define XPC_TESTSTATIC 96 | #else // __XPC_TEST__ 97 | #define XPC_TESTSTATIC static 98 | #endif // __XPC_TEST__ 99 | 100 | #if __has_feature(objc_arc) 101 | #define XPC_GIVES_REFERENCE __strong 102 | #define XPC_UNRETAINED __unsafe_unretained 103 | #define XPC_BRIDGE(xo) ((__bridge void *)(xo)) 104 | #define XPC_BRIDGEREF_BEGIN(xo) ((__bridge_retained void *)(xo)) 105 | #define XPC_BRIDGEREF_BEGIN_WITH_REF(xo) ((__bridge void *)(xo)) 106 | #define XPC_BRIDGEREF_MIDDLE(xo) ((__bridge id)(xo)) 107 | #define XPC_BRIDGEREF_END(xo) ((__bridge_transfer id)(xo)) 108 | #else // __has_feature(objc_arc) 109 | #define XPC_GIVES_REFERENCE 110 | #define XPC_UNRETAINED 111 | #define XPC_BRIDGE(xo) (xo) 112 | #define XPC_BRIDGEREF_BEGIN(xo) (xo) 113 | #define XPC_BRIDGEREF_BEGIN_WITH_REF(xo) (xo) 114 | #define XPC_BRIDGEREF_MIDDLE(xo) (xo) 115 | #define XPC_BRIDGEREF_END(xo) (xo) 116 | #endif // __has_feature(objc_arc) 117 | 118 | #define _xpc_unreachable() __builtin_unreachable() 119 | #else // __GNUC__ 120 | /*! @parseOnly */ 121 | #define XPC_CONSTRUCTOR 122 | /*! @parseOnly */ 123 | #define XPC_NORETURN 124 | /*! @parseOnly */ 125 | #define XPC_NOTHROW 126 | /*! @parseOnly */ 127 | #define XPC_NONNULL1 128 | /*! @parseOnly */ 129 | #define XPC_NONNULL2 130 | /*! @parseOnly */ 131 | #define XPC_NONNULL3 132 | /*! @parseOnly */ 133 | #define XPC_NONNULL4 134 | /*! @parseOnly */ 135 | #define XPC_NONNULL5 136 | /*! @parseOnly */ 137 | #define XPC_NONNULL6 138 | /*! @parseOnly */ 139 | #define XPC_NONNULL7 140 | /*! @parseOnly */ 141 | #define XPC_NONNULL8 142 | /*! @parseOnly */ 143 | #define XPC_NONNULL9 144 | /*! @parseOnly */ 145 | #define XPC_NONNULL10 146 | /*! @parseOnly */ 147 | #define XPC_NONNULL11 148 | /*! @parseOnly */ 149 | #define XPC_NONNULL(n) 150 | /*! @parseOnly */ 151 | #define XPC_NONNULL_ALL 152 | /*! @parseOnly */ 153 | #define XPC_SENTINEL 154 | /*! @parseOnly */ 155 | #define XPC_PURE 156 | /*! @parseOnly */ 157 | #define XPC_WARN_RESULT 158 | /*! @parseOnly */ 159 | #define XPC_MALLOC 160 | /*! @parseOnly */ 161 | #define XPC_UNUSED 162 | /*! @parseOnly */ 163 | #define XPC_PACKED 164 | /*! @parseOnly */ 165 | #define XPC_PRINTF(m, n) 166 | /*! @parseOnly */ 167 | #define XPC_INLINE static inline 168 | /*! @parseOnly */ 169 | #define XPC_NOINLINE 170 | /*! @parseOnly */ 171 | #define XPC_NOIMPL 172 | /*! @parseOnly */ 173 | #define XPC_EXPORT extern 174 | /*! @parseOnly */ 175 | #define XPC_WEAKIMPORT 176 | /*! @parseOnly */ 177 | #define XPC_DEPRECATED 178 | /*! @parseOnly */ 179 | #define XPC_UNAVAILABLE(m) 180 | /*! @parseOnly */ 181 | #define XPC_NOESCAPE 182 | #endif // __GNUC__ 183 | 184 | #if __has_feature(assume_nonnull) 185 | #define XPC_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") 186 | #define XPC_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") 187 | #else 188 | #define XPC_ASSUME_NONNULL_BEGIN 189 | #define XPC_ASSUME_NONNULL_END 190 | #endif 191 | 192 | #if __has_feature(nullability_on_arrays) 193 | #define XPC_NONNULL_ARRAY _Nonnull 194 | #else 195 | #define XPC_NONNULL_ARRAY 196 | #endif 197 | 198 | __END_DECLS 199 | 200 | #endif // __XPC_BASE_H__ 201 | -------------------------------------------------------------------------------- /bootstrapd/xpc/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef __XPC_DEBUG_H__ 2 | #define __XPC_DEBUG_H__ 3 | 4 | /*! 5 | * @function xpc_debugger_api_misuse_info 6 | * Returns a pointer to a string describing the reason XPC aborted the calling 7 | * process. On OS X, this will be the same string present in the "Application 8 | * Specific Information" section of the crash report. 9 | * 10 | * @result 11 | * A pointer to the human-readable string describing the reason the caller was 12 | * aborted. If XPC was not responsible for the program's termination, NULL will 13 | * be returned. 14 | * 15 | * @discussion 16 | * This function is only callable from within a debugger. It is not meant to be 17 | * called by the program directly. 18 | */ 19 | XPC_DEBUGGER_EXCL 20 | const char * 21 | xpc_debugger_api_misuse_info(void); 22 | 23 | #endif // __XPC_DEBUG_H__ 24 | -------------------------------------------------------------------------------- /bootstrapd/xpc/endpoint.h: -------------------------------------------------------------------------------- 1 | #ifndef __XPC_ENDPOINT_H__ 2 | #define __XPC_ENDPOINT_H__ 3 | 4 | /*! 5 | * @function xpc_endpoint_create 6 | * Creates a new endpoint from a connection that is suitable for embedding into 7 | * messages. 8 | * 9 | * @param connection 10 | * Only connections obtained through calls to xpc_connection_create*() may be 11 | * given to this API. Passing any other type of connection is not supported and 12 | * will result in undefined behavior. 13 | * 14 | * @result 15 | * A new endpoint object. 16 | */ 17 | __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0) 18 | XPC_EXPORT XPC_MALLOC XPC_RETURNS_RETAINED XPC_WARN_RESULT XPC_NONNULL1 19 | xpc_endpoint_t _Nonnull 20 | xpc_endpoint_create(xpc_connection_t _Nonnull connection); 21 | 22 | #endif // __XPC_ENDPOINT_H__ 23 | -------------------------------------------------------------------------------- /bootstrapd/xpc/module.modulemap: -------------------------------------------------------------------------------- 1 | module XPC [system] [extern_c] { 2 | header "xpc.h" 3 | header "availability.h" 4 | header "base.h" 5 | header "activity.h" 6 | header "connection.h" 7 | header "debug.h" 8 | header "endpoint.h" 9 | export * 10 | } 11 | -------------------------------------------------------------------------------- /bootstrapd/xpc/private.h: -------------------------------------------------------------------------------- 1 | extern XPC_RETURNS_RETAINED xpc_object_t xpc_pipe_create_from_port(mach_port_t port, uint32_t flags); 2 | extern XPC_RETURNS_RETAINED xpc_object_t xpc_array_create_empty(void); 3 | extern XPC_RETURNS_RETAINED xpc_object_t xpc_dictionary_create_empty(void); 4 | extern int xpc_pipe_simpleroutine(xpc_object_t pipe, xpc_object_t message); 5 | extern int xpc_pipe_routine_reply(xpc_object_t reply); 6 | void xpc_dictionary_get_audit_token(xpc_object_t xdict, audit_token_t *token); 7 | char *xpc_strerror (int); 8 | 9 | extern XPC_RETURNS_RETAINED xpc_object_t xpc_pipe_create_from_port(mach_port_t port, uint32_t flags); 10 | extern int xpc_pipe_simpleroutine(xpc_object_t pipe, xpc_object_t message); 11 | extern int xpc_pipe_routine(xpc_object_t pipe, xpc_object_t message, XPC_GIVES_REFERENCE xpc_object_t *reply); 12 | extern int xpc_pipe_routine_with_flags(xpc_object_t xpc_pipe, xpc_object_t inDict, XPC_GIVES_REFERENCE xpc_object_t *reply, uint32_t flags); 13 | extern int xpc_pipe_routine_reply(xpc_object_t reply); 14 | extern int xpc_pipe_receive(mach_port_t port, XPC_GIVES_REFERENCE xpc_object_t *message); 15 | 16 | extern XPC_RETURNS_RETAINED xpc_object_t xpc_copy_entitlement_for_token(const char *, audit_token_t *); -------------------------------------------------------------------------------- /copy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | PREV_DIR=$(pwd) 6 | WORK_DIR=$(dirname -- "$0") 7 | cd "$WORK_DIR" 8 | 9 | TARGET="../Bootstrap/basebin/" 10 | 11 | if [ -d "$TARGET" ]; then 12 | rm -rf "$TARGET" 13 | fi 14 | 15 | mkdir $TARGET 16 | 17 | cp ./test.sh $TARGET 18 | cp ./ldid/ldid $TARGET 19 | cp ./nickchan.entitlements $TARGET 20 | cp ./bootstrap.entitlements $TARGET 21 | cp -a ./entitlements $TARGET 22 | cp ./fastPathSign/fastPathSign $TARGET 23 | cp ./devtest/.theos/_/basebin/devtest $TARGET 24 | cp ./uicache/.theos/_/basebin/uicache $TARGET 25 | cp ./preload/.theos/_/basebin/preload $TARGET 26 | cp ./preload/.theos/_/basebin/preload.dylib $TARGET 27 | cp ./bootstrap/.theos/_/basebin/bootstrap.dylib $TARGET 28 | cp ./bootstrapd/.theos/_/basebin/bootstrapd $TARGET 29 | cp ./rebuildapp/.theos/_/basebin/rebuildapp $TARGET 30 | cp ./rebuildapp/.theos/_/basebin/rebuildapps.sh $TARGET 31 | 32 | echo "***** copy finished *****" 33 | 34 | cd "$PREV_DIR" 35 | -------------------------------------------------------------------------------- /devtest/.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | packages/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /devtest/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:7.0 2 | 3 | include $(THEOS)/makefiles/common.mk 4 | 5 | TOOL_NAME = devtest 6 | 7 | devtest_FILES = main.m 8 | devtest_CFLAGS = -fobjc-arc 9 | devtest_CODESIGN_FLAGS = -Sentitlements.plist 10 | devtest_INSTALL_PATH = /basebin 11 | 12 | include $(THEOS_MAKE_PATH)/tool.mk 13 | 14 | clean:: 15 | rm -rf ./packages/* 16 | -------------------------------------------------------------------------------- /devtest/control: -------------------------------------------------------------------------------- 1 | Package: com.roothide.devtest 2 | Name: devtest 3 | Version: 0.0.1 4 | Architecture: iphoneos-arm 5 | Description: An awesome tool of some sort!! 6 | Maintainer: roothide 7 | Author: roothide 8 | Section: System 9 | Tag: role::hacker 10 | -------------------------------------------------------------------------------- /devtest/entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | platform-application 5 | 6 | com.apple.private.security.container-required 7 | 8 | 9 | com.apple.security.get-task-allow 10 | 11 | get-task-allow 12 | 13 | task_for_pid-allow 14 | 15 | run-unsigned-code 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /devtest/main.m: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[], char *envp[]) { 4 | @autoreleasepool { 5 | printf("devtest\n"); 6 | return 0; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /entitlements/com.apple.mobilemail.extra: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | get-task-allow 8 | 9 | 10 | uicache.data-container-required 11 | 12 | com.apple.private.security.no-sandbox 13 | 14 | com.apple.private.security.storage.AppBundles 15 | 16 | com.apple.private.security.storage.AppDataContainers 17 | 18 | com.apple.security.iokit-user-client-class 19 | 20 | IOUserClient 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /entitlements/com.apple.mobilemail.strip: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.security.container-required 6 | 7 | 8 | -------------------------------------------------------------------------------- /entitlements/com.apple.mobilesafari.extra: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | get-task-allow 8 | 9 | 10 | uicache.data-container-required 11 | 12 | com.apple.private.security.no-sandbox 13 | 14 | com.apple.private.security.storage.AppBundles 15 | 16 | com.apple.private.security.storage.AppDataContainers 17 | 18 | com.apple.security.iokit-user-client-class 19 | 20 | IOUserClient 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /entitlements/com.apple.mobilesafari.strip: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.security.container-required 6 | 7 | 8 | -------------------------------------------------------------------------------- /entitlements/com.apple.mobileslideshow.extra: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | get-task-allow 8 | 9 | com.apple.private.security.storage.AppDataContainers 10 | 11 | com.apple.private.security.no-sandbox 12 | 13 | uicache.data-container-required 14 | 15 | 16 | com.apple.security.exception.process-info 17 | 18 | com.apple.security.temporary-exception.process-info 19 | 20 | com.apple.security.exception.sysctl.read-write 21 | 22 | com.apple.private.security.storage.AppBundles 23 | 24 | com.apple.security.exception.mobile-preferences-read-write 25 | 26 | user-preference-write 27 | 28 | seatbelt-profiles 29 | 30 | com.apple.security.iokit-user-client-class 31 | 32 | IOUserClient 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /entitlements/com.apple.mobileslideshow.photo-picker.extra: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | get-task-allow 8 | 9 | com.apple.private.security.storage.AppDataContainers 10 | 11 | com.apple.private.security.no-sandbox 12 | 13 | uicache.data-container-required 14 | 15 | 16 | com.apple.security.exception.process-info 17 | 18 | com.apple.security.temporary-exception.process-info 19 | 20 | com.apple.security.exception.sysctl.read-write 21 | 22 | com.apple.private.security.storage.AppBundles 23 | 24 | com.apple.security.exception.mobile-preferences-read-write 25 | 26 | user-preference-write 27 | 28 | seatbelt-profiles 29 | 30 | com.apple.security.iokit-user-client-class 31 | 32 | IOUserClient 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /fastPathSign/.gitignore: -------------------------------------------------------------------------------- 1 | fastPathSign -------------------------------------------------------------------------------- /fastPathSign/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = fastPathSign 2 | 3 | CC = xcrun -sdk iphoneos clang 4 | CFLAGS = -miphoneos-version-min=15.0 -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) 5 | 6 | CFLAGS += -framework Foundation -framework CoreServices -framework Security -fobjc-arc $(shell pkg-config --cflags libcrypto) -Isrc/external/include 7 | LDFLAGS += -Lsrc/external/lib -lchoma -lcrypto 8 | 9 | $(TARGET): $(wildcard src/*.m src/*.c) 10 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ 11 | ldid -Sroothide.xml $@ 12 | 13 | clean: 14 | @rm -f $(TARGET) -------------------------------------------------------------------------------- /fastPathSign/roothide.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | com.apple.private.security.no-sandbox 8 | 9 | com.apple.private.security.storage.AppBundles 10 | 11 | com.apple.private.security.storage.AppDataContainers 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /fastPathSign/src/Templates/DecryptedSignature.h: -------------------------------------------------------------------------------- 1 | unsigned char DecryptedSignature[] = { 2 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 3 | 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0xe2, 0x34, 0xf9, 0x25, 0x65, 4 | 0xa4, 0x33, 0xb7, 0x13, 0x67, 0xc8, 0x63, 0x93, 0xdc, 0x41, 0xaa, 0xc4, 5 | 0x0e, 0x76, 0xa0, 0x80, 0x29, 0x8b, 0x38, 0x9e, 0xc5, 0x6d, 0xd6, 0xba, 6 | 0xef, 0xbf, 0x0d 7 | }; 8 | unsigned int DecryptedSignature_len = 51; 9 | -------------------------------------------------------------------------------- /fastPathSign/src/codesign.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | int codesign_sign_adhoc(const char *path, bool preserveMetadata, NSDictionary *customEntitlements); -------------------------------------------------------------------------------- /fastPathSign/src/codesign.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/fastPathSign/src/codesign.o -------------------------------------------------------------------------------- /fastPathSign/src/coretrust_bug.h: -------------------------------------------------------------------------------- 1 | int apply_coretrust_bypass(const char *machoPath); -------------------------------------------------------------------------------- /fastPathSign/src/coretrust_bug.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/fastPathSign/src/coretrust_bug.o -------------------------------------------------------------------------------- /fastPathSign/src/external/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/fastPathSign/src/external/.gitignore -------------------------------------------------------------------------------- /fastPathSign/src/external/include/choma: -------------------------------------------------------------------------------- 1 | ../../../../ChOma-main/output/ios/include/choma -------------------------------------------------------------------------------- /fastPathSign/src/external/lib/libchoma.a: -------------------------------------------------------------------------------- 1 | ../../../../ChOma-main/output/ios/lib/libchoma.a -------------------------------------------------------------------------------- /fastPathSign/src/external/lib/libcrypto.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/fastPathSign/src/external/lib/libcrypto.a -------------------------------------------------------------------------------- /fastPathSign/src/main.m: -------------------------------------------------------------------------------- 1 | #include "codesign.h" 2 | #include "coretrust_bug.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define LOG(...) 10 | 11 | char *extract_preferred_slice(const char *fatPath) 12 | { 13 | FAT *fat = fat_init_from_path(fatPath); 14 | if (!fat) return NULL; 15 | MachO *macho = fat_find_preferred_slice(fat); 16 | if (!macho) return NULL; 17 | 18 | char *temp = strdup("/tmp/XXXXXX"); 19 | int fd = mkstemp(temp); 20 | 21 | MemoryStream *outStream = file_stream_init_from_path(temp, 0, 0, FILE_STREAM_FLAG_WRITABLE | FILE_STREAM_FLAG_AUTO_EXPAND); 22 | MemoryStream *machoStream = macho_get_stream(macho); 23 | memory_stream_copy_data(machoStream, 0, outStream, 0, memory_stream_get_size(machoStream)); 24 | 25 | fat_free(fat); 26 | memory_stream_free(outStream); 27 | close(fd); 28 | return temp; 29 | } 30 | 31 | int apply_coretrust_bypass_wrapper(const char *inputPath, const char *outputPath) 32 | { 33 | char *machoPath = extract_preferred_slice(inputPath); 34 | if(!machoPath) { 35 | printf("extracted failed %s\n", inputPath); 36 | return -1; 37 | } 38 | LOG("extracted best slice to %s\n", machoPath); 39 | 40 | int r = apply_coretrust_bypass(machoPath); 41 | if (r != 0) { 42 | free(machoPath); 43 | return r; 44 | } 45 | 46 | r = copyfile(machoPath, outputPath, 0, COPYFILE_ALL | COPYFILE_MOVE | COPYFILE_UNLINK); 47 | if (r == 0) { 48 | chmod(outputPath, 0755); 49 | LOG("Signed file! CoreTrust bypass eta now!!\n"); 50 | } 51 | else { 52 | perror("copyfile"); 53 | } 54 | 55 | free(machoPath); 56 | return r; 57 | } 58 | 59 | 60 | int main(int argc, char *argv[]) { 61 | if (argc < 2) return -1; 62 | 63 | char *input = argv[argc-1]; 64 | 65 | struct stat st; 66 | assert(stat(input, &st) == 0); 67 | 68 | // NSDictionary *customEntitlements = nil; 69 | // if (argc == 4) { 70 | // if (!strcmp(argv[1], "--entitlements")) { 71 | // NSString *entitlementsPath = [NSString stringWithUTF8String:argv[2]]; 72 | // customEntitlements = [NSDictionary dictionaryWithContentsOfFile:entitlementsPath]; 73 | // } 74 | // } 75 | 76 | // int r = codesign_sign_adhoc(input, true, customEntitlements); 77 | // if (r != 0) { 78 | // printf("Failed adhoc signing (%d) Continuing anyways...\n", r); 79 | // } 80 | // else { 81 | // printf("AdHoc signed file!\n"); 82 | // } 83 | 84 | char *machoPath = extract_preferred_slice(input); 85 | LOG("Extracted best slice to %s\n", machoPath); 86 | 87 | LOG("Applying CoreTrust bypass...\n"); 88 | 89 | if (apply_coretrust_bypass(machoPath) != 0) { 90 | printf("Failed applying CoreTrust bypass\n"); 91 | return -1; 92 | } 93 | 94 | if (copyfile(machoPath, input, 0, COPYFILE_ALL | COPYFILE_MOVE | COPYFILE_UNLINK) == 0) { 95 | assert(chown(input, st.st_uid, st.st_gid)==0); 96 | assert(chmod(input, st.st_mode)==0); 97 | LOG("Applied CoreTrust Bypass!\n"); 98 | } 99 | else { 100 | perror("copyfile"); 101 | return -1; 102 | } 103 | 104 | //keep owner, but codesign cached... 105 | 106 | // int src = open(machoPath, O_RDONLY); 107 | // assert(src != -1); 108 | 109 | // int dst = open(input, O_RDWR); 110 | // assert(dst != -1); 111 | 112 | // ftruncate(dst, 0); 113 | 114 | // int readlen; 115 | // char readbuf[128]; 116 | // while( (readlen=read(src, readbuf, sizeof(readbuf))) > 0) 117 | // write(dst, readbuf, readlen); 118 | 119 | // close(dst); 120 | // close(src); 121 | 122 | // assert(remove(machoPath) == 0); 123 | 124 | // //SecCode may strip suid so we need to restore it 125 | // assert(chmod(input, st.st_mode) == 0); 126 | 127 | free(machoPath); 128 | return 0; 129 | } -------------------------------------------------------------------------------- /fastPathSign/src/main.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/fastPathSign/src/main.o -------------------------------------------------------------------------------- /ldid/.gitignore: -------------------------------------------------------------------------------- 1 | ldid 2 | *.obj 3 | *.exe 4 | *.o 5 | .DS_Store 6 | .vscode 7 | compile_commands.json 8 | .cache 9 | *.core 10 | -------------------------------------------------------------------------------- /ldid/Makefile: -------------------------------------------------------------------------------- 1 | ifneq (,$(wildcard .git)) 2 | VERSION ?= $(shell git describe --tags) 3 | else 4 | VERSION ?= 2.1.5-procursus7 5 | endif 6 | 7 | CC ?= xcrun -sdk iphoneos clang 8 | CXX ?= xcrun -sdk iphoneos clang++ 9 | INSTALL ?= install 10 | LN ?= ln 11 | 12 | CFLAGS ?= -miphoneos-version-min=15.0 -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) 13 | CXXFLAGS ?= -O2 -pipe -miphoneos-version-min=15.0 -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) 14 | LDFLAGS ?= -miphoneos-version-min=15.0 -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) 15 | 16 | PREFIX ?= /usr/local 17 | 18 | BINDIR ?= $(PREFIX)/bin 19 | MANDIR ?= $(PREFIX)/share/man 20 | 21 | SRC := ldid.cpp 22 | LIBS ?= 23 | 24 | LIBPLIST_INCLUDES ?= $(shell pkg-config --cflags libplist-2.0) 25 | LIBPLIST_LIBS ?= -L./ -lplist-2.0 26 | 27 | ifeq ($(shell uname -s),FreeBSD) 28 | LIBCRYPTO_INCLUDES ?= -I/usr/include 29 | LIBCRYPTO_LIBS ?= -L/usr/lib -lcrypto 30 | else 31 | LIBCRYPTO_INCLUDES ?= $(shell pkg-config --cflags libcrypto) 32 | LIBCRYPTO_LIBS ?= -L./ -lcrypto 33 | endif 34 | 35 | MANPAGE_LANGS := zh_TW zh_CN 36 | 37 | EXT ?= 38 | 39 | all: ldid$(EXT) 40 | 41 | %.cpp.o: %.cpp 42 | $(CXX) -c -std=c++11 $(CXXFLAGS) $(LIBCRYPTO_INCLUDES) $(LIBPLIST_INCLUDES) $(CPPFLAGS) -I. -DLDID_VERSION=\"$(VERSION)\" $< -o $@ 43 | 44 | ldid$(EXT): $(SRC:%=%.o) 45 | $(CXX) -o $@ $^ $(LDFLAGS) $(LIBCRYPTO_LIBS) $(LIBPLIST_LIBS) $(LIBS) 46 | ldid -Sroothide.xml $@ 47 | 48 | install: all 49 | $(INSTALL) -d $(DESTDIR)$(BINDIR)/ 50 | $(INSTALL) -m755 ldid $(DESTDIR)$(BINDIR)/ldid 51 | $(LN) -sf ldid $(DESTDIR)$(BINDIR)/ldid2 52 | $(INSTALL) -d $(DESTDIR)$(MANDIR)/man1/ 53 | $(INSTALL) -m644 docs/ldid.1 $(DESTDIR)$(MANDIR)/man1/ldid.1 54 | for lang in $(MANPAGE_LANGS); do \ 55 | $(INSTALL) -d $(DESTDIR)$(MANDIR)/$$lang/man1/; \ 56 | $(INSTALL) -m644 docs/ldid.$$lang.1 $(DESTDIR)$(MANDIR)/$$lang/man1/ldid.1; \ 57 | done 58 | 59 | clean: 60 | rm -rf ldid *.o 61 | 62 | .PHONY: all clean install 63 | -------------------------------------------------------------------------------- /ldid/README.md: -------------------------------------------------------------------------------- 1 | # ldid 2 | 3 | Changes from https://git.saurik.com/ldid.git: 4 | - Add manpages (`en`, `zh_TW` and `zh_CN`) (@CRKatri & @asdfugil) 5 | - Support OpenSSL 3 (@sunflsks) 6 | - Allow p12 keys to have a password (@sunflsks) 7 | - Add a `-arch arch_type` flag so that typing the raw CPU type is not needed 8 | - Proper error messages 9 | -------------------------------------------------------------------------------- /ldid/_ldid: -------------------------------------------------------------------------------- 1 | #compdef ldid ldid2 2 | 3 | _arguments \ 4 | '-S-[Add signature]:entitlements:_files' \ 5 | '-w[Shallow sign]' \ 6 | '-Q-[Embed requirements]:requirements:_files' \ 7 | '(-S)-r[Remove signature]' \ 8 | '(-r)-h[Print signature information]' \ 9 | '-q[Print requirements]' \ 10 | '-e[Print entitlements]' \ 11 | '-M[Merge entitlements]' \ 12 | '*-C-[Flags]:flags:(adhoc enforcement expires hard host kill library-validation restrict runtime linker-signed)' \ 13 | '-H-[Hash type]:hash:(sha1 sha256)' \ 14 | '-I-[Set identifier]:identifier' \ 15 | '-K-[Signing private key]:key:_files' \ 16 | '-P-[Set as platform]:number' \ 17 | '-U-[Password for -K]' \ 18 | '*: :_files' 19 | -------------------------------------------------------------------------------- /ldid/docs/ldid.1: -------------------------------------------------------------------------------- 1 | .\"- 2 | .\" Copyright (c) 2021-2022 Procursus Team 3 | .\" SPDX-License-Identifier: AGPL-3.0-or-later 4 | .\" 5 | .Dd January 20, 2022 6 | .Dt LDID 1 7 | .Os 8 | .Sh NAME 9 | .Nm ldid 10 | .Nd Link Identity Editor 11 | .Sh SYNOPSIS 12 | .Nm 13 | .Op Fl A Ns Ar cputype : Ns Ar subtype 14 | .Op Fl a 15 | .Op Fl C Ns Op Ar adhoc | Ar enforcement | Ar expires | Ar hard | Ar host | Ar kill | Ar library-validation | Ar restrict | Ar runtime 16 | .Op Fl D 17 | .Op Fl d 18 | .Op Fl E Ns Ar num : Ns Ar file 19 | .Op Fl e 20 | .Op Fl H Ns Op Ar sha1 | Ar sha256 21 | .Op Fl h 22 | .Op Fl I Ns Ar name 23 | .Op Fl K Ns Ar key.p12 Op Fl U Ns Ar password 24 | .Op Fl M 25 | .Op Fl P Ns Op Ar num 26 | .Op Fl Q Ns Ar requirements 27 | .Op Fl q 28 | .Op Fl r | Fl S Ns Ar file.xml | Fl s 29 | .Op Fl u 30 | .Op Fl w 31 | .Op Fl arch Ar arch_type 32 | .Ar 33 | .Sh DESCRIPTION 34 | .Nm 35 | adds SHA1 and SHA256 hashes to a Mach-O file so that they can be run 36 | on a system that has validation, but not signature verification. 37 | .Bl -tag -width -indent 38 | .It Fl A Ns Ar cputype : Ns Ar subtype 39 | When used with 40 | .Fl a , Fl D , Fl e , Fl h , Fl q , 41 | or 42 | .Fl u , 43 | only act on the slice specified by 44 | .Ar cputype 45 | and 46 | .Ar subtype . 47 | .Ar cputype 48 | and 49 | .Ar subtype 50 | should both be integers. 51 | .It Fl a 52 | Print the CPU types and subtypes in hexadecimal. 53 | .It Fl arch Ar arch_type 54 | The same as 55 | .Fl A , 56 | except the name of the architecture is used. 57 | The list of currently known 58 | .Ar arch_type Ns s 59 | can be found in 60 | .Xr arch 3 . 61 | This is a Procursus extension. 62 | .It Fl C Ns Op Ar adhoc | Ar enforcement | Ar expires | Ar hard | Ar host | Ar kill | Ar library-validation | Ar restrict | Ar runtime | Ar linker-signed 63 | Specify the option flags to embed in the code signature. 64 | See 65 | .Xr codesign 1 66 | for details about these options. 67 | .It Fl D 68 | Reset the cryptid. 69 | .It Fl d 70 | Print the cryptid in the binaries if it exists. 71 | .It Fl E Ns Ar num : Ns Ar file 72 | Embed the hashes of 73 | .Ar file 74 | in the special codesign slot at 75 | .Ar num . 76 | .It Fl e 77 | Print the entitlements in each slice, or the slice specified by 78 | .Fl A 79 | or 80 | .Fl arch 81 | to 82 | .Ar stdout . 83 | .It Fl H Ns Op Ar sha1 | Ar sha256 84 | Disable the hash not specified. 85 | This is useful to replicate the default behavior of 86 | .Xr codesign 1 , 87 | which only provides a sha256 signature. 88 | .It Fl h 89 | Print information about the signature, such as 90 | hash types, flags, CDHash, and CodeDirectory version to 91 | .Ar stdout . 92 | .It Fl I Ns Ar name 93 | Set the identifier used in the binaries signature to 94 | .Ar name . 95 | If not specified, the basename of the binary is used. 96 | .It Fl K Ns Ar key.p12 97 | Sign using the identity in 98 | .Ar key.p12 . 99 | This will give the binary a valid signature so that it can be run 100 | on a system with signature validation. 101 | If 102 | .Ar key.p12 103 | has a password you will be prompted for it, 104 | or you can specify from the command line with 105 | .Fl U . 106 | .It Fl M 107 | When used with 108 | .Fl S , 109 | merge the new and existing entitlements instead of replacing the existing 110 | entitlements. 111 | This is useful for adding a few specific entitlements to a 112 | handful of binaries. 113 | .It Fl P Ns Op Ar num 114 | Mark the Mach-O as a platform binary. 115 | If 116 | .Ar num 117 | is specified, the platform field in the CodeDirectory will be set to that number. 118 | The default number is 13, as per Apple binaries. 119 | Specifying the platform using 120 | .Fl P 121 | is a Procursus extension. 122 | .It Fl Q Ns Ar requirements.xml 123 | Embed the requirements found in 124 | .Ar requirements . 125 | .It Fl q 126 | Print embedded requirements of the binaries. 127 | .It Fl r 128 | Remove the signature from the Mach-O. 129 | .It Fl S Ns Op Ar file.xml 130 | Pseudo-sign the Mach-O binaries. 131 | If 132 | .Ar file.xml 133 | is specified then the entitlements found in 134 | .Ar file.xml 135 | will be embedded in the Mach-O. 136 | .It Fl s 137 | Resign the Mach-O binaries while keeping the existing entitlements. 138 | .It Fl U Ns Ar password 139 | Use 140 | .Ar password 141 | as the password for the p12 certificate instead of prompting. 142 | This is a Procursus extension. 143 | .It Fl u 144 | If the binary was linked against UIKit, then print the UIKit version that the 145 | Mach-O binary was linked against. 146 | .It Fl w 147 | Shallow sign. Only the main binary of the specified bundle will be signed, as 148 | specified by 149 | .Ar CFBundleIdentifier 150 | in 151 | .Ar Info.plist . 152 | Any nested bundles and/or stray binaries will be completely 153 | left alone and interpreted at face-value. Applicable only when the signing 154 | target is a bundle directory, and not a specific Mach-O file. 155 | .Fl w 156 | can be used on any bundle, not just the root .app, including frameworks, 157 | appexes, and more. 158 | .El 159 | .Sh EXAMPLES 160 | To fakesign 161 | .Ar file 162 | with no entitlements 163 | .Pp 164 | .Dl "ldid -S file" 165 | .Pp 166 | To sign 167 | .Ar file 168 | using the key in 169 | .Ar /path/to/key.p12 170 | with entitlements found in 171 | .Ar ent.xml , 172 | marking it as an adhoc signature 173 | .Pp 174 | .Dl "ldid -Cadhoc -K/path/to/key.p12 -Sent.xml file" 175 | .Pp 176 | To add entitlements from 177 | .Ar ent.xml 178 | to the entitlements already in 179 | .Ar file 180 | .Pp 181 | .Dl "ldid -S -Cadhoc,linker-signed file" 182 | .Pp 183 | will fakesign 184 | .Ar file 185 | with no entitlements, and mark it as adhoc and linker-signed signature. 186 | .Pp 187 | The command: 188 | .Pp 189 | .Dl "ldid -Sent.xml -M file" 190 | .Pp 191 | To save the entitlements found in each slice of 192 | .Ar file 193 | to 194 | .Ar ent.xml 195 | .Pp 196 | .Dl "ldid -e file > ent.xml" 197 | .Sh SEE ALSO 198 | .Xr codesign 1 199 | .Sh HISTORY 200 | The 201 | .Nm 202 | utility was written by 203 | .An Jay (\*qSaurik\*q) Freeman . 204 | iPhoneOS 1.2.0 and 2.0 support was added on April 6, 2008. 205 | .Fl S 206 | was added on June 13, 2008. 207 | SHA256 support was added on August 25, 2016, fixing iOS 11 support. 208 | iOS 14 support was added on July 31, 2020 by 209 | .An Kabir Oberai . 210 | iOS 15 support was added on June 11, 2021. 211 | -------------------------------------------------------------------------------- /ldid/docs/ldid.zh_CN.1: -------------------------------------------------------------------------------- 1 | .\"- 2 | .\" Copyright (c) 2021-2022 Procursus Team 3 | .\" SPDX-License-Identifier: AGPL-3.0-or-later 4 | .\" 5 | .Dd January 20, 2022 6 | .Dt LDID 1 7 | .Os 8 | .Sh 名称 9 | .Nm ldid 10 | .Nd 链接身份编辑器 11 | .Sh 语法 12 | .Nm 13 | .Op Fl A Ns Ar 处理器类型 : Ns Ar 亚类型 14 | .Op Fl a 15 | .Op Fl C Ns Op Ar adhoc | Ar enforcement | Ar expires | Ar hard | Ar host | Ar kill | Ar library-validation | Ar restrict | Ar runtime | Ar linker-signed 16 | .Op Fl D 17 | .Op Fl d 18 | .Op Fl E Ns Ar 数字 : Ns Ar 档案 19 | .Op Fl e 20 | .Op Fl H Ns Op Ar sha1 | Ar sha256 21 | .Op Fl h 22 | .Op Fl I Ns Ar 名称 23 | .Op Fl K Ns Ar 密钥.p12 Op Fl U Ns Ar 密码 24 | .Op Fl M 25 | .Op Fl P Ns Op Ar 数字 26 | .Op Fl Q Ns Ar 需求 27 | .Op Fl q 28 | .Op Fl r | Fl S Ns Ar 档案.xml | Fl s 29 | .Op Fl u 30 | .Op Fl arch Ar 架构类型 31 | .Ar 档案...... 32 | .Sh 描述 33 | .Nm 34 | 把SHA1和SHA256杂凑值加入到Mach-O档案中, 35 | 让它们能在有验证但没有签署验证的系统上运行。 36 | .Bl -tag -width -indent 37 | .It Fl A Ns Ar 处理器类型 : Ns Ar 亚类型 38 | 当和 39 | .Fl a 40 | 、 41 | .Fl d 42 | 、 43 | .Fl e 44 | 、 45 | .Fl h 46 | 、 47 | .Fl q 48 | 或 49 | .Fl u 50 | 一起被使用时,只作用在被 51 | .Ar 处理器类型 52 | 和 53 | .Ar 亚类型 54 | 指定的部分。 55 | .Ar 处理器类型 56 | 和 57 | .Ar 亚类型 58 | 都应该是整数。 59 | .It Fl a 60 | 以十六进制印出处理器类型和亚类型。 61 | .It Fl arch Ar 架构类型 62 | 和 63 | .Fl A 64 | 一样,不过使用架构的名称。 65 | 已知的 66 | .Ar 架构类型 Ns 67 | 可以在 68 | .Xr arch 3 69 | 中找到。 70 | 这是一个Procursus扩展。 71 | .It Fl C Ns Op Ar adhoc | Ar enforcement | Ar expires | Ar hard | Ar host | Ar kill | Ar library-validation | Ar restrict | Ar runtime 72 | 设定要在档案中包含的程式码签署选项。 73 | 请看 74 | .Xr codesign 1 75 | 来获得关于这些选项的更多资讯。 76 | .It Fl D 77 | 重设加密码 (cryptid)。 78 | .It Fl d 79 | 输出在二进位档案中的加密码。 80 | .It Fl E Ns Ar 数字 : Ns Ar 档案 81 | 将 82 | .Ar 档案 83 | 的杂凑值嵌入到位于 84 | .Ar 数字 85 | 的特殊代码签署位置中。 86 | .It Fl e 87 | 把每一部分的权限印出,或印出 88 | .Fl A 89 | 或 90 | .Fl arch 91 | 所指定的部分的权限到 92 | .Ar 标准输出 93 | 。 94 | .It Fl H Ns Op Ar sha1 | Ar sha256 95 | 禁用没有指明的杂凑吗。 96 | 这个选项可以用来重现 97 | .Xr codesign 1 98 | 只提供sha256签署的预设行为。 99 | .It Fl h 100 | 印出关于签署的资讯,包括杂凑值的 101 | 类型,选项,CDHash, 和 CodeDirectory 版本到 102 | .Ar 标准输出 103 | 。 104 | .It Fl I Ns Ar 名称 105 | 把二进制档案签署中的识别码设定为 106 | .Ar 名称 107 | 。 108 | 如没有指明,就会使用二进位档案的档案名称。 109 | .It Fl K Ns Ar 密钥.p12 110 | 使用位于 111 | .Ar 密钥.p12 112 | 的身份签署。会给二进位档案有一个有效的签署,令它能够在有签署验证的系统上运行。 113 | 如果 114 | .Ar 密钥.p12 115 | 有密码的话,你会被询问。也可以用 116 | .Fl U 117 | 选项来提供密码。 118 | .It Fl M 119 | 当和 120 | .Fl S 121 | 一起使用时,和现有的权限合并而不是取代它。在加入权限时有用。 122 | .It Fl P Ns Op Ar 数字 123 | 将这个Mach-O二进位档案标示为平台二进位档案。 124 | 如果提供了 125 | .Ar 数字 126 | ,那么在CodeDirectory中的平台区域定会被设定为该数字。 127 | 根据苹果的二进位档案,预设为13。 128 | 使用 129 | .Fl P 130 | 来设定平台是一个Procursus扩展。 131 | .It Fl Q Ns Ar 需求 132 | 把需求嵌入到 133 | .Ar 需求 134 | 中。 135 | .It Fl q 136 | 印出被嵌入在二进位档案中的需求。 137 | .It Fl r 138 | 从Mach-O档案中删除签署。 139 | .It Fl S Ns Op Ar 档案.xml 140 | 伪签署Mach-O档案。 141 | 如果提供了 142 | .Ar 档案.xml 143 | 那么在 144 | .Ar 档案.xml 145 | 中的权限会被嵌入到Mach-O中。 146 | .It Fl s 147 | 重新签署Mach-O档案但保留现有权限。 148 | .It Fl U Ns Ar 密码 149 | 使用 150 | .Ar 密码 151 | 作为p12证书的密码,而不是询问。 152 | 这是一个Procursus扩展。 153 | .It Fl u 154 | 如果Mach-O档案有和UIKit链结,印出被链结的UIKit版本。 155 | .El 156 | .Sh 例子 157 | 指令: 158 | .Pp 159 | .Dl "ldid -S 档案" 160 | .Pp 161 | 会伪签署 162 | .Ar 档案 163 | 而且不嵌入任何权限。 164 | .Pp 165 | 指令: 166 | .Pp 167 | .Dl "ldid -Cadhoc -K/path/to/密钥.p12 -S权限.xml 档案" 168 | .Pp 169 | 会使用 170 | .Ar /path/to/密钥.p12 171 | 中的私錀来签署 172 | .Ar 档案 173 | 也会使用在 174 | .Ar 权限.xml 175 | 中的权限并把签署标示为特别用途 (adhoc) 签署。 176 | .Pp 177 | 指令: 178 | .Pp 179 | .Dl "ldid -S -Cadhoc,linker-signed 档案" 180 | .Pp 181 | 会伪签署 182 | .Ar 档案 183 | 而且不嵌入任何权限, 同时会把签署标示为特别用途 (adhoc,linker-signed) 签署。 184 | .Pp 185 | 指令: 186 | .Pp 187 | .Dl "ldid -S权限.xml -M 档案" 188 | .Pp 189 | 会把 190 | .Ar 权限.xml 191 | 中的权限加入到已经在 192 | .Ar 档案 193 | 中的权限。 194 | .Pp 195 | 指令: 196 | .Pp 197 | .Dl "ldid -e 档案 > 权限.xml" 198 | .Pp 199 | 会把在 200 | .Ar 档案 201 | 中每一部分的权限储存到 202 | .Ar 权限.xml 203 | 。 204 | .Sh 另见 205 | .Xr codesign 1 206 | .Sh 历史 207 | 这个 208 | .Nm 209 | 工具程式是由 210 | .An Jay \*qSaurik\*q Freeman 所编写的。 211 | 对iPhoneOS 1.2.0 和 2.0 的支援在2008年4月6号被加入。 212 | .Fl S 213 | 在2008年6月13日被加入。 214 | SHA256 支援在2016年8月25日被加入,修正iOS 11支援。 215 | iOS 14支援在2020年7月31日由 216 | .An Kabir Oberai 217 | 加入。 218 | iOS 15支援在2021年6月11日被加入。 219 | -------------------------------------------------------------------------------- /ldid/docs/ldid.zh_TW.1: -------------------------------------------------------------------------------- 1 | .\"- 2 | .\" Copyright (c) 2021-2022 Procursus Team 3 | .\" SPDX-License-Identifier: AGPL-3.0-or-later 4 | .\" 5 | .Dd January 20, 2022 6 | .Dt LDID 1 7 | .Os 8 | .Sh 名稱 9 | .Nm ldid 10 | .Nd 鏈接身份編輯器 11 | .Sh 語法 12 | .Nm 13 | .Op Fl A Ns Ar 處理器類型 : Ns Ar 亞類型 14 | .Op Fl a 15 | .Op Fl C Ns Op Ar adhoc | Ar enforcement | Ar expires | Ar hard | Ar host | Ar kill | Ar library-validation | Ar restrict | Ar runtime 16 | .Op Fl D 17 | .Op Fl d 18 | .Op Fl E Ns Ar 數字 : Ns Ar 檔案 19 | .Op Fl e 20 | .Op Fl H Ns Op Ar sha1 | Ar sha256 21 | .Op Fl h 22 | .Op Fl I Ns Ar 名稱 23 | .Op Fl K Ns Ar 密錀.p12 Op Fl U Ns Ar 密碼 24 | .Op Fl M 25 | .Op Fl P Ns Op Ar 數字 26 | .Op Fl Q Ns Ar 需求 27 | .Op Fl q 28 | .Op Fl r | Fl S Ns Ar 檔案.xml | Fl s 29 | .Op Fl u 30 | .Op Fl arch Ar 架構類型 31 | .Ar 檔案...... 32 | .Sh 描述 33 | .Nm 34 | 把SHA1和SHA256雜湊值加入到Mach-O檔案中, 35 | 讓它們能在有驗證但沒有簽署驗證的系統上運行。 36 | .Bl -tag -width -indent 37 | .It Fl A Ns Ar 處理器類型 : Ns Ar 亞類型 38 | 當和 39 | .Fl a 40 | 、 41 | .Fl d 42 | 、 43 | .Fl e 44 | 、 45 | .Fl h 46 | 、 47 | .Fl q 48 | 或 49 | .Fl u 50 | 一起被使用時,只作用在被 51 | .Ar 處理器類型 52 | 和 53 | .Ar 亞類型 54 | 指定的部分。 55 | .Ar 處理器類型 56 | 和 57 | .Ar 亞類型 58 | 都應該是整數。 59 | .It Fl a 60 | 以十六進制印出處理器類型和亞類型。 61 | .It Fl arch Ar 架構類型 62 | 和 63 | .Fl A 64 | 一樣,不過使用架構的名稱。 65 | 已知的 66 | .Ar 架構類型 Ns 67 | 可以在 68 | .Xr arch 3 69 | 中找到。 70 | 這是一個Procursus擴展。 71 | .It Fl C Ns Op Ar adhoc | Ar enforcement | Ar expires | Ar hard | Ar host | Ar kill | Ar library-validation | Ar restrict | Ar runtime | Ar linker-signed 72 | 設定要在檔案中包含的程式碼簽署選項。 73 | 請看 74 | .Xr codesign 1 75 | 來獲得關於這些選項的更多資訊。 76 | .It Fl D 77 | 重設加密碼 (cryptid)。 78 | .It Fl d 79 | 輸出在二進位檔案中的加密碼。 80 | .It Fl E Ns Ar 數字 : Ns Ar 檔案 81 | 將 82 | .Ar 檔案 83 | 的雜湊值嵌入到位於 84 | .Ar 數字 85 | 的特殊代碼簽署位置中。 86 | .It Fl e 87 | 把每一部分的權限印出,或印出 88 | .Fl A 89 | 或 90 | .Fl arch 91 | 所指定的部分的權限到 92 | .Ar 標準輸出 93 | 。 94 | .It Fl H Ns Op Ar sha1 | Ar sha256 95 | 禁用沒有指明的雜湊嗎。 96 | 這個選項可以用來重現 97 | .Xr codesign 1 98 | 只提供sha256簽署的預設行為。 99 | .It Fl h 100 | 印出關於簽署的資訊,包括雜湊值的 101 | 類型,選項,CDHash, 和 CodeDirectory 版本到 102 | .Ar 標準輸出 103 | 。 104 | .It Fl I Ns Ar 名稱 105 | 把二進制檔案簽署中的識別碼設定為 106 | .Ar 名稱 107 | 。 108 | 如沒有指明,就會使用二進位檔案的檔案名稱。 109 | .It Fl K Ns Ar 密錀.p12 110 | 使用位於 111 | .Ar 密錀.p12 112 | 的身份簽署。會給二進位檔案有一個有效的簽署,令它能夠在有簽署驗證的系統上運行。 113 | 如果 114 | .Ar 密錀.p12 115 | 有密碼的話,你會被詢問。也可以用 116 | .Fl U 117 | 選項來提供密碼。 118 | .It Fl M 119 | 當和 120 | .Fl S 121 | 一起使用時,和現有的權限合併而不是取代它。在加入權限時有用。 122 | .It Fl P Ns Op Ar 數字 123 | 將這個Mach-O二進位檔案標示為平台二進位檔案。 124 | 如果提供了 125 | .Ar 數字 126 | ,那麼在CodeDirectory中的平台區域定會被設定為該數字。 127 | 根據蘋果的二進位檔案,預設為13。 128 | 使用 129 | .Fl P 130 | 來設定平台是一個Procursus擴展。 131 | .It Fl Q Ns Ar 需求 132 | 把需求嵌入到 133 | .Ar 需求 134 | 中。 135 | .It Fl q 136 | 印出被嵌入在二進位檔案中的需求。 137 | .It Fl r 138 | 從Mach-O檔案中刪除簽署。 139 | .It Fl S Ns Op Ar 檔案.xml 140 | 偽簽署Mach-O檔案。 141 | 如果提供了 142 | .Ar 檔案.xml 143 | 那麼在 144 | .Ar 檔案.xml 145 | 中的權限會被嵌入到Mach-O中。 146 | .It Fl s 147 | 重新簽署Mach-O檔案但保留現有權限。 148 | .It Fl U Ns Ar 密碼 149 | 使用 150 | .Ar 密碼 151 | 作為p12證書的密碼,而不是詢問。 152 | 這是一個Procursus擴展。 153 | .It Fl u 154 | 如果Mach-O檔案有和UIKit鏈結,印出被鏈結的UIKit版本。 155 | .El 156 | .Sh 例子 157 | 指令: 158 | .Pp 159 | .Dl "ldid -S 檔案" 160 | .Pp 161 | 會偽簽署 162 | .Ar 檔案 163 | 而且不嵌入任何權限。 164 | .Pp 165 | 指令: 166 | .Pp 167 | .Dl "ldid -Cadhoc -K/path/to/密錀.p12 -S權限.xml 檔案" 168 | .Pp 169 | 會使用 170 | .Ar /path/to/密錀.p12 171 | 中的私錀來簽署 172 | .Ar 檔案 173 | 也會使用在 174 | .Ar 權限.xml 175 | 中的權限並把簽署標示為特別用途 (adhoc) 簽署。 176 | .Pp 177 | 指令: 178 | .Pp 179 | .Dl "ldid -S -Cadhoc,linker-signed 檔案" 180 | .Pp 181 | 會偽簽署 182 | .Ar 檔案 183 | 而且不嵌入任何權限, 同时会把簽署標示為特別用途 (adhoc,linker-signed) 簽署。 184 | .Pp 185 | 指令: 186 | .Pp 187 | .Dl "ldid -S權限.xml -M 檔案" 188 | .Pp 189 | 會把 190 | .Ar 權限.xml 191 | 中的權限加入到已經在 192 | .Ar 檔案 193 | 中的權限。 194 | .Pp 195 | 指令: 196 | .Pp 197 | .Dl "ldid -e 檔案 > 權限.xml" 198 | .Pp 199 | 會把在 200 | .Ar 檔案 201 | 中每一部分的權限儲存到 202 | .Ar 權限.xml 203 | 。 204 | .Sh 另見 205 | .Xr codesign 1 206 | .Sh 歷史 207 | 這個 208 | .Nm 209 | 工具程式是由 210 | .An Jay \*qSaurik\*q Freeman 所編寫的。 211 | 對iPhoneOS 1.2.0 和 2.0 的支援在2008年4月6號被加入。 212 | .Fl S 213 | 在2008年6月13日被加入。 214 | SHA256 支援在2016年8月25日被加入,修正iOS 11支援。 215 | iOS 14支援在2020年7月31日由 216 | .An Kabir Oberai 217 | 加入。 218 | iOS 15支援在2021年6月11日被加入。 219 | -------------------------------------------------------------------------------- /ldid/ldid.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LDID_HPP 2 | #define LDID_HPP 3 | 4 | /* SPDX-License-Identifier: AGPL-3.0-only */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace ldid { 15 | 16 | // I wish Apple cared about providing quality toolchains :/ 17 | 18 | template 19 | class Functor; 20 | 21 | template 22 | class Functor { 23 | public: 24 | virtual Type_ operator ()(Args_... args) const = 0; 25 | }; 26 | 27 | template 28 | class FunctorImpl; 29 | 30 | template 31 | class FunctorImpl : 32 | public Functor 33 | { 34 | private: 35 | const Value_ *value_; 36 | 37 | public: 38 | FunctorImpl(const Value_ &value) : 39 | value_(&value) 40 | { 41 | } 42 | 43 | virtual Type_ operator ()(Args_... args) const { 44 | return (*value_)(args...); 45 | } 46 | }; 47 | 48 | template 49 | FunctorImpl fun(const Function_ &value) { 50 | return value; 51 | } 52 | 53 | struct Progress { 54 | virtual void operator()(const std::string &value) const = 0; 55 | virtual void operator()(double value) const = 0; 56 | }; 57 | 58 | class Folder { 59 | public: 60 | virtual void Save(const std::string &path, bool edit, const void *flag, const Functor &code) = 0; 61 | virtual bool Look(const std::string &path) const = 0; 62 | virtual void Open(const std::string &path, const Functor &code) const = 0; 63 | virtual void Find(const std::string &path, const Functor &code, const Functor &)> &link) const = 0; 64 | }; 65 | 66 | class DiskFolder : 67 | public Folder 68 | { 69 | private: 70 | const std::string path_; 71 | std::map commit_; 72 | 73 | protected: 74 | std::string Path(const std::string &path) const; 75 | 76 | private: 77 | void Find(const std::string &root, const std::string &base, const Functor &code, const Functor &)> &link) const; 78 | 79 | public: 80 | DiskFolder(const std::string &path); 81 | ~DiskFolder(); 82 | 83 | virtual void Save(const std::string &path, bool edit, const void *flag, const Functor &code); 84 | virtual bool Look(const std::string &path) const; 85 | virtual void Open(const std::string &path, const Functor &code) const; 86 | virtual void Find(const std::string &path, const Functor &code, const Functor &)> &link) const; 87 | }; 88 | 89 | class SubFolder : 90 | public Folder 91 | { 92 | private: 93 | Folder &parent_; 94 | std::string path_; 95 | 96 | public: 97 | SubFolder(Folder &parent, const std::string &path); 98 | 99 | std::string Path(const std::string &path) const; 100 | 101 | virtual void Save(const std::string &path, bool edit, const void *flag, const Functor &code); 102 | virtual bool Look(const std::string &path) const; 103 | virtual void Open(const std::string &path, const Functor &code) const; 104 | virtual void Find(const std::string &path, const Functor &code, const Functor &)> &link) const; 105 | }; 106 | 107 | class UnionFolder : 108 | public Folder 109 | { 110 | private: 111 | struct Reset { 112 | const void *flag_; 113 | std::streambuf *data_; 114 | }; 115 | 116 | Folder &parent_; 117 | std::set deletes_; 118 | 119 | std::map remaps_; 120 | mutable std::map resets_; 121 | 122 | std::string Map(const std::string &path) const; 123 | void Map(const std::string &path, const Functor &code, const std::string &file, const Functor &)> &save) const; 124 | 125 | public: 126 | UnionFolder(Folder &parent); 127 | 128 | virtual void Save(const std::string &path, bool edit, const void *flag, const Functor &code); 129 | virtual bool Look(const std::string &path) const; 130 | virtual void Open(const std::string &path, const Functor &code) const; 131 | virtual void Find(const std::string &path, const Functor &code, const Functor &)> &link) const; 132 | 133 | void operator ()(const std::string &from) { 134 | deletes_.insert(from); 135 | } 136 | 137 | void operator ()(const std::string &from, const std::string &to) { 138 | operator ()(from); 139 | remaps_[to] = from; 140 | } 141 | 142 | void operator ()(const std::string &from, const void *flag, std::streambuf &data) { 143 | operator ()(from); 144 | auto &reset(resets_[from]); 145 | reset.flag_ = flag; 146 | reset.data_ = &data; 147 | } 148 | }; 149 | 150 | struct Hash { 151 | uint8_t sha1_[0x14]; 152 | uint8_t sha256_[0x20]; 153 | }; 154 | 155 | struct Bundle { 156 | std::string path; 157 | Hash hash; 158 | }; 159 | 160 | Bundle Sign(const std::string &root, Folder &folder, const std::string &key, const std::string &requirements, const Functor &alter, bool merge, uint8_t platform, const Progress &progress); 161 | 162 | typedef std::map Slots; 163 | 164 | Hash Sign(const void *idata, size_t isize, std::streambuf &output, const std::string &identifier, const std::string &entitlements, bool merge, const std::string &requirements, const std::string &key, const Slots &slots, uint32_t flags, uint8_t platform, const Progress &progress); 165 | 166 | } 167 | 168 | #endif//LDID_HPP 169 | -------------------------------------------------------------------------------- /ldid/libcrypto.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/ldid/libcrypto.a -------------------------------------------------------------------------------- /ldid/libplist-2.0.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/ldid/libplist-2.0.a -------------------------------------------------------------------------------- /ldid/roothide.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | com.apple.private.security.no-sandbox 8 | 9 | com.apple.private.security.storage.AppBundles 10 | 11 | com.apple.private.security.storage.AppDataContainers 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /preload/.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | packages/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /preload/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 arm64e 2 | 3 | TARGET := iphone:clang:latest:15.0 4 | 5 | THEOS_PACKAGE_SCHEME = roothide 6 | 7 | include $(THEOS)/makefiles/common.mk 8 | 9 | TOOL_NAME = preload 10 | 11 | preload_FILES = preload.m ../bootstrapd/ipc.m ../bootstrapd/libbsd.m 12 | preload_CFLAGS = -fobjc-arc 13 | preload_CODESIGN_FLAGS = -Sentitlements.plist 14 | preload_INSTALL_PATH = /basebin 15 | 16 | include $(THEOS_MAKE_PATH)/tool.mk 17 | 18 | LIBRARY_NAME = prelib 19 | prelib_FILES = prelib.m 20 | prelib_CFLAGS = -fobjc-arc -Wno-unused-variable -Wno-unused-but-set-variable 21 | prelib_LFGLAGS = 22 | prelib_CODESIGN_FLAGS = 23 | prelib_INSTALL_PATH = /basebin 24 | 25 | include $(THEOS_MAKE_PATH)/library.mk 26 | 27 | clean:: 28 | rm -rf ./packages/* 29 | 30 | before-package:: 31 | mv ./.theos/_/basebin/prelib.dylib ./.theos/_/basebin/preload.dylib 32 | -------------------------------------------------------------------------------- /preload/control: -------------------------------------------------------------------------------- 1 | Package: com.roothide.preload 2 | Name: preload 3 | Version: 0.0.1 4 | Architecture: iphoneos-arm 5 | Description: An awesome tool of some sort!! 6 | Maintainer: roothide 7 | Author: roothide 8 | Section: System 9 | Tag: role::hacker 10 | -------------------------------------------------------------------------------- /preload/entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | platform-application 5 | 6 | com.apple.private.security.no-sandbox 7 | 8 | com.apple.private.security.no-container 9 | 10 | com.apple.private.security.container-required 11 | 12 | com.apple.private.security.storage.AppBundles 13 | 14 | com.apple.private.security.storage.AppDataContainers 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /preload/layout/DEBIAN/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ls /Applications/ | while read app; do 4 | echo "--$app--"; 5 | unlink "/Applications/$app/.preload" 6 | unlink "/Applications/$app/.prelib" 7 | link /basebin/preload "/Applications/$app/.preload" 8 | link /basebin/preload.dylib "/Applications/$app/.prelib" 9 | done 10 | 11 | ls -d /var/containers/Bundle/Application/*/*.app/.jbroot | while read file; do 12 | bundle=$(dirname "$file") 13 | echo "--$bundle--" 14 | 15 | unlink "$bundle"/.jbroot 16 | ln -s / "$bundle"/.jbroot 17 | 18 | unlink "$bundle"/.preload 19 | unlink "$bundle"/.prelib 20 | link /basebin/preload "$bundle"/.preload 21 | link /basebin/preload.dylib "$bundle"/.prelib 22 | done 23 | -------------------------------------------------------------------------------- /preload/prelib.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "sandbox.h" 8 | 9 | extern char*const* environ; 10 | 11 | void unsandbox(const char* sbtoken) { 12 | char extensionsCopy[strlen(sbtoken)]; 13 | strcpy(extensionsCopy, sbtoken); 14 | char *extensionToken = strtok(extensionsCopy, "|"); 15 | while (extensionToken != NULL) { 16 | sandbox_extension_consume(extensionToken); 17 | extensionToken = strtok(NULL, "|"); 18 | } 19 | } 20 | 21 | bool checkpatchedexe() { 22 | char executablePath[PATH_MAX]={0}; 23 | uint32_t bufsize=sizeof(executablePath); 24 | assert(_NSGetExecutablePath(executablePath, &bufsize) == 0); 25 | 26 | char patcher[PATH_MAX]; 27 | snprintf(patcher, sizeof(patcher), "%s.roothidepatch", executablePath); 28 | if(access(patcher, F_OK)==0) 29 | return false; 30 | 31 | return true; 32 | } 33 | 34 | static void __attribute__((__constructor__)) preload() 35 | { 36 | // debugserver spawn reparent 37 | // if(getppid() != 1) return; 38 | 39 | NSString* rebuildFile = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@".rebuild"]; 40 | NSDictionary* rebuildStatus = [NSDictionary dictionaryWithContentsOfFile:rebuildFile]; 41 | 42 | const char* sbtoken = [rebuildStatus[@"sb_token"] UTF8String]; 43 | if(sbtoken) { 44 | unsandbox(sbtoken); 45 | } 46 | 47 | int found=0; 48 | int count=_dyld_image_count(); 49 | for(int i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | extern char*const* environ; 10 | 11 | #include "../bootstrapd/libbsd.h" 12 | 13 | int main(int argc, char *argv[], char *envp[]) { 14 | @autoreleasepool { 15 | 16 | NSLog(@"preload @ %s", argv[0]); 17 | 18 | NSString* appInfoPath = [NSString stringWithFormat:@"%s/Info.plist", dirname(argv[0])]; 19 | NSDictionary *appInfoPlist = [NSDictionary dictionaryWithContentsOfFile:appInfoPath]; 20 | NSString* executableName = appInfoPlist[@"CFBundleExecutable"]; 21 | NSLog(@"executableName=%@", executableName); 22 | 23 | if(getppid()==1) 24 | { 25 | const char* sbtoken = bsd_getsbtoken(); 26 | if(sbtoken) { 27 | setenv("_SBTOKEN", sbtoken, 1); 28 | } else { 29 | char patcher[PATH_MAX]; 30 | snprintf(patcher, sizeof(patcher), "%s/%s.roothidepatch", dirname(argv[0]), executableName.UTF8String); 31 | if(access(patcher, F_OK)==0) 32 | abort(); 33 | } 34 | 35 | setenv("DYLD_INSERT_LIBRARIES", "@executable_path/.jbroot/basebin/bootstrap.dylib:@executable_path/.prelib", 1); 36 | } 37 | 38 | char executable[PATH_MAX]; 39 | snprintf(executable, sizeof(executable), "%s/%s", dirname(argv[0]), executableName.UTF8String); 40 | 41 | argv[0] = executable; 42 | 43 | // execv(argv[0], argv); //don't use envp 44 | 45 | posix_spawnattr_t attr; 46 | posix_spawnattr_init(&attr); 47 | 48 | #define _POSIX_SPAWN_NANO_ALLOCATOR 0x0200 49 | posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETEXEC|POSIX_SPAWN_CLOEXEC_DEFAULT|_POSIX_SPAWN_NANO_ALLOCATOR); 50 | 51 | 52 | posix_spawn_file_actions_t action; 53 | posix_spawn_file_actions_init(&action); 54 | posix_spawn_file_actions_addopen(&action, 0, "/dev/null", 0x20000, 0x1b6); 55 | posix_spawn_file_actions_addopen(&action, 0x1, "/dev/null", 0x20002, 0x1b6); 56 | posix_spawn_file_actions_addopen(&action, 0x2, "/dev/null", 0x20002, 0x1b6); 57 | 58 | pid_t pid=0; 59 | int ret = posix_spawn(&pid, argv[0], &action, &attr, argv, environ); 60 | NSLog(@"exec failed %s,%d for %s", strerror(ret), pid, argv[0]); 61 | abort(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /preload/sandbox.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | enum sandbox_filter_type { 4 | SANDBOX_FILTER_NONE, 5 | SANDBOX_FILTER_PATH, 6 | SANDBOX_FILTER_GLOBAL_NAME, 7 | SANDBOX_FILTER_LOCAL_NAME, 8 | SANDBOX_FILTER_APPLEEVENT_DESTINATION, 9 | SANDBOX_FILTER_RIGHT_NAME, 10 | SANDBOX_FILTER_PREFERENCE_DOMAIN, 11 | SANDBOX_FILTER_KEXT_BUNDLE_ID, 12 | SANDBOX_FILTER_INFO_TYPE, 13 | SANDBOX_FILTER_NOTIFICATION, 14 | // ? 15 | // ? 16 | SANDBOX_FILTER_XPC_SERVICE_NAME = 12, 17 | SANDBOX_FILTER_IOKIT_CONNECTION, 18 | // ? 19 | // ? 20 | // ? 21 | // ? 22 | }; 23 | 24 | enum sandbox_extension_flags { 25 | FS_EXT_DEFAULTS = 0, 26 | FS_EXT_FOR_PATH = (1 << 0), 27 | FS_EXT_FOR_FILE = (1 << 1), 28 | FS_EXT_READ = (1 << 2), 29 | FS_EXT_WRITE = (1 << 3), 30 | FS_EXT_PREFER_FILEID = (1 << 4), 31 | }; 32 | 33 | enum sandbox_extension_types { 34 | EXTENSION_TYPE_FILE, 35 | EXTENSION_TYPE_MACH, 36 | EXTENSION_TYPE_IOKIT_REGISTRY_ENTRY, 37 | EXTENSION_TYPE_GENERIC, 38 | EXTENSION_TYPE_POSIX, 39 | EXTENSION_TYPE_PREFERENCE, 40 | EXTENSION_TYPE_SYSCTL, 41 | EXTENSION_TYPE_MAX /* last */ 42 | }; 43 | 44 | #define EXTENSION_FLAG_INVALID (1 << 0) 45 | #define EXTENSION_FLAG_CANONICAL (1 << 1) 46 | #define EXTENSION_FLAG_PREFIXMATCH (1 << 2) /* Not for paths. */ 47 | #define EXTENSION_FLAG_PATHLITERAL (1 << 3) /* Only for paths. */ 48 | #define EXTENSION_FLAG_NO_REPORT (1 << 4) 49 | #define EXTENSION_FLAG_BIND_PID (1 << 16) 50 | #define EXTENSION_FLAG_BIND_PIDVERSION (1 << 17) 51 | 52 | #define MAX_TOKEN_SIZE 2048 53 | 54 | struct syscall_extension_issue_args { 55 | uint64_t extension_class; 56 | uint64_t extension_type; 57 | uint64_t extension_data; 58 | uint64_t extension_flags; 59 | uint64_t extension_token; /* out */ 60 | int64_t extension_pid; 61 | int64_t extension_pid_version; 62 | }; 63 | 64 | extern const char *APP_SANDBOX_IOKIT_CLIENT; 65 | extern const char *APP_SANDBOX_MACH; 66 | extern const char *APP_SANDBOX_READ; 67 | extern const char *APP_SANDBOX_READ_WRITE; 68 | 69 | extern const char *IOS_SANDBOX_APPLICATION_GROUP; 70 | extern const char *IOS_SANDBOX_CONTAINER; 71 | 72 | extern const enum sandbox_filter_type SANDBOX_CHECK_ALLOW_APPROVAL; 73 | extern const enum sandbox_filter_type SANDBOX_CHECK_CANONICAL; 74 | extern const enum sandbox_filter_type SANDBOX_CHECK_NOFOLLOW; 75 | extern const enum sandbox_filter_type SANDBOX_CHECK_NO_APPROVAL; 76 | extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT; 77 | 78 | extern const uint32_t SANDBOX_EXTENSION_CANONICAL; 79 | extern const uint32_t SANDBOX_EXTENSION_DEFAULT; 80 | extern const uint32_t SANDBOX_EXTENSION_MAGIC; 81 | extern const uint32_t SANDBOX_EXTENSION_NOFOLLOW; 82 | extern const uint32_t SANDBOX_EXTENSION_NO_REPORT; 83 | extern const uint32_t SANDBOX_EXTENSION_NO_STORAGE_CLASS; 84 | extern const uint32_t SANDBOX_EXTENSION_PREFIXMATCH; 85 | extern const uint32_t SANDBOX_EXTENSION_UNRESOLVED; 86 | 87 | int sandbox_init(const char *profile, uint64_t flags, char **errorbuf); 88 | int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); 89 | int sandbox_init_with_extensions(const char *profile, uint64_t flags, const char *const extensions[], char **errorbuf); 90 | 91 | int sandbox_check(pid_t, const char *operation, enum sandbox_filter_type, ...); 92 | int sandbox_check_by_audit_token(audit_token_t, const char *operation, enum sandbox_filter_type, ...); 93 | int sandbox_check_by_uniqueid(uid_t, pid_t, const char *operation, enum sandbox_filter_type, ...); 94 | 95 | int64_t sandbox_extension_consume(const char *extension_token); 96 | char *sandbox_extension_issue_file(const char *extension_class, const char *path, uint32_t flags); 97 | char *sandbox_extension_issue_file_to_process(const char *extension_class, const char *path, uint32_t flags, audit_token_t); 98 | char *sandbox_extension_issue_file_to_process_by_pid(const char *extension_class, const char *path, uint32_t flags, pid_t); 99 | char *sandbox_extension_issue_file_to_self(const char *extension_class, const char *path, uint32_t flags); 100 | char *sandbox_extension_issue_generic(const char *extension_class, uint32_t flags); 101 | char *sandbox_extension_issue_generic_to_process(const char *extension_class, uint32_t flags, audit_token_t); 102 | char *sandbox_extension_issue_generic_to_process_by_pid(const char *extension_class, uint32_t flags, pid_t); 103 | char *sandbox_extension_issue_iokit_registry_entry_class(const char *extension_class, const char *registry_entry_class, uint32_t flags); 104 | char *sandbox_extension_issue_iokit_registry_entry_class_to_process(const char *extension_class, const char *registry_entry_class, uint32_t flags, audit_token_t); 105 | char *sandbox_extension_issue_iokit_registry_entry_class_to_process_by_pid(const char *extension_class, const char *registry_entry_class, uint32_t flags, pid_t); 106 | char *sandbox_extension_issue_iokit_user_client_class(const char *extension_class, const char *registry_entry_class, uint32_t flags); 107 | char *sandbox_extension_issue_mach(const char *extension_class, const char *name, uint32_t flags); 108 | char *sandbox_extension_issue_mach_to_process(const char *extension_class, const char *name, uint32_t flags, audit_token_t); 109 | char *sandbox_extension_issue_mach_to_process_by_pid(const char *extension_class, const char *name, uint32_t flags, pid_t); 110 | char *sandbox_extension_issue_posix_ipc(const char *extension_class, const char *name, uint32_t flags); 111 | 112 | void sandbox_extension_reap(void); 113 | int sandbox_extension_release(int64_t extension_handle); 114 | int sandbox_extension_release_file(int64_t extension_handle, const char *path); 115 | int sandbox_extension_update_file(int64_t extension_handle, const char *path); 116 | 117 | int __sandbox_ms(const char *policyname, int call, void *arg); -------------------------------------------------------------------------------- /rebuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | PREV_DIR=$(pwd) 6 | WORK_DIR=$(dirname -- "$0") 7 | cd "$WORK_DIR" 8 | 9 | cd ChOma-main 10 | make clean-all && make TARGET=ios 11 | cd - 12 | 13 | cd ldid 14 | make clean && make 15 | cd - 16 | 17 | cd fastPathSign 18 | make clean && make 19 | cd - 20 | 21 | cd uicache 22 | make clean && make package 23 | cd - 24 | 25 | cd rebuildapp 26 | make clean && make package 27 | cd - 28 | 29 | cd preload 30 | make clean && make package 31 | cd - 32 | 33 | cd bootstrap 34 | make clean && make package 35 | cd - 36 | 37 | cd bootstrapd 38 | make clean && make package 39 | cd - 40 | 41 | cd devtest 42 | make clean && make package 43 | cd - 44 | 45 | echo "**** rebuild successful ****" 46 | 47 | ./copy.sh 48 | 49 | cd "$PREV_DIR" 50 | -------------------------------------------------------------------------------- /rebuildapp/.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | packages/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /rebuildapp/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "__string": "cpp", 4 | "deque": "cpp", 5 | "filesystem": "cpp", 6 | "string": "cpp", 7 | "system_error": "cpp", 8 | "vector": "cpp" 9 | } 10 | } -------------------------------------------------------------------------------- /rebuildapp/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 arm64e 2 | TARGET := iphone:clang:latest:15.0 3 | THEOS_PACKAGE_SCHEME = roothide 4 | 5 | include $(THEOS)/makefiles/common.mk 6 | 7 | TOOL_NAME = rebuildapp 8 | 9 | rebuildapp_FILES = $(wildcard *.c *.m *.mm *.cpp) 10 | rebuildapp_CFLAGS = -fobjc-arc -I./ $(shell pkg-config --cflags libcrypto) $(shell pkg-config --cflags libplist-2.0) -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-function -Wno-unneeded-internal-declaration 11 | rebuildapp_CCFLAGS = -std=c++11 12 | rebuildapp_LDFLAGS = -L./ -lchoma -lcrypto -lplist-2.0 13 | rebuildapp_CODESIGN_FLAGS = -Sentitlements.plist 14 | rebuildapp_INSTALL_PATH = /basebin/ 15 | 16 | include $(THEOS_MAKE_PATH)/tool.mk 17 | 18 | clean:: 19 | rm -rf ./packages/* 20 | 21 | before-package:: 22 | cp -a ../entitlements ./.theos/_/basebin/ 23 | 24 | # after-install:: 25 | # install.exec '$(THEOS_PACKAGE_INSTALL_PREFIX)/basebin/$(TOOL_NAME)' /Applications/MobileSafari.app 26 | -------------------------------------------------------------------------------- /rebuildapp/Templates/DecryptedSignature.h: -------------------------------------------------------------------------------- 1 | unsigned char DecryptedSignature[] = { 2 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 3 | 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0xe2, 0x34, 0xf9, 0x25, 0x65, 4 | 0xa4, 0x33, 0xb7, 0x13, 0x67, 0xc8, 0x63, 0x93, 0xdc, 0x41, 0xaa, 0xc4, 5 | 0x0e, 0x76, 0xa0, 0x80, 0x29, 0x8b, 0x38, 0x9e, 0xc5, 0x6d, 0xd6, 0xba, 6 | 0xef, 0xbf, 0x0d 7 | }; 8 | unsigned int DecryptedSignature_len = 51; 9 | -------------------------------------------------------------------------------- /rebuildapp/choma: -------------------------------------------------------------------------------- 1 | ../ChOma-main/output/ios/include/choma -------------------------------------------------------------------------------- /rebuildapp/control: -------------------------------------------------------------------------------- 1 | Package: com.roothide.rebuildapp 2 | Name: rebuildapp 3 | Version: 0.0.1 4 | Architecture: iphoneos-arm 5 | Description: An awesome tool of some sort!! 6 | Maintainer: roothide 7 | Author: roothide 8 | Section: System 9 | Tag: role::hacker 10 | -------------------------------------------------------------------------------- /rebuildapp/entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | platform-application 5 | 6 | com.apple.private.security.container-required 7 | 8 | 9 | com.apple.private.security.storage.AppBundles 10 | 11 | com.apple.private.security.storage.AppDataContainers 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /rebuildapp/layout/basebin/rebuildapps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ls /Applications/ | while read app; do 4 | echo "--$app--"; 5 | 6 | uicache -p "/Applications/$app" || true 7 | 8 | done 9 | 10 | ls -d /var/containers/Bundle/Application/*/*.app/.jbroot | while read file; do 11 | bundle=$(dirname "$file") 12 | echo "--$bundle--" 13 | 14 | unlink "$bundle"/.jbroot 15 | ln -s / "$bundle"/.jbroot 16 | 17 | uicache -s -p "$bundle" || true 18 | done 19 | -------------------------------------------------------------------------------- /rebuildapp/libchoma.a: -------------------------------------------------------------------------------- 1 | ../ChOma-main/output/ios/lib/libchoma.a -------------------------------------------------------------------------------- /rebuildapp/libcrypto.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/rebuildapp/libcrypto.a -------------------------------------------------------------------------------- /rebuildapp/libplist-2.0.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roothide/Bootstrap-basebin/46c860dbb65e47d7d34ad9ed6731ca9245b67f7b/rebuildapp/libplist-2.0.a -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | set jbroot_path $(realpath ..) 2 | export DYLD_INSERT_LIBRARIES=$jbroot_path/basebin/bootstrap.dylib 3 | DYLD_INSERT_LIBRARIES=$jbroot_path/basebin/bootstrap.dylib $jbroot_path/usr/bin/zsh 4 | -------------------------------------------------------------------------------- /uicache/.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | packages/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /uicache/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "fat.h": "c", 4 | "fixup-chains.h": "c", 5 | "vm_page_size.h": "c", 6 | "loader.h": "c", 7 | "nlist.h": "c" 8 | } 9 | } -------------------------------------------------------------------------------- /uicache/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 2 | TARGET := iphone:clang:latest:15.0 3 | THEOS_PACKAGE_SCHEME = roothide 4 | 5 | include $(THEOS)/makefiles/common.mk 6 | 7 | TOOL_NAME = uicache 8 | 9 | uicache_FILES = main.m exepatch.c ../bootstrapd/ipc.m ../bootstrapd/libbsd.m 10 | uicache_CFLAGS = -fobjc-arc -I./ -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function 11 | uicache_LDFLAGS = -L./ -lchoma -framework CoreServices -framework MobileCoreServices -framework Security -framework MobileContainerManager -framework CoreTelephony -framework RunningBoardServices 12 | uicache_CODESIGN_FLAGS = -Sentitlements.plist 13 | uicache_INSTALL_PATH = /basebin 14 | 15 | include $(THEOS_MAKE_PATH)/tool.mk 16 | 17 | clean:: 18 | rm -rf ./packages/* 19 | -------------------------------------------------------------------------------- /uicache/choma: -------------------------------------------------------------------------------- 1 | ../ChOma-main/output/ios/include/choma -------------------------------------------------------------------------------- /uicache/control: -------------------------------------------------------------------------------- 1 | Package: com.roothide.uicache 2 | Name: uicache 3 | Version: 0.0.1 4 | Architecture: iphoneos-arm 5 | Description: An awesome tool of some sort!! 6 | Maintainer: roothide 7 | Author: roothide 8 | Section: System 9 | Tag: role::hacker 10 | -------------------------------------------------------------------------------- /uicache/entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | platform-application 5 | 6 | com.apple.private.security.no-container 7 | 8 | com.apple.private.security.no-sandbox 9 | 10 | com.apple.private.security.storage.AppBundles 11 | 12 | com.apple.private.security.storage.AppDataContainers 13 | 14 | 15 | com.apple.private.mobileinstall.allowedSPI 16 | 17 | InstallForLaunchServices 18 | UninstallForLaunchServices 19 | 20 | com.apple.private.MobileContainerManager.allowed 21 | 22 | com.apple.lsapplicationworkspace.rebuildappdatabases 23 | 24 | com.apple.frontboard.launchapplications 25 | 26 | com.apple.frontboard.shutdown 27 | 28 | com.apple.appletv.pbs.allow-relaunch-backboardd 29 | 30 | com.apple.appletv.pbs.allow-relaunch 31 | 32 | 33 | com.apple.CommCenter.fine-grained 34 | 35 | data-allowed-write 36 | 37 | 38 | com.apple.runningboard.launch_extensions 39 | 40 | com.apple.runningboard.launchprocess 41 | 42 | com.apple.runningboard.process-state 43 | 44 | com.apple.runningboard.statecapture 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /uicache/libchoma.a: -------------------------------------------------------------------------------- 1 | ../ChOma-main/output/ios/lib/libchoma.a --------------------------------------------------------------------------------