Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // ViewController.m
- // JBDBG
- //
- // Created by Jake James on 11/8/18.
- // Copyright © 2018 Jake James. All rights reserved.
- //
- #import "ViewController.h"
- #import <mach/mach.h>
- #import "jelbrekLib/jelbrekLib.h"
- #import <sys/stat.h>
- #import "vnode.h"
- #import "mount.h"
- #import "proc.h"
- #import "task.h"
- #import <sys/syscall.h>
- #import <sys/mount.h>
- #include <sys/spawn.h>
- #define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
- #define _assert(test, message) do \
- if (!(test)) { \
- fprintf(stderr, "__assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILENAME__, __LINE__, __FUNCTION__); \
- if (message) \
- showAlert(@"Error", [NSString stringWithFormat:@"Errno: %d\nTest: %s\nFilename: %s\nLine: %d\nFunction: %s\nDescription: %s", errno, #test, __FILENAME__, __LINE__, __FUNCTION__, message], 1, 0); \
- else \
- showAlert(@"Error", [NSString stringWithFormat:@"Errno: %d\nTest: %s\nFilename: %s\nLine: %d\nFunction: %s", errno, #test, __FILENAME__, __LINE__, __FUNCTION__], 1, 0); \
- term_jelbrek(); \
- exit(1); \
- } \
- while (false)
- #define NOTICE(msg, wait, destructive) showAlert(@"Notice", @(msg), wait, destructive)
- static inline void showAlert(NSString *title, NSString *message, Boolean wait, Boolean destructive) {
- dispatch_semaphore_t semaphore;
- if (wait)
- semaphore = dispatch_semaphore_create(0);
- dispatch_async(dispatch_get_main_queue(), ^{
- [[[[[UIApplication sharedApplication] delegate] window] rootViewController] dismissViewControllerAnimated:YES completion:nil];
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *OK = [UIAlertAction actionWithTitle:@"OK" style:destructive ? UIAlertActionStyleDestructive : UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
- if (wait)
- dispatch_semaphore_signal(semaphore);
- }];
- [alertController addAction:OK];
- [alertController setPreferredAction:OK];
- [[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alertController animated:YES completion:nil];
- });
- if (wait)
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- }
- // dummy func so I can do sizeof(struct whatever); if I don't use the struct at least once in code lldb will error out saying it's undefined
- void func() {
- struct vnode a;
- printf("a: 0x%x\n", a.v_id);
- struct mount_struct b;
- printf("b: %p\n", b.mnt_data);
- struct proc c;
- printf("c: %p\n", c.p_ucred);
- struct task d;
- printf("c: %p\n", d.itk_self);
- cpu_data_t ab;
- printf("d: %lx\n", ab.cpu_reset_handler);
- }
- // stuff i took from sbingner's code to iterate vnodes and patch the mount struct to be the snapshot's one (it's already the root one, so that's left to try); i'm not using this anymore
- #define tailq_empty(head) (tailq_first(head)==0)
- #define MNT_LITER 0x00000010 /* mount in iteration */
- enum vtype {
- /* 0 */
- VNON,
- /* 1 - 5 */
- VREG, VDIR, VBLK, VCHR, VLNK,
- /* 6 - 10 */
- VSOCK, VFIFO, VBAD, VSTR, VCPLX
- };
- size_t kstrlen(uint64_t strptr) {
- return (size_t)Kernel_Execute(find_symbol("_strlen", false) + KASLR_Slide, strptr, 0, 0, 0, 0, 0, 0);
- }
- void lck_mtx_lock(uint64_t mtx) {
- Kernel_Execute(find_symbol("_lck_mtx_lock", false) + KASLR_Slide, mtx, 0, 0, 0, 0, 0, 0);
- }
- void lck_mtx_unlock(uint64_t mtx) {
- Kernel_Execute(find_symbol("_lck_mtx_unlock", false) + KASLR_Slide, mtx, 0, 0, 0, 0, 0, 0);
- }
- void mount_iterate_lock(uint64_t mp) {
- lck_mtx_lock(mp + 0x9f0); // mnt_iter_lock
- }
- void mount_iterate_unlock(uint64_t mp) {
- lck_mtx_unlock(mp + 0x9f0); // mnt_iter_lock
- }
- void mount_lock(uint64_t mp) {
- lck_mtx_lock(mp + 0x18); // mlock
- }
- void mount_unlock(uint64_t mp) {
- lck_mtx_unlock(mp + 0x18); // mlock
- }
- void vnode_iterate_setup(uint64_t mp) {
- uint32_t mnt_lflag = KernelRead_32bits(mp + 0x7c); // mnt_lflag
- mnt_lflag |= MNT_LITER;
- KernelWrite_32bits(mp + 0x7c, mnt_lflag);
- }
- void vnode_iterate_clear(uint64_t mp) {
- uint32_t mnt_lflag = KernelRead_32bits(mp + 0x7c); // mnt_lflag
- mnt_lflag &= ~MNT_LITER;
- KernelWrite_32bits(mp + 0x7c, mnt_lflag);
- }
- uint64_t tailq_first(uint64_t head) {
- return KernelRead_64bits(head + 0x0); // tqh_first
- }
- uint64_t tailq_next(uint64_t elm, unsigned int field_offset) {
- return KernelRead_64bits(elm + field_offset + 0x0);
- }
- void tailq_init(uint64_t head) {
- KernelWrite_64bits(head + 0x0, 0); // tailq_first((head)) = NULL;
- KernelWrite_64bits(head + 0x8, head + 0x0); // (head)->tqh_last = &tailq_first((head));
- }
- void tailq_remove(uint64_t head, uint64_t elm, unsigned int field_offset) {
- uint64_t tq_next_ref = tailq_next(elm, field_offset);
- if (tq_next_ref != 0) {
- KernelWrite_64bits(tq_next_ref + field_offset + 0x8, KernelRead_64bits(elm + field_offset + 0x8)); // tailq_next((elm), field)->field.tqe_prev = (elm)->field.tqe_prev;
- } else {
- KernelWrite_64bits(head + 0x8, KernelRead_64bits(elm + field_offset + 0x8)); // (head)->tqh_last = (elm)->field.tqe_prev;
- }
- uint64_t prev_ref = KernelRead_64bits(elm + field_offset + 0x8);
- KernelWrite_64bits(prev_ref, tq_next_ref); // *(elm)->field.tqe_prev = tailq_next((elm), field);
- }
- void tailq_insert_tail(uint64_t head, uint64_t elm, unsigned int field_offset) {
- KernelWrite_64bits(elm + field_offset + 0x0, 0); // tailq_next((elm), field) = NULL;
- KernelWrite_64bits(elm + field_offset + 0x8, KernelRead_64bits(head + 0x8)); // (elm)->field.tqe_prev = (head)->tqh_last;
- KernelWrite_64bits(KernelRead_64bits(head + 0x8), elm); // *(head)->tqh_last = (elm);
- KernelWrite_64bits(head + 0x8, elm + field_offset + 0x0); // (head)->tqh_last = &tailq_next((elm), field);
- }
- int vnode_iterate_prepare(uint64_t mp) {
- uint64_t vp;
- uint64_t mp_mnt_vnodelist = mp + 0x40; // &mp->mnt_vnodelist
- if (tailq_empty(mp_mnt_vnodelist))
- return 0;
- vp = tailq_first(mp_mnt_vnodelist);
- KernelWrite_64bits(vp + 0x20 + 0x8, mp + 0x50 + 0x0); // vp->v_mntvnodes.tqe_prev = &(mp->mnt_workerqueue.tqh_first)
- KernelWrite_64bits(mp + 0x50 + 0x0, vp); // mp->mnt_workerqueue.tqh_first = mp->mnt_vnodelist.tqh_first;
- KernelWrite_64bits(mp + 0x50 + 0x8, KernelRead_64bits(mp + 0x40 + 0x8)); // mp->mnt_workerqueue.tqh_last = mp->mnt_vnodelist.tqh_last;
- tailq_init(mp + 0x40);
- if (!tailq_empty(mp + 0x60)) { // if (mp->mnt_newvnodes.tqh_first != NULL) panic("vnode_iterate_prepare: newvnode when entering vnode");
- fprintf(stderr, "!tailq_empty(mp + offsetof_mnt_newvnodes)\n");
- return 0;
- }
- tailq_init(mp + 0x60);
- return 1;
- }
- uint16_t rk16(uint64_t addr) {
- uint16_t data;
- KernelRead(addr, &data, 2);
- return data;
- }
- void wk16(uint64_t addr, uint16_t what) {
- uint16_t data = what;
- KernelWrite(addr, &data, 2);
- }
- int vnode_iterate(uint64_t mp, uint64_t newmp) {
- uint64_t vp;
- int retval;
- int ret=0;
- mount_iterate_lock(mp);
- mount_lock(mp);
- vnode_iterate_setup(mp);
- retval = vnode_iterate_prepare(mp);
- fprintf(stderr, "vnode_iterate_prepare(mp): %d\n", retval);
- if (retval == 0) {
- vnode_iterate_clear(mp);
- mount_unlock(mp);
- mount_iterate_unlock(mp);
- return ret;
- }
- while (!tailq_empty(mp + 0x50)) {
- vp = tailq_first(mp + 0x50);
- tailq_remove(mp + 0x50, vp, 0x20);
- tailq_insert_tail(mp + 0x40, vp, 0x20);
- if ((KernelRead_64bits(vp + 0xe0) == 0) || (rk16(vp + 0x70) == VNON) || (KernelRead_64bits(vp + 0xd8) != mp)) {
- continue;
- }
- mount_unlock(mp);
- lck_mtx_lock(vp + 0);
- //printf("Found vnode: 0x%llx\n", vp);
- KernelWrite_64bits(vp + 0xd8, newmp); // FIXME: this made my device freeze
- lck_mtx_unlock(vp + 0);
- mount_lock(mp);
- }
- out:
- printf("Party is over\n");
- vnode_iterate_clear(mp);
- mount_unlock(mp);
- mount_iterate_unlock(mp);
- return ret;
- }
- @interface ViewController ()
- @property (weak, nonatomic) IBOutlet UIButton *goButton;
- @end
- // doesn't follow symlinks (see flag); don't remember why I added this
- uint64_t get_vnode(char *path) {
- uint64_t *vnode_ptr = (uint64_t *)malloc(8);
- if (vnode_lookup(path, 1, vnode_ptr, get_vfs_context())) {
- printf("[-] unable to get vnode from path for %s\n", path);
- free(vnode_ptr);
- return -1;
- }
- else {
- uint64_t vnode = *vnode_ptr;
- free(vnode_ptr);
- return vnode;
- }
- }
- @implementation ViewController
- mach_port_t tfp0 = MACH_PORT_NULL;
- uint64_t orig_mnt_data = 0, root_mount = 0;
- bool hidden = false;
- - (void)viewDidLoad {
- [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- host_get_special_port(mach_host_self(), HOST_LOCAL_NODE, 4, &tfp0);
- if (!MACH_PORT_VALID(tfp0)) {
- [self.goButton setTitle:@"Can't get tfp0" forState:UIControlStateNormal];
- [self.goButton setEnabled:false];
- return;
- }
- printf("tfp0: 0x%x\n", tfp0);
- if (access("/bin/bash", F_OK)) {
- [self.goButton setTitle:@"Unhide Jailbreak" forState:UIControlStateNormal];
- }
- else {
- [self.goButton setTitle:@"Hide Jailbreak" forState:UIControlStateNormal];
- }
- }
- - (IBAction)go:(id)sender {
- printf("Got called!\n");
- init_jelbrek(tfp0);
- if (getuid()) {
- printf("Getting root and unsandboxing...\n");
- rootify(getpid());
- unsandbox(getpid());
- //setHSP4();
- _assert(getuid() == 0, "Failed to get root");
- }
- if (!hidden) {
- printf("Detected jailbreak, hiding...\n");
- char *message = "Failed to mount system snapshot";
- if (!access("/var/tmp/origfs", F_OK)) {
- printf("Found origfs, cleaning up...\n");
- if (!access("/var/tmp/origfs/sbin/launchd", F_OK)) goto mounted;
- _assert(rmdir("/var/tmp/origfs") == 0, message);
- }
- printf("Creating origfs & mounting\n");
- _assert(mkdir("/var/tmp/origfs", 0755) == 0, message);
- if (snapshot_check("/", "electra-prejailbreak") == 1) {
- _assert(mountSnapshot("/", "electra-prejailbreak", "/var/tmp/origfs") == 0, message);
- } else if (snapshot_check("/", "orig-fs") == 1) {
- _assert(mountSnapshot("/", "orig-fs", "/var/tmp/origfs") == 0, message);
- } else {
- _assert(mountSnapshot("/", find_system_snapshot(), "/var/tmp/origfs") == 0, message);
- }
- _assert(!access("/var/tmp/origfs/sbin/launchd", F_OK), message);
- mounted:;
- printf("Mounted orig snapshot\n");
- uint64_t snapshot_vnode = getVnodeAtPath("/private/var/tmp/origfs");
- uint64_t root_vnode = getVnodeAtPath("/");
- uint64_t snapshot_mount = KernelRead_64bits(snapshot_vnode + offsetof(struct vnode, v_mount));
- root_mount = KernelRead_64bits(root_vnode + offsetof(struct vnode, v_mount));
- uint64_t snapshot_mount_data = KernelRead_64bits(snapshot_mount + offsetof(struct mount_struct, mnt_data));
- orig_mnt_data = KernelRead_64bits(root_mount + offsetof(struct mount_struct, mnt_data));
- // this just starts looking for pointers to see if i find interesting stuff, so far nothing
- /*for (uint32_t i = 0; i < 0x2000; i++) {
- uint64_t val = KernelRead_64bits(orig_mnt_data + i);
- if (val > KernelBase) {
- printf("+ 0x%llx\n", val);
- }
- }*/
- printf("Overwriting mount data...\n");
- // experiments
- //KernelWrite_64bits(snapshot_vnode + offsetof(struct vnode, v_label), KernelRead_64bits(root_vnode + offsetof(struct vnode, v_label)));
- //(void)KernelWrite_64bits(snapshot_vnode + offsetof(struct vnode, v_data), (uint64_t)KernelRead_64bits(root_vnode + offsetof(struct vnode, v_data)));
- // back when we were trying to get double-mount working but failed because I was messing the type of something I don't remember
- /*uint64_t vardev_vnode = getVnodeAtPath("/dev/disk0s1s2");
- uint64_t specinfo = KernelRead_64bits(vardev_vnode + 0x78);
- uint32_t specflags = KernelRead_32bits(specinfo + 0x10);
- int32_t opencount = KernelRead_32bits(specinfo + 0x20);
- // step 1: clear si_flags
- KernelWrite_32bits(specinfo + 0x10, 0);
- // step 2: clear si_opencount
- KernelWrite_32bits(specinfo + 0x1c, 0);
- // test
- int vcount = (int)Kernel_Execute(find_symbol("_vcount", false) + KASLR_Slide, vardev_vnode, 0, 0, 0, 0, 0, 0);
- printf("vcount returned: %d\n", vcount);
- // step 3: remove VMOUNT
- uint32_t v_flags = KernelRead_32bits(vardev_vnode + 0x54);
- printf("v_flags now: 0x%x and then: 0x%x\n", v_flags, v_flags & ~0x80);
- KernelWrite_32bits(vardev_vnode + 0x54, v_flags & ~0x80);
- // step 4: double-mount /dev/disk0s1s2
- uint64_t creds = borrowCredsFromPid(getpid(), 0);
- int ret = mountDevAtPathAsRW("/dev/disk0s1s2", "/private/var/tmp/origfs/private/var");
- printf("Double mount returned: %d\n", ret);
- if (ret) {
- printf("Err: %s\n", strerror(errno));
- }
- undoCredDonation(getpid(), creds);
- // step 5: clean up
- KernelWrite_32bits(specinfo + 0x10, specflags);
- KernelWrite_32bits(specinfo + 0x1c, opencount);
- KernelWrite_32bits(vardev_vnode + 0x54, v_flags);
- vnode_put(vardev_vnode);
- vnode_put(root_vnode);
- vnode_put(snapshot_vnode);
- /*uint64_t creds = borrowCredsFromPid(getpid(), 0);
- int ret = unmount("/private/var", 0);
- printf("unmount: %d\n", ret);
- if (ret) printf("ERR: %s\n", strerror(errno));
- else {
- int ret = mountDevAtPathAsRW("/dev/disk0s1s2", "/private/var/tmp/origfs/private/var");
- printf("Mount returned: %d\n", ret);
- if (ret) printf("ERR: %s\n", strerror(errno));
- }
- undoCredDonation(getpid(), creds);*/
- // step 4: swap root's mnt_data with /private/var/tmp/origfs
- /*[[NSFileManager defaultManager] removeItemAtPath:@"/var/containers/Bundle/iosbinpack64/usr/bin/ldrestart" error:nil];
- [[NSFileManager defaultManager] copyItemAtPath:@"/var/mobile/Media/ldrestart" toPath:@"/var/containers/Bundle/iosbinpack64/usr/bin/ldrestart" error:nil];
- chmod("/var/containers/Bundle/iosbinpack64/usr/bin/ldrestart", 777);*/
- //[[NSFileManager defaultManager] copyItemAtPath:@"/jb/spawn" toPath:@"/var/containers/Bundle/iosbinpack64/spawnPlatform" error:nil];
- // bool a = [[NSFileManager defaultManager] copyItemAtPath:@"/usr/bin/ldrestart" toPath:@"/var/containers/Bundle/iosbinpack64/usr/bin/ldrestart" error:nil];
- bool a = [[NSFileManager defaultManager] copyItemAtPath:@"/bin/launchctl" toPath:@"/var/containers/Bundle/iosbinpack64/bin/launchctl" error:nil];
- printf("%d\n", a);
- trustbin("/var/containers/Bundle/iosbinpack64");
- // get vnode of /private/var and snapshot's /private var
- uint64_t varvp = getVnodeAtPath("/private/var");
- uint64_t snapvp = getVnodeAtPath("/private/var/tmp/origfs/private/var");
- // write root's mount struct into snapshot's mount data
- KernelWrite_64bits(snapshot_mount_data + 0x1a0, root_mount);
- // me experimenting other stuff
- // get vnode of snapshot's device
- // uint64_t rootdevvp = KernelRead_64bits(root_mount + offsetof(struct mount_struct, mnt_devvp));
- // uint64_t snapdevvp = KernelRead_64bits(KernelRead_64bits(snapvp + offsetof(struct vnode, v_mount)) + offsetof(struct mount_struct, mnt_devvp));
- // write snapshot's device into root's struct mount
- // KernelWrite_64bits(root_mount + offsetof(struct mount_struct, mnt_devvp), snapdevvp);
- // write the original vnode into the snapshot vnode
- void *vp = malloc(sizeof(struct vnode));
- KernelRead(varvp, vp, sizeof(struct vnode));
- KernelWrite(snapvp, vp, sizeof(struct vnode));
- vnode_put(varvp);
- //KernelRead(snapshot_vnode, vp, sizeof(struct vnode));
- //KernelWrite(root_vnode, vp, sizeof(struct vnode));
- free(vp);
- // me opening files to analyze their vnodes
- //int fd1 = open("/private/var/mobile/Library/Cydia/metadata.cb0", O_RDONLY);
- //int fd2 = open("/Applications/Preferences.app/Preferences", O_RDONLY);
- //int fd3 = open("/Applications/Cydia.app/Cydia", O_RDONLY);
- // do it
- KernelWrite_64bits(root_mount + offsetof(struct mount_struct, mnt_data), snapshot_mount_data);
- // not working
- int ret = syscall(SYS_vfs_purge);
- printf("%d", ret);
- //vnode_put(snapvp);
- term_jelbrek();
- // restart userland
- //ret = launch("/var/containers/Bundle/iosbinpack64/bin/bash", "-c", "/var/containers/Bundle/iosbinpack64/usr/bin/nohup /var/containers/Bundle/iosbinpack64/bin/bash -c \"/var/containers/Bundle/iosbinpack64/bin/launchctl unload /System/Library/LaunchDaemons/com.apple.backboardd.plist && /var/containers/Bundle/iosbinpack64/usr/bin/ldrestart; /var/containers/Bundle/iosbinpack64/bin/launchctl load /System/Library/LaunchDaemons/com.apple.backboardd.plist\" 2>&1 >/dev/null &", NULL, NULL, NULL, NULL, NULL);
- // panic
- ret = launch("/var/containers/Bundle/iosbinpack64/bin/launchctl", "reboot", "userspace", NULL, NULL, NULL, NULL, NULL);
- printf("%d", ret);
- //ret = launch("/var/containers/Bundle/iosbinpack64/usr/bin/ldrestart", NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- // idk. probably experimenting as well
- /* // step 5: clean up
- KernelWrite_32bits(specinfo + 0x10, specflags);
- KernelWrite_32bits(specinfo + 0x1c, opencount);
- vnode_put(vardev_vnode);
- vnode_put(root_vnode);
- vnode_put(snapshot_vnode);*/
- /*uint64_t varvp = getVnodeAtPath("/private/var");
- uint64_t snapvp = getVnodeAtPath("/private/var/tmp/origfs/private/var");
- void *vp = malloc(232);
- KernelRead(varvp, vp, 232);
- KernelWrite(snapvp, vp, 232);
- free(vp);
- KernelWrite_64bits(snapshot_mount_data + 0x1a0, root_mount);
- KernelWrite_64bits(root_mount + 0x8f8, snapshot_mount_data);
- vnode_put(varvp);*/
- //vnode_put(snapvp);
- //KernelWrite_64bits(root_mount + offsetof(struct mount_struct, mnt_vnodecovered), KernelRead_64bits(snapshot_mount + offsetof(struct mount_struct, mnt_vnodecovered)));
- //KernelWrite_64bits(root_mount + offsetof(struct mount_struct, mnt_devvp), KernelRead_64bits(snapshot_mount + offsetof(struct mount_struct, mnt_devvp)));
- //vnode_iterate(root_mount, snapshot_mount);
- //KernelWrite_64bits(root_vnode + 0xd8, snapshot_mount);
- //term_jelbrek();
- hidden = true;
- }
- else {
- if (!orig_mnt_data || !root_mount) {
- NOTICE("Error unhiding jailbreak", 1, 0);
- }
- else {
- printf("Undoing stuff...\n");
- KernelWrite_64bits(root_mount + 0x8f8, orig_mnt_data);
- }
- term_jelbrek();
- hidden = false;
- }
- }
- - (void)didReceiveMemoryWarning {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement