haiyuidesu / serialsh

safety net against bootloop
Do What The F*ck You Want To Public License
30 stars 5 forks source link

Does not ask for login. stuck at [serialsh]: #1

Closed brandonplank closed 4 years ago

brandonplank commented 4 years ago

cannot interact with the device.

haiyuidesu commented 4 years ago

Hello,

I can not help you if you do not provide me any details like your device model and its version.

brandonplank commented 4 years ago

Im sorry, it seems to work, but keyboard input is super un-reliable, and it only shows the login message after a 300 second time-out iphone X(13.3), and ipad 2019(13.5 beta 3).

brandonplank commented 4 years ago

I reverse engineered the original binary by Luca, and came up with this, but it just panics the device.

// // main.m // serial // // Created by Brandon Plank on 5/1/20. // Copyright © 2020 Brandon Plank. All rights reserved. //

include

include

import <sys/event.h>

import <Foundation/Foundation.h>

struct termios termios_struct; struct kevent changelist; int pipe_shin[2], pipe_shout[2];

int set_interface_attribs(int fd, int baudrate) { struct termios tty;

memset(&tty, 0x0, sizeof(tty));

if (tcgetattr(fd, &tty) != 0) { return -1; }

cfsetispeed(&tty, baudrate); cfsetospeed(&tty, baudrate);

tty.c_cflag &= ~CRTSCTS; tty.c_cflag |= (CLOCAL | CREAD); tty.c_iflag |= IGNPAR; tty.c_iflag &= ~(IXON | IXOFF | INLCR | IGNCR); tty.c_oflag &= ~OPOST; tty.c_cflag &= ~CSIZE; tty.c_cflag |= CS8;

tty.c_cflag &= ~PARENB; tty.c_iflag &= ~INPCK; tty.c_cflag &= ~CSTOPB; tty.c_iflag |= INPCK; tty.c_cc[VTIME] = 1; tty.c_cc[VMIN] = 0;

if (tcsetattr(fd, TCSANOW, &tty) != 0) { return -1; }

return 0; }

define spawn_shin pipe_shin[1]

define main_sherr pipe_shout[1]

pid_t pd = 0;

void set_blocking(int fd, int block_now) { struct termios tty;

memset(&tty, 0x0, sizeof(tty));

if (tcgetattr(fd, &tty) != 0) { return; }

tty.c_cc[VMIN] = block_now ? 1 : 0; tty.c_cc[VTIME] = 5;

tcsetattr(fd, TCSANOW, &tty); }

int result; int console_path; int kernel_queue; size_t read_data; size_t read_bytes; int value_of_buffer; int kq;

void spawnproc(){ int fork_pc = fork(); int fork_pc_new; if (!fork_pc){ dup2(pipe_shout[0], 0); dup2(spawn_shin, 1); dup2(spawn_shin, 2); int value1 = 0LL; char createpty[] = { "createpty", "-q", "/dev/null", "login" }; execve("/usr/bin/script", &createpty, 0LL); fork_pc_new = fork_pc; kevent(kq, (const struct kevent )&fork_pc_new, 1, 0LL, 0, 0LL); }

}

int main(int argc, const char argv[]) { @autoreleasepool { if(fork()){ result = 0; } else { console_path = open("/dev/tty.debug-console", 133250); if (!(console_path & 0x80000000)){ set_interface_attribs(console_path, 115200); memset(&termios_struct, 0, 0x40uLL); if(!tcgetattr(console_path, &termios_struct)){ termios_struct.c_cc[16] = 0; termios_struct.c_cc[17] = 5; tcsetattr(console_path, 0, &termios_struct); } write(console_path, "\r\n\r\n == serialsh (c) 2016 qwertyoruiop == \n\r\n\r", 0x2EuLL); pipe((int )&pipe_shin); pipe((int *)&pipe_shout); dup2(pipe_shout[0], 0); dup2(spawn_shin, 1); dup2(spawn_shin, 2);

            kernel_queue = kqueue();
            kq = kernel_queue;
            if(kernel_queue != -1){
                value_of_buffer = console_path;
                changelist.filter = -1;
                changelist.flags = 1;
                changelist.fflags = 0;
                changelist.data = 5LL;
                changelist.udata = 0LL;
                kevent(kernel_queue, &changelist, 1, 0LL, 0, 0LL);
                value_of_buffer = 0LL;
                changelist.filter = -1;
                changelist.flags = 1;
                changelist.fflags = 0;
                changelist.data = 5LL;
                changelist.udata = 0LL;
                kevent(kq, &changelist, 1, 0LL, 0, 0LL);
                spawnproc();
                while (1) {
                    do{
                        changelist.data = 0LL;
                        changelist.udata = 0LL;
                        value_of_buffer = 0LL;
                        changelist.filter = 0LL;
                    } while (!kevent(kq, 0LL, 0, &changelist, 1, 0LL));
                        if(value_of_buffer == console_path){
                            read_data = read(console_path, &termios_struct, 0x400uLL);
                            write(1, &termios_struct, read_data);
                        } else if (value_of_buffer){
                            if ( changelist.filter == -5 && value_of_buffer == pd )
                            {
                              waitpid(pd, 0LL, 0);
                              pd = 0;
                              spawnproc();
                            }
                        } else {
                            read_bytes = read(0, &termios_struct, 0x400uLL);
                            write(console_path, &termios_struct, read_bytes);
                        }
                    }
                }
            }
        }
    }
return 0;

}

brandonplank commented 4 years ago

Here is the all my code, none of yours this time, and no panic. but no serial output. `// // main.m // serial // // Created by Brandon Plank on 5/1/20. // Copyright © 2020 Brandon Plank. All rights reserved. //

include

include

import <sys/event.h>

import <Foundation/Foundation.h>

struct termios termios_struct; struct kevent changelist; int pipe_shin[2], pipe_shout[2];

int set_interface_attribs(int fd, int baudrate) { int tty; int result; memset(&tty, 0, sizeof(tty)); if(tcgetattr(fd, (struct termios *)&tty) != 0){ return 0xFFFFFFFFLL; }

cfsetospeed((struct termios *)&tty, baudrate);
cfsetispeed((struct termios *)&tty, baudrate);
tty = (tty & 0xFFFFFFFFFFFFF82BLL) | 0x114;
if (tcsetattr(fd, 0, (const struct termios *)&tty)){
    result = 0xFFFFFFFFLL;
} else {
    result = 0LL;
}
return result;

}

define spawn_shin pipe_shin[1]

define main_sherr pipe_shout[1]

pid_t pd = 0;

int set_blocking(int fd, int block_now) { int fd_1; int result; int tty; int block_now_1;

block_now_1 = block_now;
fd_1 = fd;
memset(&tty, 0, sizeof(tty));
result = tcgetattr(fd_1, (struct termios *)&tty);
if(!result){
    result = tcsetattr(fd_1, 0, (const struct termios *)&tty);
}
return result;

}

int result; int console_path; int kernel_queue; size_t read_data; size_t read_bytes; int value_of_buffer; int kq;

void spawnproc(){ int fork_pc = fork(); int fork_pc_new; if (!fork_pc){ dup2(pipe_shout[0], 0); dup2(spawn_shin, 1); dup2(spawn_shin, 2); int value1 = 0LL; char createpty[] = { "createpty", "-q", "/dev/null", "login" }; execve("/usr/bin/script", &createpty, 0LL); fork_pc_new = fork_pc; kevent(kq, (const struct kevent )&fork_pc_new, 1, 0LL, 0, 0LL); }

}

int serial() { @autoreleasepool { if(fork()){ result = 0; } else { console_path = open("/dev/tty.debug-console", 133250); if (!(console_path & 0x80000000)){ printf("here?\n"); set_interface_attribs(console_path, 115200); set_blocking(console_path, 0); memset(&termios_struct, 0, sizeof(termios_struct)); if(!tcgetattr(console_path, &termios_struct)){ termios_struct.c_cc[16] = 0; termios_struct.c_cc[17] = 5; tcsetattr(console_path, 0, &termios_struct); } write(console_path, "\r\n\r\n == serialsh (c) 2016 qwertyoruiop == \n\r\n\r", 46); printf("here?\n"); pipe((int )&pipe_shin); pipe((int )&pipe_shout); dup2(pipe_shout[0], 0); dup2(spawn_shin, 1); dup2(spawn_shin, 2);

            kernel_queue = kqueue();
            kq = kernel_queue;
            if(kernel_queue != -1){
                value_of_buffer = console_path;
                changelist.filter = -1;
                changelist.flags = 1;
                changelist.fflags = 0;
                changelist.data = 5LL;
                changelist.udata = 0LL;
                kevent(kernel_queue, &changelist, 1, 0LL, 0, 0LL);
                value_of_buffer = 0LL;
                changelist.filter = -1;
                changelist.flags = 1;
                changelist.fflags = 0;
                changelist.data = 5LL;
                changelist.udata = 0LL;
                kevent(kq, &changelist, 1, 0LL, 0, 0LL);
                spawnproc();
                while (1) {
                    do{
                        changelist.data = 0LL;
                        changelist.udata = 0LL;
                        value_of_buffer = 0LL;
                        changelist.filter = 0LL;
                    } while (!kevent(kq, 0LL, 0, &changelist, 1, 0LL));
                        if(value_of_buffer == console_path){
                            read_data = read(console_path, &termios_struct, sizeof(termios_struct));
                            write(1, &termios_struct, read_data);
                        } else if (value_of_buffer){
                            if ( changelist.filter == -5 && value_of_buffer == pd )
                            {
                              waitpid(pd, 0LL, 0);
                              pd = 0;
                              spawnproc();
                            }
                        } else {
                            read_bytes = read(0, &termios_struct, sizeof(termios_struct));
                            write(console_path, &termios_struct, read_bytes);
                        }
                    }
                }
            }
        }
    }
return 0;

} `

haiyuidesu commented 4 years ago

Hello again,

So to begin with, don't bother yourself to try to rewrite serialsh for simple reason there's no need to rewrite it (also your code is just an assembled version of the pseudocode generated by IDA with my code, you shouldn't leave it like that).

To answer to the main problem (stuck at '[serialsh]:' string): you said that you're on iOS 13, and I've got the same issue until I see that the problem is not from serialsh but from the jailbreak itself (checkra1n).

Basically, if you try echo "test" > /dev/tty.debug-console you should see test in the serial output, but with checkra1n no.

I have been tested my code under the etason and Meridian jailbreaks and it ran fine (less than 15sec to get the login prompt), but under checkra1n nothing appears (as you reported it), even when the serial=3 boot-arg is set, the following output appeared:

iPhone:~ root# echo "test" > /dev/tty.debug-console -sh: /dev/tty.debug-console: Resource busy

In short, I really think that the problem is from the jailbreak and not from serialsh (the code is fine).

I will open an issue in the checkra1n repo to ask for a fix (I hope you understood).