jailbreak.m 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. //
  2. // jailbreak.m
  3. // Meridian
  4. //
  5. // Created by Ben Sparkes on 16/02/2018.
  6. // Copyright © 2018 Ben Sparkes. All rights reserved.
  7. //
  8. #include "v0rtex.h"
  9. #include "kernel.h"
  10. #include "helpers.h"
  11. #include "root-rw.h"
  12. #include "amfi.h"
  13. #include "offsetfinder.h"
  14. #include "jailbreak.h"
  15. #include "ViewController.h"
  16. #include "patchfinder64.h"
  17. #include "patchfinders/offsetdump.h"
  18. #include "nvpatch.h"
  19. #include <mach/mach_types.h>
  20. #include <sys/stat.h>
  21. #import <Foundation/Foundation.h>
  22. #import "NSData+GZip.h"
  23. #include <sys/spawn.h>
  24. #import "fun_objc.h"
  25. #include "kpp.h"
  26. #include "kppremount.h"
  27. //#import "NSTask.h"
  28. //experimental kpp stuff
  29. NSFileManager *fileMgr;
  30. offsets_t offsets;
  31. BOOL great_success = FALSE;
  32. BOOL isKppless = FALSE;
  33. int remount() {
  34. //[self log:@"remounting"];
  35. NSLog(@"remounting");
  36. if (do_remount(kslide) == KERN_SUCCESS) {
  37. // [self bootstrap];
  38. return 0;
  39. } else {
  40. NSLog(@"ERROR: failed to remount system partition \n");
  41. // [self log:@"ERROR: failed to remount system partition \n"];
  42. return -1;
  43. }
  44. return -1;
  45. }
  46. int bypassKPP() {
  47. //[self log:@"pwning kernel"];
  48. if (do_kpp(1, 0, kernel_base, kslide, tfp0) == KERN_SUCCESS) {
  49. NSLog(@"you down with kpp? yeah you know me");
  50. return remount();
  51. } else {
  52. NSLog(@"ERROR: kpp bypass failed \n");
  53. //[self log:@"ERROR: kpp bypass failed \n"];
  54. return -1;
  55. }
  56. return 0;
  57. }
  58. int makeShitHappen(ViewController *view, BOOL kppless) {
  59. int ret;
  60. isKppless = kppless;
  61. fileMgr = [NSFileManager defaultManager];
  62. // run v0rtex
  63. [view writeText:@"running v0rtex..."];
  64. suspend_all_threads();
  65. ret = runV0rtex();
  66. resume_all_threads();
  67. if (ret != 0) {
  68. [view writeText:@"failed!"];
  69. if (ret == -420) {
  70. [view writeTextPlain:@"failed to load offsets!"];
  71. }
  72. return 1;
  73. }
  74. [view writeTextPlain:@"succeeded! praize siguza!"];
  75. // set up stuff
  76. init_patchfinder(NULL);
  77. //#ifndef DO_KPPLESS
  78. if (!isKppless) {
  79. ret = init_amfi();
  80. if (ret != 0) {
  81. [view writeTextPlain:@"failed to initialize amfi class!"];
  82. return 1;
  83. }
  84. // patch containermanager
  85. [view writeText:@"patching containermanager..."];
  86. ret = patchContainermanagerd();
  87. if (ret != 0) {
  88. [view writeText:@"failed!"];
  89. return 1;
  90. }
  91. [view writeText:@"done!"];
  92. // remount root fs
  93. [view writeText:@"remounting rootfs as r/w..."];
  94. ret = remountRootFs();
  95. if (ret != 0) {
  96. [view writeText:@"failed!"];
  97. return 1;
  98. }
  99. } else {
  100. //#else
  101. int kppReturn = bypassKPP();
  102. if (kppReturn == 0) {
  103. [view writeText:@"KPP has been defeated!\n"];
  104. } else {
  105. [view writeText:@"KPP bypass failed!\n"];
  106. return 1;
  107. }
  108. }
  109. //#endif
  110. [view writeText:@"done!"];
  111. /* Begin the filesystem fuckery */
  112. [view writeText:@"some filesytem fuckery..."];
  113. // Remove /meridian in the case of PB's
  114. if (file_exists("/meridian") == 0 &&
  115. file_exists("/meridian/.bootstrap") != 0) {
  116. [[NSFileManager defaultManager] removeItemAtPath:@"/meridian" error:nil];
  117. }
  118. if (file_exists("/Library/LaunchDaemons/._dropbear.plist") == 0) {
  119. unlink("/Library/LaunchDaemons/._dropbear.plist");
  120. }
  121. /*
  122. if (file_exists("/meridian/.bootstrap") == 0) {
  123. unlink("/meridian/.bootstrap");
  124. }
  125. //take these out later, just so i can update the plists as i tweak the payload
  126. if (file_exists("/Library/LaunchDaemons/com.openssh.sshd.plist") == 0) {
  127. unlink("/Library/LaunchDaemons/com.openssh.sshd.plist");
  128. }
  129. if (file_exists("/Library/LaunchDaemons/dropbear.plist") == 0) {
  130. unlink("/Library/LaunchDaemons/dropbear.plist");
  131. }
  132. */
  133. // if (file_exists("/usr/lib/TweakInject.dylib") == 0) {
  134. // ret = unlink("/usr/lib/TweakInject.dylib");
  135. // if (ret != 0) {
  136. // [view writeText:@"failed!"];
  137. // [view writeTextPlain:@"removing /usr/lib/TweakInject.dylib failed with error %d: %s", errno, strerror(errno)];
  138. // return 1;
  139. // }
  140. //
  141. // }
  142. if (file_exists("/meridian") != 0) {
  143. ret = mkdir("/meridian", 0755);
  144. if (ret != 0) {
  145. [view writeText:@"failed!"];
  146. [view writeTextPlain:@"creating /meridian failed with error %d: %s", errno, strerror(errno)];
  147. return 1;
  148. }
  149. }
  150. if (file_exists("/meridian/logs") != 0) {
  151. ret = mkdir("/meridian/logs", 0755);
  152. if (ret != 0) {
  153. [view writeText:@"failed!"];
  154. [view writeTextPlain:@"creating /meridian/logs failed with error %d: %s", errno, strerror(errno)];
  155. return 1;
  156. }
  157. }
  158. if (file_exists("/meridian/tar") == 0) {
  159. ret = unlink("/meridian/tar");
  160. if (ret != 0) {
  161. [view writeText:@"failed!"];
  162. [view writeTextPlain:@"removing /meridian/tar failed with error %d: %s", errno, strerror(errno)];
  163. return 1;
  164. }
  165. }
  166. if (file_exists("/meridian/tar.tar") == 0) {
  167. ret = unlink("/meridian/tar.tar");
  168. if (ret != 0) {
  169. [view writeText:@"failed!"];
  170. [view writeTextPlain:@"deleting /meridian/tar.tar failed with error %d: %s", errno, strerror(errno)];
  171. return 1;
  172. }
  173. }
  174. ret = extract_bundle("tar.tar", "/meridian");
  175. if (ret != 0) {
  176. [view writeText:@"failed!"];
  177. [view writeTextPlain:@"failed to extract tar.tar bundle! ret: %d, errno: %d: %s", ret, errno, strerror(errno)];
  178. return 1;
  179. }
  180. if (file_exists("/meridian/tar") != 0) {
  181. [view writeText:@"failed!"];
  182. [view writeTextPlain:@"/meridian/tar was not found :("];
  183. return 1;
  184. }
  185. ret = chmod("/meridian/tar", 0755);
  186. if (ret != 0) {
  187. [view writeText:@"failed!"];
  188. [view writeTextPlain:@"chmod(755)'ing /meridian/tar failed with error %d: %s", errno, strerror(errno)];
  189. return 1;
  190. }
  191. ret = inject_trust("/meridian/tar");
  192. if (ret != 0) {
  193. [view writeText:@"failed!"];
  194. [view writeTextPlain:@"injecting trust to /meridian/tar failed with retcode %d", ret];
  195. return 1;
  196. }
  197. [view writeText:@"done!"];
  198. // extract meridian-bootstrap
  199. [view writeText:@"extracting meridian files..."];
  200. ret = extractMeridianData();
  201. if (ret != 0) {
  202. [view writeText:@"failed!"];
  203. [view writeTextPlain:[NSString stringWithFormat:@"error code: %d", ret]];
  204. return 1;
  205. }
  206. [view writeText:@"done!"];
  207. // dump offsets to file for later use (/meridian/offsets.plist)
  208. dumpOffsetsToFile(&offsets, kernel_base, kslide);
  209. //#ifndef DO_KPPLESS
  210. if (!isKppless) {
  211. // patch amfid
  212. [view writeText:@"patching amfid..."];
  213. ret = defecateAmfi();
  214. if (ret != 0) {
  215. [view writeText:@"failed!"];
  216. if (ret > 0) {
  217. [view writeTextPlain:[NSString stringWithFormat:@"failed to patch - %d tries", ret]];
  218. }
  219. return 1;
  220. }
  221. [view writeText:@"done!"];
  222. }
  223. //#endif
  224. // touch .cydia_no_stash
  225. touch_file("/.cydia_no_stash");
  226. // symlink /Library/MobileSubstrate/DynamicLibraries -> /usr/lib/tweaks
  227. //setUpSymLinks();
  228. // remove Substrate's SafeMode (MobileSafety) if it's installed
  229. // removing from dpkg will be handled by Cydia conflicts later
  230. if (file_exists("/usr/lib/tweaks/MobileSafety.dylib") == 0) {
  231. unlink("/usr/lib/tweaks/MobileSafety.dylib");
  232. }
  233. if (file_exists("/usr/lib/tweaks/MobileSafety.plist") == 0) {
  234. unlink("/usr/lib/tweaks/MobileSafety.plist");
  235. }
  236. // extract bootstrap (if not already extracted)
  237. if (file_exists("/meridian/.bootstrap") != 0) {
  238. [view writeText:@"extracting bootstrap..."];
  239. int exitCode = 0;
  240. ret = extractBootstrap(&exitCode);
  241. if (ret != 0) {
  242. [view writeText:@"failed!"];
  243. switch (ret) {
  244. case 1:
  245. [view writeTextPlain:@"failed to extract system-base.tar"];
  246. break;
  247. case 2:
  248. [view writeTextPlain:@"failed to extract installer-base.tar"];
  249. break;
  250. case 3:
  251. [view writeTextPlain:@"failed to extract dpkgdb-base.tar"];
  252. break;
  253. case 4:
  254. [view writeTextPlain:@"failed to extract cydia-base.tar"];
  255. break;
  256. case 5:
  257. [view writeTextPlain:@"failed to extract optional-base.tar"];
  258. break;
  259. case 6:
  260. [view writeTextPlain:@"failed to run uicache!"];
  261. break;
  262. }
  263. [view writeTextPlain:@"exit code: %d", exitCode];
  264. return 1;
  265. }
  266. [view writeText:@"done!"];
  267. }
  268. //unlink("/usr/lib/libjailbreak.dylib");
  269. //cp("/usr/lib/libjailbreak.dylib","/electra/libjailbreak.dylib");
  270. /*
  271. // add the midnight repo
  272. if (file_exists("/etc/apt/sources.list.d/meridian.list") != 0) {
  273. FILE *fd = fopen("/etc/apt/sources.list.d/meridian.list", "w+");
  274. const char *text = "deb http://repo.midnight.team ./";
  275. fwrite(text, strlen(text) + 1, 1, fd);
  276. fclose(fd);
  277. }
  278. */
  279. pid_t pd;
  280. //posix_spawn(&pd, "/bin/bash", NULL, NULL, (char **)&(const char*[]){ "bash", "/usr/libexec/nito/firmware.sh", NULL }, NULL);
  281. //waitpid(pd, NULL, 0);
  282. posix_spawn(&pd, "/bin/bash", NULL, NULL, (char **)&(const char*[]){ "bash", "/Library/dpkg/info/openssh.postinst", NULL }, NULL);
  283. waitpid(pd, NULL, 0);
  284. // posix_spawn(&pd, "/bin/launchctl", NULL, NULL, (char **)&(const char*[]){ "launchctl", "load", "/Library/LaunchDaemons/com.openssh.sshd.plist", NULL }, NULL);
  285. // waitpid(pd, NULL, 0);
  286. //fixPerms();
  287. // launch dropbear
  288. [view writeText:@"launching dropbear..."];
  289. ret = launchDropbear();
  290. if (ret != 0) {
  291. [view writeText:@"failed!"];
  292. [view writeTextPlain:@"exit code: %d", ret];
  293. return 1;
  294. }
  295. //launch openssh
  296. [view writeText:@"Launching openssh..."];
  297. ret = start_launchdaemon("/Library/LaunchDaemons/com.openssh.sshd.plist");
  298. if (ret != 0) {
  299. [view writeText:@"failed!"];
  300. [view writeTextPlain:@"exit code: %d", ret];
  301. //return 1;
  302. }
  303. [view writeText:@"done!"];
  304. // link substitute stuff
  305. //setUpSubstitute();
  306. //#ifndef DO_KPPLESS
  307. if (!isKppless) {
  308. // start jailbreakd
  309. ret = inject_trust("/meridian/inject_criticald");
  310. //ret = inject_trust("/electra/amfid_payload.dylib");
  311. //ret = inject_trust("/electra/pspawn_payload.dylib");
  312. //ret = inject_trust("/electra/libjailbreak.dylib");
  313. //if (ret != 0) return -1;
  314. [view writeText:@"starting jailbreakd..."];
  315. ret = startJailbreakd();
  316. if (ret != 0) {
  317. [view writeText:@"failed"];
  318. if (ret > 1) {
  319. [view writeTextPlain:@"failed to launch - %d tries", ret];
  320. }
  321. return 1;
  322. }
  323. [view writeText:@"done!"];
  324. // patch com.apple.System.boot-nonce
  325. [view writeText:@"patching boot-nonce..."];
  326. ret = nvpatch("com.apple.System.boot-nonce");
  327. if (ret != 0) {
  328. [view writeText:@"failed!"];
  329. return 1;
  330. }
  331. [view writeText:@"done!"];
  332. }
  333. //#endif
  334. // load launchdaemons
  335. [view writeText:@"loading launchdaemons..."];
  336. ret = loadLaunchDaemons();
  337. if (ret != 0) {
  338. [view writeText:@"failed!"];
  339. return 1;
  340. }
  341. [view writeText:@"done!"];
  342. great_success = TRUE;
  343. return 0;
  344. }
  345. void fixPerms() {
  346. int rv = execprog("/usr/bin/chmod", (const char **)&(const char*[]) {
  347. "/usr/bin/chmod",
  348. "-R",
  349. "0700",
  350. "/private/var/root/.ssh",
  351. NULL
  352. });
  353. rv = execprog("/usr/bin/chmod", (const char **)&(const char*[]) {
  354. "/usr/bin/chmod",
  355. "-R",
  356. "0700",
  357. "/private/etc/dropbear",
  358. NULL
  359. });
  360. }
  361. kern_return_t callback(task_t kern_task, kptr_t kbase, void *cb_data) {
  362. tfp0 = kern_task;
  363. kernel_base = kbase;
  364. kslide = kernel_base - 0xFFFFFFF007004000;
  365. return KERN_SUCCESS;
  366. }
  367. int runV0rtex() {
  368. offsets_t *offs = get_offsets();
  369. if (offs == NULL) {
  370. return -420;
  371. }
  372. offsets = *offs;
  373. int ret = v0rtex(&offsets, &callback, NULL);
  374. uint64_t kernel_task_addr = rk64(offs->kernel_task + kslide);
  375. kernprocaddr = rk64(kernel_task_addr + offs->task_bsd_info);
  376. kern_ucred = rk64(kernprocaddr + offs->proc_ucred);
  377. if (ret == 0) {
  378. NSLog(@"tfp0: 0x%x", tfp0);
  379. NSLog(@"kernel_base: 0x%llx", kernel_base);
  380. NSLog(@"kslide: 0x%llx", kslide);
  381. NSLog(@"kern_ucred: 0x%llx", kern_ucred);
  382. NSLog(@"kernprocaddr: 0x%llx", kernprocaddr);
  383. }
  384. return ret;
  385. }
  386. int patchContainermanagerd() {
  387. uint64_t cmgr = find_proc_by_name("containermanager");
  388. if (cmgr == 0) {
  389. NSLog(@"unable to find containermanager!");
  390. return 1;
  391. }
  392. wk64(cmgr + 0x100, kern_ucred);
  393. return 0;
  394. }
  395. int remountRootFs() {
  396. NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
  397. int pre130 = osVersion.minorVersion < 2 ? 1 : 0;
  398. int rv = mount_root(kslide, offsets.root_vnode, pre130);
  399. if (rv != 0) {
  400. return 1;
  401. }
  402. return 0;
  403. }
  404. int extractMeridianData() {
  405. int rv = extract_bundle_tar("meridian-bootstrap.tar");
  406. unlink("/usr/bin/cynject");
  407. unlink("/usr/bin/cycc");
  408. symlink("/meridian/inject_criticald", "/usr/bin/cynject"); //mimic cynject
  409. symlink("/usr/bin/ssh", "/usr/local/bin/"); //get scp working
  410. //rv = extract_bundle_tar("basebinaries.tar");
  411. return rv;
  412. }
  413. void setUpSymLinks() {
  414. struct stat file;
  415. stat("/Library/MobileSubstrate/DynamicLibraries", &file);
  416. if (file_exists("/Library/MobileSubstrate/DynamicLibraries") == 0 &&
  417. file_exists("/usr/lib/tweaks") == 0 &&
  418. S_ISLNK(file.st_mode)) {
  419. return;
  420. }
  421. // By the end of this check, /usr/lib/tweaks should exist containing any
  422. // tweaks (if applicable), and /Lib/MobSub/DynLib should NOT exist
  423. if (file_exists("/Library/MobileSubstrate/DynamicLibraries") == 0 &&
  424. file_exists("/usr/lib/tweaks") != 0) {
  425. // Move existing tweaks folder to /usr/lib/tweaks
  426. [[NSFileManager defaultManager] moveItemAtPath:@"/Library/MobileSubstrate/DynamicLibraries" toPath:@"/usr/lib/tweaks" error:nil];
  427. } else if (file_exists("/Library/MobileSubstrate/DynamicLibraries") == 0 &&
  428. file_exists("/usr/lib/tweaks") == 0) {
  429. // Move existing tweaks to /usr/lib/tweaks and delete the MobSub folder
  430. NSArray *fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/Library/MobileSubstrate/DynamicLibraries" error:nil];
  431. for (NSString *item in fileList) {
  432. NSString *fullPath = [NSString stringWithFormat:@"/Library/MobileSubstrate/DynamicLibraries/%@", item];
  433. [[NSFileManager defaultManager] moveItemAtPath:fullPath toPath:@"/usr/lib/tweaks" error:nil];
  434. }
  435. [[NSFileManager defaultManager] removeItemAtPath:@"/Library/MobileSubstrate/DynamicLibraries" error:nil];
  436. } else if (file_exists("/Library/MobileSubstrate/DynamicLibraries") != 0 &&
  437. file_exists("/usr/lib/tweaks") != 0) {
  438. // Just create /usr/lib/tweaks - /Lib/MobSub/DynLibs doesn't exist
  439. mkdir("/Library/MobileSubstrate", 0755);
  440. mkdir("/usr/lib/tweaks", 0755);
  441. } else if (file_exists("/Library/MobileSubstrate/DynamicLibraries") != 0 &&
  442. file_exists("/usr/lib/tweaks") == 0) {
  443. // We should be fine in this case
  444. mkdir("/Library/MobileSubstrate", 0755);
  445. }
  446. // Symlink it!
  447. symlink("/usr/lib/tweaks", "/Library/MobileSubstrate/DynamicLibraries");
  448. }
  449. void extractGz_merd(const char *from, const char *to) {
  450. NSData *gz = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@(from) ofType:@"gz"]];
  451. NSData *extracted = [gz gunzippedData];
  452. [extracted writeToFile:@(to) atomically:YES];
  453. }
  454. int extractBootstrap(int *exitCode) {
  455. int rv;
  456. unlink("/meridian/bootstrap.tar");
  457. extractGz_merd("bootstrap.tar", "/meridian/bootstrap.tar");
  458. rv = extract_tar("/meridian/bootstrap.tar");
  459. if (rv != 0) {
  460. *exitCode = rv;
  461. return 1;
  462. }
  463. // rv = uicache();
  464. // if (rv != 0) {
  465. // *exitCode = rv;
  466. // return 6;
  467. // }
  468. touch_file("/meridian/.bootstrap");
  469. touch_file("/var/mobile/Library/Preferences/.kickstart");
  470. //touch_file("/var/mobile/Library/Preferences/.nitolaunch");
  471. pid_t pd;
  472. posix_spawn(&pd, "/bin/bash", NULL, NULL, (char **)&(const char*[]){ "bash", "/usr/libexec/nito/firmware.sh", NULL }, NULL);
  473. waitpid(pd, NULL, 0);
  474. char *myenviron[] = {
  475. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games",
  476. "PS1=\\h:\\w \\u\\$ ",
  477. NULL
  478. };
  479. /*
  480. posix_spawn(&pd, "/usr/bin/dpkg", NULL, NULL, (char **)&(const char*[]){ "dpkg", "-i", "--refuse-downgrade", progname("nitotv.deb"), NULL }, (char **)&myenviron);
  481. waitpid(pd, NULL, 0);
  482. */
  483. posix_spawn(&pd, "/usr/bin/dpkg", NULL, NULL, (char **)&(const char*[]){ "dpkg", "-i", "--refuse-downgrade", progname("safetynet.deb"), NULL }, (char **)&myenviron);
  484. waitpid(pd, NULL, 0);
  485. return 0;
  486. }
  487. int old_extractBootstrap(int *exitCode) {
  488. int rv;
  489. // extract system-base.tar
  490. rv = extract_bundle_tar("system-base.tar");
  491. if (rv != 0) {
  492. *exitCode = rv;
  493. return 1;
  494. }
  495. // extract installer-base.tar
  496. rv = extract_bundle_tar("installer-base.tar");
  497. if (rv != 0) {
  498. *exitCode = rv;
  499. return 2;
  500. }
  501. if (file_exists("/private/var/lib/dpkg/status") != 0) {
  502. rv = extract_bundle_tar("dpkgdb-base.tar");
  503. if (rv != 0) {
  504. *exitCode = rv;
  505. return 3;
  506. }
  507. }
  508. // extract cydia-base.tar
  509. rv = extract_bundle_tar("cydia-base.tar");
  510. if (rv != 0) {
  511. *exitCode = rv;
  512. return 4;
  513. }
  514. // extract optional-base.tar
  515. rv = extract_bundle_tar("optional-base.tar");
  516. if (rv != 0) {
  517. *exitCode = rv;
  518. return 5;
  519. }
  520. //enableHiddenApps();
  521. touch_file("/meridian/.bootstrap");
  522. rv = uicache();
  523. if (rv != 0) {
  524. *exitCode = rv;
  525. return 6;
  526. }
  527. return 0;
  528. }
  529. int newdefecateAmfi() {
  530. #define BinaryLocation "/electra/inject_criticald"
  531. pid_t amfid_pid = get_pid_for_name("amfid");
  532. if (amfid_pid == 0) {
  533. return -2;
  534. }
  535. pid_t pd;
  536. int rv = 0;
  537. const char* args_amfid[] = {BinaryLocation, itoa(amfid_pid), "/electra/amfid_payload.dylib", NULL};
  538. rv = posix_spawn(&pd, BinaryLocation, NULL, NULL, (char **)&args_amfid, NULL);
  539. waitpid(pd, NULL, 0);
  540. unlink("/.amfid_success");
  541. const char *args_helloworld[] = {"helloworld", NULL};
  542. rv = posix_spawn(&pd, "/electra/helloworld", NULL, NULL, (char **)&args_helloworld, NULL);
  543. waitpid(pd, NULL, 0);
  544. if (!file_exists("/.amfid_success")){
  545. return -3;
  546. }
  547. unlink("/.amfid_success");
  548. return 0;
  549. }
  550. int defecateAmfi() {
  551. // write kslide to file
  552. unlink("/meridian/kernel_slide");
  553. FILE *fd = fopen("/meridian/kernel_slide", "w");
  554. fprintf(fd, "%016llx", kslide);
  555. fclose(fd);
  556. int ret = inject_trust("/meridian/inject_criticald");
  557. if (ret != 0) return -1;
  558. // trust our payload
  559. ret = inject_trust("/meridian/amfid_payload.dylib");
  560. if (ret != 0) return -1;
  561. unlink("/var/tmp/amfid_payload.alive");
  562. pid_t pid = get_pid_for_name("amfid");
  563. if (pid == 0) {
  564. return -2;
  565. }
  566. ret = inject_library(pid, "/meridian/amfid_payload.dylib");
  567. if (ret != 0) return -2;
  568. int tries = 0;
  569. while (file_exists("/var/tmp/amfid_payload.alive") != 0) {
  570. if (tries >= 100) {
  571. NSLog(@"failed to patch amfid (%d tries)", tries);
  572. return tries;
  573. }
  574. NSLog(@"waiting for amfid patch...");
  575. usleep(100000); // 0.1 sec
  576. tries++;
  577. }
  578. return 0;
  579. }
  580. int launchDropbear() {
  581. return start_launchdaemon("/Library/LaunchDaemons/dropbear.plist");
  582. }
  583. void setUpSubstitute() {
  584. // link CydiaSubstrate.framework -> /usr/lib/libsubstrate.dylib
  585. if (file_exists("/Library/Frameworks/CydiaSubstrate.framework") == 0) {
  586. [[NSFileManager defaultManager] removeItemAtPath:@"/Library/Frameworks/CydiaSubstrate.framework" error:nil];
  587. }
  588. mkdir("/Library/Frameworks", 0755);
  589. mkdir("/Library/Frameworks/CydiaSubstrate.framework", 0755);
  590. symlink("/usr/lib/libsubstrate.dylib", "/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate");
  591. }
  592. int start_jailbreakd_e() {
  593. unlink("/var/tmp/jailbreakd.pid");
  594. unlink("/var/run/jailbreakd.pid");
  595. unlink("/var/log/jailbreakd-stderr.log");
  596. unlink("/var/log/jailbreakd-stdout.log");
  597. NSData *blob = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"jailbreakd" ofType:@"plist"]];
  598. NSMutableDictionary *job = [NSPropertyListSerialization propertyListWithData:blob options:NSPropertyListMutableContainers format:nil error:nil];
  599. job[@"EnvironmentVariables"][@"KernelBase"] = [NSString stringWithFormat:@"0x%16llx", kernel_base];
  600. [job writeToFile:@"/Library/LaunchDaemons/jailbreakd.plist" atomically:YES];
  601. chmod("/Library/LaunchDaemons/jailbreakd.plist", 0644);
  602. chown("/Library/LaunchDaemons/jailbreakd.plist", 0, 0);
  603. pid_t pid = 0;
  604. //int rv = run("/bin/launchctl load /Library/LaunchDaemons/jailbreakd.plist");
  605. int rv = start_launchdaemon("/Library/LaunchDaemons/jailbreakd.plist");
  606. if (rv == -1) {
  607. return -1;
  608. }
  609. int ex = 0;
  610. waitpid(pid, &ex, 0);
  611. NSLog(@"The dragon becomes me!");
  612. NSLog(@"once it is drawn, it cannot be sheathed without causing death");
  613. return 0;
  614. }
  615. int startJailbreakd() {
  616. unlink("/var/tmp/jailbreakd.pid");
  617. NSData *blob = [NSData dataWithContentsOfFile:@"/meridian/jailbreakd/jailbreakd.plist"];
  618. NSMutableDictionary *job = [NSPropertyListSerialization propertyListWithData:blob options:NSPropertyListMutableContainers format:nil error:nil];
  619. job[@"EnvironmentVariables"][@"KernelBase"] = [NSString stringWithFormat:@"0x%16llx", kernel_base];
  620. job[@"EnvironmentVariables"][@"KernProcAddr"] = [NSString stringWithFormat:@"0x%16llx", kernprocaddr];
  621. job[@"EnvironmentVariables"][@"ZoneMapOffset"] = [NSString stringWithFormat:@"0x%16llx", offsets.zone_map];
  622. [job writeToFile:@"/meridian/jailbreakd/jailbreakd.plist" atomically:YES];
  623. chmod("/meridian/jailbreakd/jailbreakd.plist", 0600);
  624. chown("/meridian/jailbreakd/jailbreakd.plist", 0, 0);
  625. int rv = start_launchdaemon("/meridian/jailbreakd/jailbreakd.plist");
  626. if (rv != 0) return 1;
  627. int tries = 0;
  628. while (file_exists("/var/tmp/jailbreakd.pid") != 0) {
  629. printf("Waiting for jailbreakd \n");
  630. tries++;
  631. usleep(300000); // 300ms
  632. if (tries >= 100) {
  633. NSLog(@"too many tries for jbd - %d", tries);
  634. return tries;
  635. }
  636. }
  637. usleep(100000);
  638. // tell jailbreakd to platformize launchd
  639. // this adds skip-lib-val to MACF slot and allows us
  640. // to inject pspawn without it being in trust cache
  641. // (plus FAT/multiarch in trust cache is a pain to code, i'm lazy)
  642. rv = call_jailbreakd(JAILBREAKD_COMMAND_ENTITLE, 1);
  643. if (rv != 0) return 2;
  644. // inject pspawn_hook.dylib to launchd
  645. rv = inject_library(1, "/usr/lib/pspawn_hook.dylib");
  646. //rv = inject_library(1, "/meridian/pspawn_payload.dylib");
  647. if (rv != 0) return 3;
  648. /*
  649. rv = execprog("/meridian/inject_criticald", (const char **)&(const char*[]) {
  650. "/meridian/inject_criticald",
  651. "1",
  652. "/meridian/pspawn_payload.dylib",
  653. NULL
  654. });
  655. if (rv != 0) return 3;
  656. */
  657. return 0;
  658. }
  659. int loadLaunchDaemons() {
  660. NSArray *daemons = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/Library/LaunchDaemons" error:nil];
  661. for (NSString *file in daemons) {
  662. NSString *path = [NSString stringWithFormat:@"/Library/LaunchDaemons/%@", file];
  663. NSLog(@"found launchdaemon: %@", path);
  664. chmod([path UTF8String], 0755);
  665. chown([path UTF8String], 0, 0);
  666. }
  667. return start_launchdaemon("/Library/LaunchDaemons");
  668. }
  669. void enableHiddenApps() {
  670. // enable showing of system apps on springboard
  671. // this is some funky killall stuff tho
  672. killall("cfprefsd", "-SIGSTOP");
  673. NSMutableDictionary* md = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/mobile/Library/Preferences/com.apple.springboard.plist"];
  674. [md setObject:[NSNumber numberWithBool:YES] forKey:@"SBShowNonDefaultSystemApps"];
  675. [md writeToFile:@"/var/mobile/Library/Preferences/com.apple.springboard.plist" atomically:YES];
  676. killall("cfprefsd", "-9");
  677. }