ViewController.m 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  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. #import "Reachability.h"
  17. //electra
  18. #import "NSTask.h"
  19. #include "async_wake.h"
  20. #include "fun.h"
  21. #include "codesign.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <unistd.h>
  25. #include <string.h>
  26. #include <dlfcn.h>
  27. CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
  28. CF_EXPORT CFDictionaryRef _CFCopyServerVersionDictionary(void);
  29. static ViewController *currentViewController;
  30. typedef NS_ENUM(NSInteger, BSInstallType) {
  31. BSInstallTypeUnsupported,
  32. BSInstallTypeMeridian,
  33. BSInstallTypeElectra,
  34. };
  35. @interface ViewController () {
  36. BOOL _respringReady;
  37. UITapGestureRecognizer *playPauseOrMenuDoubleTapRecognizer;
  38. BOOL kppless;
  39. }
  40. @property (readwrite, assign) BSInstallType installMode; //0 = meridian 1 = electra
  41. @property (strong, nonatomic) UIButton *goButton;
  42. @property (strong, nonatomic) UIButton *creditsButton;
  43. @property (strong, nonatomic) UIButton *websiteButton;
  44. @property (strong, nonatomic) UIActivityIndicatorView *progressSpinner;
  45. @property (strong, nonatomic) UITextView *textArea;
  46. @property (strong, nonatomic) UILabel *versionLabel;
  47. @end
  48. NSString *Version = @"backr00m: 1.2.2";
  49. NSOperatingSystemVersion osVersion;
  50. id thisClass;
  51. bool has_run_once = false;
  52. bool jailbreak_has_run = false;
  53. @implementation FocusedButton
  54. - (instancetype)initWithCoder:(NSCoder *)coder
  55. {
  56. self = [super initWithCoder:coder];
  57. if (self) {
  58. self.layer.cornerRadius = 5;
  59. self.backgroundColor = [UIColor lightGrayColor];
  60. self.focusColor = [UIColor redColor];
  61. self.unfocusedColor = [UIColor lightGrayColor];
  62. }
  63. return self;
  64. }
  65. - (id)initForAutoLayout {
  66. self = [super initForAutoLayout];
  67. if (self) {
  68. self.layer.cornerRadius = 5;
  69. self.backgroundColor = [UIColor lightGrayColor];
  70. self.focusColor = [UIColor redColor];
  71. self.unfocusedColor = [UIColor lightGrayColor];
  72. }
  73. return self;
  74. }
  75. - (void)buttonColors:(UIColor *)focusedColor andUnfocused:(UIColor *)unfocusedColor {
  76. self.focusColor = focusedColor;
  77. self.unfocusedColor = unfocusedColor;
  78. self.backgroundColor = unfocusedColor;
  79. }
  80. - (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator {
  81. [coordinator addCoordinatedAnimations:^{
  82. if (self.focused) {
  83. self.backgroundColor = self.focusColor;
  84. self.transform = CGAffineTransformMakeScale(1.1, 1.1);
  85. self.layer.shadowColor = [UIColor blackColor].CGColor;
  86. self.layer.shadowOffset = CGSizeMake(0, 27);
  87. self.layer.shadowOpacity = 0.25;
  88. self.layer.shadowRadius = 10;
  89. self.clipsToBounds = NO;
  90. }
  91. else {
  92. self.transform = CGAffineTransformIdentity;
  93. self.backgroundColor = self.unfocusedColor;
  94. self.clipsToBounds = YES;
  95. }
  96. } completion:nil];
  97. }
  98. @end
  99. @implementation ViewController
  100. #define NB [NSBundle mainBundle]
  101. #define UD [NSUserDefaults standardUserDefaults]
  102. #define FM [NSFileManager defaultManager]
  103. #define LAST_UPDATE_CHECK @"lastSelfUpdateCheck"
  104. #define UPDATE_CHECK_FREQUENCY @"updateCheckFrequency"
  105. #define NOW_STRING [df stringFromDate:[NSDate date]]
  106. #define CHECK_FREQ [UD integerForKey:UPDATE_CHECK_FREQUENCY]
  107. - (void)_updateDateCheck
  108. {
  109. NSDateFormatter *df = [[NSDateFormatter alloc] init];
  110. [df setDateFormat:@"MMddyy_HHmmss"];
  111. NSString *newDate = [df stringFromDate:[NSDate date]];
  112. [UD setObject:newDate forKey:LAST_UPDATE_CHECK];
  113. }
  114. - (NSString *)_lastCheckDate
  115. {
  116. return [UD objectForKey:LAST_UPDATE_CHECK];
  117. }
  118. - (NSString *)updatePlist {
  119. return [[ViewController documentsFolder] stringByAppendingPathComponent:@"meridian.plist"];
  120. }
  121. -(BOOL)_shouldCheckUpdate
  122. {
  123. // return true;
  124. if (![FM fileExistsAtPath:[self updatePlist]])
  125. {
  126. return YES;
  127. }
  128. NSDateFormatter *df = [[NSDateFormatter alloc] init];
  129. [df setDateFormat:@"MMddyy_HHmmss"];
  130. NSDate *myDate = [df dateFromString: [self _lastCheckDate]];
  131. NSDate *now = [df dateFromString:NOW_STRING];
  132. double timeSinceDate = [now timeIntervalSinceDate:myDate];
  133. double minutes = (timeSinceDate / 60);
  134. NSLog(@"minutes: %g",minutes ); //minutes since check
  135. if (minutes > CHECK_FREQ) //FIXME change to higher value!!!
  136. {
  137. [self _updateDateCheck];
  138. return YES;
  139. }
  140. return NO;
  141. }
  142. + (NSString *)documentsFolder
  143. {
  144. NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  145. return [paths objectAtIndex:0];
  146. }
  147. - (NSURL *)remotePathURL { return [NSURL URLWithString:@"https://nitosoft.com/ATV4/backr00m/meridian.plist"]; };
  148. //us.scw.afctwoadd
  149. + (void)validateFile:(NSString *)inputFile withChecksum:(NSString *)checksum completion:(void(^)(BOOL valid))completeBlock
  150. {
  151. //LOG_SELF;
  152. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
  153. NSTask *sslTask = [[NSTask alloc] init];
  154. NSPipe *sspipe = [[NSPipe alloc] init];
  155. NSFileHandle *ssh = [sspipe fileHandleForReading];
  156. [sslTask setLaunchPath:@"/usr/bin/openssl"];
  157. [sslTask setArguments:[NSArray arrayWithObjects:@"sha1", inputFile, nil]];
  158. [sslTask setStandardOutput:sspipe];
  159. [sslTask setStandardError:sspipe];
  160. [sslTask launch];
  161. NSData *outData = [ssh readDataToEndOfFile];
  162. [sslTask waitUntilExit];
  163. NSString *outputString = [[[NSString alloc] initWithData:outData
  164. encoding:NSASCIIStringEncoding]
  165. stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  166. //example outputString: SHA1(~/Documents/Tether/AppleTV2,1_4.3_8F455_Restore.ipsw)= b6a2b0baae79daf95f75044c12946839c662d01d
  167. //b6a2b0baae79daf95f75044c12946839c662d01d cleaned up
  168. NSString *outputSHA = [[[outputString componentsSeparatedByString:@"="] lastObject] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  169. NSLog(@"sha1: %@ against: %@", outputSHA, checksum);
  170. if ([outputSHA isEqualToString:checksum])
  171. {
  172. sslTask = nil;
  173. sspipe = nil;
  174. completeBlock(YES);
  175. }
  176. sslTask = nil;
  177. sspipe = nil;
  178. completeBlock(NO);
  179. });
  180. }
  181. - (void)checkForUpdate //change update check to look for a typedef int rather than bool, then we can say 0 == update nitotv 1 = update essential 2 = both -1 = none?
  182. {
  183. @autoreleasepool {
  184. if ([self _shouldCheckUpdate] == FALSE)
  185. {
  186. NSLog(@"checked within the last %li minutes!!!", (long)CHECK_FREQ);
  187. //return nil;
  188. return;
  189. }
  190. BOOL internetAvailable = [Reachability isInternetReachable];
  191. if (internetAvailable == TRUE)
  192. {
  193. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
  194. NSDictionary *theDict = [NSDictionary dictionaryWithContentsOfURL:[self remotePathURL]];
  195. //lastUpdated
  196. //bootstrapInfo
  197. //meridianToolsInfo
  198. //electraToolsInfo
  199. //version
  200. //link
  201. //SHA1
  202. NSLog(@"science bro: %@", theDict);
  203. });
  204. // NSArray *updateArray = [packageManagement basicEssentialUpdatesAvailable];
  205. // if ([updateArray count] > 0)
  206. // {
  207. // [[NSNotificationCenter defaultCenter] postNotificationName:@"CheckForUpdate" object:updateArray userInfo:nil];
  208. // //return updateArray;
  209. // }
  210. }
  211. }
  212. //return nil;
  213. }
  214. - (void)checkForUpdatedPayloads {
  215. }
  216. + (instancetype)currentViewController {
  217. return currentViewController;
  218. }
  219. #define PROC_PIDPATHINFO_MAXSIZE (4*MAXPATHLEN)
  220. - (void)customTVSetup {
  221. //redudant
  222. /*
  223. if (kCFCoreFoundationVersionNumber < 1443 || kCFCoreFoundationVersionNumber > 1445.32){
  224. [self.goButton setEnabled:NO];
  225. [self.goButton setTitle:@"Version Error" forState:UIControlStateNormal];
  226. }
  227. uint32_t flags;
  228. csops(getpid(), CS_OPS_STATUS, &flags, 0);
  229. if ((flags & CS_PLATFORM_BINARY)){
  230. [self.goButton setEnabled:NO];
  231. [self.goButton setTitle:@"Already Jailbroken" forState:UIControlStateNormal];
  232. }
  233. */
  234. _respringReady = FALSE;
  235. [self writeTextPlain:@">"];
  236. self.installMode = BSInstallTypeUnsupported;
  237. if (SYSTEM_VERSION_EQUAL_TO(@"10.2.2")){
  238. self.installMode = BSInstallTypeMeridian;
  239. [self writeTextPlain:@"> 10.2.2 detected, using Meridian based jailbreak. Thanks PsychoTea!"];
  240. } else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0") && SYSTEM_VERSION_LESS_THAN(@"11.2") ){
  241. self.installMode = BSInstallTypeElectra;
  242. [self writeTextPlain:@"> 11.x detected, using Electra based jailbreak. Thanks Electra Team!"];
  243. }
  244. UIImageView *bgImageView = [[UIImageView alloc] initForAutoLayout];
  245. [self.view addSubview:bgImageView];
  246. [bgImageView autoPinEdgesToSuperviewEdges];
  247. [bgImageView setImage:[UIImage imageNamed:@"bgTemp.jpg"]];
  248. UILabel *meridianTV = [[UILabel alloc] initForAutoLayout];
  249. [self.view addSubview:meridianTV];
  250. [meridianTV autoAlignAxisToSuperviewAxis:ALAxisVertical];
  251. [meridianTV autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:160];
  252. [meridianTV setFont:[UIFont systemFontOfSize:205 weight:UIFontWeightHeavy]];
  253. [meridianTV setText:@"backr00m"];
  254. [meridianTV setTextColor:[UIColor whiteColor]];
  255. self.goButton = [UIButton buttonWithType:UIButtonTypeSystem];
  256. [self.goButton autoSetDimensionsToSize:CGSizeMake(250, 100)];
  257. [self.goButton setTitle:@"jailbreak" forState:UIControlStateFocused];
  258. //[self.goButton buttonColors:[UIColor colorFromHex:@"DB1E00"]
  259. // andUnfocused:[UIColor darkTextColor]];
  260. [self.view addSubview:self.goButton];
  261. [self.goButton autoCenterInSuperview];
  262. [self.goButton addTarget:self action:@selector(goButtonPressed:) forControlEvents:UIControlEventPrimaryActionTriggered];
  263. self.versionLabel = [[UILabel alloc] initForAutoLayout];
  264. self.versionLabel.textColor = [UIColor whiteColor];
  265. [self.view addSubview:self.versionLabel];
  266. [self.versionLabel autoAlignAxisToSuperviewAxis:ALAxisVertical];
  267. [self.versionLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.goButton withOffset:10];
  268. self.textArea = [[UITextView alloc] initForAutoLayout];
  269. [self.view addSubview:self.textArea];
  270. [self.textArea autoAlignAxisToSuperviewAxis:ALAxisVertical];
  271. [self.textArea autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.versionLabel];
  272. [self.textArea autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.view withMultiplier:0.8];
  273. [self.textArea autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:40];
  274. //[self.goButton setBackgroundColor:[UIColor colorFromHex:@"DB1E00"]];
  275. [self.goButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  276. [self.goButton setTitleColor:[UIColor blackColor] forState:UIControlStateDisabled];
  277. [self.goButton setTitleColor:[UIColor blackColor] forState:UIControlStateFocused];
  278. [self.textArea setBackgroundColor:[UIColor blackColor]];
  279. [self.textArea setTextColor:[UIColor colorFromHex:@"CACBCA"]];
  280. //DB1E00
  281. //CACBCA
  282. }
  283. -(void)handleDoubleTapMenuOrPlayPause:(UITapGestureRecognizer *)sender {
  284. if (sender.state == UIGestureRecognizerStateEnded) {
  285. NSString *kpplessString = @"KPPless: OFF";
  286. if (kppless) {
  287. kpplessString = @"KPPless: ON";
  288. }
  289. UIAlertController *alertController = [UIAlertController
  290. alertControllerWithTitle:@"KPPless?"
  291. message:@"Turn KPPless on if you are attempting to futurerestore to a newer version"
  292. preferredStyle:UIAlertControllerStyleAlert];
  293. UIAlertAction *kpplessAction = [UIAlertAction
  294. actionWithTitle:kpplessString
  295. style:UIAlertActionStyleDefault
  296. handler:^(UIAlertAction *action)
  297. {
  298. kppless = !kppless;
  299. }];
  300. [alertController addAction:kpplessAction];
  301. UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
  302. [alertController addAction:cancel];
  303. [self presentViewController:alertController animated:YES completion:nil];
  304. }
  305. }
  306. - (IBAction)tappedOnSetNonce:(id)sender {
  307. __block NSString *generatorToSet = nil;
  308. NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  309. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:localize(@"Set the system boot nonce on jailbreak") message:localize(@"Enter the generator for the nonce you want the system to generate on boot") preferredStyle:UIAlertControllerStyleAlert];
  310. [alertController addAction:[UIAlertAction actionWithTitle:localize(@"Cancel") style:UIAlertActionStyleDefault handler:nil]];
  311. UIAlertAction *set = [UIAlertAction actionWithTitle:localize(@"Set") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  312. const char *generatorInput = [alertController.textFields.firstObject.text UTF8String];
  313. char compareString[22];
  314. uint64_t rawGeneratorValue;
  315. sscanf(generatorInput, "0x%16llx",&rawGeneratorValue);
  316. sprintf(compareString, "0x%016llx", rawGeneratorValue);
  317. if(strcmp(compareString, generatorInput) != 0) {
  318. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:localize(@"Error") message:localize(@"Failed to validate generator") preferredStyle:UIAlertControllerStyleAlert];
  319. [alertController addAction:[UIAlertAction actionWithTitle:localize(@"OK") style:UIAlertActionStyleDefault handler:nil]];
  320. [self presentViewController:alertController animated:YES completion:nil];
  321. return;
  322. }
  323. generatorToSet = [NSString stringWithUTF8String:generatorInput];
  324. [userDefaults setObject:generatorToSet forKey:@K_GENERATOR];
  325. [userDefaults synchronize];
  326. uint32_t flags;
  327. csops(getpid(), CS_OPS_STATUS, &flags, 0);
  328. UIAlertController *alertController = nil;
  329. if ((flags & CS_PLATFORM_BINARY)) {
  330. alertController = [UIAlertController alertControllerWithTitle:localize(@"Notice") message:localize(@"The system boot nonce will be set the next time you enable your jailbreak") preferredStyle:UIAlertControllerStyleAlert];
  331. } else {
  332. alertController = [UIAlertController alertControllerWithTitle:localize(@"Notice") message:localize(@"The system boot nonce will be set once you enable the jailbreak") preferredStyle:UIAlertControllerStyleAlert];
  333. }
  334. [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
  335. [self presentViewController:alertController animated:YES completion:nil];
  336. }];
  337. [alertController addAction:set];
  338. [alertController setPreferredAction:set];
  339. [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
  340. textField.placeholder = [NSString stringWithFormat:@"%s", genToSet()];
  341. }];
  342. [self presentViewController:alertController animated:YES completion:nil];
  343. }
  344. - (void)setGoButtonTitle:(NSString *)title {
  345. dispatch_async(dispatch_get_main_queue(), ^{
  346. [self.goButton setTitle:title forState:UIControlStateNormal];
  347. [self.goButton setTitle:title forState:UIControlStateDisabled];
  348. [self.goButton setTitle:title forState:UIControlStateFocused];
  349. });
  350. }
  351. - (void)viewDidLoad {
  352. [super viewDidLoad];
  353. kppless = FALSE;
  354. thisClass = self;
  355. [self customTVSetup];
  356. [self.goButton.layer setCornerRadius:5];
  357. [self.creditsButton.layer setCornerRadius:5];
  358. [self.websiteButton.layer setCornerRadius:5];
  359. NSString *buildDate = [NSString stringWithContentsOfFile:[NSString stringWithFormat:@"%s", bundled_file("build_time")]
  360. encoding:NSUTF8StringEncoding
  361. error:nil];
  362. [self.versionLabel setText:[NSString stringWithFormat:@"%@: %@", Version, buildDate]];
  363. jailbreak_has_run = check_for_jailbreak();
  364. //[self doUpdateCheck];
  365. // Log current device and version info
  366. osVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
  367. [self writeTextPlain:[NSString stringWithFormat:@"> %@", Version]];
  368. [self writeTextPlain:@"> Includes software / explots by Ian Beer, CoolStar, Jaywalker, nitoTV, nullpixel, PsychoTea, pwn20wnd, Siguza, stek29 and xerub" ];
  369. if (self.installMode == BSInstallTypeUnsupported) {
  370. [self writeTextPlain:@"> backr00m does not work on versions of iOS other than iOS 10.2.2, 11.0 and 11.1."];
  371. [self writeTextPlain:[NSString stringWithFormat:@"> found iOS version %@", [self getVersionString]]];
  372. [self.goButton setHidden:YES];
  373. return;
  374. }
  375. /*
  376. if (osVersion.majorVersion != 10) {
  377. [self writeTextPlain:@"> Meridian does not work on versions of iOS other than iOS 10."];
  378. [self writeTextPlain:[NSString stringWithFormat:@"> found iOS version %@", [self getVersionString]]];
  379. [self.goButton setHidden:YES];
  380. return;
  381. }
  382. */
  383. [self writeTextPlain:[NSString stringWithFormat:@"> %s on iOS %@ (Build %@)",
  384. [self getDeviceIdentifier],
  385. [self getVersionString],
  386. [self getBuildString]]];
  387. if (jailbreak_has_run) {
  388. [self writeTextPlain:@"> already jailbroken."];
  389. // set done button
  390. [self.goButton setTitle:@"done" forState:UIControlStateFocused];
  391. // aaaaand grey it out
  392. [self.goButton setEnabled:NO];
  393. [self.goButton setAlpha:0.5];
  394. return;
  395. }
  396. /*
  397. // Device is already jailbroken, but not with Meridian
  398. if (file_exists("/private/var/lib/dpkg/status") == 0 &&
  399. file_exists("/meridian/.installed") != 0) {
  400. [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"];
  401. [self.goButton setTitle:@"please erase" forState:UIControlStateFocused];
  402. [self.goButton setEnabled:NO];
  403. [self.goButton setAlpha:0.5];
  404. return;
  405. }
  406. */
  407. if (self.installMode == BSInstallTypeMeridian) {
  408. /*
  409. playPauseOrMenuDoubleTapRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTapMenuOrPlayPause:)];
  410. playPauseOrMenuDoubleTapRecognizer.numberOfTapsRequired = 2;
  411. playPauseOrMenuDoubleTapRecognizer.allowedPressTypes = @[[NSNumber numberWithInteger:UIPressTypePlayPause], [NSNumber numberWithInteger:UIPressTypeMenu]];
  412. [self.view addGestureRecognizer:playPauseOrMenuDoubleTapRecognizer];
  413. */
  414. if ([self shouldShowTimer]){
  415. [self showWaitTimer];
  416. }
  417. } else {
  418. playPauseOrMenuDoubleTapRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tappedOnSetNonce:)];
  419. playPauseOrMenuDoubleTapRecognizer.numberOfTapsRequired = 2;
  420. playPauseOrMenuDoubleTapRecognizer.allowedPressTypes = @[[NSNumber numberWithInteger:UIPressTypePlayPause], [NSNumber numberWithInteger:UIPressTypeMenu]];
  421. [self.view addGestureRecognizer:playPauseOrMenuDoubleTapRecognizer];
  422. }
  423. NSLog(@"App bundle directory: %s", bundle_path());
  424. }
  425. - (BOOL)shouldShowTimer {
  426. int waitTime;
  427. return ((waitTime = 90 - uptime()) > 0);
  428. }
  429. - (void)showWaitTimer {
  430. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void) {
  431. int waitTime;
  432. while ((waitTime = 90 - uptime()) > 0) {
  433. dispatch_async(dispatch_get_main_queue(), ^{
  434. NSString *wt2 = [NSString stringWithFormat:@"wait: %d", waitTime];
  435. //NSLog(@"%@", wt2);
  436. [self.goButton setTitle:wt2 forState:UIControlStateFocused];
  437. [self.goButton setTitle:wt2 forState:UIControlStateNormal];
  438. [self.goButton setTitle:wt2 forState:UIControlStateDisabled];
  439. [self.goButton setTitle:wt2 forState:UIControlStateHighlighted];
  440. //[self.goButton setEnabled:false];
  441. [self.goButton setAlpha:0.6];
  442. });
  443. sleep(1);
  444. }
  445. dispatch_async(dispatch_get_main_queue(), ^{
  446. [self.goButton setTitle:@"go" forState:UIControlStateFocused];
  447. [self.goButton setEnabled:true];
  448. [self.goButton setAlpha:1];
  449. [self writeTextPlain:@"> ready."];
  450. });
  451. });
  452. }
  453. - (IBAction)goButtonPressed:(UIButton *)sender {
  454. if (self.installMode == BSInstallTypeElectra) {
  455. [self doit:nil];
  456. return;
  457. }
  458. if (sender.alpha != 1) {
  459. return;
  460. }
  461. // when jailbreak runs, 'go' button is
  462. // turned to 'respring'
  463. if (jailbreak_has_run) {
  464. int rv = respring();
  465. if (rv != 0) {
  466. [self writeTextPlain:@"failed to respring."];
  467. }
  468. return;
  469. }
  470. //not sure what this is all about, why would we want to reboot?
  471. /*
  472. // if we've run once, just reboot
  473. if (has_run_once) {
  474. [self.goButton setHidden:YES];
  475. restart_device();
  476. return;
  477. }
  478. */
  479. // set up the UI to 'running' state
  480. [self.goButton setEnabled:NO];
  481. [self.goButton setHidden:YES];
  482. [self.creditsButton setEnabled:NO];
  483. self.creditsButton.alpha = 0.5;
  484. [self.websiteButton setEnabled:NO];
  485. self.websiteButton.alpha = 0.5;
  486. [self.progressSpinner startAnimating];
  487. has_run_once = true;
  488. // background thread so we can update the UI
  489. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void) {
  490. int ret = makeShitHappen(self, kppless);
  491. if (ret != 0) {
  492. NSLog(@"MERIDIAN HAS FAILED TO RUN :(");
  493. dispatch_async(dispatch_get_main_queue(), ^{
  494. [self exploitFailed];
  495. });
  496. return;
  497. }
  498. dispatch_async(dispatch_get_main_queue(), ^{
  499. [self exploitSucceeded];
  500. });
  501. });
  502. }
  503. - (IBAction)websiteButtonPressed:(UIButton *)sender {
  504. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://meridian.sparkes.zone"]
  505. options:@{}
  506. completionHandler:nil];
  507. }
  508. - (char *)getDeviceIdentifier {
  509. static struct utsname u;
  510. uname(&u);
  511. return u.machine;
  512. }
  513. - (NSString *)getVersionString {
  514. return [NSString stringWithFormat:@"%ld.%ld.%ld",
  515. (long)osVersion.majorVersion,
  516. (long)osVersion.minorVersion,
  517. (long)osVersion.patchVersion];
  518. }
  519. - (NSString *)getBuildString {
  520. CFDictionaryRef dict= NULL;
  521. CFStringRef str = NULL;
  522. dict = _CFCopyServerVersionDictionary();
  523. if (dict == NULL)
  524. dict = _CFCopySystemVersionDictionary();
  525. str = CFDictionaryGetValue(dict, CFSTR("ProductBuildVersion"));
  526. //NSLog(@"pbv: %@", str);
  527. return (__bridge NSString *)str;
  528. }
  529. - (void)exploitSucceeded {
  530. jailbreak_has_run = true;
  531. [self writeTextPlain:@"\n> your device has been freed! \n"];
  532. [self writeTextPlain:@"note: please click 'respring' to get this party started :) \n"];
  533. //if you want to run anything post process on device you can do it here for diagnostic purposes.
  534. execprog("/bin/ps", (const char **)&(const char *[]) {
  535. "/bin/ps",
  536. "awwwx",
  537. NULL
  538. });
  539. execprog("/usr/sbin/sshd", (const char **)&(const char *[]) {
  540. NULL
  541. });
  542. execprog("/usr/bin/ls", (const char **)&(const char *[]) {
  543. "/usr/bin/ls",
  544. "-alR",
  545. "/private",
  546. NULL
  547. });
  548. execprog("/bin/bash", (const char **)&(const char *[]) {
  549. "/bin/bash",
  550. NULL
  551. });
  552. /*
  553. execprog("/bin/bash", (const char **)&(const char *[]) {
  554. "/bin/bash",
  555. NULL
  556. });
  557. */
  558. [self.progressSpinner stopAnimating];
  559. [self.goButton setEnabled:YES];
  560. [self.goButton setHidden:NO];
  561. [self.goButton setTitle:@"respring" forState:UIControlStateFocused];
  562. [self.creditsButton setEnabled:YES];
  563. self.creditsButton.alpha = 1;
  564. [self.websiteButton setEnabled:YES];
  565. self.websiteButton.alpha = 1;
  566. }
  567. - (void)exploitFailed {
  568. [self writeTextPlain:@"exploit failed. please reboot & try again."];
  569. [self.goButton setEnabled:YES];
  570. [self.goButton setHidden:NO];
  571. [self.goButton setTitle:@"reboot" forState:UIControlStateFocused];
  572. [self.creditsButton setEnabled:YES];
  573. [self.creditsButton setAlpha:1];
  574. [self.websiteButton setEnabled:YES];
  575. [self.websiteButton setAlpha:1];
  576. [self.progressSpinner stopAnimating];
  577. }
  578. - (void)doUpdateCheck {
  579. // skip the version check if we're running an internal build
  580. if ([Version containsString:@"Internal"]) {
  581. return;
  582. }
  583. NSURL *url = [NSURL URLWithString:@"https://meridian.sparkes.zone/latest"];
  584. NSURLSessionDataTask *downloadTask = [[NSURLSession sharedSession]
  585. dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *header, NSError *error) {
  586. if (error != nil) {
  587. NSLog(@"failed to get information from the update server.");
  588. return;
  589. }
  590. NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  591. if (response != Version) {
  592. [self doUpdatePopup:response];
  593. }
  594. }];
  595. [downloadTask resume];
  596. }
  597. - (void)doUpdatePopup:(NSString *)update {
  598. NSString *message = [NSString stringWithFormat:@"An update is available for Meridian: %@It can be downloaded from the website.", update];
  599. UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Meridian Update"
  600. message:message
  601. preferredStyle:UIAlertControllerStyleAlert];
  602. UIAlertAction *websiteAction = [UIAlertAction actionWithTitle:@"Website" style:UIAlertActionStyleDefault
  603. handler:^(UIAlertAction * action) {
  604. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://meridian.sparkes.zone"]
  605. options:@{}
  606. completionHandler:nil];
  607. }];
  608. UIAlertAction *closeAction = [UIAlertAction actionWithTitle:@"Close"
  609. style:UIAlertActionStyleCancel
  610. handler:nil];
  611. [alert addAction:websiteAction];
  612. [alert addAction:closeAction];
  613. [self presentViewController:alert animated:YES completion:nil];
  614. }
  615. - (void)writeText:(NSString *)message {
  616. dispatch_async(dispatch_get_main_queue(), ^{
  617. if (![message isEqual: @"done!"] && ![message isEqual:@"failed!"]) {
  618. NSLog(@"%@", message);
  619. _textArea.text = [_textArea.text stringByAppendingString:[NSString stringWithFormat:@"%@ ", message]];
  620. } else {
  621. _textArea.text = [_textArea.text stringByAppendingString:[NSString stringWithFormat:@"%@\n", message]];
  622. }
  623. NSRange bottom = NSMakeRange(_textArea.text.length - 1, 1);
  624. [self.textArea scrollRangeToVisible:bottom];
  625. });
  626. }
  627. - (void)writeTextPlain:(NSString *)message, ... {
  628. va_list args;
  629. va_start(args, message);
  630. message = [[NSString alloc] initWithFormat:[message stringByAppendingString:@"\n"] arguments:args];
  631. dispatch_async(dispatch_get_main_queue(), ^{
  632. _textArea.text = [_textArea.text stringByAppendingString:message];
  633. NSRange bottom = NSMakeRange(_textArea.text.length - 1, 1);
  634. [self.textArea scrollRangeToVisible:bottom];
  635. NSLog(@"%@", message);
  636. });
  637. va_end(args);
  638. }
  639. // kinda dumb, kinda lazy, ¯\_(ツ)_/¯
  640. void log_message(NSString *message) {
  641. [thisClass writeTextPlain:message];
  642. }
  643. #pragma mark ELECTRA
  644. - (IBAction)doit:(id)sender {
  645. if (_respringReady) {
  646. [self writeText:@"Respringing please wait..."];
  647. [NSTask launchedTaskWithLaunchPath:@"/usr/bin/killall" arguments:@[@"-9", @"backboardd"]];
  648. return;
  649. }
  650. NSLog(@"DO IT!");
  651. [self.goButton setEnabled:NO];
  652. [self.goButton setHidden:YES];
  653. [self writeText:@"Starting jailbreak..."];
  654. currentViewController = self;
  655. [self.goButton setTitle:@"Please Wait (1/3)" forState:UIControlStateNormal];
  656. BOOL shouldEnableTweaks = YES;
  657. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), ^{
  658. mach_port_t user_client;
  659. mach_port_t tfp0 = get_tfp0(&user_client);
  660. dispatch_async(dispatch_get_main_queue(), ^{
  661. [self.goButton setTitle:@"Please Wait (2/3)" forState:UIControlStateNormal];
  662. });
  663. int jailbreakstatus = begin_fun(tfp0, user_client, shouldEnableTweaks);
  664. if (jailbreakstatus == 0){
  665. [self setGoButtonTitle:@"Respring"];
  666. dispatch_async(dispatch_get_main_queue(), ^{
  667. //[self.goButton setTitle:@"Jailbroken" forState:UIControlStateNormal];
  668. [self writeText:@"\nFREEEEEEEEDOM!!!!!\n"];
  669. [self writeText:@"\nPlease select respring to continue!\n"];
  670. [self.goButton setEnabled:TRUE];
  671. [self.goButton setHidden:FALSE];
  672. _respringReady = TRUE;
  673. /*
  674. UIAlertController *dropbearRunning = [UIAlertController alertControllerWithTitle:@"Dropbear Running" message:@"Dropbear is now running! Enjoy." preferredStyle:UIAlertControllerStyleAlert];
  675. [dropbearRunning addAction:[UIAlertAction actionWithTitle:@"Exit" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
  676. [dropbearRunning dismissViewControllerAnimated:YES completion:nil];
  677. //exit(0);
  678. [NSTask launchedTaskWithLaunchPath:@"/usr/bin/killall" arguments:@[@"-9", @"backboardd"]];
  679. }]];
  680. [self presentViewController:dropbearRunning animated:YES completion:nil];
  681. */
  682. });
  683. } else if (jailbreakstatus == -1) {
  684. dispatch_async(dispatch_get_main_queue(), ^{
  685. [self.goButton setTitle:@"Already Jailbroken" forState:UIControlStateNormal];
  686. });
  687. } else if (jailbreakstatus == -2) {
  688. dispatch_async(dispatch_get_main_queue(), ^{
  689. [self.goButton setTitle:@"Error: topanga" forState:UIControlStateNormal];
  690. });
  691. } else if (jailbreakstatus == -3) {
  692. dispatch_async(dispatch_get_main_queue(), ^{
  693. [self.goButton setTitle:@"Error: amfid patch" forState:UIControlStateNormal];
  694. });
  695. } else {
  696. dispatch_async(dispatch_get_main_queue(), ^{
  697. [self.goButton setTitle:@"Error Jailbreaking" forState:UIControlStateNormal];
  698. });
  699. }
  700. //NSLog(@" ♫ KPP never bothered me anyway... ♫ ");
  701. [self writeText:@"\n ♫ KPP never bothered me anyway... ♫ \n"];
  702. });
  703. }
  704. - (void)removingLiberiOS {
  705. dispatch_async(dispatch_get_main_queue(), ^{
  706. //[self.goButton setTitle:@"Removing liberiOS" forState:UIControlStateNormal];
  707. [self writeText:@"Removing liberiOS"];
  708. });
  709. }
  710. - (void)removingElectraBeta {
  711. dispatch_async(dispatch_get_main_queue(), ^{
  712. //[self.goButton setTitle:@"Removing beta" forState:UIControlStateNormal];
  713. [self writeText:@"Removing beta"];
  714. });
  715. }
  716. - (void)installingNitoTV {
  717. dispatch_async(dispatch_get_main_queue(), ^{
  718. //[self.goButton setTitle:@"Installing Cydia" forState:UIControlStateNormal];
  719. [self writeText:@"Installing nitoTV\n"];
  720. });
  721. }
  722. - (void)nitoTVDone {
  723. dispatch_async(dispatch_get_main_queue(), ^{
  724. [self.goButton setTitle:@"Please Wait (2/3)" forState:UIControlStateNormal];
  725. });
  726. }
  727. - (void)displaySnapshotNotice {
  728. dispatch_async(dispatch_get_main_queue(), ^{
  729. [self.goButton setTitle:@"user prompt" forState:UIControlStateNormal];
  730. 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];
  731. [apfsNoticeController addAction:[UIAlertAction actionWithTitle:@"Continue Jailbreak" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  732. [self.goButton setTitle:@"Please Wait (2/3)" forState:UIControlStateNormal];
  733. snapshotWarningRead();
  734. }]];
  735. [self presentViewController:apfsNoticeController animated:YES completion:nil];
  736. });
  737. }
  738. - (void)displaySnapshotWarning {
  739. dispatch_async(dispatch_get_main_queue(), ^{
  740. [self.goButton setTitle:@"user prompt" forState:UIControlStateNormal];
  741. 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];
  742. [apfsWarningController addAction:[UIAlertAction actionWithTitle:@"Continue Jailbreak" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  743. [self.goButton setTitle:@"Please Wait (2/3)" forState:UIControlStateNormal];
  744. snapshotWarningRead();
  745. }]];
  746. [self presentViewController:apfsWarningController animated:YES completion:nil];
  747. });
  748. }
  749. - (UIStatusBarStyle)preferredStatusBarStyle {
  750. return UIStatusBarStyleLightContent;
  751. }
  752. - (void)dealloc {
  753. [[NSNotificationCenter defaultCenter] removeObserver:self];
  754. }
  755. @end