Closed brandonplank closed 4 years ago
Hello,
I can not help you if you do not provide me any details like your device model and its version.
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).
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. //
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; }
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;
}
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. //
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;
}
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;
} `
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).
cannot interact with the device.