ViewController.m 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. //
  2. // ViewController.m
  3. // meridianTV
  4. //
  5. // Created by Kevin Bradley on 6/24/18.
  6. // Copyright © 2018 Ben Sparkes. All rights reserved.
  7. //
  8. #import "ViewController.h"
  9. #import "helpers.h"
  10. #import "jailbreak.h"
  11. #import <sys/utsname.h>
  12. #import <Foundation/Foundation.h>
  13. #import "PureLayout.h"
  14. #import "UIColor+Additions.h"
  15. #import <CoreFoundation/CoreFoundation.h>
  16. //electra
  17. #import "NSTask.h"
  18. #include "async_wake.h"
  19. #include "fun.h"
  20. #include "codesign.h"
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <dlfcn.h>
  26. CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
  27. CF_EXPORT CFDictionaryRef _CFCopyServerVersionDictionary(void);
  28. static ViewController *currentViewController;
  29. typedef NS_ENUM(NSInteger, BSInstallType) {
  30. BSInstallTypeUnsupported,
  31. BSInstallTypeMeridian,
  32. BSInstallTypeElectra,
  33. };
  34. @interface ViewController () {
  35. BOOL _respringReady;
  36. UITapGestureRecognizer *playPauseOrMenuDoubleTapRecognizer;
  37. BOOL kppless;
  38. }
  39. @property (readwrite, assign) BSInstallType installMode; //0 = meridian 1 = electra
  40. @property (strong, nonatomic) UIButton *goButton;
  41. @property (strong, nonatomic) UIButton *creditsButton;
  42. @property (strong, nonatomic) UIButton *websiteButton;
  43. @property (strong, nonatomic) UIActivityIndicatorView *progressSpinner;
  44. @property (strong, nonatomic) UITextView *textArea;
  45. @property (strong, nonatomic) UILabel *versionLabel;
  46. @end
  47. NSString *Version = @"backr00m: 1.1";
  48. NSOperatingSystemVersion osVersion;
  49. id thisClass;
  50. bool has_run_once = false;
  51. bool jailbreak_has_run = false;
  52. @implementation FocusedButton
  53. - (instancetype)initWithCoder:(NSCoder *)coder
  54. {
  55. self = [super initWithCoder:coder];
  56. if (self) {
  57. self.layer.cornerRadius = 5;
  58. self.backgroundColor = [UIColor lightGrayColor];
  59. self.focusColor = [UIColor redColor];
  60. self.unfocusedColor = [UIColor lightGrayColor];
  61. }
  62. return self;
  63. }
  64. - (id)initForAutoLayout {
  65. self = [super initForAutoLayout];
  66. if (self) {
  67. self.layer.cornerRadius = 5;
  68. self.backgroundColor = [UIColor lightGrayColor];
  69. self.focusColor = [UIColor redColor];
  70. self.unfocusedColor = [UIColor lightGrayColor];
  71. }
  72. return self;
  73. }
  74. - (void)buttonColors:(UIColor *)focusedColor andUnfocused:(UIColor *)unfocusedColor {
  75. self.focusColor = focusedColor;
  76. self.unfocusedColor = unfocusedColor;
  77. self.backgroundColor = unfocusedColor;
  78. }
  79. - (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator {
  80. [coordinator addCoordinatedAnimations:^{
  81. if (self.focused) {
  82. self.backgroundColor = self.focusColor;
  83. self.transform = CGAffineTransformMakeScale(1.1, 1.1);
  84. self.layer.shadowColor = [UIColor blackColor].CGColor;
  85. self.layer.shadowOffset = CGSizeMake(0, 27);
  86. self.layer.shadowOpacity = 0.25;
  87. self.layer.shadowRadius = 10;
  88. self.clipsToBounds = NO;
  89. }
  90. else {
  91. self.transform = CGAffineTransformIdentity;
  92. self.backgroundColor = self.unfocusedColor;
  93. self.clipsToBounds = YES;
  94. }
  95. } completion:nil];
  96. }
  97. @end
  98. @implementation ViewController
  99. + (instancetype)currentViewController {
  100. return currentViewController;
  101. }
  102. - (void)customTVSetup {
  103. //redudant
  104. /*
  105. if (kCFCoreFoundationVersionNumber < 1443 || kCFCoreFoundationVersionNumber > 1445.32){
  106. [self.goButton setEnabled:NO];
  107. [self.goButton setTitle:@"Version Error" forState:UIControlStateNormal];
  108. }
  109. uint32_t flags;
  110. csops(getpid(), CS_OPS_STATUS, &flags, 0);
  111. if ((flags & CS_PLATFORM_BINARY)){
  112. [self.goButton setEnabled:NO];
  113. [self.goButton setTitle:@"Already Jailbroken" forState:UIControlStateNormal];
  114. }
  115. */
  116. _respringReady = FALSE;
  117. [self writeTextPlain:@">"];
  118. self.installMode = BSInstallTypeUnsupported;
  119. if (SYSTEM_VERSION_EQUAL_TO(@"10.2.2")){
  120. self.installMode = BSInstallTypeMeridian;
  121. [self writeTextPlain:@"> 10.2.2 detected, using Meridian based jailbreak. Thanks PsychoTea!"];
  122. } else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0") && SYSTEM_VERSION_LESS_THAN(@"11.2") ){
  123. self.installMode = BSInstallTypeElectra;
  124. [self writeTextPlain:@"> 11.x detected, using Electra based jailbreak. Thanks Electra Team!"];
  125. }
  126. UIImageView *bgImageView = [[UIImageView alloc] initForAutoLayout];
  127. [self.view addSubview:bgImageView];
  128. [bgImageView autoPinEdgesToSuperviewEdges];
  129. [bgImageView setImage:[UIImage imageNamed:@"bgTemp.jpg"]];
  130. UILabel *meridianTV = [[UILabel alloc] initForAutoLayout];
  131. [self.view addSubview:meridianTV];
  132. [meridianTV autoAlignAxisToSuperviewAxis:ALAxisVertical];
  133. [meridianTV autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:160];
  134. [meridianTV setFont:[UIFont systemFontOfSize:205 weight:UIFontWeightHeavy]];
  135. [meridianTV setText:@"backr00m"];
  136. [meridianTV setTextColor:[UIColor whiteColor]];
  137. self.goButton = [UIButton buttonWithType:UIButtonTypeSystem];
  138. [self.goButton autoSetDimensionsToSize:CGSizeMake(250, 100)];
  139. [self.goButton setTitle:@"jailbreak" forState:UIControlStateFocused];
  140. //[self.goButton buttonColors:[UIColor colorFromHex:@"DB1E00"]
  141. // andUnfocused:[UIColor darkTextColor]];
  142. [self.view addSubview:self.goButton];
  143. [self.goButton autoCenterInSuperview];
  144. [self.goButton addTarget:self action:@selector(goButtonPressed:) forControlEvents:UIControlEventPrimaryActionTriggered];
  145. self.versionLabel = [[UILabel alloc] initForAutoLayout];
  146. self.versionLabel.textColor = [UIColor whiteColor];
  147. [self.view addSubview:self.versionLabel];
  148. [self.versionLabel autoAlignAxisToSuperviewAxis:ALAxisVertical];
  149. [self.versionLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.goButton withOffset:10];
  150. self.textArea = [[UITextView alloc] initForAutoLayout];
  151. [self.view addSubview:self.textArea];
  152. [self.textArea autoAlignAxisToSuperviewAxis:ALAxisVertical];
  153. [self.textArea autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.versionLabel];
  154. [self.textArea autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.view withMultiplier:0.8];
  155. [self.textArea autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:40];
  156. //[self.goButton setBackgroundColor:[UIColor colorFromHex:@"DB1E00"]];
  157. [self.goButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  158. [self.goButton setTitleColor:[UIColor blackColor] forState:UIControlStateDisabled];
  159. [self.goButton setTitleColor:[UIColor blackColor] forState:UIControlStateFocused];
  160. [self.textArea setBackgroundColor:[UIColor blackColor]];
  161. [self.textArea setTextColor:[UIColor colorFromHex:@"CACBCA"]];
  162. //DB1E00
  163. //CACBCA
  164. }
  165. -(void)handleDoubleTapMenuOrPlayPause:(UITapGestureRecognizer *)sender {
  166. if (sender.state == UIGestureRecognizerStateEnded) {
  167. NSString *kpplessString = @"KPPless: OFF";
  168. if (kppless) {
  169. kpplessString = @"KPPless: ON";
  170. }
  171. UIAlertController *alertController = [UIAlertController
  172. alertControllerWithTitle:@"KPPless?"
  173. message:@"Turn KPPless on if you are attempting to futurerestore to a newer version"
  174. preferredStyle:UIAlertControllerStyleAlert];
  175. UIAlertAction *kpplessAction = [UIAlertAction
  176. actionWithTitle:kpplessString
  177. style:UIAlertActionStyleDefault
  178. handler:^(UIAlertAction *action)
  179. {
  180. kppless = !kppless;
  181. }];
  182. [alertController addAction:kpplessAction];
  183. UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
  184. [alertController addAction:cancel];
  185. [self presentViewController:alertController animated:YES completion:nil];
  186. }
  187. }
  188. - (void)setGoButtonTitle:(NSString *)title {
  189. dispatch_async(dispatch_get_main_queue(), ^{
  190. [self.goButton setTitle:title forState:UIControlStateNormal];
  191. [self.goButton setTitle:title forState:UIControlStateDisabled];
  192. [self.goButton setTitle:title forState:UIControlStateFocused];
  193. });
  194. }
  195. - (void)viewDidLoad {
  196. [super viewDidLoad];
  197. kppless = FALSE;
  198. thisClass = self;
  199. [self customTVSetup];
  200. [self.goButton.layer setCornerRadius:5];
  201. [self.creditsButton.layer setCornerRadius:5];
  202. [self.websiteButton.layer setCornerRadius:5];
  203. NSString *buildDate = [NSString stringWithContentsOfFile:[NSString stringWithFormat:@"%s", bundled_file("build_time")]
  204. encoding:NSUTF8StringEncoding
  205. error:nil];
  206. [self.versionLabel setText:[NSString stringWithFormat:@"%@: %@", Version, buildDate]];
  207. jailbreak_has_run = check_for_jailbreak();
  208. //[self doUpdateCheck];
  209. // Log current device and version info
  210. osVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
  211. [self writeTextPlain:[NSString stringWithFormat:@"> %@", Version]];
  212. [self writeTextPlain:@"> Includes software / explots by Ian Beer, CoolStar, Jaywalker, nitoTV, nullpixel, PsychoTea, pwn20wnd, Siguza and tihmstar" ];
  213. if (self.installMode == BSInstallTypeUnsupported) {
  214. [self writeTextPlain:@"> backr00m does not work on versions of iOS other than iOS 10.2.2, 11.0 and 11.1."];
  215. [self writeTextPlain:[NSString stringWithFormat:@"> found iOS version %@", [self getVersionString]]];
  216. [self.goButton setHidden:YES];
  217. return;
  218. }
  219. /*
  220. if (osVersion.majorVersion != 10) {
  221. [self writeTextPlain:@"> Meridian does not work on versions of iOS other than iOS 10."];
  222. [self writeTextPlain:[NSString stringWithFormat:@"> found iOS version %@", [self getVersionString]]];
  223. [self.goButton setHidden:YES];
  224. return;
  225. }
  226. */
  227. [self writeTextPlain:[NSString stringWithFormat:@"> %s on iOS %@ (Build %@)",
  228. [self getDeviceIdentifier],
  229. [self getVersionString],
  230. [self getBuildString]]];
  231. if (jailbreak_has_run) {
  232. [self writeTextPlain:@"> already jailbroken."];
  233. // set done button
  234. [self.goButton setTitle:@"done" forState:UIControlStateFocused];
  235. // aaaaand grey it out
  236. [self.goButton setEnabled:NO];
  237. [self.goButton setAlpha:0.5];
  238. return;
  239. }
  240. /*
  241. // Device is already jailbroken, but not with Meridian
  242. if (file_exists("/private/var/lib/dpkg/status") == 0 &&
  243. file_exists("/meridian/.installed") != 0) {
  244. [self writeTextPlain:@"this device has already been jailbroken with another tool. please run Cydia Eraser to wipe this device to ensure you encounter no issues with Meridian"];
  245. [self.goButton setTitle:@"please erase" forState:UIControlStateFocused];
  246. [self.goButton setEnabled:NO];
  247. [self.goButton setAlpha:0.5];
  248. return;
  249. }
  250. */
  251. if (self.installMode == BSInstallTypeMeridian) {
  252. playPauseOrMenuDoubleTapRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTapMenuOrPlayPause:)];
  253. playPauseOrMenuDoubleTapRecognizer.numberOfTapsRequired = 2;
  254. playPauseOrMenuDoubleTapRecognizer.allowedPressTypes = @[[NSNumber numberWithInteger:UIPressTypePlayPause], [NSNumber numberWithInteger:UIPressTypeMenu]];
  255. [self.view addGestureRecognizer:playPauseOrMenuDoubleTapRecognizer];
  256. if ([self shouldShowTimer]){
  257. [self showWaitTimer];
  258. }
  259. }
  260. NSLog(@"App bundle directory: %s", bundle_path());
  261. }
  262. - (BOOL)shouldShowTimer {
  263. int waitTime;
  264. return ((waitTime = 90 - uptime()) > 0);
  265. }
  266. - (void)showWaitTimer {
  267. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void) {
  268. int waitTime;
  269. while ((waitTime = 90 - uptime()) > 0) {
  270. dispatch_async(dispatch_get_main_queue(), ^{
  271. NSString *wt2 = [NSString stringWithFormat:@"wait: %d", waitTime];
  272. //NSLog(@"%@", wt2);
  273. [self.goButton setTitle:wt2 forState:UIControlStateFocused];
  274. [self.goButton setTitle:wt2 forState:UIControlStateNormal];
  275. [self.goButton setTitle:wt2 forState:UIControlStateDisabled];
  276. [self.goButton setTitle:wt2 forState:UIControlStateHighlighted];
  277. //[self.goButton setEnabled:false];
  278. [self.goButton setAlpha:0.6];
  279. });
  280. sleep(1);
  281. }
  282. dispatch_async(dispatch_get_main_queue(), ^{
  283. [self.goButton setTitle:@"go" forState:UIControlStateFocused];
  284. [self.goButton setEnabled:true];
  285. [self.goButton setAlpha:1];
  286. [self writeTextPlain:@"> ready."];
  287. });
  288. });
  289. }
  290. - (IBAction)goButtonPressed:(UIButton *)sender {
  291. if (self.installMode == BSInstallTypeElectra) {
  292. [self doit:nil];
  293. return;
  294. }
  295. if (sender.alpha != 1) {
  296. return;
  297. }
  298. // when jailbreak runs, 'go' button is
  299. // turned to 'respring'
  300. if (jailbreak_has_run) {
  301. int rv = respring();
  302. if (rv != 0) {
  303. [self writeTextPlain:@"failed to respring."];
  304. }
  305. return;
  306. }
  307. //not sure what this is all about, why would we want to reboot?
  308. /*
  309. // if we've run once, just reboot
  310. if (has_run_once) {
  311. [self.goButton setHidden:YES];
  312. restart_device();
  313. return;
  314. }
  315. */
  316. // set up the UI to 'running' state
  317. [self.goButton setEnabled:NO];
  318. [self.goButton setHidden:YES];
  319. [self.creditsButton setEnabled:NO];
  320. self.creditsButton.alpha = 0.5;
  321. [self.websiteButton setEnabled:NO];
  322. self.websiteButton.alpha = 0.5;
  323. [self.progressSpinner startAnimating];
  324. has_run_once = true;
  325. // background thread so we can update the UI
  326. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void) {
  327. int ret = makeShitHappen(self, kppless);
  328. if (ret != 0) {
  329. NSLog(@"MERIDIAN HAS FAILED TO RUN :(");
  330. dispatch_async(dispatch_get_main_queue(), ^{
  331. [self exploitFailed];
  332. });
  333. return;
  334. }
  335. dispatch_async(dispatch_get_main_queue(), ^{
  336. [self exploitSucceeded];
  337. });
  338. });
  339. }
  340. - (IBAction)websiteButtonPressed:(UIButton *)sender {
  341. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://meridian.sparkes.zone"]
  342. options:@{}
  343. completionHandler:nil];
  344. }
  345. - (char *)getDeviceIdentifier {
  346. static struct utsname u;
  347. uname(&u);
  348. return u.machine;
  349. }
  350. - (NSString *)getVersionString {
  351. return [NSString stringWithFormat:@"%ld.%ld.%ld",
  352. (long)osVersion.majorVersion,
  353. (long)osVersion.minorVersion,
  354. (long)osVersion.patchVersion];
  355. }
  356. - (NSString *)getBuildString {
  357. CFDictionaryRef dict= NULL;
  358. CFStringRef str = NULL;
  359. dict = _CFCopyServerVersionDictionary();
  360. if (dict == NULL)
  361. dict = _CFCopySystemVersionDictionary();
  362. str = CFDictionaryGetValue(dict, CFSTR("ProductBuildVersion"));
  363. //NSLog(@"pbv: %@", str);
  364. return (__bridge NSString *)str;
  365. }
  366. - (void)exploitSucceeded {
  367. jailbreak_has_run = true;
  368. [self writeTextPlain:@"\n> your device has been freed! \n"];
  369. [self writeTextPlain:@"note: please click 'respring' to get this party started :) \n"];
  370. //if you want to run anything post process on device you can do it here for diagnostic purposes.
  371. /*
  372. execprog("/bin/ps", (const char **)&(const char *[]) {
  373. "/bin/ps",
  374. "awwwx",
  375. NULL
  376. });
  377. execprog("/usr/bin/ls", (const char **)&(const char *[]) {
  378. "/usr/bin/ls",
  379. "-alR",
  380. "/private/etc",
  381. NULL
  382. });
  383. */
  384. /*
  385. execprog("/bin/bash", (const char **)&(const char *[]) {
  386. "/bin/bash",
  387. NULL
  388. });
  389. */
  390. [self.progressSpinner stopAnimating];
  391. [self.goButton setEnabled:YES];
  392. [self.goButton setHidden:NO];
  393. [self.goButton setTitle:@"respring" forState:UIControlStateFocused];
  394. [self.creditsButton setEnabled:YES];
  395. self.creditsButton.alpha = 1;
  396. [self.websiteButton setEnabled:YES];
  397. self.websiteButton.alpha = 1;
  398. }
  399. - (void)exploitFailed {
  400. [self writeTextPlain:@"exploit failed. please reboot & try again."];
  401. [self.goButton setEnabled:YES];
  402. [self.goButton setHidden:NO];
  403. [self.goButton setTitle:@"reboot" forState:UIControlStateFocused];
  404. [self.creditsButton setEnabled:YES];
  405. [self.creditsButton setAlpha:1];
  406. [self.websiteButton setEnabled:YES];
  407. [self.websiteButton setAlpha:1];
  408. [self.progressSpinner stopAnimating];
  409. }
  410. - (void)doUpdateCheck {
  411. // skip the version check if we're running an internal build
  412. if ([Version containsString:@"Internal"]) {
  413. return;
  414. }
  415. NSURL *url = [NSURL URLWithString:@"https://meridian.sparkes.zone/latest"];
  416. NSURLSessionDataTask *downloadTask = [[NSURLSession sharedSession]
  417. dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *header, NSError *error) {
  418. if (error != nil) {
  419. NSLog(@"failed to get information from the update server.");
  420. return;
  421. }
  422. NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  423. if (response != Version) {
  424. [self doUpdatePopup:response];
  425. }
  426. }];
  427. [downloadTask resume];
  428. }
  429. - (void)doUpdatePopup:(NSString *)update {
  430. NSString *message = [NSString stringWithFormat:@"An update is available for Meridian: %@It can be downloaded from the website.", update];
  431. UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Meridian Update"
  432. message:message
  433. preferredStyle:UIAlertControllerStyleAlert];
  434. UIAlertAction *websiteAction = [UIAlertAction actionWithTitle:@"Website" style:UIAlertActionStyleDefault
  435. handler:^(UIAlertAction * action) {
  436. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://meridian.sparkes.zone"]
  437. options:@{}
  438. completionHandler:nil];
  439. }];
  440. UIAlertAction *closeAction = [UIAlertAction actionWithTitle:@"Close"
  441. style:UIAlertActionStyleCancel
  442. handler:nil];
  443. [alert addAction:websiteAction];
  444. [alert addAction:closeAction];
  445. [self presentViewController:alert animated:YES completion:nil];
  446. }
  447. - (void)writeText:(NSString *)message {
  448. dispatch_async(dispatch_get_main_queue(), ^{
  449. if (![message isEqual: @"done!"] && ![message isEqual:@"failed!"]) {
  450. NSLog(@"%@", message);
  451. _textArea.text = [_textArea.text stringByAppendingString:[NSString stringWithFormat:@"%@ ", message]];
  452. } else {
  453. _textArea.text = [_textArea.text stringByAppendingString:[NSString stringWithFormat:@"%@\n", message]];
  454. }
  455. NSRange bottom = NSMakeRange(_textArea.text.length - 1, 1);
  456. [self.textArea scrollRangeToVisible:bottom];
  457. });
  458. }
  459. - (void)writeTextPlain:(NSString *)message, ... {
  460. va_list args;
  461. va_start(args, message);
  462. message = [[NSString alloc] initWithFormat:[message stringByAppendingString:@"\n"] arguments:args];
  463. dispatch_async(dispatch_get_main_queue(), ^{
  464. _textArea.text = [_textArea.text stringByAppendingString:message];
  465. NSRange bottom = NSMakeRange(_textArea.text.length - 1, 1);
  466. [self.textArea scrollRangeToVisible:bottom];
  467. NSLog(@"%@", message);
  468. });
  469. va_end(args);
  470. }
  471. // kinda dumb, kinda lazy, ¯\_(ツ)_/¯
  472. void log_message(NSString *message) {
  473. [thisClass writeTextPlain:message];
  474. }
  475. #pragma mark ELECTRA
  476. - (IBAction)doit:(id)sender {
  477. if (_respringReady) {
  478. [self writeText:@"Respringing please wait..."];
  479. [NSTask launchedTaskWithLaunchPath:@"/usr/bin/killall" arguments:@[@"-9", @"backboardd"]];
  480. return;
  481. }
  482. NSLog(@"DO IT!");
  483. [self.goButton setEnabled:NO];
  484. [self.goButton setHidden:YES];
  485. [self writeText:@"Starting jailbreak..."];
  486. currentViewController = self;
  487. [self.goButton setTitle:@"Please Wait (1/3)" forState:UIControlStateNormal];
  488. BOOL shouldEnableTweaks = YES;
  489. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), ^{
  490. mach_port_t user_client;
  491. mach_port_t tfp0 = get_tfp0(&user_client);
  492. dispatch_async(dispatch_get_main_queue(), ^{
  493. [self.goButton setTitle:@"Please Wait (2/3)" forState:UIControlStateNormal];
  494. });
  495. int jailbreakstatus = begin_fun(tfp0, user_client, shouldEnableTweaks);
  496. if (jailbreakstatus == 0){
  497. [self setGoButtonTitle:@"Respring"];
  498. dispatch_async(dispatch_get_main_queue(), ^{
  499. //[self.goButton setTitle:@"Jailbroken" forState:UIControlStateNormal];
  500. [self writeText:@"\nFREEEEEEEEDOM!!!!!\n"];
  501. [self writeText:@"\nPlease select respring to continue!\n"];
  502. [self.goButton setEnabled:TRUE];
  503. [self.goButton setHidden:FALSE];
  504. _respringReady = TRUE;
  505. /*
  506. UIAlertController *dropbearRunning = [UIAlertController alertControllerWithTitle:@"Dropbear Running" message:@"Dropbear is now running! Enjoy." preferredStyle:UIAlertControllerStyleAlert];
  507. [dropbearRunning addAction:[UIAlertAction actionWithTitle:@"Exit" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
  508. [dropbearRunning dismissViewControllerAnimated:YES completion:nil];
  509. //exit(0);
  510. [NSTask launchedTaskWithLaunchPath:@"/usr/bin/killall" arguments:@[@"-9", @"backboardd"]];
  511. }]];
  512. [self presentViewController:dropbearRunning animated:YES completion:nil];
  513. */
  514. });
  515. } else if (jailbreakstatus == -1) {
  516. dispatch_async(dispatch_get_main_queue(), ^{
  517. [self.goButton setTitle:@"Already Jailbroken" forState:UIControlStateNormal];
  518. });
  519. } else if (jailbreakstatus == -2) {
  520. dispatch_async(dispatch_get_main_queue(), ^{
  521. [self.goButton setTitle:@"Error: topanga" forState:UIControlStateNormal];
  522. });
  523. } else if (jailbreakstatus == -3) {
  524. dispatch_async(dispatch_get_main_queue(), ^{
  525. [self.goButton setTitle:@"Error: amfid patch" forState:UIControlStateNormal];
  526. });
  527. } else {
  528. dispatch_async(dispatch_get_main_queue(), ^{
  529. [self.goButton setTitle:@"Error Jailbreaking" forState:UIControlStateNormal];
  530. });
  531. }
  532. //NSLog(@" ♫ KPP never bothered me anyway... ♫ ");
  533. [self writeText:@"\n ♫ KPP never bothered me anyway... ♫ \n"];
  534. });
  535. }
  536. - (void)removingLiberiOS {
  537. dispatch_async(dispatch_get_main_queue(), ^{
  538. //[self.goButton setTitle:@"Removing liberiOS" forState:UIControlStateNormal];
  539. [self writeText:@"Removing liberiOS"];
  540. });
  541. }
  542. - (void)removingElectraBeta {
  543. dispatch_async(dispatch_get_main_queue(), ^{
  544. //[self.goButton setTitle:@"Removing beta" forState:UIControlStateNormal];
  545. [self writeText:@"Removing beta"];
  546. });
  547. }
  548. - (void)installingNitoTV {
  549. dispatch_async(dispatch_get_main_queue(), ^{
  550. //[self.goButton setTitle:@"Installing Cydia" forState:UIControlStateNormal];
  551. [self writeText:@"Installing nitoTV\n"];
  552. });
  553. }
  554. - (void)cydiaDone {
  555. dispatch_async(dispatch_get_main_queue(), ^{
  556. [self.goButton setTitle:@"Please Wait (2/3)" forState:UIControlStateNormal];
  557. });
  558. }
  559. - (void)displaySnapshotNotice {
  560. dispatch_async(dispatch_get_main_queue(), ^{
  561. [self.goButton setTitle:@"user prompt" forState:UIControlStateNormal];
  562. UIAlertController *apfsNoticeController = [UIAlertController alertControllerWithTitle:@"APFS Snapshot Created" message:@"An APFS Snapshot has been successfully created! You may be able to use SemiRestore to restore your phone to this snapshot in the future." preferredStyle:UIAlertControllerStyleAlert];
  563. [apfsNoticeController addAction:[UIAlertAction actionWithTitle:@"Continue Jailbreak" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  564. [self.goButton setTitle:@"Please Wait (2/3)" forState:UIControlStateNormal];
  565. snapshotWarningRead();
  566. }]];
  567. [self presentViewController:apfsNoticeController animated:YES completion:nil];
  568. });
  569. }
  570. - (void)displaySnapshotWarning {
  571. dispatch_async(dispatch_get_main_queue(), ^{
  572. [self.goButton setTitle:@"user prompt" forState:UIControlStateNormal];
  573. UIAlertController *apfsWarningController = [UIAlertController alertControllerWithTitle:@"APFS Snapshot Not Found" message:@"Warning: Your device was bootstrapped using a pre-release version of Electra and thus does not have an APFS Snapshot present. While Electra may work fine, you will not be able to use SemiRestore to restore to stock if you need to. Please clean your device and re-bootstrap with this version of Electra to create a snapshot." preferredStyle:UIAlertControllerStyleAlert];
  574. [apfsWarningController addAction:[UIAlertAction actionWithTitle:@"Continue Jailbreak" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  575. [self.goButton setTitle:@"Please Wait (2/3)" forState:UIControlStateNormal];
  576. snapshotWarningRead();
  577. }]];
  578. [self presentViewController:apfsWarningController animated:YES completion:nil];
  579. });
  580. }
  581. - (UIStatusBarStyle)preferredStatusBarStyle {
  582. return UIStatusBarStyleLightContent;
  583. }
  584. - (void)dealloc {
  585. [[NSNotificationCenter defaultCenter] removeObserver:self];
  586. }
  587. @end