├── .gitignore ├── ARM.hpp ├── Baton.hpp ├── Bootstrap.cpp ├── Buffer.hpp ├── Common.hpp ├── Cydia.hpp ├── Cydia.mm ├── CydiaSubstrate.h ├── DarwinFindSymbol.cpp ├── DarwinInjector.cpp ├── DarwinLauncher.cpp ├── DarwinLoader.cpp ├── DarwinThreadInternal.hpp ├── Debug.cpp ├── Debug.hpp ├── Environment.cpp ├── Environment.hpp ├── Hooker.cpp ├── Info.plist ├── LaunchDaemons.hpp ├── LaunchDaemons.mm ├── Log.hpp ├── MachInterface.sh ├── MachMemory.cpp ├── MachMessage.cpp ├── MachMessage.hpp ├── MachProtect.defs ├── MobileSafety.jpg ├── MobileSafety.mm ├── MobileSafety.png ├── ObjectiveC.cpp ├── PosixMemory.cpp ├── TestSuperCall.mm ├── Trampoline.hpp ├── Trampoline.t.cpp ├── control ├── control.arm ├── control.i386 ├── control.sh ├── cycc ├── cynject.cpp ├── darwin.mk ├── extra ├── CoreFoundation │ ├── CFBundlePriv.h │ ├── CFLogUtilities.h │ └── CFPriv.h └── machine │ └── exec.h ├── extrainst_.mm ├── hde64c ├── LICENSE ├── NEWS ├── THANKS ├── doc │ ├── en │ │ └── manual.txt │ └── ru │ │ └── manual.txt ├── examples │ └── example.c ├── include │ └── hde64.h └── src │ ├── hde64.c │ └── table64.h ├── include ├── System │ └── machine │ │ └── cpu_capabilities.h ├── machine │ └── cpu_capabilities.h ├── posix_sched.h ├── pthread_internals.h ├── pthread_machdep.h ├── pthread_spinlock.h └── pthread_spis.h ├── ldid.sh ├── package.sh ├── postrm.mm ├── safe.sh ├── task_for_pid.xml ├── trampoline.sh ├── version.sh └── x86.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.dylib 3 | *.deb 4 | *.t.hpp 5 | MachProtect.h 6 | MachProtect.c 7 | package.* 8 | extrainst_ 9 | postrm 10 | cynject 11 | TestSuperCall 12 | -------------------------------------------------------------------------------- /ARM.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_ARM_HPP 23 | #define SUBSTRATE_ARM_HPP 24 | 25 | enum A$r { 26 | A$r0, A$r1, A$r2, A$r3, 27 | A$r4, A$r5, A$r6, A$r7, 28 | A$r8, A$r9, A$r10, A$r11, 29 | A$r12, A$r13, A$r14, A$r15, 30 | A$sp = A$r13, 31 | A$lr = A$r14, 32 | A$pc = A$r15 33 | }; 34 | 35 | enum A$c { 36 | A$eq, A$ne, A$cs, A$cc, 37 | A$mi, A$pl, A$vs, A$vc, 38 | A$hi, A$ls, A$ge, A$lt, 39 | A$gt, A$le, A$al, 40 | A$hs = A$cs, 41 | A$lo = A$cc 42 | }; 43 | 44 | #define A$mrs_rm_cpsr(rd) /* mrs rd, cpsr */ \ 45 | (0xe10f0000 | ((rd) << 12)) 46 | #define A$msr_cpsr_f_rm(rm) /* msr cpsr_f, rm */ \ 47 | (0xe128f000 | (rm)) 48 | #define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \ 49 | (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) 50 | #define A$str_rd_$rn_im$(rd, rn, im) /* sr rd, [rn, #im] */ \ 51 | (0xe5000000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) 52 | #define A$sub_rd_rn_$im(rd, rn, im) /* sub, rd, rn, #im */ \ 53 | (0xe2400000 | ((rn) << 16) | ((rd) << 12) | (im & 0xff)) 54 | #define A$blx_rm(rm) /* blx rm */ \ 55 | (0xe12fff30 | (rm)) 56 | #define A$mov_rd_rm(rd, rm) /* mov rd, rm */ \ 57 | (0xe1a00000 | ((rd) << 12) | (rm)) 58 | #define A$ldmia_sp$_$rs$(rs) /* ldmia sp!, {rs} */ \ 59 | (0xe8b00000 | (A$sp << 16) | (rs)) 60 | #define A$stmdb_sp$_$rs$(rs) /* stmdb sp!, {rs} */ \ 61 | (0xe9200000 | (A$sp << 16) | (rs)) 62 | #define A$stmia_sp$_$r0$ 0xe8ad0001 /* stmia sp!, {r0} */ 63 | #define A$bx_r0 0xe12fff10 /* bx r0 */ 64 | 65 | #endif//SUBSTRATE_ARM_HPP 66 | -------------------------------------------------------------------------------- /Baton.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_BATOM_HPP 23 | #define SUBSTRATE_BATOM_HPP 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | struct Baton { 30 | void (*__pthread_set_self)(pthread_t); 31 | 32 | int (*pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); 33 | int (*pthread_join)(pthread_t, void **); 34 | 35 | mach_port_t (*mach_thread_self)(); 36 | kern_return_t (*thread_terminate)(thread_act_t); 37 | 38 | char *(*dlerror)(); 39 | void *(*dlsym)(void *, const char *); 40 | 41 | char library[]; 42 | }; 43 | 44 | #endif//SUBSTRATE_BATOM_HPP 45 | -------------------------------------------------------------------------------- /Bootstrap.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "CydiaSubstrate.h" 23 | 24 | #include 25 | 26 | MSInitialize { 27 | if (getenv("MSExitZero") != NULL) { 28 | // skeels / planetbeing / rpetrich <- reporting SMS crash 29 | if (dlopen("/System/Library/PrivateFrameworks/Search.framework/AppIndexer", RTLD_LAZY | RTLD_NOLOAD) != NULL) 30 | _exit(EXIT_FAILURE); 31 | 32 | _exit(EXIT_SUCCESS); 33 | } 34 | 35 | // Skype 36 | if (dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY | RTLD_NOLOAD) == NULL) 37 | return; 38 | 39 | // Maps 40 | dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_LAZY | RTLD_GLOBAL); 41 | 42 | dlopen("/Library/Frameworks/CydiaSubstrate.framework/Libraries/SubstrateLoader.dylib", RTLD_LAZY | RTLD_GLOBAL); 43 | } 44 | -------------------------------------------------------------------------------- /Buffer.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_BUFFER_HPP 23 | #define SUBSTRATE_BUFFER_HPP 24 | 25 | #include 26 | 27 | template 28 | _disused static _finline void MSWrite(uint8_t *&buffer, Type_ value) { 29 | *reinterpret_cast(buffer) = value; 30 | buffer += sizeof(Type_); 31 | } 32 | 33 | _disused static _finline void MSWrite(uint8_t *&buffer, uint8_t *data, size_t size) { 34 | memcpy(buffer, data, size); 35 | buffer += size; 36 | } 37 | 38 | #endif//SUBSTRATE_BUFFER_HPP 39 | -------------------------------------------------------------------------------- /Common.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_COMMON_HPP 23 | #define SUBSTRATE_COMMON_HPP 24 | 25 | #include 26 | #include "Log.hpp" 27 | 28 | #define _syscall(expr) ({ \ 29 | __typeof__(expr) _value; \ 30 | for(;;) if ((long) (_value = (expr)) != -1 || errno != EINTR) \ 31 | break; \ 32 | _value; \ 33 | }) 34 | 35 | #define _trace() do { \ 36 | MSLog(MSLogLevelError, "%s(%d): _trace()", __FILE__, __LINE__); \ 37 | } while (false) 38 | 39 | #endif//SUBSTRATE_COMMON_HPP 40 | -------------------------------------------------------------------------------- /Cydia.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_CYDIA_HPP 23 | #define SUBSTRATE_CYDIA_HPP 24 | 25 | void FinishCydia(const char *finish); 26 | 27 | enum ForkBugStatus { 28 | ForkBugUnknown, 29 | ForkBugMissing, 30 | ForkBugPresent, 31 | }; 32 | 33 | ForkBugStatus DetectForkBug(); 34 | 35 | #endif//SUBSTRATE_CYDIA_HPP 36 | -------------------------------------------------------------------------------- /Cydia.mm: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #include "Common.hpp" 30 | #include "Cydia.hpp" 31 | 32 | void FinishCydia(const char *finish) { 33 | if (finish == NULL) 34 | return; 35 | 36 | const char *cydia(getenv("CYDIA")); 37 | if (cydia == NULL) 38 | return; 39 | 40 | 41 | // XXX: I think I'd like to rewrite this code using C++ 42 | int fd([[[[NSString stringWithUTF8String:cydia] componentsSeparatedByString:@" "] objectAtIndex:0] intValue]); 43 | 44 | FILE *fout(fdopen(fd, "w")); 45 | fprintf(fout, "finish:%s\n", finish); 46 | fclose(fout); 47 | } 48 | 49 | ForkBugStatus DetectForkBug() { 50 | mach_port_t self(mach_task_self()); 51 | int page(getpagesize()); 52 | 53 | volatile uint8_t *data(reinterpret_cast(&fopen)); 54 | uintptr_t base(reinterpret_cast(data) / page * page); 55 | 56 | vm_protect(self, base, page, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY); 57 | data[0] = data[0]; 58 | vm_protect(self, base, page, FALSE, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); 59 | 60 | pid_t pid(fork()); 61 | if (pid == 0) { 62 | fopen("/tmp/fork", "rb"); 63 | _exit(EXIT_SUCCESS); 64 | } 65 | 66 | int status; 67 | if (_syscall(waitpid(pid, &status, 0) == -1)) { 68 | fprintf(stderr, "waitpid() -> %d\n", errno); 69 | return ForkBugUnknown; 70 | } 71 | 72 | if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS) 73 | return ForkBugMissing; 74 | else 75 | // XXX: consider checking for a killed status, and returning ForBugUnknown if not 76 | return ForkBugPresent; 77 | } 78 | -------------------------------------------------------------------------------- /DarwinFindSymbol.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | extern "C" { 30 | #include 31 | } 32 | 33 | #define BSD_KERNEL_PRIVATE 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include "CydiaSubstrate.h" 41 | 42 | #define _trace() do { \ 43 | MSLog(MSLogLevelNotice, "_trace(%u)", __LINE__); \ 44 | } while (false) 45 | 46 | struct MSSymbolData { 47 | const char *name_; 48 | uint8_t type_; 49 | uint8_t sect_; 50 | int16_t desc_; 51 | uintptr_t value_; 52 | }; 53 | 54 | #ifdef __LP64__ 55 | typedef struct mach_header_64 mach_header_xx; 56 | typedef struct nlist_64 nlist_xx; 57 | typedef struct segment_command_64 segment_command_xx; 58 | 59 | static const uint32_t LC_SEGMENT_XX = LC_SEGMENT_64; 60 | static const uint32_t MH_MAGIC_XX = MH_MAGIC_64; 61 | #else 62 | typedef struct mach_header mach_header_xx; 63 | typedef struct nlist nlist_xx; 64 | typedef struct segment_command segment_command_xx; 65 | 66 | static const uint32_t LC_SEGMENT_XX = LC_SEGMENT; 67 | static const uint32_t MH_MAGIC_XX = MH_MAGIC; 68 | #endif 69 | 70 | static ssize_t MSMachONameList_(const void *stuff, struct MSSymbolData *list, size_t nreq) { 71 | // XXX: ok, this is just pathetic; API fail much? 72 | size_t slide(0); 73 | for (uint32_t image(0), images(_dyld_image_count()); image != images; ++image) 74 | if (_dyld_get_image_header(image) == stuff) { 75 | slide = _dyld_get_image_vmaddr_slide(image); 76 | goto fat; 77 | } 78 | 79 | return -1; 80 | 81 | fat: 82 | const uint8_t *base(reinterpret_cast(stuff)); 83 | const struct exec *buf(reinterpret_cast(base)); 84 | 85 | if (OSSwapBigToHostInt32(buf->a_magic) == FAT_MAGIC) { 86 | struct host_basic_info hbi; { 87 | host_t host(mach_host_self()); 88 | mach_msg_type_number_t count(HOST_BASIC_INFO_COUNT); 89 | if (host_info(host, HOST_BASIC_INFO, reinterpret_cast(&hbi), &count) != KERN_SUCCESS) 90 | return -1; 91 | mach_port_deallocate(mach_task_self(), host); 92 | } 93 | 94 | const struct fat_header *fh(reinterpret_cast(base)); 95 | uint32_t nfat_arch(OSSwapBigToHostInt32(fh->nfat_arch)); 96 | const struct fat_arch *fat_archs(reinterpret_cast(fh + 1)); 97 | 98 | for (uint32_t i(0); i != nfat_arch; ++i) 99 | if (static_cast(OSSwapBigToHostInt32(fat_archs[i].cputype)) == hbi.cpu_type) { 100 | buf = reinterpret_cast(base + OSSwapBigToHostInt32(fat_archs[i].offset)); 101 | goto thin; 102 | } 103 | 104 | return -1; 105 | } 106 | 107 | thin: 108 | const nlist_xx *symbols; 109 | const char *strings; 110 | size_t n; 111 | 112 | // XXX: this check looks really scary when it fails 113 | if (buf->a_magic == MH_MAGIC_XX) { 114 | const mach_header_xx *mh(reinterpret_cast(base)); 115 | const struct load_command *load_commands(reinterpret_cast(mh + 1)); 116 | 117 | const struct symtab_command *stp(NULL); 118 | const struct load_command *lcp; 119 | 120 | /* forlc (command, mh, LC_SYMTAB, struct symtab_command) { 121 | stp = command; 122 | goto found; 123 | } */ 124 | 125 | lcp = load_commands; 126 | for (uint32_t i(0); i != mh->ncmds; ++i) { 127 | if ( 128 | lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 || 129 | reinterpret_cast(lcp) + lcp->cmdsize > reinterpret_cast(load_commands) + mh->sizeofcmds 130 | ) 131 | return -1; 132 | 133 | if (lcp->cmd == LC_SYMTAB) { 134 | if (lcp->cmdsize != sizeof(struct symtab_command)) 135 | return -1; 136 | stp = reinterpret_cast(lcp); 137 | goto found; 138 | } 139 | 140 | lcp = reinterpret_cast(reinterpret_cast(lcp) + lcp->cmdsize); 141 | } 142 | 143 | return -1; 144 | 145 | found: 146 | n = stp->nsyms; 147 | 148 | symbols = NULL; 149 | strings = NULL; 150 | 151 | /* forlc (command, mh, LC_SEGMENT_XX, segment_command_xx) { 152 | stp = command; 153 | goto found; 154 | } */ 155 | 156 | lcp = load_commands; 157 | for (uint32_t i(0); i != mh->ncmds; ++i) { 158 | if ( 159 | lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 || 160 | reinterpret_cast(lcp) + lcp->cmdsize > reinterpret_cast(load_commands) + mh->sizeofcmds 161 | ) 162 | return -1; 163 | 164 | if (lcp->cmd == LC_SEGMENT_XX) { 165 | if (lcp->cmdsize < sizeof(segment_command_xx)) 166 | return -1; 167 | const segment_command_xx *segment(reinterpret_cast(lcp)); 168 | if (stp->symoff >= segment->fileoff && stp->symoff < segment->fileoff + segment->filesize) 169 | symbols = reinterpret_cast(stp->symoff - segment->fileoff + segment->vmaddr + slide); 170 | if (stp->stroff >= segment->fileoff && stp->stroff < segment->fileoff + segment->filesize) 171 | strings = reinterpret_cast(stp->stroff - segment->fileoff + segment->vmaddr + slide); 172 | } 173 | 174 | lcp = reinterpret_cast(reinterpret_cast(lcp) + lcp->cmdsize); 175 | } 176 | 177 | if (symbols == NULL || strings == NULL) 178 | return -1; 179 | // XXX: detect a.out somehow? 180 | } else if (false) { 181 | /* XXX: is this right anymore?!? */ 182 | symbols = reinterpret_cast(base + N_SYMOFF(*buf)); 183 | strings = reinterpret_cast(reinterpret_cast(symbols) + buf->a_syms); 184 | n = buf->a_syms / sizeof(nlist_xx); 185 | } else return -1; 186 | 187 | size_t result(nreq); 188 | 189 | for (size_t m(0); m != n; ++m) { 190 | const nlist_xx *q(&symbols[m]); 191 | if (q->n_un.n_strx == 0 || (q->n_type & N_STAB) != 0) 192 | continue; 193 | 194 | const char *nambuf(strings + q->n_un.n_strx); 195 | //fprintf(stderr, " == %s\n", nambuf); 196 | 197 | for (size_t item(0); item != nreq; ++item) { 198 | struct MSSymbolData *p(list + item); 199 | if (p->name_ == NULL || strcmp(p->name_, nambuf) != 0) 200 | continue; 201 | 202 | p->name_ = NULL; 203 | 204 | p->value_ = q->n_value; 205 | if (p->value_ != 0) 206 | p->value_ += slide; 207 | 208 | p->type_ = q->n_type; 209 | p->desc_ = q->n_desc; 210 | p->sect_ = q->n_sect; 211 | 212 | if (--result == 0) 213 | return 0; 214 | break; 215 | } 216 | } 217 | 218 | return result; 219 | } 220 | 221 | _extern MSImageRef MSGetImageByName(const char *file) { 222 | for (uint32_t image(0), images(_dyld_image_count()); image != images; ++image) 223 | if (strcmp(_dyld_get_image_name(image), file) == 0) 224 | return _dyld_get_image_header(image); 225 | return NULL; 226 | } 227 | 228 | static void MSFindSymbols(MSImageRef image, size_t count, const char *names[], void *values[]) { 229 | MSSymbolData items[count]; 230 | 231 | for (size_t index(0); index != count; ++index) { 232 | MSSymbolData &item(items[index]); 233 | 234 | item.name_ = names[index]; 235 | item.type_ = 0; 236 | item.sect_ = 0; 237 | item.desc_ = 0; 238 | item.value_ = 0; 239 | } 240 | 241 | if (image != NULL) 242 | MSMachONameList_(image, items, count); 243 | else { 244 | size_t remain(count); 245 | 246 | for (uint32_t image(0), images(_dyld_image_count()); image != images; ++image) { 247 | //fprintf(stderr, ":: %s\n", _dyld_get_image_name(image)); 248 | 249 | ssize_t result(MSMachONameList_(_dyld_get_image_header(image), items, count)); 250 | if (result == -1) 251 | continue; 252 | 253 | // XXX: maybe avoid this happening at all? a flag to NSMachONameList_? 254 | for (size_t index(0); index != count; ++index) { 255 | MSSymbolData &item(items[index]); 256 | if (item.name_ == NULL && item.value_ == 0) { 257 | ++result; 258 | item.name_ = names[index]; 259 | } 260 | } 261 | 262 | remain -= count - result; 263 | if (remain == 0) 264 | break; 265 | } 266 | } 267 | 268 | for (size_t index(0); index != count; ++index) { 269 | MSSymbolData &item(items[index]); 270 | uintptr_t value(item.value_); 271 | #ifdef __arm__ 272 | if ((item.desc_ & N_ARM_THUMB_DEF) != 0) 273 | value |= 0x00000001; 274 | #endif 275 | values[index] = reinterpret_cast(value); 276 | } 277 | } 278 | 279 | _extern void *MSFindSymbol(MSImageRef image, const char *name) { 280 | void *value; 281 | MSFindSymbols(image, 1, &name, &value); 282 | return value; 283 | } 284 | 285 | #ifdef __arm__ 286 | MSHook(int, nlist, const char *file, struct nlist *names) { 287 | const void *image(MSGetImageByName(file)); 288 | if (image == NULL) 289 | return (*_nlist)(file, names); 290 | 291 | size_t count(0); 292 | for (struct nlist *list(names); list->n_un.n_name != NULL; ++list) 293 | ++count; 294 | 295 | MSSymbolData items[count]; 296 | 297 | for (size_t index(0); index != count; ++index) { 298 | MSSymbolData &item(items[index]); 299 | struct nlist &name(names[index]); 300 | 301 | item.name_ = name.n_un.n_name; 302 | item.type_ = 0; 303 | item.sect_ = 0; 304 | item.desc_ = 0; 305 | item.value_ = 0; 306 | } 307 | 308 | int result(MSMachONameList_(image, items, count)); 309 | 310 | for (size_t index(0); index != count; ++index) { 311 | MSSymbolData &item(items[index]); 312 | struct nlist &name(names[index]); 313 | 314 | name.n_type = item.type_; 315 | name.n_sect = item.sect_; 316 | name.n_desc = item.desc_; 317 | name.n_value = item.value_; 318 | } 319 | 320 | return result; 321 | } 322 | 323 | MSInitialize { 324 | MSHookFunction(&nlist, MSHake(nlist)); 325 | } 326 | #endif 327 | -------------------------------------------------------------------------------- /DarwinInjector.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "CydiaSubstrate.h" 31 | 32 | #include "Log.hpp" 33 | 34 | #include "Baton.hpp" 35 | #include "Trampoline.t.hpp" 36 | 37 | extern "C" void __pthread_set_self(pthread_t); 38 | 39 | #define _krncall(expr) \ 40 | do { \ 41 | kern_return_t _krnstatus((expr)); \ 42 | if (_krnstatus != KERN_SUCCESS) { \ 43 | MSLog(MSLogLevelError, "MS:Error: _krncall(%s)", #expr); \ 44 | return false; \ 45 | } \ 46 | } while (false) 47 | 48 | _extern bool MSHookProcess(pid_t pid, const char *library) { 49 | if (library[0] != '/') { 50 | MSLog(MSLogLevelError, "MSError: require absolute path to %s", library); 51 | return false; 52 | } 53 | 54 | static const size_t Stack_(8 * 1024); 55 | size_t length(strlen(library) + 1), depth(sizeof(Baton) + length); 56 | depth = (depth + sizeof(uintptr_t) + 1) / sizeof(uintptr_t) * sizeof(uintptr_t); 57 | 58 | uint8_t local[depth]; 59 | Baton *baton(reinterpret_cast(local)); 60 | 61 | 62 | // the dyld shared cache is only shuffled once per boot, allowing us to assume no ASLR 63 | // however, it is important that we restrict ourselves to those in cached libraries 64 | // XXX: it would be preferable to do this in a cross-architecture way, remotely 65 | 66 | baton->__pthread_set_self = &__pthread_set_self; 67 | 68 | baton->pthread_create = &pthread_create; 69 | baton->pthread_join = &pthread_join; 70 | 71 | baton->mach_thread_self = &mach_thread_self; 72 | baton->thread_terminate = &thread_terminate; 73 | 74 | baton->dlerror = &dlerror; 75 | baton->dlsym = &dlsym; 76 | 77 | 78 | memcpy(baton->library, library, length); 79 | 80 | vm_size_t size(depth + Stack_); 81 | 82 | mach_port_t self(mach_task_self()), task; 83 | _krncall(task_for_pid(self, pid, &task)); 84 | 85 | vm_address_t stack; 86 | _krncall(vm_allocate(task, &stack, size, true)); 87 | vm_address_t data(stack + Stack_); 88 | 89 | _krncall(vm_write(task, data, reinterpret_cast(baton), depth)); 90 | 91 | thread_act_t thread; 92 | _krncall(thread_create(task, &thread)); 93 | 94 | 95 | // XXX: look into using thread_get_state(THREAD_STATE_FLAVOR_LIST) to look up flavor 96 | 97 | thread_state_flavor_t flavor; 98 | mach_msg_type_number_t count; 99 | size_t push; 100 | 101 | Trampoline *trampoline; 102 | 103 | #if defined(__arm__) 104 | trampoline = &Trampoline_armv6_; 105 | arm_thread_state_t state; 106 | flavor = ARM_THREAD_STATE; 107 | count = ARM_THREAD_STATE_COUNT; 108 | push = 0; 109 | #elif defined(__i386__) 110 | trampoline = &Trampoline_i386_; 111 | i386_thread_state_t state; 112 | flavor = i386_THREAD_STATE; 113 | count = i386_THREAD_STATE_COUNT; 114 | push = 5; 115 | #elif defined(__x86_64__) 116 | trampoline = &Trampoline_x86_64_; 117 | x86_thread_state64_t state; 118 | flavor = x86_THREAD_STATE64; 119 | count = x86_THREAD_STATE64_COUNT; 120 | push = 2; 121 | #else 122 | #error XXX: implement 123 | #endif 124 | 125 | 126 | vm_address_t code; 127 | _krncall(vm_allocate(task, &code, trampoline->size_, true)); 128 | _krncall(vm_write(task, code, reinterpret_cast(trampoline->data_), trampoline->size_)); 129 | _krncall(vm_protect(task, code, trampoline->size_, false, VM_PROT_READ | VM_PROT_EXECUTE)); 130 | 131 | uint32_t frame[push]; 132 | if (sizeof(frame) != 0) 133 | memset(frame, 0, sizeof(frame)); 134 | memset(&state, 0, sizeof(state)); 135 | 136 | mach_msg_type_number_t read(count); 137 | _krncall(thread_get_state(thread, flavor, reinterpret_cast(&state), &read)); 138 | 139 | if (read != count) { 140 | MSLog(MSLogLevelError, "MSError: thread_get_state(%d) == %d", count, read); 141 | return false; 142 | } 143 | 144 | 145 | // this code is very similar to that found in Libc/pthread's _pthread_setup 146 | 147 | #if defined(__arm__) 148 | state.__r[0] = data; 149 | state.__sp = stack + Stack_; 150 | state.__pc = code + trampoline->entry_; 151 | 152 | 153 | // ARM has two execution states: ARM (32-bit) and Thumb (16/32-bit), using different instruction sets 154 | // for addressing, we tell using the least significant bit: off-aligned addresses are assumed to be Thumb 155 | // however, despite the CPU interpreting this bit during branches, it stores this information in CPSR 156 | 157 | if ((state.__pc & 0x1) != 0) { 158 | state.__pc &= ~0x1; 159 | state.__cpsr |= 0x20; 160 | } 161 | #elif defined(__i386__) 162 | frame[1] = data; 163 | 164 | state.__eip = code + trampoline->entry_; 165 | state.__esp = stack + Stack_ - sizeof(frame); 166 | #elif defined(__x86_64__) 167 | // XXX: I do not remember why this is here 168 | frame[0] = 0xdeadbeef; 169 | 170 | state.__rdi = data; 171 | state.__rip = code + trampoline->entry_; 172 | state.__rsp = stack + Stack_ - sizeof(frame); 173 | #else 174 | #error XXX: implement 175 | #endif 176 | 177 | 178 | if (sizeof(frame) != 0) 179 | _krncall(vm_write(task, stack + Stack_ - sizeof(frame), reinterpret_cast(frame), sizeof(frame))); 180 | 181 | _krncall(thread_set_state(thread, flavor, reinterpret_cast(&state), count)); 182 | _krncall(thread_resume(thread)); 183 | 184 | 185 | // XXX: I feel like there must be a way to get an event when the thread dies, rather than poll 186 | // XXX: all we now know is that the thread finished, but what we really care about is whether it worked 187 | 188 | do loop: switch (kern_return_t status = thread_get_state(thread, flavor, reinterpret_cast(&state), &(read = count))) { 189 | case KERN_SUCCESS: 190 | usleep(10000); 191 | goto loop; 192 | 193 | case KERN_TERMINATED: 194 | case MACH_SEND_INVALID_DEST: 195 | break; 196 | 197 | default: 198 | MSLog(MSLogLevelError, "MSError: thread_get_state() == %d", status); 199 | return false; 200 | } while (false); 201 | 202 | 203 | _krncall(mach_port_deallocate(self, thread)); 204 | 205 | _krncall(vm_deallocate(task, code, trampoline->size_)); 206 | _krncall(vm_deallocate(task, stack, size)); 207 | 208 | _krncall(mach_port_deallocate(self, task)); 209 | 210 | return true; 211 | } 212 | -------------------------------------------------------------------------------- /DarwinLauncher.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "CydiaSubstrate.h" 23 | 24 | #include "Log.hpp" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | #include 38 | 39 | #include "Common.hpp" 40 | #include "Environment.hpp" 41 | 42 | #include 43 | #define environ (*_NSGetEnviron()) 44 | 45 | MSHook(int, posix_spawn, pid_t *pid, const char *path, const posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char * const argv[], char * const envp[]) { 46 | // quit is a goto target that is used below to exit this function without manipulating envp 47 | 48 | if (false) quit: 49 | return _posix_spawn(pid, path, file_actions, attrp, argv, envp); 50 | 51 | 52 | // safe is a goto target that is used below to indicate that Substrate should be removed from envp 53 | 54 | bool safe(false); 55 | if (false) safe: { 56 | safe = true; 57 | goto scan; 58 | } 59 | 60 | 61 | // we use these arguments below, so we need to fix them or fail early 62 | 63 | if (path == NULL) 64 | goto quit; 65 | if (envp == NULL) 66 | envp = environ; 67 | 68 | 69 | // it is possible we are still installed in the kernel, even though substrate was removed 70 | // in this situation, it is safest if we goto safe, not quit, to remove DYLD_INSERT_LIBRARIES 71 | 72 | if (_syscall(access(SubstrateLibrary_, R_OK | X_OK)) == -1) 73 | goto safe; 74 | 75 | 76 | // if a process wants to turn off Substrate for its children, it needs to communicate this to us 77 | // a process can also indicate "I'm good, just do it", bypassing the later (expensive) safety checks 78 | 79 | for (char * const *env(envp); *env != NULL; ++env) 80 | if (false); 81 | else if (strncmp(SubstrateSafeMode_ "=", *env, sizeof(SubstrateSafeMode_)) == 0) { 82 | const char *value(*env + sizeof(SubstrateSafeMode_)); 83 | 84 | if (false); 85 | else if (strcmp(value, "0") == 0 || strcmp(value, "NO") == 0) 86 | goto scan; 87 | else if (strcmp(value, "1") == 0 || strcmp(value, "YES") == 0 || strcmp(value, "") == 0) 88 | goto safe; 89 | else goto quit; 90 | } 91 | 92 | 93 | // DYLD_INSERT_LIBRARIES does not work in processes that are setugid 94 | // testing this condition prevents us from having a runaway test below 95 | 96 | struct stat info; 97 | if (_syscall(stat(path, &info)) == -1) 98 | goto safe; 99 | if ((info.st_mode & S_ISUID) != 0 && getuid() != info.st_uid) 100 | goto safe; 101 | // XXX: technically, if this user is not a member of the group 102 | if ((info.st_mode & S_ISGID) != 0 && getgid() != info.st_gid) 103 | goto safe; 104 | 105 | 106 | // some jailbreaks (example: iOS 3.0 PwnageTool) have broken (restrictive) sandbox patches 107 | // spawning the process with DYLD_INSERT_LIBRARIES causes them to immediately crash 108 | 109 | switch (pid_t child = _syscall(fork())) { 110 | case -1: 111 | goto quit; 112 | 113 | case 0: 114 | // XXX: figure out a way to turn off CrashReporter for this process 115 | _syscall(execle(path, path, NULL, (const char *[]) { SubstrateVariable_ "=" SubstrateLibrary_, "MSExitZero" "=", NULL })); 116 | _exit(EXIT_FAILURE); 117 | 118 | default: 119 | int status; 120 | if (_syscall(waitpid(child, &status, 0)) == -1) 121 | goto safe; 122 | if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) 123 | goto safe; 124 | } 125 | 126 | 127 | scan: 128 | size_t size(0); 129 | for (char * const *env(envp); *env != NULL; ++env) 130 | ++size; 131 | 132 | char **envs(reinterpret_cast(malloc(sizeof(char *) * (size + 2)))); 133 | if (envs == NULL) 134 | goto quit; 135 | 136 | size_t last(0); 137 | 138 | 139 | // fail is a goto target that can be used to deallocate our new environment and quit 140 | 141 | if (false) fail: { 142 | for (size_t i(0); i != last; ++i) 143 | free(envs[i]); 144 | free(envs); 145 | goto quit; 146 | } 147 | 148 | 149 | bool found(false); 150 | 151 | for (char * const *env(envp); *env != NULL; ++env) { 152 | const char *equal(strchr(*env, '=')); 153 | if (equal == NULL) 154 | goto copy; 155 | 156 | #define envcmp(value) ( \ 157 | (equal - *env == sizeof(value) - 1) && \ 158 | strncmp(value, *env, sizeof(value) - 1) == 0 \ 159 | ) 160 | 161 | if (false); 162 | else if (envcmp("_MSLaunchHandle")) 163 | continue; 164 | else if (envcmp("_MSPosixSpawn")) 165 | continue; 166 | else if (envcmp(SubstrateVariable_)) { 167 | // if the variable is empty, let's just pretend we didn't find it (you with me? ;P)... 168 | // the problem is that the insanely hilarious code below doesn't work in this case 169 | 170 | if (equal[1] == '\0') 171 | continue; 172 | found = true; 173 | 174 | 175 | // our initial goal is to get a string :1:2:3: <- with leading and trailing colons 176 | // if we are adding the environment variable, then 1 will be the dylib being added 177 | 178 | const char *extra(safe ? "" : ":" SubstrateLibrary_); 179 | 180 | char *value; 181 | int count(asprintf(&value, "%s=%s:%s:", SubstrateVariable_, extra, equal + 1)); 182 | if (count == -1) 183 | goto fail; 184 | 185 | 186 | // once that is complete, we will find the colon preceding the old content 187 | // this allows us to scan the string, removing any excess copies of :dylib 188 | 189 | // - strlen(equal + 1) <- subtract the bounded %s (orginal value) 190 | // - 1 - 1 <- subtract the leading and trailing colons around %s 191 | 192 | char *end(value + count); 193 | char *colon(end - 1 - strlen(equal + 1) - 1); 194 | 195 | for (char *scan(colon); (scan = strstr(scan, ":" SubstrateLibrary_ ":")) != NULL; ) { 196 | // end - scan <- all remaining characters 197 | // - sizeof(SubstrateLibrary_) <- subtract :dylib 198 | // + 1 <- add the null terminator 199 | 200 | memmove(scan, scan + sizeof(SubstrateLibrary_), end - scan - sizeof(SubstrateLibrary_) + 1); 201 | 202 | // move end of string back by :dylib length 203 | 204 | end -= sizeof(SubstrateLibrary_); 205 | } 206 | 207 | 208 | // if the variable is empty ("=:"), we just remove it entirely 209 | // end - value <- the total length of the string 210 | 211 | // sizeof(SubstrateVariable_) <- includes the = 212 | // + 1 <- we still need to compensate for the : 213 | 214 | if (end - value == sizeof(SubstrateVariable_) + 1) { 215 | free(value); 216 | continue; 217 | } 218 | 219 | 220 | // otherwise, we need to delete the leading and trailing colons 221 | // we reposition colon to the first colon (before our injection) 222 | 223 | colon = value + sizeof(SubstrateVariable_); 224 | memmove(colon, colon + 1, end - colon - 1); 225 | end[-2] = '\0'; 226 | envs[last++] = value; 227 | continue; 228 | } 229 | 230 | copy: 231 | envs[last++] = strdup(*env); 232 | } 233 | 234 | if (!safe && !found) 235 | envs[last++] = strdup(SubstrateVariable_ "=" SubstrateLibrary_); 236 | 237 | envs[last++] = NULL; 238 | 239 | int value(_posix_spawn(pid, path, file_actions, attrp, argv, envs)); 240 | 241 | for (char * const *env(envs); *env != NULL; ++env) 242 | free(*env); 243 | free(envs); 244 | 245 | return value; 246 | } 247 | 248 | template 249 | static void MSReinterpretAssign(Left_ &left, const Right_ &right) { 250 | left = reinterpret_cast(right); 251 | } 252 | 253 | MSInitialize { 254 | // this installation routine keeps a reference to the current library in _MSLaunchHandle 255 | // dlopen() is called now, and dlclose() will be called in the new version during upgrade 256 | 257 | Dl_info info; 258 | if (dladdr(reinterpret_cast(&$posix_spawn), &info) == 0) 259 | return; 260 | void *handle(dlopen(info.dli_fname, RTLD_NOLOAD)); 261 | 262 | 263 | // before we unload the previous version, we hook posix_spawn to call our replacements 264 | // the original posix_spawn (from Apple) is kept in _MSPosixSpawn for use by new versions 265 | 266 | if (const char *cache = getenv("_MSPosixSpawn")) { 267 | MSReinterpretAssign(_posix_spawn, strtoull(cache, NULL, 0)); 268 | MSHookFunction(&posix_spawn, &$posix_spawn); 269 | } else { 270 | MSHookFunction(&posix_spawn, MSHake(posix_spawn)); 271 | 272 | char cache[32]; 273 | sprintf(cache, "%p", _posix_spawn); 274 | setenv("_MSPosixSpawn", cache, false); 275 | } 276 | 277 | 278 | // specifically after having updated posix_spawn, we can unload the previous version 279 | 280 | if (const char *cache = getenv("_MSLaunchHandle")) { 281 | void *obsolete; 282 | MSReinterpretAssign(obsolete, strtoull(cache, NULL, 0)); 283 | dlclose(obsolete); 284 | } 285 | 286 | 287 | // as installation has completed, we now set _MSLaunchHandle to the address of this version 288 | 289 | char cache[32]; 290 | sprintf(cache, "%p", handle); 291 | // XXX: there is a race condition installing new versions: need atomic get/setenv() 292 | setenv("_MSLaunchHandle", cache, true); 293 | } 294 | -------------------------------------------------------------------------------- /DarwinThreadInternal.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_DARWINTHREADINTERNAL_HPP 23 | #define SUBSTRATE_DARWINTHREADINTERNAL_HPP 24 | 25 | 26 | // forces _pthread_setspecific_direct() to not call pthread_setspecific() 27 | // this is required to use thread local storage in trampolines and hooks 28 | // we save the old value here so we can restore it later in this file 29 | 30 | #ifndef __OPTIMIZE__ 31 | #define MSNoOptimize 32 | #define __OPTIMIZE__ 33 | #endif 34 | 35 | 36 | #include 37 | 38 | 39 | // we will now restore the original value of __OPTIMIZE__, for other code 40 | 41 | #ifdef MSNoOptimize 42 | #undef MSNoOptimize 43 | #undef __OPTIMIZE__ 44 | #endif 45 | 46 | #endif//SUBSTRATE_DARWINTHREADINTERNAL_HPP 47 | -------------------------------------------------------------------------------- /Debug.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "CydiaSubstrate.h" 23 | #include "Debug.hpp" 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | _extern bool MSDebug; 30 | bool MSDebug = false; 31 | 32 | static char _MSHexChar(uint8_t value) { 33 | return value < 0x20 || value >= 0x80 ? '.' : value; 34 | } 35 | 36 | #define HexWidth_ 16 37 | #define HexDepth_ 4 38 | 39 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark) { 40 | const uint8_t *data((const uint8_t *) vdata); 41 | 42 | size_t i(0), j; 43 | 44 | char d[256]; 45 | size_t b(0); 46 | d[0] = '\0'; 47 | 48 | while (i != size) { 49 | if (i % HexWidth_ == 0) { 50 | if (mark != NULL) 51 | b += sprintf(d + b, "[%s] ", mark); 52 | b += sprintf(d + b, "0x%.3zx:", i); 53 | } 54 | 55 | b += sprintf(d + b, " "); 56 | 57 | for (size_t q(0); q != stride; ++q) 58 | b += sprintf(d + b, "%.2x", data[i + stride - q - 1]); 59 | 60 | i += stride; 61 | 62 | for (size_t q(1); q != stride; ++q) 63 | b += sprintf(d + b, " "); 64 | 65 | if (i % HexDepth_ == 0) 66 | b += sprintf(d + b, " "); 67 | 68 | if (i % HexWidth_ == 0) { 69 | b += sprintf(d + b, " "); 70 | for (j = i - HexWidth_; j != i; ++j) 71 | b += sprintf(d + b, "%c", _MSHexChar(data[j])); 72 | 73 | lprintf("%s", d); 74 | b = 0; 75 | d[0] = '\0'; 76 | } 77 | } 78 | 79 | if (i % HexWidth_ != 0) { 80 | for (j = i % HexWidth_; j != HexWidth_; ++j) 81 | b += sprintf(d + b, " "); 82 | for (j = 0; j != (HexWidth_ - i % HexWidth_ + HexDepth_ - 1) / HexDepth_; ++j) 83 | b += sprintf(d + b, " "); 84 | b += sprintf(d + b, " "); 85 | for (j = i / HexWidth_ * HexWidth_; j != i; ++j) 86 | b += sprintf(d + b, "%c", _MSHexChar(data[j])); 87 | 88 | lprintf("%s", d); 89 | b = 0; 90 | d[0] = '\0'; 91 | } 92 | } 93 | 94 | void MSLogHex(const void *vdata, size_t size, const char *mark) { 95 | return MSLogHexEx(vdata, size, 1, mark); 96 | } 97 | -------------------------------------------------------------------------------- /Debug.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_DEBUG_HPP 23 | #define SUBSTRATE_DEBUG_HPP 24 | 25 | #include "Log.hpp" 26 | #define lprintf(format, ...) \ 27 | MSLog(MSLogLevelNotice, format, ## __VA_ARGS__) 28 | 29 | extern "C" bool MSDebug; 30 | void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark = 0); 31 | void MSLogHex(const void *vdata, size_t size, const char *mark = 0); 32 | 33 | #endif//SUBSTRATE_DEBUG_HPP 34 | -------------------------------------------------------------------------------- /Environment.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | #include 24 | 25 | #include "Log.hpp" 26 | #include "Environment.hpp" 27 | 28 | void MSClearEnvironment() { 29 | setenv(SubstrateSafeMode_, "1", true); 30 | 31 | char *dil(getenv(SubstrateVariable_)); 32 | if (dil == NULL) { 33 | MSLog(MSLogLevelError, "MS:Error: %s is unset?", SubstrateVariable_); 34 | return; 35 | } 36 | 37 | size_t length(strlen(dil)); 38 | char buffer[length + 3]; 39 | 40 | buffer[0] = ':'; 41 | memcpy(buffer + 1, dil, length); 42 | buffer[length + 1] = ':'; 43 | buffer[length + 2] = '\0'; 44 | 45 | char *index(strstr(buffer, ":" SubstrateLibrary_ ":")); 46 | if (index == NULL) { 47 | MSLog(MSLogLevelError, "MS:Error: dylib not in %s", SubstrateVariable_); 48 | return; 49 | } 50 | 51 | size_t skip(sizeof(SubstrateLibrary_)); 52 | if (length == skip - 1) { 53 | unsetenv(SubstrateVariable_); 54 | return; 55 | } 56 | 57 | buffer[length + 1] = '\0'; 58 | memmove(index + 1, index + 1 + skip, length - (index - buffer) - skip + 2); 59 | setenv(SubstrateVariable_, buffer + 1, true); 60 | } 61 | -------------------------------------------------------------------------------- /Environment.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_ENVIRONMENT_HPP 23 | #define SUBSTRATE_ENVIRONMENT_HPP 24 | 25 | #define SubstrateVariable_ "DYLD_INSERT_LIBRARIES" 26 | #define SubstrateLibrary_ "/Library/MobileSubstrate/MobileSubstrate.dylib" 27 | 28 | #define SubstrateSafeMode_ "_MSSafeMode" 29 | 30 | void MSClearEnvironment(); 31 | 32 | #endif//SUBSTRATE_ENVIRONMENT_HPP 33 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | CFBundlePackageType = "FMWK"; 2 | CFBundleSignature = "????"; 3 | CFBundleExecutable = "CydiaSubstrate"; 4 | CFBundleIdentifier = "com.saurik.CydiaSubstate"; 5 | CFBundleGetInfoString = "Cydia Substrate, SaurikIT LLC"; 6 | CFBundleShortVersionString = "0.9"; 7 | CFBundleInfoDictionaryVersion = "6.0"; 8 | CFBundleName = "Cydia Substrate"; 9 | CFBundleDevelopmentRegion = "English"; 10 | -------------------------------------------------------------------------------- /LaunchDaemons.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_LAUNCHDAEMONS_HPP 23 | #define SUBSTRATE_LAUNCHDAEMONS_HPP 24 | 25 | #define SubstrateLaunchDaemons_ "/System/Library/LaunchDaemons" 26 | #define SubstrateLaunchConfig_ "/etc/launchd.conf" 27 | 28 | #define SubstrateLauncher_ "/Library/Frameworks/CydiaSubstrate.framework/Libraries/SubstrateLauncher.dylib" 29 | #define SubstrateBootstrapExecute_ "bsexec .. /usr/bin/cynject 1 " SubstrateLauncher_ 30 | 31 | bool MSClearLaunchDaemons(); 32 | 33 | #endif//SUBSTRATE_LAUNCHDAEMONS_HPP 34 | -------------------------------------------------------------------------------- /LaunchDaemons.mm: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | 24 | #include "Environment.hpp" 25 | #include "LaunchDaemons.hpp" 26 | 27 | // XXX: NO means "failed", false means "unneeded" 28 | 29 | static bool MSClearLaunchDaemon(NSString *file) { 30 | NSMutableDictionary *root([NSMutableDictionary dictionaryWithContentsOfFile:file]); 31 | if (root == nil) 32 | return NO; 33 | 34 | NSMutableDictionary *environment([root objectForKey:@"EnvironmentVariables"]); 35 | if (environment == nil) 36 | return false; 37 | 38 | NSString *variable([environment objectForKey:@ SubstrateVariable_]); 39 | if (variable == nil) 40 | return false; 41 | 42 | NSMutableArray *dylibs([[variable componentsSeparatedByString:@":"] mutableCopy]); 43 | if (dylibs == nil) 44 | return NO; 45 | 46 | NSUInteger index([dylibs indexOfObject:@ SubstrateLibrary_]); 47 | if (index == NSNotFound) 48 | return false; 49 | 50 | [dylibs removeObject:@ SubstrateLibrary_]; 51 | 52 | if ([dylibs count] != 0) 53 | [environment setObject:[dylibs componentsJoinedByString:@":"] forKey:@ SubstrateVariable_]; 54 | else if ([environment count] == 1) 55 | [root removeObjectForKey:@"EnvironmentVariables"]; 56 | else 57 | [environment removeObjectForKey:@ SubstrateVariable_]; 58 | 59 | NSString *error; 60 | NSData *data([NSPropertyListSerialization dataFromPropertyList:root format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]); 61 | if (data == nil) 62 | return NO; 63 | 64 | if (![data writeToFile:file atomically:YES]) 65 | return NO; 66 | 67 | return true; 68 | } 69 | 70 | bool MSClearLaunchDaemons() { 71 | NSError *error; 72 | 73 | NSArray *contents([[NSFileManager defaultManager] contentsOfDirectoryAtPath:@ SubstrateLaunchDaemons_ error:&error]); 74 | if (contents == nil) 75 | return NO; 76 | 77 | bool cleared(false); 78 | 79 | // XXX: this should filter to only files 80 | for (NSString *file in contents) 81 | cleared |= MSClearLaunchDaemon([@ SubstrateLaunchDaemons_ stringByAppendingPathComponent:file]); 82 | 83 | return cleared; 84 | } 85 | -------------------------------------------------------------------------------- /Log.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_LOG_HPP 23 | #define SUBSTRATE_LOG_HPP 24 | 25 | #if 0 26 | 27 | #include 28 | 29 | #define MSLog(level, format, ...) CFLog(level, CFSTR(format), ## __VA_ARGS__) 30 | 31 | #define MSLogLevelNotice kCFLogLevelNotice 32 | #define MSLogLevelWarning kCFLogLevelWarning 33 | #define MSLogLevelError kCFLogLevelError 34 | 35 | #else 36 | 37 | #include 38 | 39 | #if __COREFOUNDATION__ 40 | 41 | #define MSLog(level, format, ...) do { \ 42 | CFStringRef _formatted(CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(format), ## __VA_ARGS__)); \ 43 | size_t _size(CFStringGetMaximumSizeForEncoding(CFStringGetLength(_formatted), kCFStringEncodingUTF8)); \ 44 | char _utf8[_size + sizeof('\0')]; \ 45 | CFStringGetCString(_formatted, _utf8, sizeof(_utf8), kCFStringEncodingUTF8); \ 46 | CFRelease(_formatted); \ 47 | syslog(level, "%s", _utf8); \ 48 | } while (false) 49 | 50 | #else 51 | 52 | #define MSLog(level, format, ...) do { \ 53 | syslog(level, format, ## __VA_ARGS__); \ 54 | } while (false) 55 | 56 | #endif 57 | 58 | #define MSLogLevelNotice LOG_NOTICE 59 | #define MSLogLevelWarning LOG_WARNING 60 | #define MSLogLevelError LOG_ERR 61 | 62 | #endif 63 | 64 | #endif//SUBSTRATE_LOG_HPP 65 | -------------------------------------------------------------------------------- /MachInterface.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | user=$1 7 | header=$2 8 | defs=$3 9 | 10 | mig -arch i386 -server /dev/null -user /dev/stdout -header "${header}" "${defs}" | sed -e $' 11 | /^mig_external kern_return_t / { 12 | n; 13 | n; 14 | x; 15 | s/.*/\tmach_msg_id_t msgh_id,/; 16 | p; 17 | s/.*/\tmach_port_t reply_port,/; 18 | p; 19 | x; 20 | }; 21 | 22 | s/^\\(mig_internal kern_return_t __MIG_check__Reply__[^(]*(\\)/\\1mach_msg_id_t msgh_id, /; 23 | s/\\(check_result = __MIG_check__Reply__[^(]*(\\)/\\1msgh_id, /; 24 | 25 | s/mig_get_reply_port()/reply_port/g; 26 | s/31337\\([0-9][0-9]\\)/msgh_id/g; 27 | s/31338\\([0-9][0-9]\\)/(msgh_id + 100)/g; 28 | ' >"${user}" || rm -f "${user}" 29 | -------------------------------------------------------------------------------- /MachMemory.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #define SubstrateInternal 23 | #include "CydiaSubstrate.h" 24 | 25 | #include "Log.hpp" 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | #ifdef __arm__ 36 | 37 | #include "MachMessage.hpp" 38 | 39 | static mach_msg_return_t MS_mach_msg(mach_msg_header_t *msg, mach_msg_option_t option, mach_msg_size_t send_size, mach_msg_size_t rcv_size, mach_port_name_t rcv_name, mach_msg_timeout_t timeout, mach_port_name_t notify) { 40 | for (;;) switch (mach_msg_return_t error = MS_mach_msg_trap(msg, option, send_size, rcv_size, rcv_name, timeout, notify)) { 41 | case MACH_SEND_INTERRUPT: 42 | break; 43 | 44 | case MACH_RCV_INTERRUPT: 45 | option &= ~MACH_SEND_MSG; 46 | break; 47 | 48 | default: 49 | return error; 50 | } 51 | } 52 | 53 | #define mach_msg MS_mach_msg 54 | #include "MachProtect.h" 55 | #include "MachProtect.c" 56 | #undef mach_msg 57 | 58 | static kern_return_t MS_vm_protect(mach_port_t reply_port, vm_map_t target_task, vm_address_t address, vm_size_t size, boolean_t set_maximum, vm_prot_t new_protection) { 59 | kern_return_t error; 60 | 61 | 62 | #if 0 63 | // on iOS >= 5.0, Apple now provides a number of system call traps for common mach interfaces, like vm_map 64 | // XXX: this code, when tested on iOS 2.2 (not tested on >> 2.2 && << 5.0) returns 0x807 with signal "?" 65 | 66 | error = MS_vm_protect_trap(target_task, address, size, set_maximum, new_protection); 67 | if (error != MACH_SEND_INVALID_DEST) 68 | return error; 69 | #endif 70 | 71 | 72 | // 3803 is vm_map's vm_protect. it is guaranteed to take 32-bit arguments on all platforms, which is convenient 73 | // unfortunately, this kernel-side interface seems to be missing on at least iOS 4.0, so we cannot rely on it 74 | 75 | error = MS_vm_protect_mach(3803, reply_port, target_task, address, size, set_maximum, new_protection); 76 | if (error != MIG_BAD_ID) 77 | return error; 78 | 79 | 80 | // 4802 is mach_vm's mach_vm_protect. it is supposed to always take "the largest size type for the platform" 81 | // unfortunately, while on iOS << 5.0 ARM was considered 32-bit, with iOS 5.0 Apple decided ARM could be 64-bit 82 | // therefore, we cannot know what size arguments to pass to this function, and Apple has nigh unto deprecated it 83 | // thankfully, current devices that have a 64-bit mach_vm_protect also support the 32-bit vm_protect interface 84 | 85 | error = MS_vm_protect_mach(4802, reply_port, target_task, address, size, set_maximum, new_protection); 86 | if (error != MIG_BAD_ID) 87 | return error; 88 | 89 | 90 | return error; 91 | } 92 | 93 | #else 94 | 95 | #define MS_vm_protect(a0, a1, a2, a3, a4, a5) vm_protect(a1, a2, a3, a4, a5) 96 | 97 | #endif 98 | 99 | struct __SubstrateMemory { 100 | mach_port_t reply_; 101 | mach_port_t self_; 102 | uintptr_t base_; 103 | size_t width_; 104 | 105 | __SubstrateMemory(mach_port_t reply, mach_port_t self, uintptr_t base, size_t width) : 106 | reply_(reply), 107 | self_(self), 108 | base_(base), 109 | width_(width) 110 | { 111 | } 112 | }; 113 | 114 | extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size) { 115 | if (allocator != NULL) { 116 | MSLog(MSLogLevelError, "MS:Error:allocator != NULL"); 117 | return NULL; 118 | } 119 | 120 | if (size == 0) 121 | return NULL; 122 | 123 | int page(getpagesize()); 124 | 125 | mach_port_t reply(mig_get_reply_port()); 126 | mach_port_t self(mach_task_self()); 127 | 128 | uintptr_t base(reinterpret_cast(data) / page * page); 129 | size_t width(((reinterpret_cast(data) + size - 1) / page + 1) * page - base); 130 | 131 | 132 | // the max_protection of this memory, on ARM, is normally r-x (as it is currently executable and marked clean) 133 | // however, we need to write to it; mprotect() can't do it, so we use vm_protect(VM_PROT_COPY), to get a new page 134 | 135 | // XXX: I should try for RWX here, but it seriously never works and you get this irritating log: 136 | // kernel[0] : EMBEDDED: vm_map_protect can't have both write and exec at the same time 137 | 138 | if (kern_return_t error = MS_vm_protect(reply, self, base, width, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY)) { 139 | MSLog(MSLogLevelError, "MS:Error:vm_protect() = %d", error); 140 | return NULL; 141 | } 142 | 143 | 144 | return new __SubstrateMemory(reply, self, base, width); 145 | } 146 | 147 | extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) { 148 | if (kern_return_t error = MS_vm_protect(memory->reply_, memory->self_, memory->base_, memory->width_, FALSE, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY)) 149 | MSLog(MSLogLevelError, "MS:Error:vm_protect() = %d", error); 150 | 151 | 152 | // Apple removed __clear_cache in iOS 4.1, so we can't rely on it here 153 | // however, it also was always a nop, and as no never really worked... 154 | 155 | sys_dcache_flush(reinterpret_cast(memory->base_), memory->width_); 156 | sys_icache_invalidate(reinterpret_cast(memory->base_), memory->width_); 157 | 158 | 159 | delete memory; 160 | } 161 | -------------------------------------------------------------------------------- /MachMessage.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | 24 | #ifdef __arm__ 25 | 26 | __attribute__((__naked__)) 27 | __attribute__((__noinline__)) 28 | mach_msg_return_t MS_mach_msg_trap(mach_msg_header_t *, mach_msg_option_t, mach_msg_size_t, mach_msg_size_t, mach_port_name_t, mach_msg_timeout_t, mach_port_name_t) { 29 | register mach_msg_return_t error asm("r0"); 30 | 31 | asm volatile ( 32 | "mov r12, sp\n" 33 | "push.w {r4, r5, r6, r8}\n" 34 | "ldm.w r12, {r4, r5, r6}\n" 35 | "mvn.w r12, #30\n" 36 | "svc 0x80\n" 37 | "pop.w {r4, r5, r6, r8}\n" 38 | : "=a" (error) 39 | : 40 | : "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r12" 41 | ); 42 | 43 | return error; 44 | } 45 | 46 | __attribute__((__naked__)) 47 | __attribute__((__noinline__)) 48 | mach_msg_return_t MS_vm_protect_trap(vm_map_t target_task, vm_address_t address, vm_size_t size, boolean_t set_maximum, vm_prot_t new_protection) { 49 | register mach_msg_return_t error asm("r0"); 50 | 51 | asm volatile ( 52 | "mov r12, sp\n" 53 | "push {r4, r5}\n" 54 | "ldr.w r4, [r12]\n" 55 | "mvn.w r12, #14\n" 56 | "svc 0x80\n" 57 | "pop {r4, r5}\n" 58 | : "=a" (error) 59 | : 60 | : "r1", "r2", "r3", "r4", "r5", "r12" 61 | ); 62 | 63 | return error; 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /MachMessage.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_MACHMESSAGE_HPP 23 | #define SUBSTRATE_MACHMESSAGE_HPP 24 | 25 | #ifdef __arm__ 26 | extern mach_msg_return_t MS_mach_msg_trap(mach_msg_header_t *, mach_msg_option_t, mach_msg_size_t, mach_msg_size_t, mach_port_name_t, mach_msg_timeout_t, mach_port_name_t); 27 | extern mach_msg_return_t MS_vm_protect_trap(vm_map_t, vm_address_t, vm_size_t, boolean_t, vm_prot_t); 28 | #else 29 | extern "C" mach_msg_return_t mach_msg_trap(mach_msg_header_t *, mach_msg_option_t, mach_msg_size_t, mach_msg_size_t, mach_port_name_t, mach_msg_timeout_t, mach_port_name_t); 30 | #define MS_mach_msg_trap mach_msg_trap 31 | 32 | static _finline MS_vm_protect_trap(vm_map_t, vm_address_t, vm_size_t, boolean_t, vm_prot_t) { 33 | return MACH_SEND_INVALID_DEST; 34 | } 35 | #endif 36 | 37 | #endif//SUBSTRATE_MACHMESSAGE_HPP 38 | -------------------------------------------------------------------------------- /MachProtect.defs: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | subsystem MS_vm_map 3133700; 5 | 6 | routine MS_vm_protect_mach( 7 | target_task : vm_task_entry_t; 8 | address : vm_address_t; 9 | size : vm_size_t; 10 | set_maximum : boolean_t; 11 | new_protection : vm_prot_t); 12 | -------------------------------------------------------------------------------- /MobileSafety.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-plus/substrate/904d20f414c79a2716680f4d29d833e6ce0dcea2/MobileSafety.jpg -------------------------------------------------------------------------------- /MobileSafety.mm: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | %apt Package: com.saurik.substrate.safemode 23 | %apt Author: Jay Freeman (saurik) 24 | 25 | %apt Name: Substrate Safe Mode 26 | %apt Description: safe mode safety extension (safe) 27 | 28 | %apt Depends: mobilesubstrate (>= 0.9.3367+38) 29 | 30 | %fflag 1 31 | %fflag 2 32 | 33 | %bundle com.apple.springboard 34 | 35 | %flag -framework Foundation 36 | %flag -framework UIKit 37 | 38 | #import 39 | #import 40 | #import 41 | #import 42 | 43 | #include "CydiaSubstrate.h" 44 | 45 | MSClassHook(UIStatusBar) 46 | 47 | MSClassHook(UIImage) 48 | MSMetaClassHook(UIImage) 49 | 50 | MSClassHook(AAAccountManager) 51 | MSMetaClassHook(AAAccountManager) 52 | 53 | MSClassHook(BBSectionInfo) 54 | 55 | MSClassHook(SBAlertItemsController) 56 | MSClassHook(SBButtonBar) 57 | MSClassHook(SBIconController) 58 | MSClassHook(SBStatusBar) 59 | MSClassHook(SBStatusBarDataManager) 60 | MSClassHook(SBStatusBarTimeView) 61 | MSClassHook(SBUIController) 62 | 63 | Class $SafeModeAlertItem; 64 | 65 | @interface SBAlertItem : NSObject { 66 | } 67 | - (UIAlertView *) alertSheet; 68 | - (void) dismiss; 69 | @end 70 | 71 | @interface SBAlertItemsController : NSObject { 72 | } 73 | + (SBAlertItemsController *) sharedInstance; 74 | - (void) activateAlertItem:(SBAlertItem *)item; 75 | @end 76 | 77 | @interface SBStatusBarTimeView : UIView { 78 | } 79 | - (id) textFont; 80 | @end 81 | 82 | @interface UIApplication (CydiaSubstrate) 83 | - (void) applicationOpenURL:(id)url; 84 | @end 85 | 86 | @interface UIAlertView (CydiaSubstrate) 87 | - (void) setForceHorizontalButtonsLayout:(BOOL)force; 88 | - (void) setBodyText:(NSString *)body; 89 | - (void) setNumberOfRows:(NSInteger)rows; 90 | @end 91 | 92 | void SafeModeAlertItem$alertSheet$buttonClicked$(id self, SEL sel, id sheet, int button) { 93 | switch (button) { 94 | case 1: 95 | break; 96 | 97 | case 2: 98 | // XXX: there are better ways of restarting SpringBoard that would actually save state 99 | exit(0); 100 | break; 101 | 102 | case 3: 103 | [[UIApplication sharedApplication] applicationOpenURL:[NSURL URLWithString:@"http://cydia.saurik.com/safemode/"]]; 104 | break; 105 | } 106 | 107 | [self dismiss]; 108 | } 109 | 110 | void SafeModeAlertItem$configure$requirePasscodeForActions$(id self, SEL sel, BOOL configure, BOOL require) { 111 | UIAlertView *sheet([self alertSheet]); 112 | 113 | [sheet setDelegate:self]; 114 | [sheet setBodyText:@"We apologize for the inconvenience, but SpringBoard has just crashed.\n\nMobileSubstrate /did not/ cause this problem: it has protected you from it.\n\nYour device is now running in Safe Mode. All extensions that support this safety system are disabled.\n\nReboot (or restart SpringBoard) to return to the normal mode. To return to this dialog touch the status bar.\n\nTap \"Help\" below for more tips."]; 115 | [sheet addButtonWithTitle:@"OK"]; 116 | [sheet addButtonWithTitle:@"Restart"]; 117 | [sheet addButtonWithTitle:@"Help"]; 118 | [sheet setNumberOfRows:1]; 119 | 120 | if ([sheet respondsToSelector:@selector(setForceHorizontalButtonsLayout:)]) 121 | [sheet setForceHorizontalButtonsLayout:YES]; 122 | } 123 | 124 | void SafeModeAlertItem$performUnlockAction(id self, SEL sel) { 125 | [[$SBAlertItemsController sharedInstance] activateAlertItem:self]; 126 | } 127 | 128 | static void MSAlert() { 129 | if ($SafeModeAlertItem == nil) 130 | $SafeModeAlertItem = objc_lookUpClass("SafeModeAlertItem"); 131 | if ($SafeModeAlertItem == nil) { 132 | $SafeModeAlertItem = objc_allocateClassPair(objc_getClass("SBAlertItem"), "SafeModeAlertItem", 0); 133 | if ($SafeModeAlertItem == nil) 134 | return; 135 | 136 | class_addMethod($SafeModeAlertItem, @selector(alertSheet:buttonClicked:), (IMP) &SafeModeAlertItem$alertSheet$buttonClicked$, "v@:@i"); 137 | class_addMethod($SafeModeAlertItem, @selector(configure:requirePasscodeForActions:), (IMP) &SafeModeAlertItem$configure$requirePasscodeForActions$, "v@:cc"); 138 | class_addMethod($SafeModeAlertItem, @selector(performUnlockAction), (IMP) SafeModeAlertItem$performUnlockAction, "v@:"); 139 | objc_registerClassPair($SafeModeAlertItem); 140 | } 141 | 142 | if ($SBAlertItemsController != nil) 143 | [[$SBAlertItemsController sharedInstance] activateAlertItem:[[[$SafeModeAlertItem alloc] init] autorelease]]; 144 | } 145 | 146 | 147 | // XXX: on iOS 5.0, we really would prefer avoiding 148 | 149 | MSInstanceMessageHook2(void, SBStatusBar, touchesEnded,withEvent, id, touches, id, event) { 150 | MSAlert(); 151 | MSOldCall(touches, event); 152 | } 153 | 154 | MSInstanceMessageHook1(void, SBStatusBar, mouseDown, void *, event) { 155 | MSAlert(); 156 | MSOldCall(event); 157 | } 158 | 159 | MSInstanceMessageHook2(void, UIStatusBar, touchesBegan,withEvent, void *, touches, void *, event) { 160 | MSAlert(); 161 | MSOldCall(touches, event); 162 | } 163 | 164 | 165 | // this fairly complex code came from Grant, to solve the "it Safe Mode"-in-bar bug 166 | 167 | MSInstanceMessageHook0(void, SBStatusBarDataManager, _updateTimeString) { 168 | char *_data(&MSHookIvar(self, "_data")); 169 | if (_data == NULL) 170 | return; 171 | 172 | Ivar _itemIsEnabled(object_getInstanceVariable(self, "_itemIsEnabled", NULL)); 173 | if (_itemIsEnabled == NULL) 174 | return; 175 | 176 | Ivar _itemIsCloaked(object_getInstanceVariable(self, "_itemIsCloaked", NULL)); 177 | if (_itemIsCloaked == NULL) 178 | return; 179 | 180 | size_t enabledOffset(ivar_getOffset(_itemIsEnabled)); 181 | size_t cloakedOffset(ivar_getOffset(_itemIsCloaked)); 182 | if (enabledOffset >= cloakedOffset) 183 | return; 184 | 185 | size_t offset(cloakedOffset - enabledOffset); 186 | char *timeString(_data + offset); 187 | strcpy(timeString, "Exit Safe Mode"); 188 | } 189 | 190 | 191 | static bool alerted_; 192 | 193 | static void AlertIfNeeded() { 194 | if (alerted_) 195 | return; 196 | alerted_ = true; 197 | MSAlert(); 198 | } 199 | 200 | 201 | // on iOS 4.3 and above we can use this advertisement, which seems to check every time the user unlocks 202 | // XXX: verify that this still works on iOS 5.0 203 | 204 | MSClassMessageHook0(void, AAAccountManager, showMobileMeOfferIfNecessary) { 205 | AlertIfNeeded(); 206 | } 207 | 208 | 209 | // -[SBIconController showInfoAlertIfNeeded] explains how to drag icons around the iPhone home screen 210 | // it used to be shown to users when they unlocked their screen for the first time, and happened every unlock 211 | // however, as of iOS 4.3, it got relegated to only appearing once the user installed an app or web clip 212 | 213 | MSInstanceMessageHook0(void, SBIconController, showInfoAlertIfNeeded) { 214 | AlertIfNeeded(); 215 | } 216 | 217 | 218 | // the icon state, including crazy configurations like Five Icon Dock, is stored in SpringBoard's defaults 219 | // unfortunately, SpringBoard on iOS 2.0 and 2.1 (maybe 2.2 as well) buffer overrun with more than 4 icons 220 | // there is a third party package called IconSupport that remedies this, but not everyone is using it yet 221 | 222 | MSInstanceMessageHook0(int, SBButtonBar, maxIconColumns) { 223 | static int max; 224 | if (max == 0) { 225 | max = MSOldCall(); 226 | if (NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]) 227 | if (NSDictionary *iconState = [defaults objectForKey:@"iconState"]) 228 | if (NSDictionary *buttonBar = [iconState objectForKey:@"buttonBar"]) 229 | if (NSArray *iconMatrix = [buttonBar objectForKey:@"iconMatrix"]) 230 | if ([iconMatrix count] != 0) 231 | if (NSArray *row = [iconMatrix objectAtIndex:0]) { 232 | int count([row count]); 233 | if (max < count) 234 | max = count; 235 | } 236 | } return max; 237 | } 238 | 239 | 240 | MSInstanceMessageHook0(id, SBUIController, init) { 241 | if ((self = MSOldCall()) != nil) { 242 | UIView *&_contentLayer(MSHookIvar(self, "_contentLayer")); 243 | UIView *&_contentView(MSHookIvar(self, "_contentView")); 244 | 245 | UIView *layer; 246 | if (&_contentLayer != NULL) 247 | layer = _contentLayer; 248 | else if (&_contentView != NULL) 249 | layer = _contentView; 250 | else 251 | layer = nil; 252 | 253 | if (layer != nil) 254 | [layer setBackgroundColor:[UIColor darkGrayColor]]; 255 | } return self; 256 | } 257 | 258 | #define Paper_ "/Library/MobileSubstrate/MobileSafety.png" 259 | 260 | MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) { 261 | return [UIImage imageWithContentsOfFile:@Paper_]; 262 | } 263 | 264 | MSInstanceMessageHook0(void, SBStatusBarTimeView, tile) { 265 | NSString *&_time(MSHookIvar(self, "_time")); 266 | CGRect &_textRect(MSHookIvar(self, "_textRect")); 267 | if (_time != nil) 268 | [_time release]; 269 | _time = [@"Exit Safe Mode" retain]; 270 | id font([self textFont]); 271 | CGSize size([_time sizeWithFont:font]); 272 | CGRect frame([self frame]); 273 | _textRect.size = size; 274 | _textRect.origin.x = (frame.size.width - size.width) / 2; 275 | _textRect.origin.y = (frame.size.height - size.height) / 2; 276 | } 277 | 278 | 279 | // notification widgets ("wee apps" or "bulletin board sections") are capable of crashing SpringBoard 280 | // unfortunately, which ones are in use are stored in SpringBoard's defaults, so we need to turn them off 281 | 282 | MSInstanceMessageHook0(BOOL, BBSectionInfo, showsInNotificationCenter) { 283 | return NO; 284 | } 285 | -------------------------------------------------------------------------------- /MobileSafety.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-plus/substrate/904d20f414c79a2716680f4d29d833e6ce0dcea2/MobileSafety.png -------------------------------------------------------------------------------- /ObjectiveC.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "CydiaSubstrate.h" 23 | 24 | // XXX: this is required by some code below 25 | #ifdef __arm__ 26 | #include "ARM.hpp" 27 | #elif defined(__i386__) || defined(__x86_64__) 28 | #include "x86.hpp" 29 | #endif 30 | 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include "Debug.hpp" 41 | #include "Log.hpp" 42 | 43 | extern "C" void *NSPushAutoreleasePool(unsigned); 44 | extern "C" void NSPopAutoreleasePool(void *); 45 | 46 | static Method MSFindMethod(Class _class, SEL sel) { 47 | for (; _class != nil; _class = class_getSuperclass(_class)) { 48 | unsigned int size; 49 | Method *methods(class_copyMethodList(_class, &size)); 50 | if (methods == NULL) 51 | continue; 52 | 53 | for (unsigned int j(0); j != size; ++j) { 54 | Method method(methods[j]); 55 | if (!sel_isEqual(method_getName(methods[j]), sel)) 56 | continue; 57 | 58 | free(methods); 59 | return method; 60 | } 61 | 62 | free(methods); 63 | } 64 | 65 | return nil; 66 | } 67 | 68 | static void MSHookMessageInternal(Class _class, SEL sel, IMP imp, IMP *result, const char *prefix) { 69 | if (MSDebug) 70 | MSLog(MSLogLevelNotice, "MSHookMessageInternal(%s, %s, %p, %p, \"%s\")", 71 | _class == nil ? "nil" : class_getName(_class), 72 | sel == NULL ? "NULL" : sel_getName(sel), 73 | imp, result, prefix 74 | ); 75 | if (_class == nil) { 76 | MSLog(MSLogLevelWarning, "MS:Warning: nil class argument"); 77 | return; 78 | } else if (sel == nil) { 79 | MSLog(MSLogLevelWarning, "MS:Warning: nil sel argument"); 80 | return; 81 | } else if (imp == nil) { 82 | MSLog(MSLogLevelWarning, "MS:Warning: nil imp argument"); 83 | return; 84 | } 85 | 86 | Method method(MSFindMethod(_class, sel)); 87 | if (method == nil) { 88 | MSLog(MSLogLevelWarning, "MS:Warning: message not found [%s %s]", class_getName(_class), sel_getName(sel)); 89 | return; 90 | } 91 | 92 | const char *type(method_getTypeEncoding(method)); 93 | 94 | bool direct(false); 95 | 96 | unsigned count; 97 | Method *methods(class_copyMethodList(_class, &count)); 98 | for (unsigned i(0); i != count; ++i) 99 | if (methods[i] == method) { 100 | direct = true; 101 | break; 102 | } 103 | free(methods); 104 | 105 | IMP old(NULL); 106 | 107 | if (!direct) { 108 | #if defined(__arm__) 109 | size_t length(11 * sizeof(uint32_t)); 110 | #elif defined(__i386__) 111 | size_t length(20); 112 | #elif defined(__x86_64__) 113 | size_t length(50); 114 | #endif 115 | 116 | uint32_t *buffer(reinterpret_cast(mmap( 117 | NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 118 | ))); 119 | 120 | if (buffer == MAP_FAILED) 121 | MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); 122 | else if (false) fail: 123 | munmap(buffer, length); 124 | else { 125 | Class super(class_getSuperclass(_class)); 126 | 127 | #if defined(__arm__) 128 | buffer[ 0] = A$stmdb_sp$_$rs$((1 << A$r0) | (1 << A$r1) | (1 << A$r2) | (1 << A$r3) | (1 << A$lr)); 129 | buffer[ 1] = A$ldr_rd_$rn_im$(A$r0, A$pc, ( 8 - 1 - 2) * 4); 130 | buffer[ 2] = A$ldr_rd_$rn_im$(A$r1, A$pc, ( 9 - 2 - 2) * 4); 131 | buffer[ 3] = A$ldr_rd_$rn_im$(A$lr, A$pc, (10 - 3 - 2) * 4); 132 | buffer[ 4] = A$blx_rm(A$lr); 133 | buffer[ 5] = A$str_rd_$rn_im$(A$r0, A$sp, -4); 134 | buffer[ 6] = A$ldmia_sp$_$rs$((1 << A$r0) | (1 << A$r1) | (1 << A$r2) | (1 << A$r3) | (1 << A$lr)); 135 | buffer[ 7] = A$ldr_rd_$rn_im$(A$pc, A$sp, -4 - (5 * 4)); 136 | buffer[ 8] = reinterpret_cast(super); 137 | buffer[ 9] = reinterpret_cast(sel); 138 | buffer[10] = reinterpret_cast(&class_getMethodImplementation); 139 | #elif defined(__i386__) 140 | uint8_t *current(reinterpret_cast(buffer)); 141 | 142 | MSPushPointer(current, sel); 143 | MSPushPointer(current, super); 144 | MSWriteCall(current, &class_getMethodImplementation); 145 | MSWriteAdd(current, I$rsp, 8); 146 | MSWriteJump(current, I$rax); 147 | #elif defined(__x86_64__) 148 | uint8_t *current(reinterpret_cast(buffer)); 149 | 150 | MSWritePush(current, I$rdi); 151 | MSWritePush(current, I$rsi); 152 | MSWritePush(current, I$rdx); 153 | 154 | MSWritePush(current, I$rcx); 155 | MSWritePush(current, I$r8); 156 | MSWritePush(current, I$r9); 157 | 158 | MSWriteSet64(current, I$rdi, super); 159 | MSWriteSet64(current, I$rsi, sel); 160 | 161 | MSWriteSet64(current, I$rax, &class_getMethodImplementation); 162 | MSWriteCall(current, I$rax); 163 | 164 | MSWritePop(current, I$r9); 165 | MSWritePop(current, I$r8); 166 | MSWritePop(current, I$rcx); 167 | 168 | MSWritePop(current, I$rdx); 169 | MSWritePop(current, I$rsi); 170 | MSWritePop(current, I$rdi); 171 | 172 | MSWriteJump(current, I$rax); 173 | #endif 174 | 175 | if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { 176 | MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); 177 | goto fail; 178 | } 179 | 180 | old = reinterpret_cast(buffer); 181 | 182 | if (MSDebug) { 183 | char name[16]; 184 | sprintf(name, "%p", old); 185 | MSLogHex(buffer, length, name); 186 | MSLog(MSLogLevelNotice, "jmp %p(%p, %p)", &class_getMethodImplementation, super, sel); 187 | } 188 | } 189 | } 190 | 191 | if (old == NULL) 192 | old = method_getImplementation(method); 193 | 194 | if (result != NULL) 195 | *result = old; 196 | 197 | if (prefix != NULL) { 198 | const char *name(sel_getName(sel)); 199 | size_t namelen(strlen(name)); 200 | size_t fixlen(strlen(prefix)); 201 | 202 | char *newname(reinterpret_cast(alloca(fixlen + namelen + 1))); 203 | memcpy(newname, prefix, fixlen); 204 | memcpy(newname + fixlen, name, namelen + 1); 205 | 206 | if (!class_addMethod(_class, sel_registerName(newname), old, type)) 207 | MSLog(MSLogLevelError, "MS:Error: failed to rename [%s %s]", class_getName(_class), name); 208 | } 209 | 210 | if (direct) 211 | method_setImplementation(method, imp); 212 | else 213 | class_addMethod(_class, sel, imp, type); 214 | } 215 | 216 | _extern void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result) { 217 | MSHookMessageInternal(_class, sel, imp, result, NULL); 218 | } 219 | 220 | #ifdef __arm__ 221 | _extern IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix) { 222 | IMP result(NULL); 223 | MSHookMessageInternal(_class, sel, imp, &result, prefix); 224 | return result; 225 | } 226 | #endif 227 | 228 | #ifdef __arm__ 229 | _extern void _Z13MSHookMessageP10objc_classP13objc_selectorPFP11objc_objectS4_S2_zEPKc(Class _class, SEL sel, IMP imp, const char *prefix) { 230 | MSHookMessageInternal(_class, sel, imp, NULL, prefix); 231 | } 232 | #endif 233 | -------------------------------------------------------------------------------- /PosixMemory.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #define SubstrateInternal 23 | #include "CydiaSubstrate.h" 24 | 25 | #include "Log.hpp" 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | extern "C" void __clear_cache (void *beg, void *end); 34 | 35 | struct __SubstrateMemory { 36 | void *address_; 37 | size_t width_; 38 | 39 | __SubstrateMemory(void *address, size_t width) : 40 | address_(address), 41 | width_(width) 42 | { 43 | } 44 | }; 45 | 46 | extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size) { 47 | if (allocator != NULL) { 48 | MSLog(MSLogLevelError, "MS:Error:allocator != NULL"); 49 | return NULL; 50 | } 51 | 52 | if (size == 0) 53 | return NULL; 54 | 55 | int page(getpagesize()); 56 | 57 | uintptr_t base(reinterpret_cast(data) / page * page); 58 | size_t width(((reinterpret_cast(data) + size - 1) / page + 1) * page - base); 59 | void *address(reinterpret_cast(base)); 60 | 61 | if (mprotect(address, width, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { 62 | MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); 63 | return NULL; 64 | } 65 | 66 | return new __SubstrateMemory(address, width); 67 | } 68 | 69 | extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) { 70 | if (mprotect(memory->address_, memory->width_, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) 71 | MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); 72 | 73 | __clear_cache(reinterpret_cast(memory->address_), reinterpret_cast(memory->address_) + memory->width_); 74 | 75 | delete memory; 76 | } 77 | -------------------------------------------------------------------------------- /TestSuperCall.mm: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | #include "CydiaSubstrate.h" 24 | 25 | struct dat { 26 | uint32_t a; 27 | uint32_t b; 28 | uint32_t c; 29 | uint32_t d; 30 | uint32_t e; 31 | uint32_t f; 32 | uint32_t g; 33 | uint32_t h; 34 | }; 35 | 36 | @interface A : NSObject 37 | - (int) testI; 38 | - (dat) testS; 39 | @end 40 | 41 | @implementation A 42 | 43 | - (int) testI { 44 | return 0x31337; 45 | } 46 | 47 | - (dat) testS { 48 | dat value = { 0x31337 }; 49 | return value; 50 | } 51 | 52 | @end 53 | 54 | @interface B : A 55 | @end 56 | 57 | @implementation B 58 | @end 59 | 60 | extern "C" bool MSDebug; 61 | 62 | struct Debug { 63 | Debug() { 64 | MSDebug = true; 65 | } } debug_; 66 | 67 | MSClassHook(B) 68 | 69 | MSInstanceMessageHook0(int, B, testI) { 70 | return MSOldCall() - 0x31337 + 0xae5bda7a; 71 | } 72 | 73 | MSInstanceMessageHook0(dat, B, testS) { 74 | dat value = { MSOldCall().a - 0x31337 + 0xae5bda7a }; 75 | return value; 76 | } 77 | 78 | int main() { 79 | B *b([[B alloc] init]); 80 | printf("0x%x\n", [b testI]); 81 | printf("0x%x\n", [b testS].a); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /Trampoline.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_TRAMPOLINE_HPP 23 | #define SUBSTRATE_TRAMPOLINE_HPP 24 | 25 | struct Trampoline { 26 | const char *data_; 27 | size_t size_; 28 | size_t entry_; 29 | }; 30 | 31 | #endif//SUBSTRATE_TRAMPOLINE_HPP 32 | -------------------------------------------------------------------------------- /Trampoline.t.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "DarwinThreadInternal.hpp" 23 | 24 | #include "Baton.hpp" 25 | #include "CydiaSubstrate.h" 26 | 27 | template 28 | static _finline void dlset(Baton *baton, Type_ &function, const char *name, void *handle = RTLD_DEFAULT) { 29 | function = reinterpret_cast(baton->dlsym(handle, name)); 30 | if (function == NULL) 31 | baton->dlerror(); 32 | } 33 | 34 | void *Routine(void *arg) { 35 | Baton *baton(reinterpret_cast(arg)); 36 | 37 | void *(*dlopen)(const char *, int); 38 | dlset(baton, dlopen, "dlopen"); 39 | 40 | void *handle(dlopen(baton->library, RTLD_LAZY | RTLD_LOCAL)); 41 | if (handle == NULL) { 42 | baton->dlerror(); 43 | return NULL; 44 | } 45 | 46 | int (*dlclose)(void *); 47 | dlset(baton, dlclose, "dlclose"); 48 | 49 | dlclose(handle); 50 | 51 | return NULL; 52 | } 53 | 54 | 55 | // I am unable to link against any external functions, so reimplement bzero 56 | // XXX: there might be a gcc builtin for memset/bzero: use it instead? 57 | 58 | static void $bzero(void *data, size_t size) { 59 | char *bytes(reinterpret_cast(data)); 60 | for (size_t i(0); i != size; ++i) 61 | bytes[i] = 0; 62 | } 63 | 64 | 65 | extern "C" void Start(Baton *baton) { 66 | // XXX: I am not certain if I should deallocate this port (an academic question, as I can't) 67 | mach_port_t port(baton->mach_thread_self()); 68 | 69 | // normally, a pthread has a _pthread associated with it; pthread_t is a pointer to it 70 | // these are normally initialized by either _pthread_create or _pthread_struct_init 71 | // however, for our purposes, just initializing it to 0 is reasonably sufficient 72 | // XXX: look into using _pthread_create instead (_pthread_struct_init is often private) 73 | 74 | struct _pthread self; 75 | $bzero(&self, sizeof(self)); 76 | 77 | 78 | // this code comes from _pthread_set_self, which is the startup routine of _pthread_body 79 | // XXX: __pthread_set_self seems to syscall thread_set_cthread... what does that do? 80 | // XXX: if we use _pthread_create/_pthread_struct_init, the tsd[0] will be handled 81 | 82 | self.tsd[0] = &self; 83 | baton->__pthread_set_self(&self); 84 | 85 | 86 | // on ARM, a coprocessor register has been allocated to keep track of a thread identifier 87 | // on iOS << 4.2, this register points at a pthread_t. the tsd table is at +0x48 offset 88 | // on iOS >= 4.2, this register points at the tsd table, with pthread_t at +0x00 offset 89 | 90 | // here, we need to detect whether the thread register is pointing at a valid table 91 | // otherwise, later code that attempts to use _pthread_setspecific_direct will crash 92 | // luckily, on iOS << 4.2, we also do not need to initialize thread local storage! 93 | 94 | bool setspecific; 95 | #ifdef __arm__ 96 | void **tsd; 97 | __asm__ ("mrc p15, 0, %0, c13, c0, 3\n" : "=r"(tsd)); 98 | setspecific = tsd != NULL; 99 | #else 100 | setspecific = true; 101 | #endif 102 | 103 | 104 | // the current thread identifier is stored in the 0th thread-specific data slot 105 | // thread-specific data, especially the 0th slot, is often stored in hardware registers 106 | // the _pthread_setspecific_direct macro allows us to update these static entries 107 | // we check setspecific, a variable defined above, to see whether this function works 108 | 109 | // note: it is not sufficient to set tsd[0] or to call _pthread_create/__pthread_set_self 110 | // even more interestingly, calling the full pthread_setspecific(0) doesn't even work 111 | 112 | if (setspecific) 113 | _pthread_setspecific_direct(0, &self); 114 | 115 | 116 | pthread_t thread; 117 | baton->pthread_create(&thread, NULL, &Routine, baton); 118 | 119 | void *status; 120 | baton->pthread_join(thread, &status); 121 | 122 | baton->thread_terminate(port); 123 | } 124 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Priority: optional 2 | Version: 3 | Description: powerful code insertion platform 4 | Maintainer: Jay Freeman (saurik) 5 | Section: System 6 | -------------------------------------------------------------------------------- /control.arm: -------------------------------------------------------------------------------- 1 | Package: mobilesubstrate 2 | Architecture: iphoneos-arm 3 | Name: Mobile Substrate 4 | Author: Jay Freeman (saurik) 5 | Depiction: http://cydia.saurik.com/info/mobilesubstrate/ 6 | Depends: com.saurik.substrate.safemode 7 | Breaks: uikittools (<< 1.1.1), com.mywi4 (<= 5.03.2), com.phoenix.pandoracontrols (<= 1.1.0-1), com.intelliborn.intelliscreenx (<= 1.0.110) 8 | -------------------------------------------------------------------------------- /control.i386: -------------------------------------------------------------------------------- 1 | Package: com.cydia.substrate 2 | Architecture: cydia 3 | Depends: cy+cpu.arm | cy+cpu.i386, cy+os.macosx (>= 10.5) | cy+os.ios (>= 2.0), cy+os.macosx | com.saurik.substrate.safemode 4 | Cydia-Name: Cydia Substrate 5 | Cydia-Author: Jay Freeman (saurik) 6 | Cydia-Depiction: http://cydia.saurik.com/info/mobilesubstrate/ 7 | -------------------------------------------------------------------------------- /control.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | dir=$1 3 | dir=${dir:=_} 4 | sed -e "s@^\(Version:\).*@\1 $(./version.sh)@" control 5 | #echo "Installed-Size: $(du -s "${dir}" | cut -f 1)" 6 | -------------------------------------------------------------------------------- /cynject.cpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include "CydiaSubstrate.h" 23 | 24 | #include 25 | 26 | int main(int argc, const char *argv[]) { 27 | if (argc != 3) { 28 | fprintf(stderr, "usage: %s \n", argv[0]); 29 | return 1; 30 | } 31 | 32 | pid_t pid(strtoul(argv[1], NULL, 10)); 33 | const char *library(argv[2]); 34 | 35 | if (!MSHookProcess(pid, library)) { 36 | fprintf(stderr, "MSHookProcess() failed.\n"); 37 | return 1; 38 | } 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /darwin.mk: -------------------------------------------------------------------------------- 1 | # Cydia Substrate - Powerful Code Insertion Platform 2 | # Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | 4 | # GNU Lesser General Public License, Version 3 {{{ 5 | # 6 | # Substrate is free software: you can redistribute it and/or modify it under 7 | # the terms of the GNU Lesser General Public License as published by the 8 | # Free Software Foundation, either version 3 of the License, or (at your 9 | # option) any later version. 10 | # 11 | # Substrate is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 14 | # License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with Substrate. If not, see . 18 | # }}} 19 | 20 | ios := -i2.0 21 | mac := -m10.5 22 | 23 | flags := 24 | flags += -O2 -g0 25 | 26 | flags += -isystem extra 27 | flags += -fno-exceptions 28 | flags += -fvisibility=hidden 29 | 30 | flags_Hooker := -Ihde64c/include 31 | flags_MachMessage := -Xarch_armv6 -marm 32 | 33 | hde64c := -Xarch_i386 hde64c/src/hde64.c -Xarch_x86_64 hde64c/src/hde64.c 34 | lsubstrate := Debug.o Hooker.o MachMemory.o MachMessage.o hde64c/src/hde64.c 35 | 36 | framework := /Library/Frameworks/CydiaSubstrate.framework 37 | 38 | cycc = ./cycc $(ios) $(mac) -o$@ -- $(flags) $(filter %.o,$^) $(filter %.dylib,$^) 39 | 40 | all: darwin 41 | 42 | darwin: libsubstrate.dylib SubstrateBootstrap.dylib SubstrateLauncher.dylib SubstrateLoader.dylib cynject 43 | ios: darwin 44 | 45 | %.t.hpp: %.t.cpp trampoline.sh 46 | ./trampoline.sh $@ $*.dylib $* sed otool lipo nm ./cycc $(ios) $(mac) -o$*.dylib -- -dynamiclib $< -Iinclude -Xarch_armv6 -marm 47 | 48 | MachProtect.c: MachProtect.defs MachInterface.sh 49 | ./MachInterface.sh $@ MachProtect.h $< 50 | 51 | MachMemory.o: MachProtect.c 52 | DarwinInjector.o: Trampoline.t.hpp 53 | 54 | %.o: %.cpp 55 | $(cycc) $(flags_$*) -c -Iinclude $< 56 | 57 | %.o: %.mm 58 | $(cycc) $(flags_$*) -c -Iinclude $< 59 | 60 | libsubstrate.dylib: DarwinFindSymbol.o DarwinInjector.o ObjectiveC.o $(lsubstrate) 61 | $(cycc) -dynamiclib $(hde64c) -lobjc -install_name $(framework)/CydiaSubstrate 62 | 63 | SubstrateBootstrap.dylib: Bootstrap.o 64 | $(cycc) -dynamiclib 65 | 66 | SubstrateLauncher.dylib: DarwinLauncher.o $(lsubstrate) 67 | $(cycc) -dynamiclib $(hde64c) 68 | 69 | SubstrateLoader.dylib: DarwinLoader.o Environment.o 70 | $(cycc) -dynamiclib -framework CoreFoundation 71 | 72 | cynject: cynject.o libsubstrate.dylib 73 | $(cycc) 74 | ldid -Stask_for_pid.xml $@ 75 | 76 | %: %.o 77 | $(cycc) -framework CoreFoundation -framework Foundation 78 | 79 | extrainst_ postrm: LaunchDaemons.o Cydia.o 80 | 81 | deb: ios extrainst_ postrm 82 | ./package.sh i386 83 | ./package.sh arm 84 | 85 | package: deb 86 | 87 | install: deb 88 | PATH=/Library/Cydia/bin:/usr/sbin:/usr/bin:/sbin:/bin sudo dpkg -i com.cydia.substrate_$(shell ./version.sh)_cydia.deb 89 | 90 | upgrade: all 91 | sudo cp -a libsubstrate.dylib $(framework)/CydiaSubstrate 92 | sudo cp -a SubstrateBootstrap.dylib $(framework)/Libraries 93 | sudo cp -a SubstrateLauncher.dylib $(framework)/Libraries 94 | sudo cp -a SubstrateLoader.dylib $(framework)/Libraries 95 | 96 | clean: 97 | rm -f MachProtect.h MachProtect.c *.o libsubstrate.dylib SubstrateBootstrap.dylib SubstrateLauncher.dylib SubstrateLoader.dylib extrainst_ postrm cynject 98 | 99 | TestSuperCall: libsubstrate.dylib 100 | 101 | test: TestSuperCall 102 | arch -i386 ./TestSuperCall 103 | arch -x86_64 ./TestSuperCall 104 | 105 | .PHONY: all clean darwin deb install ios test package upgrade 106 | -------------------------------------------------------------------------------- /extra/CoreFoundation/CFBundlePriv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | /* CFBundlePriv.h 24 | Copyright (c) 1999-2007, Apple Inc. All rights reserved. 25 | */ 26 | 27 | #if !defined(__COREFOUNDATION_CFBUNDLEPRIV__) 28 | #define __COREFOUNDATION_CFBUNDLEPRIV__ 1 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | CF_EXTERN_C_BEGIN 38 | 39 | /* Finder stuff */ 40 | CF_EXPORT 41 | const CFStringRef _kCFBundlePackageTypeKey; 42 | CF_EXPORT 43 | const CFStringRef _kCFBundleSignatureKey; 44 | CF_EXPORT 45 | const CFStringRef _kCFBundleIconFileKey; 46 | CF_EXPORT 47 | const CFStringRef _kCFBundleDocumentTypesKey; 48 | CF_EXPORT 49 | const CFStringRef _kCFBundleURLTypesKey; 50 | 51 | /* Localizable Finder stuff */ 52 | CF_EXPORT 53 | const CFStringRef _kCFBundleDisplayNameKey; 54 | CF_EXPORT 55 | const CFStringRef _kCFBundleShortVersionStringKey; 56 | CF_EXPORT 57 | const CFStringRef _kCFBundleGetInfoStringKey; 58 | CF_EXPORT 59 | const CFStringRef _kCFBundleGetInfoHTMLKey; 60 | 61 | /* Sub-keys for CFBundleDocumentTypes dictionaries */ 62 | CF_EXPORT 63 | const CFStringRef _kCFBundleTypeNameKey; 64 | CF_EXPORT 65 | const CFStringRef _kCFBundleTypeRoleKey; 66 | CF_EXPORT 67 | const CFStringRef _kCFBundleTypeIconFileKey; 68 | CF_EXPORT 69 | const CFStringRef _kCFBundleTypeOSTypesKey; 70 | CF_EXPORT 71 | const CFStringRef _kCFBundleTypeExtensionsKey; 72 | CF_EXPORT 73 | const CFStringRef _kCFBundleTypeMIMETypesKey; 74 | 75 | /* Sub-keys for CFBundleURLTypes dictionaries */ 76 | CF_EXPORT 77 | const CFStringRef _kCFBundleURLNameKey; 78 | CF_EXPORT 79 | const CFStringRef _kCFBundleURLIconFileKey; 80 | CF_EXPORT 81 | const CFStringRef _kCFBundleURLSchemesKey; 82 | 83 | /* Compatibility key names */ 84 | CF_EXPORT 85 | const CFStringRef _kCFBundleOldExecutableKey; 86 | CF_EXPORT 87 | const CFStringRef _kCFBundleOldInfoDictionaryVersionKey; 88 | CF_EXPORT 89 | const CFStringRef _kCFBundleOldNameKey; 90 | CF_EXPORT 91 | const CFStringRef _kCFBundleOldIconFileKey; 92 | CF_EXPORT 93 | const CFStringRef _kCFBundleOldDocumentTypesKey; 94 | CF_EXPORT 95 | const CFStringRef _kCFBundleOldShortVersionStringKey; 96 | 97 | /* Compatibility CFBundleDocumentTypes key names */ 98 | CF_EXPORT 99 | const CFStringRef _kCFBundleOldTypeNameKey; 100 | CF_EXPORT 101 | const CFStringRef _kCFBundleOldTypeRoleKey; 102 | CF_EXPORT 103 | const CFStringRef _kCFBundleOldTypeIconFileKey; 104 | CF_EXPORT 105 | const CFStringRef _kCFBundleOldTypeExtensions1Key; 106 | CF_EXPORT 107 | const CFStringRef _kCFBundleOldTypeExtensions2Key; 108 | CF_EXPORT 109 | const CFStringRef _kCFBundleOldTypeOSTypesKey; 110 | 111 | 112 | /* Functions for examining directories that may "look like" bundles */ 113 | 114 | CF_EXPORT 115 | CFURLRef _CFBundleCopyBundleURLForExecutableURL(CFURLRef url); 116 | 117 | CF_EXPORT 118 | Boolean _CFBundleURLLooksLikeBundle(CFURLRef url); 119 | 120 | CF_EXPORT 121 | CFBundleRef _CFBundleCreateIfLooksLikeBundle(CFAllocatorRef allocator, CFURLRef url); 122 | 123 | CF_EXPORT 124 | CFBundleRef _CFBundleGetMainBundleIfLooksLikeBundle(void); 125 | 126 | CF_EXPORT 127 | Boolean _CFBundleMainBundleInfoDictionaryComesFromResourceFork(void); 128 | 129 | CF_EXPORT 130 | CFBundleRef _CFBundleCreateWithExecutableURLIfLooksLikeBundle(CFAllocatorRef allocator, CFURLRef url); 131 | 132 | CF_EXPORT 133 | CFURLRef _CFBundleCopyMainBundleExecutableURL(Boolean *looksLikeBundle); 134 | 135 | CF_EXPORT 136 | CFBundleRef _CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL); 137 | 138 | /* Functions for examining the structure of a bundle */ 139 | 140 | CF_EXPORT 141 | CFURLRef _CFBundleCopyResourceForkURL(CFBundleRef bundle); 142 | 143 | CF_EXPORT 144 | CFURLRef _CFBundleCopyInfoPlistURL(CFBundleRef bundle); 145 | 146 | 147 | /* Functions for working without a bundle instance */ 148 | 149 | CF_EXPORT 150 | CFURLRef _CFBundleCopyExecutableURLInDirectory(CFURLRef url); 151 | 152 | CF_EXPORT 153 | CFURLRef _CFBundleCopyOtherExecutableURLInDirectory(CFURLRef url); 154 | 155 | 156 | /* Functions for dealing with localizations */ 157 | 158 | CF_EXPORT 159 | void _CFBundleGetLanguageAndRegionCodes(SInt32 *languageCode, SInt32 *regionCode); 160 | // may return -1 for either one if no code can be found 161 | 162 | CF_EXPORT 163 | Boolean CFBundleGetLocalizationInfoForLocalization(CFStringRef localizationName, SInt32 *languageCode, SInt32 *regionCode, SInt32 *scriptCode, CFStringEncoding *stringEncoding); 164 | /* Gets the appropriate language and region codes, and the default */ 165 | /* script code and encoding, for the localization specified. */ 166 | /* Pass NULL for the localizationName to get these values for the */ 167 | /* single most preferred localization in the current context. */ 168 | /* May give -1 if there is no language or region code for a particular */ 169 | /* localization. Returns false if CFBundle has no information about */ 170 | /* the given localization. */ 171 | 172 | CF_EXPORT 173 | CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SInt32 regionCode, SInt32 scriptCode, CFStringEncoding stringEncoding); 174 | /* Returns the default localization for the combination of codes */ 175 | /* specified. Pass in -1 for language, region code, or script code, or */ 176 | /* 0xFFFF for stringEncoding, if you do not wish to specify one of these. */ 177 | 178 | CF_EXPORT 179 | void _CFBundleSetDefaultLocalization(CFStringRef localizationName); 180 | 181 | 182 | /* Functions for dealing specifically with CFM executables */ 183 | 184 | CF_EXPORT 185 | void *_CFBundleGetCFMFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName); 186 | 187 | CF_EXPORT 188 | void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle, CFArrayRef functionNames, void *ftbl[]); 189 | 190 | CF_EXPORT 191 | void _CFBundleSetCFMConnectionID(CFBundleRef bundle, void *connectionID); 192 | 193 | 194 | /* Miscellaneous functions */ 195 | 196 | CF_EXPORT 197 | CFStringRef _CFBundleCopyFileTypeForFileURL(CFURLRef url); 198 | 199 | CF_EXPORT 200 | CFStringRef _CFBundleCopyFileTypeForFileData(CFDataRef data); 201 | 202 | CF_EXPORT 203 | Boolean _CFBundleGetHasChanged(CFBundleRef bundle); 204 | 205 | CF_EXPORT 206 | void _CFBundleFlushCaches(void); 207 | 208 | CF_EXPORT 209 | void _CFBundleFlushCachesForURL(CFURLRef url); 210 | 211 | CF_EXPORT 212 | void _CFBundleFlushBundleCaches(CFBundleRef bundle); // The previous two functions flush cached resource paths; this one also flushes bundle-specific caches such as the info dictionary and strings files 213 | 214 | CF_EXPORT 215 | void _CFBundleSetStringsFilesShared(CFBundleRef bundle, Boolean flag); 216 | 217 | CF_EXPORT 218 | Boolean _CFBundleGetStringsFilesShared(CFBundleRef bundle); 219 | 220 | 221 | /* Functions deprecated as SPI */ 222 | 223 | CF_EXPORT 224 | CFDictionaryRef _CFBundleGetLocalInfoDictionary(CFBundleRef bundle); // deprecated in favor of CFBundleGetLocalInfoDictionary 225 | 226 | CF_EXPORT 227 | CFPropertyListRef _CFBundleGetValueForInfoKey(CFBundleRef bundle, CFStringRef key); // deprecated in favor of CFBundleGetValueForInfoDictionaryKey 228 | 229 | CF_EXPORT 230 | Boolean _CFBundleGetPackageInfoInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt32 *packageType, UInt32 *packageCreator); // deprecated in favor of CFBundleGetPackageInfoInDirectory 231 | 232 | CF_EXPORT 233 | CFDictionaryRef _CFBundleCopyInfoDictionaryInResourceFork(CFURLRef url); // CFBundleCopyInfoDictionaryForURL is usually preferred; for the main bundle, however, no special call is necessary, since the info dictionary will automatically be available whether the app is bundled or not 234 | 235 | CF_EXPORT 236 | CFURLRef _CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle); // deprecated in favor of CFBundleCopyPrivateFrameworksURL 237 | 238 | CF_EXPORT 239 | CFURLRef _CFBundleCopySharedFrameworksURL(CFBundleRef bundle); // deprecated in favor of CFBundleCopySharedFrameworksURL 240 | 241 | CF_EXPORT 242 | CFURLRef _CFBundleCopySharedSupportURL(CFBundleRef bundle); // deprecated in favor of CFBundleCopySharedSupportURL 243 | 244 | CF_EXPORT 245 | CFURLRef _CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle); // deprecated in favor of CFBundleCopyBuiltInPlugInsURL 246 | 247 | CF_EXPORT 248 | CFArrayRef _CFBundleCopyBundleRegionsArray(CFBundleRef bundle); // deprecated in favor of CFBundleCopyBundleLocalizations 249 | 250 | CF_EXPORT 251 | CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language); // deprecated in favor of CFBundleCopyResourceURLForLocalization 252 | 253 | CF_EXPORT 254 | CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language); // deprecated in favor of CFBundleCopyResourceURLsOfTypeForLocalization 255 | 256 | CF_EXPORT 257 | CFBundleRefNum _CFBundleOpenBundleResourceFork(CFBundleRef bundle); // deprecated in favor of CFBundleOpenBundleResourceMap 258 | 259 | CF_EXPORT 260 | void _CFBundleCloseBundleResourceFork(CFBundleRef bundle); // deprecated in favor of CFBundleCloseBundleResourceMap 261 | 262 | CF_EXTERN_C_END 263 | 264 | #endif /* ! __COREFOUNDATION_CFBUNDLEPRIV__ */ 265 | 266 | -------------------------------------------------------------------------------- /extra/CoreFoundation/CFLogUtilities.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | /* CFLogUtilities.h 24 | Copyright (c) 2004-2007, Apple Inc. All rights reserved. 25 | */ 26 | 27 | /* 28 | APPLE SPI: NOT TO BE USED OUTSIDE APPLE! 29 | */ 30 | 31 | #if !defined(__COREFOUNDATION_CFLOGUTILITIES__) 32 | #define __COREFOUNDATION_CFLOGUTILITIES__ 1 33 | 34 | #include 35 | #include 36 | 37 | CF_EXTERN_C_BEGIN 38 | 39 | 40 | enum { // Legal level values for CFLog() 41 | kCFLogLevelEmergency = 0, 42 | kCFLogLevelAlert = 1, 43 | kCFLogLevelCritical = 2, 44 | kCFLogLevelError = 3, 45 | kCFLogLevelWarning = 4, 46 | kCFLogLevelNotice = 5, 47 | kCFLogLevelInfo = 6, 48 | kCFLogLevelDebug = 7, 49 | }; 50 | 51 | CF_EXPORT void CFLog(int32_t level, CFStringRef format, ...); 52 | /* Passing in a level value which is outside the range of 0-7 will cause the the call to do nothing. 53 | CFLog() logs the message using the asl.h API, and uses the level parameter as the log level. 54 | Note that the asl subsystem ignores some log levels by default. 55 | CFLog() is not fast, and is not going to be guaranteed to be fast. 56 | Even "no-op" CFLogs are not necessarily fast. 57 | If you care about performance, you shouldn't be logging. 58 | */ 59 | 60 | CF_EXTERN_C_END 61 | 62 | #endif /* ! __COREFOUNDATION_CFLOGUTILITIES__ */ 63 | 64 | -------------------------------------------------------------------------------- /extra/machine/exec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_OSREFERENCE_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. The rights granted to you under the License 10 | * may not be used to create, or enable the creation or redistribution of, 11 | * unlawful or unlicensed copies of an Apple operating system, or to 12 | * circumvent, violate, or enable the circumvention or violation of, any 13 | * terms of an Apple operating system software license agreement. 14 | * 15 | * Please obtain a copy of the License at 16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 | * 18 | * The Original Code and all software distributed under the License are 19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 | * Please see the License for the specific language governing rights and 24 | * limitations under the License. 25 | * 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 | */ 28 | /*- 29 | * Copyright (c) 1992, 1993 30 | * The Regents of the University of California. All rights reserved. 31 | * 32 | * Redistribution and use in source and binary forms, with or without 33 | * modification, are permitted provided that the following conditions 34 | * are met: 35 | * 1. Redistributions of source code must retain the above copyright 36 | * notice, this list of conditions and the following disclaimer. 37 | * 2. Redistributions in binary form must reproduce the above copyright 38 | * notice, this list of conditions and the following disclaimer in the 39 | * documentation and/or other materials provided with the distribution. 40 | * 3. All advertising materials mentioning features or use of this software 41 | * must display the following acknowledgement: 42 | * This product includes software developed by the University of 43 | * California, Berkeley and its contributors. 44 | * 4. Neither the name of the University nor the names of its contributors 45 | * may be used to endorse or promote products derived from this software 46 | * without specific prior written permission. 47 | * 48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 | * SUCH DAMAGE. 59 | * 60 | * @(#)exec.h 8.1 (Berkeley) 6/11/93 61 | */ 62 | 63 | #ifndef _BSD_I386_EXEC_H_ 64 | #define _BSD_I386_EXEC_H_ 65 | 66 | 67 | #ifdef BSD_KERNEL_PRIVATE 68 | /* Size of a page in an object file. */ 69 | #define __LDPGSZ 4096 70 | 71 | /* Valid magic number check. */ 72 | #define N_BADMAG(ex) \ 73 | ((ex).a_magic != NMAGIC && (ex).a_magic != OMAGIC && \ 74 | (ex).a_magic != ZMAGIC) 75 | 76 | /* Address of the bottom of the text segment. */ 77 | #define N_TXTADDR(X) 0 78 | 79 | /* Address of the bottom of the data segment. */ 80 | #define N_DATADDR(ex) \ 81 | (N_TXTADDR(ex) + ((ex).a_magic == OMAGIC ? (ex).a_text \ 82 | : __LDPGSZ + ((ex).a_text - 1 & ~(__LDPGSZ - 1)))) 83 | 84 | /* Text segment offset. */ 85 | #define N_TXTOFF(ex) \ 86 | ((ex).a_magic == ZMAGIC ? __LDPGSZ : sizeof(struct exec)) 87 | 88 | /* Data segment offset. */ 89 | #define N_DATOFF(ex) \ 90 | (N_TXTOFF(ex) + ((ex).a_magic != ZMAGIC ? (ex).a_text : \ 91 | __LDPGSZ + ((ex).a_text - 1 & ~(__LDPGSZ - 1)))) 92 | 93 | /* Symbol table offset. */ 94 | #define N_SYMOFF(ex) \ 95 | (N_TXTOFF(ex) + (ex).a_text + (ex).a_data + (ex).a_trsize + \ 96 | (ex).a_drsize) 97 | 98 | /* String table offset. */ 99 | #define N_STROFF(ex) (N_SYMOFF(ex) + (ex).a_syms) 100 | 101 | /* Description of the object file header (a.out format). */ 102 | struct exec { 103 | #define OMAGIC 0407 /* old impure format */ 104 | #define NMAGIC 0410 /* read-only text */ 105 | #define ZMAGIC 0413 /* demand load format */ 106 | #define QMAGIC 0314 /* demand load format. Header in text. */ 107 | unsigned int a_magic; /* magic number */ 108 | 109 | unsigned int a_text; /* text segment size */ 110 | unsigned int a_data; /* initialized data size */ 111 | unsigned int a_bss; /* uninitialized data size */ 112 | unsigned int a_syms; /* symbol table size */ 113 | unsigned int a_entry; /* entry point */ 114 | unsigned int a_trsize; /* text relocation size */ 115 | unsigned int a_drsize; /* data relocation size */ 116 | }; 117 | 118 | #endif /* BSD_KERNEL_PRIVATE */ 119 | 120 | #endif /* _BSD_I386_EXEC_H_ */ 121 | -------------------------------------------------------------------------------- /extrainst_.mm: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | #import 24 | #include 25 | #include 26 | 27 | #include "Cydia.hpp" 28 | #include "Environment.hpp" 29 | #include "LaunchDaemons.hpp" 30 | 31 | #ifdef __arm__ 32 | 33 | // XXX: NO means "failed", false means "unneeded" 34 | 35 | static bool HookEnvironment(const char *name) { 36 | NSString *file([NSString stringWithFormat:@"%@/%s.plist", @ SubstrateLaunchDaemons_, name]); 37 | if (file == nil) 38 | return NO; 39 | 40 | NSMutableDictionary *root([NSMutableDictionary dictionaryWithContentsOfFile:file]); 41 | if (root == nil) 42 | return NO; 43 | 44 | NSMutableDictionary *environment([root objectForKey:@"EnvironmentVariables"]); 45 | if (environment == nil) { 46 | environment = [NSMutableDictionary dictionaryWithCapacity:1]; 47 | if (environment == nil) 48 | return NO; 49 | 50 | [root setObject:environment forKey:@"EnvironmentVariables"]; 51 | } 52 | 53 | NSString *variable([environment objectForKey:@ SubstrateVariable_]); 54 | if (variable == nil || [variable length] == 0) 55 | [environment setObject:@ SubstrateLibrary_ forKey:@ SubstrateVariable_]; 56 | else { 57 | NSArray *dylibs([variable componentsSeparatedByString:@":"]); 58 | if (dylibs == nil) 59 | return NO; 60 | 61 | NSUInteger index([dylibs indexOfObject:@ SubstrateLibrary_]); 62 | if (index != NSNotFound) 63 | return false; 64 | 65 | [environment setObject:[NSString stringWithFormat:@"%@:%@", variable, @ SubstrateLibrary_] forKey:@ SubstrateVariable_]; 66 | } 67 | 68 | NSString *error; 69 | NSData *data([NSPropertyListSerialization dataFromPropertyList:root format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]); 70 | if (data == nil) 71 | return NO; 72 | 73 | if (![data writeToFile:file atomically:YES]) 74 | return NO; 75 | 76 | return true; 77 | } 78 | 79 | static int InstallTether() { 80 | HookEnvironment("com.apple.mediaserverd"); 81 | HookEnvironment("com.apple.itunesstored"); 82 | HookEnvironment("com.apple.CommCenter"); 83 | HookEnvironment("com.apple.AOSNotification"); 84 | 85 | HookEnvironment("com.apple.BTServer"); 86 | HookEnvironment("com.apple.iapd"); 87 | 88 | HookEnvironment("com.apple.lsd"); 89 | HookEnvironment("com.apple.imagent"); 90 | 91 | HookEnvironment("com.apple.mobile.lockdown"); 92 | HookEnvironment("com.apple.itdbprep.server"); 93 | 94 | HookEnvironment("com.apple.locationd"); 95 | 96 | HookEnvironment("com.apple.mediaremoted"); 97 | HookEnvironment("com.apple.frontrow"); 98 | 99 | HookEnvironment("com.apple.voiced"); 100 | HookEnvironment("com.apple.MobileInternetSharing"); 101 | 102 | HookEnvironment("com.apple.CommCenterClassic"); 103 | HookEnvironment("com.apple.gamed"); 104 | 105 | HookEnvironment("com.apple.mobile.softwareupdated"); 106 | HookEnvironment("com.apple.softwareupdateservicesd"); 107 | HookEnvironment("com.apple.twitterd"); 108 | HookEnvironment("com.apple.mediaremoted"); 109 | 110 | HookEnvironment("com.apple.assistivetouchd"); 111 | HookEnvironment("com.apple.accountsd"); 112 | 113 | HookEnvironment("com.apple.configd"); 114 | HookEnvironment("com.apple.wifid"); 115 | HookEnvironment("com.apple.mobile.installd"); 116 | 117 | HookEnvironment("com.apple.SpringBoard"); 118 | 119 | FinishCydia("reboot"); 120 | 121 | return 0; 122 | } 123 | 124 | #endif 125 | 126 | static int InstallSemiTether() { 127 | MSClearLaunchDaemons(); 128 | 129 | NSFileManager *manager([NSFileManager defaultManager]); 130 | NSError *error; 131 | 132 | 133 | // we must copy the dylib to a new filename in order to guarantee that dlopen() considers it to be different 134 | // if we fail to do this, it is quite unfortunate, but often it will work to use the original name 135 | 136 | NSString *temp([NSString stringWithFormat:@"/tmp/ms-%f.dylib", [[NSDate date] timeIntervalSinceReferenceDate]]); 137 | 138 | NSString *dylib; 139 | if ([manager copyItemAtPath:@ SubstrateLauncher_ toPath:temp error:&error]) 140 | dylib = temp; 141 | else { 142 | fprintf(stderr, "unable to copy: %s\n", [[error description] UTF8String]); 143 | // XXX: this is not actually reasonable 144 | dylib = @ SubstrateLauncher_; 145 | temp = nil; 146 | } 147 | 148 | 149 | // XXX: check the result code and do something about failures 150 | system([[@"/usr/bin/cynject 1 " stringByAppendingString:dylib] UTF8String]); 151 | 152 | 153 | // if we are unable to remove the file copied into /tmp, it is interesting, but harmless 154 | 155 | if (temp != nil && ![manager removeItemAtPath:temp error:&error]) 156 | if (unlink([temp UTF8String]) == -1) 157 | fprintf(stderr, "unable to remove: (%s):%d\n", [[error description] UTF8String], errno); 158 | 159 | 160 | NSString *config([NSString stringWithContentsOfFile:@ SubstrateLaunchConfig_ encoding:NSNonLossyASCIIStringEncoding error:&error]); 161 | // XXX: if the file fails to load, it might not be missing: it might be unreadable for some reason 162 | if (config == nil) 163 | config = @""; 164 | 165 | NSArray *lines([config componentsSeparatedByString:@"\n"]); 166 | NSMutableArray *copy([lines mutableCopy]); 167 | 168 | [copy removeObject:@""]; 169 | 170 | if ([lines indexOfObject:@ SubstrateBootstrapExecute_] == NSNotFound) 171 | [copy addObject:@ SubstrateBootstrapExecute_]; 172 | 173 | [copy addObject:@""]; 174 | 175 | if (![copy isEqualToArray:lines]) 176 | [[copy componentsJoinedByString:@"\n"] writeToFile:@ SubstrateLaunchConfig_ atomically:YES encoding:NSNonLossyASCIIStringEncoding error:&error]; 177 | 178 | return 0; 179 | } 180 | 181 | #ifdef __arm__ 182 | 183 | static int InstallQuasiTether() { 184 | // JailbreakMe 3.0 "Saffron" bootstrapped itself using /usr/libexec/dirhelper 185 | // unfortunately, dirhelper is run too long after launchd.conf is processed 186 | // here we detect whether dirhelper is /boot/untether so as to install tethered 187 | 188 | // further, Saffron used a special filesystem called "unionfs" instead of stashing 189 | // this prevents us from easily being able to make modifications to the injector 190 | // it should be noted that we cannot use launchd.conf itself, also due to unionfs 191 | 192 | // luckily, comex implemented rename() to work on files in situ (under the mount) 193 | // however, most of the programs we can execute from launchctl require /bin/sh 194 | // the two that do not: rc.boot (before fstab mount), cc_fips_test (not on 4.3) 195 | // so, we really don't have any good options to fix this: we need to mark it buggy 196 | 197 | // XXX: the one remaining option is to unmount /etc, modify injection, and remount 198 | 199 | char dirhelper[1024]; 200 | memset(dirhelper, 0, sizeof(dirhelper)); 201 | 202 | // we use sizeof(dirhelper) - 1, as readlink() does not NUL-terminate the buffer 203 | 204 | if (readlink("/usr/libexec/dirhelper", dirhelper, sizeof(dirhelper) - 1) > 0) 205 | if (strcmp(dirhelper, "/boot/untether") == 0) 206 | return InstallTether(); 207 | 208 | 209 | // there is a horrible bug in some jailbreaks where fork() causes dirty pages to become codesign invalid 210 | // as our posix_spawn hook in launchd occurs after a call to fork(), we cannot use that injection mechanism 211 | 212 | switch (DetectForkBug()) { 213 | case ForkBugUnknown: 214 | return 1; 215 | 216 | case ForkBugPresent: 217 | return InstallTether(); 218 | 219 | case ForkBugMissing: 220 | break; 221 | } 222 | 223 | return InstallSemiTether(); 224 | } 225 | 226 | #endif 227 | 228 | int main(int argc, char *argv[]) { 229 | if (argc < 2 || ( 230 | strcmp(argv[1], "install") != 0 && 231 | strcmp(argv[1], "upgrade") != 0 && 232 | true)) return 0; 233 | 234 | NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); 235 | 236 | #ifdef __arm__ 237 | int result(InstallQuasiTether()); 238 | #else 239 | int result(InstallSemiTether()); 240 | #endif 241 | 242 | [pool release]; 243 | 244 | // XXX: in general, this return 0 happens way too often 245 | return result; 246 | } 247 | -------------------------------------------------------------------------------- /hde64c/LICENSE: -------------------------------------------------------------------------------- 1 | License agreement 2 | 3 | Hacker Disassembler Engine 64 C 4 | Copyright (c) 2008-2009, Vyacheslav Patkov. 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 21 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /hde64c/NEWS: -------------------------------------------------------------------------------- 1 | 2 | My english is bad, I hope that you understand me ;) 3 | 4 | 5 | version 0.04 [2009.03.09] FINAL 6 | + now relative addresses stored to hde64s.imm* (see doc/ for more info) 7 | + removed first sentence from LICENSE 8 | 9 | version 0.03 [2009.01.02] 10 | + fixed bug: error setting 0x800000 flag to "hde64s.flags" when no prefixes 11 | 12 | version 0.02 [2008.11.02] 13 | + associated some fields of "hde64s" structure into unions 14 | + repacked table, it redecued on 37 bytes 15 | 16 | version 0.01 [2008.09.22] 17 | + first release 18 | -------------------------------------------------------------------------------- /hde64c/THANKS: -------------------------------------------------------------------------------- 1 | HDE64 would not be what it is today without the invaluable help of: 2 | 3 | IceStudent 4 | herm1t 5 | Christian Ludloff 6 | Intel Corporation 7 | -------------------------------------------------------------------------------- /hde64c/doc/en/manual.txt: -------------------------------------------------------------------------------- 1 | 2 | Hacker Disassembler Engine 64 C 0.04 FINAL 3 | ========================================== 4 | 5 | 1. What is it? 6 | 2. How to use? 7 | 3. Invalid instructions 8 | 4. Contacts 9 | 10 | My english is bad, I hope that you understand me ;) If you can translate the 11 | russian documentation, email me, please :) 12 | 13 | 1. What is it? 14 | ============== 15 | 16 | HDE64C is a small disassembler engine, intended for analysis of x86-64 code. It 17 | gets information about instruction (length, prefixes, opcode, ModR/M, SIB,..) 18 | and also detects invalid instructions. You can use the engine, for example, 19 | when working with executables, writing viruses, because most disassemblers too 20 | get only assembler mnemonic and aren't intended for analysis of code, but 21 | most simple length disassemblers get too little info. HDE64C gets enough info 22 | for analysis, but it has very small size. 23 | 24 | + support General-Purpose, FPU, MMX, SSE-SSE3, 3DNow! instructions 25 | + high-speed and small size (~ 2.5 kb) 26 | + operating system independent code 27 | 28 | 2. How to use? 29 | ============== 30 | 31 | To disassemble instruction should call "hde64_disasm" function. First argument 32 | is pointer to code, second - pointer to "hde64s" structure: 33 | 34 | unsigned int hde64_disasm(const void *code, hde64s *hs); 35 | 36 | You should follow C convention of arguments passing. The function returns 37 | length of the instruction and fill "hde64s" structure: 38 | 39 | typedef struct { 40 | uint8_t len; // length of command 41 | uint8_t p_rep; // rep/repz (0xf3) & repnz (0xf2) prefix 42 | uint8_t p_lock; // lock prefix: 0xf0 43 | uint8_t p_seg; // segment prefix: 0x26,0x2e,0x36,0x3e,0x64,0x65 44 | uint8_t p_66; // operand-size override prefix: 0x66 45 | uint8_t p_67; // address-size override prefix: 0x67 46 | uint8_t rex; // REX prefix 47 | uint8_t rex_w; // REX.W 48 | uint8_t rex_r; // REX.R 49 | uint8_t rex_x; // REX.X 50 | uint8_t rex_b; // REX.B 51 | uint8_t opcode; // opcode 52 | uint8_t opcode2; // second opcode (if first opcode is 0x0f) 53 | uint8_t modrm; // ModR/M byte 54 | uint8_t modrm_mod; // ModR/M.mod 55 | uint8_t modrm_reg; // ModR/M.reg 56 | uint8_t modrm_rm; // ModR/M.r/m 57 | uint8_t sib; // SIB byte 58 | uint8_t sib_scale; // SIB.scale 59 | uint8_t sib_index; // SIB.index 60 | uint8_t sib_base; // SIB.base 61 | union { 62 | uint8_t imm8; // immediate value imm8 63 | uint16_t imm16; // immediate value imm16 64 | uint32_t imm32; // immediate value imm32 65 | uint64_t imm64; // immediate value imm64 66 | } imm; 67 | union { 68 | uint8_t disp8; // displacement disp8 69 | uint16_t disp16; // displacement disp16 70 | uint32_t disp32; // displacement disp32 71 | } disp; 72 | uint32_t flags; // flags 73 | } hde64s; 74 | 75 | Special cases of immediate values are relative addresses. In previous versions 76 | of the engine this values stores to hde32s.rel* fields. But now it stored to 77 | hde32s.imm* as all others immediates. You can detect relative address by flag 78 | F_RELATIVE, which setted with one of F_IMM* flags (see below). 79 | 80 | Alignment of structure "hde64s" is 1 byte (no alignment). Be careful, check 81 | settings of your compiler or use headers from this package. 82 | 83 | Fields "hde64s.opcode" and "hde64s.len" will be always. Presence of other 84 | fields you can get with following flags in field "hde64s.flags": 85 | 86 | #define F_MODRM 0x00000001 // ModR/M exists 87 | #define F_SIB 0x00000002 // SIB exists 88 | #define F_IMM8 0x00000004 // immediate value imm8 exists 89 | #define F_IMM16 0x00000008 // immediate value imm16 exists 90 | #define F_IMM32 0x00000010 // immediate value imm32 exists 91 | #define F_IMM64 0x00000020 // immediate value imm64 exists 92 | #define F_DISP8 0x00000040 // displacement disp8 exists 93 | #define F_DISP16 0x00000080 // displacement disp16 exists 94 | #define F_DISP32 0x00000100 // displacement disp32 exists 95 | #define F_RELATIVE 0x00000200 // relative address rel8 exists 96 | #define F_PREFIX_REPNZ 0x01000000 // repnz prefix exists 97 | #define F_PREFIX_REPX 0x02000000 // rep(z) prefix exists 98 | #define F_PREFIX_REP 0x03000000 // rep(z) or repnz prefix exists 99 | #define F_PREFIX_66 0x04000000 // 0x66 prefix exists 100 | #define F_PREFIX_67 0x08000000 // 0x67 prefix exists 101 | #define F_PREFIX_LOCK 0x10000000 // lock prefix exists 102 | #define F_PREFIX_SEG 0x20000000 // segment prefix exists 103 | #define F_PREFIX_REX 0x40000000 // REX prefix exists 104 | #define F_PREFIX_ANY 0x7f000000 // any prefix esists 105 | 106 | HDE64C guaranteed that it read from "const void *code" no more than 26 bytes, 107 | if instruction is valid, than HDE64C read no more than "hde64s.len" bytes and 108 | "hde64s.len" always no more than 15. 109 | 110 | 3. Invalid instructions 111 | ======================= 112 | 113 | HDE64C analyses instruction for invalid, and do it thoroughly (more than half 114 | of the size of engine is code and tables for detecting invalid instructions). 115 | If HDE64C think, that instruction is invalid, it set flag "F_ERROR": 116 | 117 | #define F_ERROR 0x00001000 // invalid instruction 118 | 119 | Besides, HDE64C set flags to explain type of error: 120 | 121 | #define F_ERROR_OPCODE 0x00002000 // invalid opcode 122 | #define F_ERROR_LENGTH 0x00004000 // length of command more than 15 123 | #define F_ERROR_LOCK 0x00008000 // prefix lock isn't allowed 124 | #define F_ERROR_OPERAND 0x00010000 // operand isn't allowed 125 | 126 | On case of "F_ERROR_OPCODE" flag, under notion opcode is understood not only 127 | "hde64s.opcode(2)" byte, but besides opcode's extension in ModR/M.reg, ModR/M 128 | or prefix (when two-byte opcode). So, HDE64C detects commands like "c6 c8 00" 129 | as invalid, because opcode "c6 /1" is invalid. 130 | 131 | If HDE64C setted flag "F_ERROR_LENGTH", then field "hde64s.len" is 15, so 132 | maximal value of "hde64s.len" is 15. 133 | 134 | If engine detect instruction as invalid, it doesn't stop disassembling and 135 | continue disassembling in general rules, but error flag (F_ERROR) and flag 136 | of error's type (F_ERROR_*) will be setted. 137 | 138 | 4. Contacts 139 | =========== 140 | 141 | Author: Vyacheslav Patkov 142 | E-mail: patkov-mail at mail.ru 143 | WWW: http://hde32.narod.ru/ 144 | 145 | Please, mail me on russian or english language. Use text format of email, don't 146 | send me beautiful HTML or (oh my god) DOC messages. 147 | 148 | P. S. 149 | 150 | I'm boring with HDE64. So, the version is final. And maybe there are bugs (but 151 | I have no bug reports yet, and the engine succesfully passed my own tests). 152 | If YOU want continute HDE64 history -- fork it. 153 | -------------------------------------------------------------------------------- /hde64c/doc/ru/manual.txt: -------------------------------------------------------------------------------- 1 | 2 | Hacker Disassembler Engine 64 C 0.04 FINAL 3 | ========================================== 4 | 5 | 1. Что это такое? 6 | 2. Как использовать? 7 | 3. Неправильные инструкции 8 | 4. Контакты 9 | 10 | Прежде, чем использовать HDE64, обязательно прочти данное руководство, чтобы 11 | потом не было неприятных неожиданностей. Предполагается, что читатель хотя бы 12 | немного разбирается в процессорах x86-64 и под рукой у него есть Интеловские 13 | мануалы или другие справочники. Руководство написано в разговорном стиле, слова 14 | "инструкция" и "каманда" я употреблял как синонимы. Для ассемблерных мнемоник 15 | использовался intel-синтаксис (как в nasm), прототипы и определения записаны 16 | в Си-нотации. 17 | 18 | 1. Что это такое? 19 | ================= 20 | 21 | Небольшой дизассемблерный движок, предназначенный для анализа x86-64 кода. 22 | HDE64 получает информацию о команде (длина, префиксы, опкод, ModR/M,..), а 23 | также анализирует ее на вилидность. Движок может пригодиться, например, при 24 | работе с исполняемыми файлами, написании вирусов, когда простого дизассемблера 25 | длин недостаточно, а большой дизассемблер тащить тяжело, к тому же большинство 26 | из них служат лишь для получения человекочитаемой мнемоники. HDE64 предназначен 27 | для "внутреннего" анализа, поэтому поддержки мнемоник в нем принципиально 28 | никогда не будет. Из-за этого он очень мал, но получает достаточно информации 29 | для анализа. 30 | 31 | + поддержка General-Purpose, FPU, MMX, SSE-SSE3, 3DNow! инструкций 32 | + высокая скорость и маленький размер (~ 2.5 кб) 33 | + не привязан ни к какой ОС 34 | 35 | 2. Как использовать? 36 | ==================== 37 | 38 | Для дизассемблирования команды необходимо вызвать функцию hde64_disasm, 39 | первый аргумент -- указатель на код, второй -- указатель на структуру hde64s: 40 | 41 | unsigned int hde64_disasm(const void *code, hde64s *hs); 42 | 43 | Аргументы следует передавать в C конвенции. Функция возвращает длину команды, 44 | а также заполняет структуру "hde64s": 45 | 46 | typedef struct { 47 | uint8_t len; // длина команды 48 | uint8_t p_rep; // префикс rep/repz (0xf3) или repnz (0xf2) 49 | uint8_t p_lock; // префикс lock: 0xf0 50 | uint8_t p_seg; // сегментный префикс: 0x26,0x2e,0x36,0x3e,0x64,0x65 51 | uint8_t p_66; // префикс переопределения размера операнда: 0x66 52 | uint8_t p_67; // префикс переопределения размера адреса: 0x67 53 | uint8_t rex; // префикс REX 54 | uint8_t rex_w; // REX.W 55 | uint8_t rex_r; // REX.R 56 | uint8_t rex_x; // REX.X 57 | uint8_t rex_b; // REX.B 58 | uint8_t opcode; // опкод 59 | uint8_t opcode2; // второй опкод (если первый 0x0f) 60 | uint8_t modrm; // ModR/M байт 61 | uint8_t modrm_mod; // ModR/M.mod 62 | uint8_t modrm_reg; // ModR/M.reg 63 | uint8_t modrm_rm; // ModR/M.r/m 64 | uint8_t sib; // SIB байт 65 | uint8_t sib_scale; // SIB.scale 66 | uint8_t sib_index; // SIB.index 67 | uint8_t sib_base; // SIB.base 68 | union { 69 | uint8_t imm8; // непосредственное значение imm8 70 | uint16_t imm16; // непосредственное значение imm16 71 | uint32_t imm32; // непосредственное значение imm32 72 | uint64_t imm64; // непосредственное значение imm64 73 | } imm; 74 | union { 75 | uint8_t disp8; // смещение disp8 76 | uint16_t disp16; // смещение disp16 77 | uint32_t disp32; // смещение disp32 78 | } disp; 79 | uint32_t flags; // флаги 80 | } hde32s; 81 | 82 | Частным случаем непосредственного значения может быть относительный адрес. В 83 | предыдущих версиях движка в структуре для них были выделены специальные поля 84 | hde64s.rel*, но теперь они записываются в свое законное место -- hde64s.imm*, 85 | а отличить их можно по флагу F_RELATIVE, который устанавливается вместе с 86 | одним из флагов F_IMM* (см. ниже). 87 | 88 | Выравнивание структуры "hde64s" равно 1 байту, т.е. его нет. Помните это при 89 | работе с компиляторами, которые любят выранивать данные по кратным адресам. 90 | Рекомендую брать хидеры из этого дистрибутива, там все настроено. 91 | 92 | Поля "hde64s.opcode" и "hde64s.len" заполняются всегда. Присутствие остальных 93 | полей следует определять по следущим флагам поля "hde64s.flags": 94 | 95 | #define F_MODRM 0x00000001 // присутствует ModR/M 96 | #define F_SIB 0x00000002 // присутствует SIB 97 | #define F_IMM8 0x00000004 // присутствует значение imm8 98 | #define F_IMM16 0x00000008 // присутствует значение imm16 99 | #define F_IMM32 0x00000010 // присутствует значение imm32 100 | #define F_IMM64 0x00000020 // присутствует значение imm64 101 | #define F_DISP8 0x00000040 // присутствует смещение disp8 102 | #define F_DISP16 0x00000080 // присутствует смещение disp16 103 | #define F_DISP32 0x00000100 // присутствует смещение disp32 104 | #define F_RELATIVE 0x00000200 // imm* является относительным адресом 105 | #define F_PREFIX_REPNZ 0x01000000 // присутствует префикс repnz 106 | #define F_PREFIX_REPX 0x02000000 // присутствует префикс rep(z) 107 | #define F_PREFIX_REP 0x03000000 // присутствует префикс rep(z) или repnz 108 | #define F_PREFIX_66 0x04000000 // присутствует префикс 0x66 109 | #define F_PREFIX_67 0x08000000 // присутствует префикс 0x67 110 | #define F_PREFIX_LOCK 0x10000000 // присутствует префикс lock 111 | #define F_PREFIX_SEG 0x20000000 // присутствует префикс сегмента 112 | #define F_PREFIX_REX 0x40000000 // присутствует префикс REX 113 | #define F_PREFIX_ANY 0x7f000000 // присутствует любой префикс 114 | 115 | Движок гарантирует, что он прочитает, начиная с места в памяти, на которое 116 | указывает "const void *code", не более 26 байт. Причем если инструкция 117 | правильная (см. п.3), то движок прочитает не более "hde64s.len" байт, которое, 118 | в свою очередь, не больше 15. 119 | 120 | 3. Неправильные инструкции 121 | ========================== 122 | 123 | HDE64C анализирует команды на правильность, причем достаточно тщательно, а не 124 | просто беглой проверкой опкода и длины (более половины размера движка занимает 125 | код и таблицы для определения ошибочных инструкций). Если HDE64C считает 126 | команду ошибочной, он устанавливает флаг "F_ERROR" в поле флагов: 127 | 128 | #define F_ERROR 0x00001000 // инструкция неправильная 129 | 130 | Кроме того, устанавливаются следущие флаги, которые немного проясняют причины 131 | установки флага ошибки: 132 | 133 | #define F_ERROR_OPCODE 0x00002000 // неправильный опкод 134 | #define F_ERROR_LENGTH 0x00004000 // длина инструкции больше 15 байт 135 | #define F_ERROR_LOCK 0x00008000 // префикс lock недопустим 136 | #define F_ERROR_OPERAND 0x00010000 // недопустимый операнд 137 | 138 | В случае флага "F_ERROR_OPCODE" под опкодом понимается не только байт, который 139 | записан в "hde64s.opcode(2)" но и его расширение за счет ModR/M.reg, всего 140 | ModR/M или префикса (для двухбайтовых опкодов), так что команды типа "c6 c8 00" 141 | будут верно определяться как ошибочные, т.к. опкод "c6 /1" ошибочный. 142 | 143 | Если движок установил флаг "F_ERROR_LENGTH", то в качестве длины команды он 144 | вернет 15, т.о. максимальное значение поля "hde64s.len" равно 15. 145 | 146 | Если движок определил команду как ошибочную, то дизассемблирование на этом 147 | не останавливается, а продолжается по общим правилам, просто ко всему прочему 148 | будет установлен флаг ошибки (F_ERROR) и причины ошибки (F_ERROR_*). 149 | 150 | 4. Контакты 151 | =========== 152 | 153 | Автор: Вячеслав Патьков 154 | E-mail: patkov-mail на mail.ru 155 | WWW: http://hde32.narod.ru/ 156 | 157 | Пожалуйста, пишите письма на русском или английском языке, в обычном текстовом 158 | виде, не надо мне слать красивые письма в HTML или (еще хуже) в DOC. 159 | 160 | P. S. 161 | 162 | Мне скучно с HDE64. Поэтому, скорее всего, эта версия последняя. И не исключено, 163 | что есть баги (но пока я ни одного сообщения о них не получал, и мои тесты движок 164 | прошёл). Если ВЫ хотите развивать HDE64 -- fork'айте на здоровье. 165 | -------------------------------------------------------------------------------- /hde64c/examples/example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../include/hde64.h" 3 | 4 | char fmt[] = "\n" 5 | " mov rax,0x1122334455667788\n\n" 6 | " length of command: 0x%02x\n" 7 | " immediate64: 0x%08x%08x\n"; 8 | 9 | unsigned char code[] = {0x48,0xb8,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11}; 10 | 11 | int main(void) 12 | { 13 | hde64s hs; 14 | 15 | unsigned int length = hde64_disasm(code,&hs); 16 | 17 | if (hs.flags & F_ERROR) 18 | printf("Invalid instruction !\n"); 19 | else 20 | printf(fmt,length,(uint32_t)(hs.imm.imm64 >> 32), 21 | (uint32_t)hs.imm.imm64); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /hde64c/include/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE64_H_ 11 | #define _HDE64_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_IMM64 0x00000020 30 | #define F_DISP8 0x00000040 31 | #define F_DISP16 0x00000080 32 | #define F_DISP32 0x00000100 33 | #define F_RELATIVE 0x00000200 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_REX 0x40000000 47 | #define F_PREFIX_ANY 0x7f000000 48 | 49 | #define PREFIX_SEGMENT_CS 0x2e 50 | #define PREFIX_SEGMENT_SS 0x36 51 | #define PREFIX_SEGMENT_DS 0x3e 52 | #define PREFIX_SEGMENT_ES 0x26 53 | #define PREFIX_SEGMENT_FS 0x64 54 | #define PREFIX_SEGMENT_GS 0x65 55 | #define PREFIX_LOCK 0xf0 56 | #define PREFIX_REPNZ 0xf2 57 | #define PREFIX_REPX 0xf3 58 | #define PREFIX_OPERAND_SIZE 0x66 59 | #define PREFIX_ADDRESS_SIZE 0x67 60 | 61 | #pragma pack(push,1) 62 | 63 | typedef struct { 64 | uint8_t len; 65 | uint8_t p_rep; 66 | uint8_t p_lock; 67 | uint8_t p_seg; 68 | uint8_t p_66; 69 | uint8_t p_67; 70 | uint8_t rex; 71 | uint8_t rex_w; 72 | uint8_t rex_r; 73 | uint8_t rex_x; 74 | uint8_t rex_b; 75 | uint8_t opcode; 76 | uint8_t opcode2; 77 | uint8_t modrm; 78 | uint8_t modrm_mod; 79 | uint8_t modrm_reg; 80 | uint8_t modrm_rm; 81 | uint8_t sib; 82 | uint8_t sib_scale; 83 | uint8_t sib_index; 84 | uint8_t sib_base; 85 | union { 86 | uint8_t imm8; 87 | uint16_t imm16; 88 | uint32_t imm32; 89 | uint64_t imm64; 90 | } imm; 91 | union { 92 | uint8_t disp8; 93 | uint16_t disp16; 94 | uint32_t disp32; 95 | } disp; 96 | uint32_t flags; 97 | } hde64s; 98 | 99 | #pragma pack(pop) 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | /* __cdecl */ 106 | unsigned int hde64_disasm(const void *code, hde64s *hs); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* _HDE64_H_ */ 113 | -------------------------------------------------------------------------------- /hde64c/src/hde64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "../include/hde64.h" 12 | #include "table64.h" 13 | 14 | unsigned int hde64_disasm(const void *code, hde64s *hs) 15 | { 16 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 17 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; 18 | uint8_t op64 = 0; 19 | 20 | memset(hs,0,sizeof(hde64s)); 21 | 22 | for (x = 16; x; x--) 23 | switch (c = *p++) { 24 | case 0xf3: 25 | hs->p_rep = c; 26 | pref |= PRE_F3; 27 | break; 28 | case 0xf2: 29 | hs->p_rep = c; 30 | pref |= PRE_F2; 31 | break; 32 | case 0xf0: 33 | hs->p_lock = c; 34 | pref |= PRE_LOCK; 35 | break; 36 | case 0x26: case 0x2e: case 0x36: 37 | case 0x3e: case 0x64: case 0x65: 38 | hs->p_seg = c; 39 | pref |= PRE_SEG; 40 | break; 41 | case 0x66: 42 | hs->p_66 = c; 43 | pref |= PRE_66; 44 | break; 45 | case 0x67: 46 | hs->p_67 = c; 47 | pref |= PRE_67; 48 | break; 49 | default: 50 | goto pref_done; 51 | } 52 | pref_done: 53 | 54 | hs->flags = (uint32_t)pref << 23; 55 | 56 | if (!pref) 57 | pref |= PRE_NONE; 58 | 59 | if ((c & 0xf0) == 0x40) { 60 | hs->flags |= F_PREFIX_REX; 61 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) 62 | op64++; 63 | hs->rex_r = (c & 7) >> 2; 64 | hs->rex_x = (c & 3) >> 1; 65 | hs->rex_b = c & 1; 66 | if (((c = *p++) & 0xf0) == 0x40) { 67 | opcode = c; 68 | goto error_opcode; 69 | } 70 | } 71 | 72 | if ((hs->opcode = c) == 0x0f) { 73 | hs->opcode2 = c = *p++; 74 | ht += DELTA_OPCODES; 75 | } else if (c >= 0xa0 && c <= 0xa3) { 76 | op64++; 77 | if (pref & PRE_67) 78 | pref |= PRE_66; 79 | else 80 | pref &= ~PRE_66; 81 | } 82 | 83 | opcode = c; 84 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 85 | 86 | if (cflags == C_ERROR) { 87 | error_opcode: 88 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 89 | cflags = 0; 90 | if ((opcode & -3) == 0x24) 91 | cflags++; 92 | } 93 | 94 | x = 0; 95 | if (cflags & C_GROUP) { 96 | uint16_t t; 97 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 98 | cflags = (uint8_t)t; 99 | x = (uint8_t)(t >> 8); 100 | } 101 | 102 | if (hs->opcode2) { 103 | ht = hde64_table + DELTA_PREFIXES; 104 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 105 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 106 | } 107 | 108 | if (cflags & C_MODRM) { 109 | hs->flags |= F_MODRM; 110 | hs->modrm = c = *p++; 111 | hs->modrm_mod = m_mod = c >> 6; 112 | hs->modrm_rm = m_rm = c & 7; 113 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 114 | 115 | if (x && ((x << m_reg) & 0x80)) 116 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 117 | 118 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 119 | uint8_t t = opcode - 0xd9; 120 | if (m_mod == 3) { 121 | ht = hde64_table + DELTA_FPU_MODRM + t*8; 122 | t = ht[m_reg] << m_rm; 123 | } else { 124 | ht = hde64_table + DELTA_FPU_REG; 125 | t = ht[t] << m_reg; 126 | } 127 | if (t & 0x80) 128 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 129 | } 130 | 131 | if (pref & PRE_LOCK) { 132 | if (m_mod == 3) { 133 | hs->flags |= F_ERROR | F_ERROR_LOCK; 134 | } else { 135 | uint8_t *table_end, op = opcode; 136 | if (hs->opcode2) { 137 | ht = hde64_table + DELTA_OP2_LOCK_OK; 138 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 139 | } else { 140 | ht = hde64_table + DELTA_OP_LOCK_OK; 141 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 142 | op &= -2; 143 | } 144 | for (; ht != table_end; ht++) 145 | if (*ht++ == op) { 146 | if (!((*ht << m_reg) & 0x80)) 147 | goto no_lock_error; 148 | else 149 | break; 150 | } 151 | hs->flags |= F_ERROR | F_ERROR_LOCK; 152 | no_lock_error: 153 | ; 154 | } 155 | } 156 | 157 | if (hs->opcode2) { 158 | switch (opcode) { 159 | case 0x20: case 0x22: 160 | m_mod = 3; 161 | if (m_reg > 4 || m_reg == 1) 162 | goto error_operand; 163 | else 164 | goto no_error_operand; 165 | case 0x21: case 0x23: 166 | m_mod = 3; 167 | if (m_reg == 4 || m_reg == 5) 168 | goto error_operand; 169 | else 170 | goto no_error_operand; 171 | } 172 | } else { 173 | switch (opcode) { 174 | case 0x8c: 175 | if (m_reg > 5) 176 | goto error_operand; 177 | else 178 | goto no_error_operand; 179 | case 0x8e: 180 | if (m_reg == 1 || m_reg > 5) 181 | goto error_operand; 182 | else 183 | goto no_error_operand; 184 | } 185 | } 186 | 187 | if (m_mod == 3) { 188 | uint8_t *table_end; 189 | if (hs->opcode2) { 190 | ht = hde64_table + DELTA_OP2_ONLY_MEM; 191 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; 192 | } else { 193 | ht = hde64_table + DELTA_OP_ONLY_MEM; 194 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 195 | } 196 | for (; ht != table_end; ht += 2) 197 | if (*ht++ == opcode) { 198 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 199 | goto error_operand; 200 | else 201 | break; 202 | } 203 | goto no_error_operand; 204 | } else if (hs->opcode2) { 205 | switch (opcode) { 206 | case 0x50: case 0xd7: case 0xf7: 207 | if (pref & (PRE_NONE | PRE_66)) 208 | goto error_operand; 209 | break; 210 | case 0xd6: 211 | if (pref & (PRE_F2 | PRE_F3)) 212 | goto error_operand; 213 | break; 214 | case 0xc5: 215 | goto error_operand; 216 | } 217 | goto no_error_operand; 218 | } else 219 | goto no_error_operand; 220 | 221 | error_operand: 222 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 223 | no_error_operand: 224 | 225 | c = *p++; 226 | if (m_reg <= 1) { 227 | if (opcode == 0xf6) 228 | cflags |= C_IMM8; 229 | else if (opcode == 0xf7) 230 | cflags |= C_IMM_P66; 231 | } 232 | 233 | switch (m_mod) { 234 | case 0: 235 | if (pref & PRE_67) { 236 | if (m_rm == 6) 237 | disp_size = 2; 238 | } else 239 | if (m_rm == 5) 240 | disp_size = 4; 241 | break; 242 | case 1: 243 | disp_size = 1; 244 | break; 245 | case 2: 246 | disp_size = 2; 247 | if (!(pref & PRE_67)) 248 | disp_size <<= 1; 249 | } 250 | 251 | if (m_mod != 3 && m_rm == 4) { 252 | hs->flags |= F_SIB; 253 | p++; 254 | hs->sib = c; 255 | hs->sib_scale = c >> 6; 256 | hs->sib_index = (c & 0x3f) >> 3; 257 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 258 | disp_size = 4; 259 | } 260 | 261 | p--; 262 | switch (disp_size) { 263 | case 1: 264 | hs->flags |= F_DISP8; 265 | hs->disp.disp8 = *p; 266 | break; 267 | case 2: 268 | hs->flags |= F_DISP16; 269 | hs->disp.disp16 = *(uint16_t *)p; 270 | break; 271 | case 4: 272 | hs->flags |= F_DISP32; 273 | hs->disp.disp32 = *(uint32_t *)p; 274 | } 275 | p += disp_size; 276 | } else if (pref & PRE_LOCK) 277 | hs->flags |= F_ERROR | F_ERROR_LOCK; 278 | 279 | if (cflags & C_IMM_P66) { 280 | if (cflags & C_REL32) { 281 | if (pref & PRE_66) { 282 | hs->flags |= F_IMM16 | F_RELATIVE; 283 | hs->imm.imm16 = *(uint16_t *)p; 284 | p += 2; 285 | goto disasm_done; 286 | } 287 | goto rel32_ok; 288 | } 289 | if (op64) { 290 | hs->flags |= F_IMM64; 291 | hs->imm.imm64 = *(uint64_t *)p; 292 | p += 8; 293 | } else if (!(pref & PRE_66)) { 294 | hs->flags |= F_IMM32; 295 | hs->imm.imm32 = *(uint32_t *)p; 296 | p += 4; 297 | } else 298 | goto imm16_ok; 299 | } 300 | 301 | 302 | if (cflags & C_IMM16) { 303 | imm16_ok: 304 | hs->flags |= F_IMM16; 305 | hs->imm.imm16 = *(uint16_t *)p; 306 | p += 2; 307 | } 308 | if (cflags & C_IMM8) { 309 | hs->flags |= F_IMM8; 310 | hs->imm.imm8 = *p++; 311 | } 312 | 313 | if (cflags & C_REL32) { 314 | rel32_ok: 315 | hs->flags |= F_IMM32 | F_RELATIVE; 316 | hs->imm.imm32 = *(uint32_t *)p; 317 | p += 4; 318 | } else if (cflags & C_REL8) { 319 | hs->flags |= F_IMM8 | F_RELATIVE; 320 | hs->imm.imm8 = *p++; 321 | } 322 | 323 | disasm_done: 324 | 325 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 326 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 327 | hs->len = 15; 328 | } 329 | 330 | return (unsigned int)hs->len; 331 | } 332 | -------------------------------------------------------------------------------- /hde64c/src/table64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xfd 30 | #define DELTA_FPU_MODRM 0x104 31 | #define DELTA_PREFIXES 0x13c 32 | #define DELTA_OP_LOCK_OK 0x1ae 33 | #define DELTA_OP2_LOCK_OK 0x1c6 34 | #define DELTA_OP_ONLY_MEM 0x1d8 35 | #define DELTA_OP2_ONLY_MEM 0x1e7 36 | 37 | unsigned char hde64_table[] = { 38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 73 | 0x00,0xf0,0x02,0x00 74 | }; 75 | -------------------------------------------------------------------------------- /include/System/machine/cpu_capabilities.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_OSREFERENCE_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. The rights granted to you under the License 10 | * may not be used to create, or enable the creation or redistribution of, 11 | * unlawful or unlicensed copies of an Apple operating system, or to 12 | * circumvent, violate, or enable the circumvention or violation of, any 13 | * terms of an Apple operating system software license agreement. 14 | * 15 | * Please obtain a copy of the License at 16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 | * 18 | * The Original Code and all software distributed under the License are 19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 | * Please see the License for the specific language governing rights and 24 | * limitations under the License. 25 | * 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 | */ 28 | #ifdef PRIVATE 29 | 30 | #ifndef _MACHINE_CPU_CAPABILITIES_H 31 | #define _MACHINE_CPU_CAPABILITIES_H 32 | 33 | #ifdef KERNEL_PRIVATE 34 | #if defined (__ppc__) 35 | #include "ppc/cpu_capabilities.h" 36 | #elif defined (__i386__) 37 | #include "i386/cpu_capabilities.h" 38 | #else 39 | #error architecture not supported 40 | #endif 41 | 42 | #else /* !KERNEL_PRIVATE -- System Framework header */ 43 | #if defined (__ppc__) || defined(__ppc64__) 44 | #include 45 | #elif defined (__i386__) || defined(__x86_64__) 46 | #include 47 | #else 48 | #error architecture not supported 49 | #endif 50 | #endif /* KERNEL_PRIVATE */ 51 | 52 | #endif /* _MACHINE_CPU_CAPABILITIES_H */ 53 | #endif /* PRIVATE */ 54 | -------------------------------------------------------------------------------- /include/machine/cpu_capabilities.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_OSREFERENCE_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. The rights granted to you under the License 10 | * may not be used to create, or enable the creation or redistribution of, 11 | * unlawful or unlicensed copies of an Apple operating system, or to 12 | * circumvent, violate, or enable the circumvention or violation of, any 13 | * terms of an Apple operating system software license agreement. 14 | * 15 | * Please obtain a copy of the License at 16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 | * 18 | * The Original Code and all software distributed under the License are 19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 | * Please see the License for the specific language governing rights and 24 | * limitations under the License. 25 | * 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 | */ 28 | #ifdef PRIVATE 29 | 30 | #ifndef _MACHINE_CPU_CAPABILITIES_H 31 | #define _MACHINE_CPU_CAPABILITIES_H 32 | 33 | #ifdef KERNEL_PRIVATE 34 | #if defined (__ppc__) 35 | #include "ppc/cpu_capabilities.h" 36 | #elif defined (__i386__) 37 | #include "i386/cpu_capabilities.h" 38 | #else 39 | #error architecture not supported 40 | #endif 41 | 42 | #else /* !KERNEL_PRIVATE -- System Framework header */ 43 | #if defined (__ppc__) || defined(__ppc64__) 44 | #include 45 | #elif defined (__i386__) || defined(__x86_64__) 46 | #include 47 | #else 48 | #error architecture not supported 49 | #endif 50 | #endif /* KERNEL_PRIVATE */ 51 | 52 | #endif /* _MACHINE_CPU_CAPABILITIES_H */ 53 | #endif /* PRIVATE */ 54 | -------------------------------------------------------------------------------- /include/posix_sched.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2003 Apple Computer, 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 | /* 24 | * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 25 | * All Rights Reserved 26 | * 27 | * Permission to use, copy, modify, and distribute this software and 28 | * its documentation for any purpose and without fee is hereby granted, 29 | * provided that the above copyright notice appears in all copies and 30 | * that both the copyright notice and this permission notice appear in 31 | * supporting documentation. 32 | * 33 | * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 34 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 35 | * FOR A PARTICULAR PURPOSE. 36 | * 37 | * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 38 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 39 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 40 | * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 41 | * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 | * 43 | */ 44 | /* 45 | * MkLinux 46 | */ 47 | 48 | /* 49 | * POSIX Realtime Scheduling Framework - IEEE 1003.1b 50 | */ 51 | 52 | #ifndef _POSIX_SCHED_H 53 | #define _POSIX_SCHED_H 54 | 55 | struct sched_param 56 | { 57 | int sched_priority; 58 | int quantum; 59 | }; 60 | 61 | /* 62 | * POSIX scheduling policies 63 | */ 64 | 65 | #define SCHED_OTHER POLICY_TIMESHARE 66 | #define SCHED_FIFO POLICY_FIFO 67 | #define SCHED_RR POLICY_RR 68 | 69 | #endif /* _POSIX_SCHED_H */ 70 | -------------------------------------------------------------------------------- /include/pthread_machdep.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003-2004, 2008 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 | /* 24 | * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 25 | * All Rights Reserved 26 | * 27 | * Permission to use, copy, modify, and distribute this software and 28 | * its documentation for any purpose and without fee is hereby granted, 29 | * provided that the above copyright notice appears in all copies and 30 | * that both the copyright notice and this permission notice appear in 31 | * supporting documentation. 32 | * 33 | * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 34 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 35 | * FOR A PARTICULAR PURPOSE. 36 | * 37 | * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 38 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 39 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 40 | * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 41 | * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 | */ 43 | /* 44 | * MkLinux 45 | */ 46 | 47 | /* Machine-dependent definitions for pthread internals. */ 48 | 49 | #ifndef _POSIX_PTHREAD_MACHDEP_H 50 | #define _POSIX_PTHREAD_MACHDEP_H 51 | 52 | #ifndef __ASSEMBLER__ 53 | 54 | #include 55 | #ifdef __arm__ 56 | #include 57 | #endif 58 | #include 59 | 60 | /* 61 | ** Define macros for inline pthread_getspecific() usage. 62 | ** We reserve a number of slots for Apple internal use. 63 | ** This number can grow dynamically, no need to fix it. 64 | */ 65 | 66 | /* This header contains pre defined thread specific keys */ 67 | /* 0 is used for pthread_self */ 68 | #define _PTHREAD_TSD_SLOT_PTHREAD_SELF 0 69 | /* Keys 1- 9 for use by dyld, directly or indirectly */ 70 | #define _PTHREAD_TSD_SLOT_DYLD_1 1 71 | #define _PTHREAD_TSD_SLOT_DYLD_2 2 72 | #define _PTHREAD_TSD_SLOT_DYLD_3 3 73 | #define _PTHREAD_TSD_RESERVED_SLOT_COUNT 4 74 | /* To mirror the usage by dyld for Unwind_SjLj */ 75 | #define _PTHREAD_TSD_SLOT_DYLD_8 8 76 | 77 | /* Keys 10 - 29 are for Libc/Libsystem internal ussage */ 78 | /* used as __pthread_tsd_first + Num */ 79 | #define __PTK_LIBC_LOCALE_KEY 10 80 | #define __PTK_LIBC_TTYNAME_KEY 11 81 | #define __PTK_LIBC_LOCALTIME_KEY 12 82 | #define __PTK_LIBC_GMTIME_KEY 13 83 | #define __PTK_LIBC_GDTOA_BIGINT_KEY 14 84 | #define __PTK_LIBC_PARSEFLOAT_KEY 15 85 | /* for usage by dyld */ 86 | #define __PTK_LIBC_DYLD_Unwind_SjLj_Key 18 87 | 88 | /* Keys 20-25 for libdispactch usage */ 89 | #define __PTK_LIBDISPATCH_KEY0 20 90 | #define __PTK_LIBDISPATCH_KEY1 21 91 | #define __PTK_LIBDISPATCH_KEY2 22 92 | #define __PTK_LIBDISPATCH_KEY3 23 93 | #define __PTK_LIBDISPATCH_KEY4 24 94 | #define __PTK_LIBDISPATCH_KEY5 25 95 | 96 | /* Keys 30-255 for Non Libsystem usage */ 97 | 98 | /* Keys 30-39 for Graphic frameworks usage */ 99 | #define _PTHREAD_TSD_SLOT_OPENGL 30 /* backwards compat sake */ 100 | #define __PTK_FRAMEWORK_OPENGL_KEY 30 101 | #define __PTK_FRAMEWORK_GRAPHICS_KEY1 31 102 | #define __PTK_FRAMEWORK_GRAPHICS_KEY2 32 103 | #define __PTK_FRAMEWORK_GRAPHICS_KEY3 33 104 | #define __PTK_FRAMEWORK_GRAPHICS_KEY4 34 105 | #define __PTK_FRAMEWORK_GRAPHICS_KEY5 35 106 | #define __PTK_FRAMEWORK_GRAPHICS_KEY6 36 107 | #define __PTK_FRAMEWORK_GRAPHICS_KEY7 37 108 | #define __PTK_FRAMEWORK_GRAPHICS_KEY8 38 109 | #define __PTK_FRAMEWORK_GRAPHICS_KEY9 39 110 | 111 | /* Keys 40-49 for Objective-C runtime usage */ 112 | #define __PTK_FRAMEWORK_OBJC_KEY0 40 113 | #define __PTK_FRAMEWORK_OBJC_KEY1 41 114 | #define __PTK_FRAMEWORK_OBJC_KEY2 42 115 | #define __PTK_FRAMEWORK_OBJC_KEY3 43 116 | #define __PTK_FRAMEWORK_OBJC_KEY4 44 117 | #define __PTK_FRAMEWORK_OBJC_KEY5 45 118 | #define __PTK_FRAMEWORK_OBJC_KEY6 46 119 | #define __PTK_FRAMEWORK_OBJC_KEY7 47 120 | #define __PTK_FRAMEWORK_OBJC_KEY8 48 121 | #define __PTK_FRAMEWORK_OBJC_KEY9 49 122 | 123 | /* Keys 50-59 for Core Foundation usage */ 124 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY0 50 125 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY1 51 126 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY2 52 127 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY3 53 128 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY4 54 129 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY5 55 130 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY6 56 131 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY7 57 132 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY8 58 133 | #define __PTK_FRAMEWORK_COREFOUNDATION_KEY9 59 134 | 135 | /* Keys 60-69 for Foundation usage */ 136 | #define __PTK_FRAMEWORK_FOUNDATION_KEY0 60 137 | #define __PTK_FRAMEWORK_FOUNDATION_KEY1 61 138 | #define __PTK_FRAMEWORK_FOUNDATION_KEY2 62 139 | #define __PTK_FRAMEWORK_FOUNDATION_KEY3 63 140 | #define __PTK_FRAMEWORK_FOUNDATION_KEY4 64 141 | #define __PTK_FRAMEWORK_FOUNDATION_KEY5 65 142 | #define __PTK_FRAMEWORK_FOUNDATION_KEY6 66 143 | #define __PTK_FRAMEWORK_FOUNDATION_KEY7 67 144 | #define __PTK_FRAMEWORK_FOUNDATION_KEY8 68 145 | #define __PTK_FRAMEWORK_FOUNDATION_KEY9 69 146 | 147 | /* Keys 70-79 for Core Animation/QuartzCore usage */ 148 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY0 70 149 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY1 71 150 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY2 72 151 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY3 73 152 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY4 74 153 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY5 75 154 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY6 76 155 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY7 77 156 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY8 78 157 | #define __PTK_FRAMEWORK_QUARTZCORE_KEY9 79 158 | 159 | 160 | /* Keys 80-89 for Garbage Collection */ 161 | #define __PTK_FRAMEWORK_OLDGC_KEY0 80 162 | #define __PTK_FRAMEWORK_OLDGC_KEY1 81 163 | #define __PTK_FRAMEWORK_OLDGC_KEY2 82 164 | #define __PTK_FRAMEWORK_OLDGC_KEY3 83 165 | #define __PTK_FRAMEWORK_OLDGC_KEY4 84 166 | #define __PTK_FRAMEWORK_OLDGC_KEY5 85 167 | #define __PTK_FRAMEWORK_OLDGC_KEY6 86 168 | #define __PTK_FRAMEWORK_OLDGC_KEY7 87 169 | #define __PTK_FRAMEWORK_OLDGC_KEY8 88 170 | #define __PTK_FRAMEWORK_OLDGC_KEY9 89 171 | 172 | /* Keys 90-94 for JavaScriptCore Collection */ 173 | #define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0 90 174 | #define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1 91 175 | #define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY2 92 176 | #define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY3 93 177 | #define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 94 178 | 179 | /* Keys 110-119 for Garbage Collection */ 180 | #define __PTK_FRAMEWORK_GC_KEY0 110 181 | #define __PTK_FRAMEWORK_GC_KEY1 111 182 | #define __PTK_FRAMEWORK_GC_KEY2 112 183 | #define __PTK_FRAMEWORK_GC_KEY3 113 184 | #define __PTK_FRAMEWORK_GC_KEY4 114 185 | #define __PTK_FRAMEWORK_GC_KEY5 115 186 | #define __PTK_FRAMEWORK_GC_KEY6 116 187 | #define __PTK_FRAMEWORK_GC_KEY7 117 188 | #define __PTK_FRAMEWORK_GC_KEY8 118 189 | #define __PTK_FRAMEWORK_GC_KEY9 119 190 | 191 | /* 192 | ** Define macros for inline pthread_getspecific() usage. 193 | ** We reserve a number of slots for Apple internal use. 194 | ** This number can grow dynamically, no need to fix it. 195 | */ 196 | 197 | 198 | #if defined(__cplusplus) 199 | extern "C" { 200 | #endif 201 | 202 | extern void *pthread_getspecific(unsigned long); 203 | /* setup destructor function for static key as it is not created with pthread_key_create() */ 204 | int pthread_key_init_np(int, void (*)(void *)); 205 | 206 | #if defined(__cplusplus) 207 | } 208 | #endif 209 | 210 | typedef int pthread_lock_t; 211 | 212 | #if TARGET_IPHONE_SIMULATOR 213 | 214 | /* Similator will use the host implementation, so bypass the macro that is in the target code */ 215 | 216 | inline static int 217 | _pthread_has_direct_tsd(void) 218 | { 219 | return 0; 220 | } 221 | 222 | #define _pthread_getspecific_direct(key) pthread_getspecific(key) 223 | #define _pthread_setspecific_direct(key, val) pthread_setspecific(key, val) 224 | 225 | #else /* TARGET_IPHONE_SIMULATOR */ 226 | 227 | inline static int 228 | _pthread_has_direct_tsd(void) 229 | { 230 | #if defined(__ppc__) 231 | int *caps = (int *)_COMM_PAGE_CPU_CAPABILITIES; 232 | if (*caps & kFastThreadLocalStorage) { 233 | return 1; 234 | } else { 235 | return 0; 236 | } 237 | #else 238 | return 1; 239 | #endif 240 | } 241 | 242 | /* To be used with static constant keys only */ 243 | inline static void * 244 | _pthread_getspecific_direct(unsigned long slot) 245 | { 246 | void *ret; 247 | 248 | #if defined(__i386__) || defined(__x86_64__) 249 | asm("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *)))); 250 | #elif defined(__ppc64__) || defined(__ppc__) 251 | ret = pthread_getspecific(slot); 252 | #elif defined(__arm__) && defined(_ARM_ARCH_6) && !defined(_ARM_ARCH_7) && defined(__thumb__) && !defined(__OPTIMIZE__) 253 | ret = pthread_getspecific(slot); 254 | #elif defined(__arm__) && defined(_ARM_ARCH_6) 255 | void **__pthread_tsd; 256 | __asm__ ( 257 | "mrc p15, 0, %0, c13, c0, 3\n" 258 | "bic %0, %0, #3\n" 259 | : "=r"(__pthread_tsd)); 260 | ret = __pthread_tsd[slot]; 261 | #elif defined(__arm__) && !defined(_ARM_ARCH_6) 262 | register void **__pthread_tsd asm ("r9"); 263 | ret = __pthread_tsd[slot]; 264 | #else 265 | #error no pthread_getspecific_direct implementation for this arch 266 | #endif 267 | return ret; 268 | } 269 | 270 | #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) 271 | /* To be used with static constant keys only */ 272 | inline static int 273 | _pthread_setspecific_direct(unsigned long slot, void * val) 274 | { 275 | 276 | #if defined(__i386__) 277 | #if defined(__PIC__) 278 | asm("movl %1,%%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "rn" (val)); 279 | #else 280 | asm("movl %1,%%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "ri" (val)); 281 | #endif 282 | #elif defined(__x86_64__) 283 | /* PIC is free and cannot be disabled, even with: gcc -mdynamic-no-pic ... */ 284 | asm("movq %1,%%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "rn" (val)); 285 | #elif defined(__arm__) && defined(_ARM_ARCH_6) 286 | void **__pthread_tsd; 287 | __asm__ ( 288 | "mrc p15, 0, %0, c13, c0, 3\n" 289 | "bic %0, %0, #3\n" 290 | : "=r"(__pthread_tsd)); 291 | __pthread_tsd[slot] = val; 292 | #elif defined(__arm__) && !defined(_ARM_ARCH_6) 293 | register void **__pthread_tsd asm ("r9"); 294 | __pthread_tsd[slot] = val; 295 | #endif 296 | return(0); 297 | } 298 | #elif defined(__ppc__) || defined(__ppc64__) 299 | /* To be used with static constant keys only */ 300 | #define _pthread_setspecific_direct(key, val) pthread_setspecific(key, val) 301 | #else 302 | #error no pthread_setspecific_direct implementation for this arch 303 | #endif 304 | 305 | #endif /* TARGET_IPHONE_SIMULATOR */ 306 | 307 | #define LOCK_INIT(l) ((l) = 0) 308 | #define LOCK_INITIALIZER 0 309 | 310 | #endif /* ! __ASSEMBLER__ */ 311 | #endif /* _POSIX_PTHREAD_MACHDEP_H */ 312 | -------------------------------------------------------------------------------- /include/pthread_spinlock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Apple Computer, 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 | /* 24 | * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 25 | * All Rights Reserved 26 | * 27 | * Permission to use, copy, modify, and distribute this software and 28 | * its documentation for any purpose and without fee is hereby granted, 29 | * provided that the above copyright notice appears in all copies and 30 | * that both the copyright notice and this permission notice appear in 31 | * supporting documentation. 32 | * 33 | * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 34 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 35 | * FOR A PARTICULAR PURPOSE. 36 | * 37 | * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 38 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 39 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 40 | * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 41 | * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 | * 43 | */ 44 | /* 45 | * MkLinux 46 | */ 47 | 48 | /* 49 | * POSIX Threads - IEEE 1003.1c 50 | */ 51 | 52 | #ifndef _POSIX_PTHREAD_SPINLOCK_H 53 | #define _POSIX_PTHREAD_SPINLOCK_H 54 | 55 | #include 56 | #define __APPLE_API_PRIVATE 57 | #include 58 | 59 | #ifndef __POSIX_LIB__ 60 | #define __POSIX_LIB__ 61 | #endif 62 | 63 | #include "pthread_machdep.h" /* Machine-dependent definitions. */ 64 | 65 | /* Number of times to spin when the lock is unavailable and we are on a 66 | multiprocessor. On a uniprocessor we yield the processor immediately. */ 67 | #define MP_SPIN_TRIES 1000 68 | extern int _spin_tries; 69 | extern int __is_threaded; 70 | 71 | /* Internal mutex locks for data structures */ 72 | #define TRY_LOCK(v) (!__is_threaded || _spin_lock_try((pthread_lock_t *)&(v))) 73 | 74 | /* _DO_SPINLOCK_LOCK() takes a (pthread_lock_t *) */ 75 | #define _DO_SPINLOCK_LOCK(v) _spin_lock(v) 76 | 77 | /* _DO_SPINLOCK_UNLOCK() takes a (pthread_lock_t *) */ 78 | #define _DO_SPINLOCK_UNLOCK(v) _spin_unlock(v) 79 | 80 | /* LOCK() takes a (pthread_lock_t) */ 81 | #define LOCK(v) \ 82 | do { \ 83 | if (__is_threaded) { \ 84 | _DO_SPINLOCK_LOCK((pthread_lock_t *)&(v)); \ 85 | } \ 86 | } while (0) 87 | 88 | /* UNLOCK() takes a (pthread_lock_t) */ 89 | #define UNLOCK(v) \ 90 | do { \ 91 | if (__is_threaded) { \ 92 | _DO_SPINLOCK_UNLOCK((pthread_lock_t *)&(v)); \ 93 | } \ 94 | } while (0) 95 | 96 | /* Prototypes. */ 97 | 98 | /* Functions defined in machine-dependent files. */ 99 | extern void _spin_lock(pthread_lock_t *lockp); 100 | extern int _spin_lock_try(pthread_lock_t *lockp); 101 | extern void _spin_unlock(pthread_lock_t *lockp); 102 | 103 | #endif /* _POSIX_PTHREAD_SPINLOCK_H */ 104 | -------------------------------------------------------------------------------- /include/pthread_spis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2011 Apple Computer, 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 | /* 24 | * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 25 | * All Rights Reserved 26 | * 27 | * Permission to use, copy, modify, and distribute this software and 28 | * its documentation for any purpose and without fee is hereby granted, 29 | * provided that the above copyright notice appears in all copies and 30 | * that both the copyright notice and this permission notice appear in 31 | * supporting documentation. 32 | * 33 | * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 34 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 35 | * FOR A PARTICULAR PURPOSE. 36 | * 37 | * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 38 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 39 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 40 | * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 41 | * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 | * 43 | */ 44 | /* 45 | * MkLinux 46 | */ 47 | 48 | /* 49 | * Extension SPIs. 50 | */ 51 | 52 | #ifndef _PTHREAD_SPIS_H 53 | #define _PTHREAD_SPIS_H 54 | 55 | 56 | #include 57 | 58 | __BEGIN_DECLS 59 | 60 | #if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) 61 | /* firstfit */ 62 | #define PTHREAD_FIRSTFIT_MUTEX_INITIALIZER {_PTHREAD_FIRSTFIT_MUTEX_SIG_init, {0}} 63 | /* 64 | * Mutex attributes 65 | */ 66 | #define _PTHREAD_MUTEX_POLICY_NONE 0 67 | #define _PTHREAD_MUTEX_POLICY_FAIRSHARE 1 68 | #define _PTHREAD_MUTEX_POLICY_FIRSTFIT 2 69 | 70 | /* sets the mutex policy attributes */ 71 | int pthread_mutexattr_setpolicy_np(pthread_mutexattr_t *, int ); 72 | 73 | #endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE */ 74 | 75 | __END_DECLS 76 | 77 | #endif /* _PTHREAD_SPIS_H */ 78 | -------------------------------------------------------------------------------- /ldid.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Cydia Substrate - Powerful Code Insertion Platform 4 | # Copyright (C) 2008-2011 Jay Freeman (saurik) 5 | 6 | # GNU Lesser General Public License, Version 3 {{{ 7 | # 8 | # Substrate is free software: you can redistribute it and/or modify it under 9 | # the terms of the GNU Lesser General Public License as published by the 10 | # Free Software Foundation, either version 3 of the License, or (at your 11 | # option) any later version. 12 | # 13 | # Substrate is distributed in the hope that it will be useful, but WITHOUT 14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 | # License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with Substrate. If not, see . 20 | # }}} 21 | 22 | set -e 23 | 24 | file=$1 25 | shift 1 26 | 27 | archs=($(lipo -detailed_info "${file}" | grep '^architecture ' | cut -d ' ' -f 2)) 28 | 29 | if [[ ${#archs[@]} == 0 ]]; then 30 | ldid -S "${file}" 31 | else 32 | files=() 33 | 34 | for arch in "${archs[@]}"; do 35 | lipo -extract "${arch}" "${file}" -output "${file}.${arch}" 36 | if [[ ${arch} == arm* ]]; then ldid -S "${file}.${arch}"; fi 37 | files[${#files[@]}]=${file}.${arch} 38 | done 39 | 40 | lipo -create "${files[@]}" -output "${file}" 41 | rm -f "${files[@]}" 42 | fi 43 | -------------------------------------------------------------------------------- /package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Cydia Substrate - Powerful Code Insertion Platform 4 | # Copyright (C) 2008-2011 Jay Freeman (saurik) 5 | 6 | # GNU Lesser General Public License, Version 3 {{{ 7 | # 8 | # Substrate is free software: you can redistribute it and/or modify it under 9 | # the terms of the GNU Lesser General Public License as published by the 10 | # Free Software Foundation, either version 3 of the License, or (at your 11 | # option) any later version. 12 | # 13 | # Substrate is distributed in the hope that it will be useful, but WITHOUT 14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 | # License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with Substrate. If not, see . 20 | # }}} 21 | 22 | set -e 23 | 24 | arch=$1 25 | shift 1 26 | 27 | pkg=package.${arch} 28 | sudo rm -rf "${pkg}" 29 | 30 | mkdir -p "${pkg}"/DEBIAN 31 | control=${pkg}/DEBIAN/control 32 | cat control."${arch}" >"${control}" 33 | ./control.sh >>"${control}" 34 | 35 | lib=/Library/MobileSubstrate 36 | mkdir -p "${pkg}/${lib}/DynamicLibraries" 37 | 38 | fwk=/Library/Frameworks/CydiaSubstrate.framework 39 | 40 | if [[ ${arch} == arm ]]; then 41 | rsc=${fwk} 42 | else 43 | rsc=${fwk}/Resources 44 | fi 45 | 46 | mkdir -p "${pkg}/${rsc}" 47 | 48 | for sub in Commands Headers Libraries; do 49 | mkdir -p "${pkg}/${fwk}/${sub}" 50 | done 51 | 52 | cp -a Info.plist "${pkg}/${rsc}/Info.plist" 53 | cp -a CydiaSubstrate.h "${pkg}/${fwk}/Headers" 54 | 55 | cp -a SubstrateBootstrap.dylib "${pkg}/${fwk}/Libraries" 56 | cp -a SubstrateLauncher.dylib "${pkg}/${fwk}/Libraries" 57 | cp -a SubstrateLoader.dylib "${pkg}/${fwk}/Libraries" 58 | 59 | cp -a libsubstrate.dylib "${pkg}/${fwk}/CydiaSubstrate" 60 | 61 | mkdir -p "${pkg}/usr/lib" 62 | ln -s libsubstrate.0.dylib "${pkg}/usr/lib/libsubstrate.dylib" 63 | ln -s "${fwk}/CydiaSubstrate" "${pkg}/usr/lib/libsubstrate.0.dylib" 64 | 65 | mkdir -p "${pkg}/usr/include" 66 | ln -s "${fwk}/Headers/CydiaSubstrate.h" "${pkg}/usr/include/substrate.h" 67 | 68 | mkdir -p "${pkg}/usr/bin" 69 | 70 | for cmd in cycc cynject; do 71 | ln -s "${fwk}/Commands/${cmd}" "${pkg}/usr/bin" 72 | cp -a "${cmd}" "${pkg}/${fwk}/Commands" 73 | done 74 | 75 | cp -a extrainst_ postrm "${pkg}/DEBIAN" 76 | 77 | if [[ ${arch} == arm ]]; then 78 | ln -s "${fwk}"/Libraries/SubstrateInjection.dylib "${pkg}/${lib}/MobileSubstrate.dylib" 79 | 80 | ln -s SubstrateBootstrap.dylib "${pkg}/${fwk}/Libraries/SubstrateInjection.dylib" 81 | else 82 | ln -s SubstrateLoader.dylib "${pkg}/${fwk}/Libraries/SubstrateInjection.dylib" 83 | fi 84 | 85 | function field() { 86 | grep ^"$1": "${control}" | cut -d ' ' -f 2 87 | } 88 | 89 | sudo chown -R root:staff "${pkg}" 90 | 91 | sudo chgrp procmod "${pkg}/${fwk}/Commands/cynject" 92 | sudo chmod g+s "${pkg}/${fwk}/Commands/cynject" 93 | 94 | #(cd "${pkg}" && find . -type f -o -type l) 95 | deb=$(field Package)_$(field Version)_$(field Architecture).deb 96 | dpkg-deb -b "${pkg}" "${deb}" 97 | ln -sf "${deb}" "$(field Package)_$(field Architecture).deb" 98 | -------------------------------------------------------------------------------- /postrm.mm: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | #include "Cydia.hpp" 31 | #include "LaunchDaemons.hpp" 32 | 33 | int main(int argc, char *argv[]) { 34 | if (argc < 2 || ( 35 | strcmp(argv[1], "abort-install") != 0 && 36 | strcmp(argv[1], "remove") != 0 && 37 | true)) return 0; 38 | 39 | NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); 40 | 41 | NSFileManager *manager([NSFileManager defaultManager]); 42 | NSError *error; 43 | 44 | if (NSString *config = [NSString stringWithContentsOfFile:@ SubstrateLaunchConfig_ encoding:NSNonLossyASCIIStringEncoding error:&error]) { 45 | NSArray *lines([config componentsSeparatedByString:@"\n"]); 46 | NSMutableArray *copy([lines mutableCopy]); 47 | 48 | [copy removeObject:@""]; 49 | [copy removeObject:@ SubstrateBootstrapExecute_]; 50 | 51 | if ([copy count] == 0) 52 | [manager removeItemAtPath:@ SubstrateLaunchConfig_ error:&error]; 53 | else { 54 | [copy addObject:@""]; 55 | 56 | if (![copy isEqualToArray:lines]) 57 | [[copy componentsJoinedByString:@"\n"] writeToFile:@ SubstrateLaunchConfig_ atomically:YES encoding:NSNonLossyASCIIStringEncoding error:&error]; 58 | } 59 | } 60 | 61 | #ifdef __arm__ 62 | if (MSClearLaunchDaemons()) 63 | FinishCydia("reboot"); 64 | #endif 65 | 66 | [pool release]; 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /safe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CYCC_APT_VERSION=$(./version.sh) cycc -i2.0 -s -p MobileSafety.mm 3 | -------------------------------------------------------------------------------- /task_for_pid.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | com.apple.springboard.debugapplications 5 | 6 | get-task-allow 7 | 8 | task_for_pid-allow 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /trampoline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Cydia Substrate - Powerful Code Insertion Platform 4 | # Copyright (C) 2008-2011 Jay Freeman (saurik) 5 | 6 | # GNU Lesser General Public License, Version 3 {{{ 7 | # 8 | # Substrate is free software: you can redistribute it and/or modify it under 9 | # the terms of the GNU Lesser General Public License as published by the 10 | # Free Software Foundation, either version 3 of the License, or (at your 11 | # option) any later version. 12 | # 13 | # Substrate is distributed in the hope that it will be useful, but WITHOUT 14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 | # License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with Substrate. If not, see . 20 | # }}} 21 | 22 | set -e 23 | 24 | shopt -s extglob 25 | 26 | hpp=$1 27 | object=$2 28 | name=$3 29 | sed=$4 30 | otool=$5 31 | lipo=$6 32 | nm=$7 33 | shift 7 34 | 35 | #shift 1 36 | #set /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -I/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.3.sdk/usr/include "$@" 37 | 38 | "$@" 39 | 40 | detailed=$("${lipo}" -detailed_info "${object}") 41 | 42 | { 43 | 44 | echo '#include "Trampoline.hpp"' 45 | 46 | for arch in $(echo "${detailed}" | "${sed}" -e '/^architecture / { s/^architecture //; p; }; d;'); do 47 | offset=$(echo "${detailed}" | "${sed}" -e ' 48 | /^architecture / { x; s/.*/0/; x; }; 49 | /^architecture '${arch}'$/ { x; s/.*/1/; x; }; 50 | x; /^1$/ { x; /^ *offset / { s/^ *offset //; p; }; x; }; x; 51 | d; 52 | ') 53 | 54 | file=($("${otool}" -arch "${arch}" -l "${object}" | "${sed}" -e ' 55 | x; /^1$/ { x; 56 | /^ *fileoff / { s/^.* //; p; }; 57 | /^ *filesize / { s/^.* //; p; }; 58 | x; }; x; 59 | 60 | /^ *cmd LC_SEGMENT/ { x; s/.*/1/; x; }; 61 | 62 | d; 63 | ')) 64 | 65 | fileoff=${file[0]} 66 | filesize=${file[1]} 67 | 68 | echo 69 | echo "static const char ${name}_${arch}_data_[] = {" 70 | 71 | od -v -t x1 -t c -j "$((offset + fileoff))" -N "${filesize}" "${object}" | "${sed}" -e ' 72 | /^[0-7]/ ! { 73 | s@^ @// @; 74 | s/\(....\)/ \1/g; 75 | s@^ // @//@; 76 | s/ *$/,/; 77 | }; 78 | 79 | /^[0-7]/ { 80 | s/^[^ ]*//; 81 | s/ */ /g; 82 | s/^ *//; 83 | s/ $//; 84 | s/ /,/g; 85 | s/\([^,][^,]\)/0x\1/g; 86 | s/$/,/; 87 | /^,$/ ! { s/^/ /g; p; }; d; 88 | }; 89 | ' 90 | 91 | echo "};" 92 | 93 | echo 94 | entry=$("${nm}" -arch "${arch}" "${object}" | "${sed}" -e '/ _Start$/ { s/ .*//; p; }; d;') 95 | entry=${entry##*(0)} 96 | echo "static size_t ${name}_${arch}_entry_ = 0x${entry:=0};" 97 | 98 | echo 99 | echo "/*" 100 | "${otool}" -vVt -arch "${arch}" "${object}" 101 | echo "*/" 102 | 103 | echo 104 | echo "static Trampoline ${name}_${arch}_ = {" 105 | echo " ${name}_${arch}_data_," 106 | echo " sizeof(${name}_${arch}_data_)," 107 | echo " ${name}_${arch}_entry_," 108 | echo "};" 109 | done 110 | 111 | } >"${hpp}" 112 | 113 | #rm -f "${object}" 114 | -------------------------------------------------------------------------------- /version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git describe --tags --dirty="+" --match="v*" | sed -e 's@-\([^-]*\)-\([^-]*\)$@+\1.\2@;s@^v@@' 3 | -------------------------------------------------------------------------------- /x86.hpp: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_X86_HPP 23 | #define SUBSTRATE_X86_HPP 24 | 25 | #include "Buffer.hpp" 26 | 27 | #ifdef __LP64__ 28 | static const bool ia32 = false; 29 | #else 30 | static const bool ia32 = true; 31 | #endif 32 | 33 | enum I$r { 34 | I$rax, I$rcx, I$rdx, I$rbx, 35 | I$rsp, I$rbp, I$rsi, I$rdi, 36 | I$r8, I$r9, I$r10, I$r11, 37 | I$r12, I$r13, I$r14, I$r15, 38 | }; 39 | 40 | _disused static bool MSIs32BitOffset(uintptr_t target, uintptr_t source) { 41 | intptr_t offset(target - source); 42 | return int32_t(offset) == offset; 43 | } 44 | 45 | _disused static size_t MSSizeOfSkip() { 46 | return 5; 47 | } 48 | 49 | _disused static size_t MSSizeOfPushPointer(uintptr_t target) { 50 | return uint64_t(target) >> 32 == 0 ? 5 : 13; 51 | } 52 | 53 | _disused static size_t MSSizeOfPushPointer(void *target) { 54 | return MSSizeOfPushPointer(reinterpret_cast(target)); 55 | } 56 | 57 | _disused static size_t MSSizeOfJump(bool blind, uintptr_t target, uintptr_t source = 0) { 58 | if (ia32 || !blind && MSIs32BitOffset(target, source + 5)) 59 | return MSSizeOfSkip(); 60 | else 61 | return MSSizeOfPushPointer(target) + 1; 62 | } 63 | 64 | _disused static size_t MSSizeOfJump(uintptr_t target, uintptr_t source) { 65 | return MSSizeOfJump(false, target, source); 66 | } 67 | 68 | _disused static size_t MSSizeOfJump(uintptr_t target) { 69 | return MSSizeOfJump(true, target); 70 | } 71 | 72 | _disused static size_t MSSizeOfJump(void *target, void *source) { 73 | return MSSizeOfJump(reinterpret_cast(target), reinterpret_cast(source)); 74 | } 75 | 76 | _disused static size_t MSSizeOfJump(void *target) { 77 | return MSSizeOfJump(reinterpret_cast(target)); 78 | } 79 | 80 | _disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) { 81 | MSWrite(current, 0xe9); 82 | MSWrite(current, size); 83 | } 84 | 85 | _disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) { 86 | MSWrite(current, 0x68); 87 | MSWrite(current, target); 88 | 89 | if (uint32_t high = uint64_t(target) >> 32) { 90 | MSWrite(current, 0xc7); 91 | MSWrite(current, 0x44); 92 | MSWrite(current, 0x24); 93 | MSWrite(current, 0x04); 94 | MSWrite(current, high); 95 | } 96 | } 97 | 98 | _disused static void MSPushPointer(uint8_t *¤t, void *target) { 99 | return MSPushPointer(current, reinterpret_cast(target)); 100 | } 101 | 102 | _disused static void MSWriteCall(uint8_t *¤t, I$r target) { 103 | if (target >> 3 != 0) 104 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 105 | MSWrite(current, 0xff); 106 | MSWrite(current, 0xd0 | target & 0x07); 107 | } 108 | 109 | _disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) { 110 | uintptr_t source(reinterpret_cast(current)); 111 | 112 | if (ia32 || MSIs32BitOffset(target, source + 5)) { 113 | MSWrite(current, 0xe8); 114 | MSWrite(current, target - (source + 5)); 115 | } else { 116 | MSPushPointer(current, target); 117 | 118 | MSWrite(current, 0x83); 119 | MSWrite(current, 0xc4); 120 | MSWrite(current, 0x08); 121 | 122 | MSWrite(current, 0x67); 123 | MSWrite(current, 0xff); 124 | MSWrite(current, 0x54); 125 | MSWrite(current, 0x24); 126 | MSWrite(current, 0xf8); 127 | } 128 | } 129 | 130 | template 131 | _disused static void MSWriteCall(uint8_t *¤t, Type_ *target) { 132 | return MSWriteCall(current, reinterpret_cast(target)); 133 | } 134 | 135 | _disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) { 136 | uintptr_t source(reinterpret_cast(current)); 137 | 138 | if (ia32 || MSIs32BitOffset(target, source + 5)) 139 | MSWriteSkip(current, target - (source + 5)); 140 | else { 141 | MSPushPointer(current, target); 142 | MSWrite(current, 0xc3); 143 | } 144 | } 145 | 146 | _disused static void MSWriteJump(uint8_t *¤t, void *target) { 147 | return MSWriteJump(current, reinterpret_cast(target)); 148 | } 149 | 150 | _disused static void MSWriteJump(uint8_t *¤t, I$r target) { 151 | if (target >> 3 != 0) 152 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 153 | MSWrite(current, 0xff); 154 | MSWrite(current, 0xe0 | target & 0x07); 155 | } 156 | 157 | _disused static void MSWritePop(uint8_t *¤t, uint8_t target) { 158 | if (target >> 3 != 0) 159 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 160 | MSWrite(current, 0x58 | target & 0x07); 161 | } 162 | 163 | _disused static size_t MSSizeOfPop(uint8_t target) { 164 | return target >> 3 != 0 ? 2 : 1; 165 | } 166 | 167 | _disused static void MSWritePush(uint8_t *¤t, I$r target) { 168 | if (target >> 3 != 0) 169 | MSWrite(current, 0x40 | (target & 0x08) >> 3); 170 | MSWrite(current, 0x50 | target & 0x07); 171 | } 172 | 173 | _disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) { 174 | MSWrite(current, 0x83); 175 | MSWrite(current, 0xc4 | target & 0x07); 176 | MSWrite(current, source); 177 | } 178 | 179 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) { 180 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2); 181 | MSWrite(current, 0xb8 | target & 0x7); 182 | MSWrite(current, source); 183 | } 184 | 185 | template 186 | _disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) { 187 | return MSWriteSet64(current, target, reinterpret_cast(source)); 188 | } 189 | 190 | _disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) { 191 | MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3); 192 | MSWrite(current, 0x8b); 193 | MSWrite(current, (target & 0x07) << 3 | source & 0x07); 194 | } 195 | 196 | _disused static size_t MSSizeOfMove64() { 197 | return 3; 198 | } 199 | 200 | #endif//SUBSTRATE_X86_HPP 201 | --------------------------------------------------------------------------------