From 4d39248bf9699b426b1da5f47fbc82180cb7e2bb Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Sun, 7 Jan 2024 19:39:47 -0800 Subject: [PATCH 1/6] Add bootstrapping support Add tools for launching a root shell on the device, and for sending serial commands to the device. Extend the make.sh script to push those and configure a root shell. Commands can now be executed as root via: adb shell rootshell -c \"touch /tmp/test\" allowing automatic configuration of the tooling. --- Cargo.lock | 45 ++++++++++++++++ Cargo.toml | 2 + make.sh | 8 +++ rootshell/Cargo.toml | 8 +++ rootshell/src/main.rs | 15 ++++++ serial/Cargo.toml | 10 ++++ serial/src/main.rs | 117 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 205 insertions(+) create mode 100644 rootshell/Cargo.toml create mode 100644 rootshell/src/main.rs create mode 100644 serial/Cargo.toml create mode 100644 serial/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index d29868d..40f7c94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -583,6 +583,18 @@ version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +[[package]] +name = "libusb1-sys" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.12" @@ -764,6 +776,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -836,6 +854,20 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rootshell" +version = "0.1.0" + +[[package]] +name = "rusb" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45fff149b6033f25e825cbb7b2c625a11ee8e6dac09264d49beb125e39aa97bf" +dependencies = [ + "libc", + "libusb1-sys", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -935,6 +967,13 @@ dependencies = [ "serde", ] +[[package]] +name = "serial" +version = "0.1.0" +dependencies = [ + "rusb", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1181,6 +1220,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index a019f56..37d1adf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,8 @@ members = [ "orca", + "serial", + "rootshell", "wavehunter", ] resolver = "2" diff --git a/make.sh b/make.sh index af6d329..8195c15 100755 --- a/make.sh +++ b/make.sh @@ -1,3 +1,11 @@ cargo build +# Force a switch into the debug mode to enable ADB +target/x86_64-unknown-linux-gnu/debug/serial AT +adb push target/armv7-unknown-linux-gnueabihf/debug/rootshell /tmp/ +target/x86_64-unknown-linux-gnu/debug/serial "AT+SYSCMD=mv /tmp/rootshell /bin/rootshell" +sleep 1 +target/x86_64-unknown-linux-gnu/debug/serial "AT+SYSCMD=chown root /bin/rootshell" +sleep 1 +target/x86_64-unknown-linux-gnu/debug/serial "AT+SYSCMD=chmod 4755 /bin/rootshell" adb push target/armv7-unknown-linux-gnueabihf/debug/wavehunter /data/wavehunter/wavehunter adb push target/armv7-unknown-linux-gnueabihf/debug/wavehunter-reader /data/wavehunter/wavehunter-reader diff --git a/rootshell/Cargo.toml b/rootshell/Cargo.toml new file mode 100644 index 0000000..52cb6bd --- /dev/null +++ b/rootshell/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rootshell" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rootshell/src/main.rs b/rootshell/src/main.rs new file mode 100644 index 0000000..b78b168 --- /dev/null +++ b/rootshell/src/main.rs @@ -0,0 +1,15 @@ +use std::process::Command; +use std::os::unix::process::CommandExt; +use std::env; + +fn main() { + let mut args = env::args(); + + // discard argv[0] + let _ = args.next(); + Command::new("/bin/bash") + .args(args) + .uid(0) + .gid(0) + .exec(); +} \ No newline at end of file diff --git a/serial/Cargo.toml b/serial/Cargo.toml new file mode 100644 index 0000000..dd1d59b --- /dev/null +++ b/serial/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "serial" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rusb = "0.9.3" + diff --git a/serial/src/main.rs b/serial/src/main.rs new file mode 100644 index 0000000..72cc6f5 --- /dev/null +++ b/serial/src/main.rs @@ -0,0 +1,117 @@ +use std::str; +use std::thread::sleep; +use std::time::Duration; + +use rusb::{ + Context, DeviceHandle, UsbContext, +}; + +fn main() { + let args: Vec = std::env::args().collect(); + + if args.len() < 2 { + println!("usage: {0} ", args[0]); + return; + } + + match Context::new() { + Ok(mut context) => match open_orbic(&mut context) { + Some(mut handle) => { + send_command(&mut handle, &args[1]) + }, + None => panic!("No Orbic device found"), + }, + Err(e) => panic!("Failed to initialize libusb: {0}", e), + } +} + +fn send_command( + handle: &mut DeviceHandle, + command: &String, +) { + let mut data = String::new(); + data.push_str("\r\n"); + data.push_str(command); + data.push_str("\r\n"); + + let timeout = Duration::from_secs(1); + let mut response = [0; 256]; + match handle.write_control(0x21, 0x22, 3, 1, &[], timeout) { + Ok(_) => match handle.write_bulk(0x2, data.as_bytes(), timeout) { + Ok(_) => match handle.read_bulk(0x82, &mut response, timeout) { + Ok(_) => match handle.read_bulk(0x82, &mut response, timeout) { + Ok(_) => { + let responsestr = str::from_utf8(&response).unwrap(); + if !responsestr.starts_with("\r\nOK\r\n") { + println!("Received unexpected response{0}", responsestr); + } + }, + Err(e) => panic!("Failed to read response: {0}", e), + }, + Err(e) => panic!("Failed to read submitted command: {0}", e), + } + Err(e) => panic!("Failed to write command: {0}", e), + }, + Err(e) => panic!("Failed to send control request: {0}", e), + } +} + +fn switch_device( + handle: &mut DeviceHandle, +) { + // Send a command to switch the device into generic mode, exposing serial + let timeout = Duration::from_secs(1); + match handle.write_control(0xc0, 0xa0, 0, 0, &[], timeout) { + Ok(_) => (), + Err(e) => panic!("Failed to send device switch control request: {0}", e), + } +} + +fn open_orbic( + context: &mut T, +) -> Option> { + match open_device(context, 0x05c6, 0xf601) { + Some(handle) => return Some(handle), + None => (), + } + match open_device(context, 0x11f6, 0x900e) { + Some(mut handle) => switch_device(&mut handle), + None => panic!("No Orbic device detected") + } + + for _ in 1..10 { + match open_device(context, 0x05c6, 0xf601) { + Some(handle) => return Some(handle), + None => (), + } + sleep(Duration::from_secs(10)) + } + panic!("No Orbic device detected") +} + +fn open_device( + context: &mut T, + vid: u16, + pid: u16, +) -> Option> { + let devices = match context.devices() { + Ok(d) => d, + Err(_) => return None, + }; + + for device in devices.iter() { + let device_desc = match device.device_descriptor() { + Ok(d) => d, + Err(_) => continue, + }; + + if device_desc.vendor_id() == vid && device_desc.product_id() == pid { + match device.open() { + Ok(handle) => return Some(handle), + Err(e) => panic!("device found but failed to open: {}", e), + } + } + } + + None +} From ea84d74f9d3bf0b6ff068f56f3dd6ac6fdb85318 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 10 Jan 2024 15:13:28 -0800 Subject: [PATCH 2/6] Some fixes Ensure the mode switch works, and handle broken pipe failures. Also handle devices that are in diag+rndis mode. --- serial/src/main.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/serial/src/main.rs b/serial/src/main.rs index 72cc6f5..f727aa8 100644 --- a/serial/src/main.rs +++ b/serial/src/main.rs @@ -38,7 +38,9 @@ fn send_command( let mut response = [0; 256]; match handle.write_control(0x21, 0x22, 3, 1, &[], timeout) { Ok(_) => match handle.write_bulk(0x2, data.as_bytes(), timeout) { + // Consume the echoed back command Ok(_) => match handle.read_bulk(0x82, &mut response, timeout) { + // Read the actual response Ok(_) => match handle.read_bulk(0x82, &mut response, timeout) { Ok(_) => { let responsestr = str::from_utf8(&response).unwrap(); @@ -61,20 +63,35 @@ fn switch_device( ) { // Send a command to switch the device into generic mode, exposing serial let timeout = Duration::from_secs(1); - match handle.write_control(0xc0, 0xa0, 0, 0, &[], timeout) { + match handle.write_control(0x40, 0xa0, 0, 0, &[], timeout) { Ok(_) => (), - Err(e) => panic!("Failed to send device switch control request: {0}", e), + Err(e) => { + // If the device reboots while the command is still executing we + // may get a pipe error here + if e == rusb::Error::Pipe { + return; + } + panic!("Failed to send device switch control request: {0}", e); + }, } } fn open_orbic( context: &mut T, ) -> Option> { + // Device after initial mode switch match open_device(context, 0x05c6, 0xf601) { Some(handle) => return Some(handle), None => (), } - match open_device(context, 0x11f6, 0x900e) { + // Device with rndis enabled as well + match open_device(context, 0x05c6, 0xf622) { + Some(handle) => return Some(handle), + None => (), + } + + // Device in out-of-the-box state, need to switch to diag mode + match open_device(context, 0x05c6, 0xf626) { Some(mut handle) => switch_device(&mut handle), None => panic!("No Orbic device detected") } From 23edacc877744e0721737498a6183d9e2e2cdec3 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 10 Jan 2024 20:28:14 -0800 Subject: [PATCH 3/6] Make more idiomatic --- serial/src/main.rs | 71 +++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/serial/src/main.rs b/serial/src/main.rs index f727aa8..c6f2ee2 100644 --- a/serial/src/main.rs +++ b/serial/src/main.rs @@ -27,7 +27,7 @@ fn main() { fn send_command( handle: &mut DeviceHandle, - command: &String, + command: &str, ) { let mut data = String::new(); data.push_str("\r\n"); @@ -36,25 +36,22 @@ fn send_command( let timeout = Duration::from_secs(1); let mut response = [0; 256]; - match handle.write_control(0x21, 0x22, 3, 1, &[], timeout) { - Ok(_) => match handle.write_bulk(0x2, data.as_bytes(), timeout) { - // Consume the echoed back command - Ok(_) => match handle.read_bulk(0x82, &mut response, timeout) { - // Read the actual response - Ok(_) => match handle.read_bulk(0x82, &mut response, timeout) { - Ok(_) => { - let responsestr = str::from_utf8(&response).unwrap(); - if !responsestr.starts_with("\r\nOK\r\n") { - println!("Received unexpected response{0}", responsestr); - } - }, - Err(e) => panic!("Failed to read response: {0}", e), - }, - Err(e) => panic!("Failed to read submitted command: {0}", e), - } - Err(e) => panic!("Failed to write command: {0}", e), - }, - Err(e) => panic!("Failed to send control request: {0}", e), + + // Set up the serial port appropriately + handle.write_control(0x21, 0x22, 3, 1, &[], timeout).expect("Failed to send control request"); + + // Send the command + handle.write_bulk(0x2, data.as_bytes(), timeout).expect("Failed to write command"); + + // Consume the echoed command + handle.read_bulk(0x82, &mut response, timeout).expect("Failed to read submitted command"); + + // Read the actual response + handle.read_bulk(0x82, &mut response, timeout).expect("Failed to read response"); + + let responsestr = str::from_utf8(&response).expect("Failed to parse response"); + if !responsestr.starts_with("\r\nOK\r\n") { + println!("Received unexpected response{0}", responsestr) } } @@ -63,16 +60,14 @@ fn switch_device( ) { // Send a command to switch the device into generic mode, exposing serial let timeout = Duration::from_secs(1); - match handle.write_control(0x40, 0xa0, 0, 0, &[], timeout) { - Ok(_) => (), - Err(e) => { - // If the device reboots while the command is still executing we - // may get a pipe error here - if e == rusb::Error::Pipe { - return; - } - panic!("Failed to send device switch control request: {0}", e); - }, + + if let Err(e) = handle.write_control(0x40, 0xa0, 0, 0, &[], timeout) { + // If the device reboots while the command is still executing we + // may get a pipe error here + if e == rusb::Error::Pipe { + return + } + panic!("Failed to send device switch control request: {0}", e) } } @@ -80,14 +75,13 @@ fn open_orbic( context: &mut T, ) -> Option> { // Device after initial mode switch - match open_device(context, 0x05c6, 0xf601) { - Some(handle) => return Some(handle), - None => (), + if let Some(handle) = open_device(context, 0x05c6, 0xf601) { + return Some(handle) } + // Device with rndis enabled as well - match open_device(context, 0x05c6, 0xf622) { - Some(handle) => return Some(handle), - None => (), + if let Some(handle) = open_device(context, 0x05c6, 0xf622) { + return Some(handle) } // Device in out-of-the-box state, need to switch to diag mode @@ -97,9 +91,8 @@ fn open_orbic( } for _ in 1..10 { - match open_device(context, 0x05c6, 0xf601) { - Some(handle) => return Some(handle), - None => (), + if let Some(handle) = open_device(context, 0x05c6, 0xf601) { + return Some(handle) } sleep(Duration::from_secs(10)) } From 71d7b90dd9c670106948a61b720a54600e41dbfe Mon Sep 17 00:00:00 2001 From: Cooper Quintin Date: Wed, 31 Jan 2024 18:18:42 -0800 Subject: [PATCH 4/6] update installer --- install.sh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/install.sh b/install.sh index 05dbd4d..3c830df 100755 --- a/install.sh +++ b/install.sh @@ -1,8 +1,13 @@ +cd serial +cargo build_pc +cd .. +cd rootshell cargo build --release +cd .. # Force a switch into the debug mode to enable ADB -target/x86_64-unknown-linux-gnu/release/serial AT +target/x86_64-unknown-linux-gnu/debug/serial AT echo -n "device rooted, waiting for reboot" -until adb shell true +until adb shell true 2> /dev/null do echo -n . sleep 1 @@ -10,11 +15,11 @@ done echo echo "it's alive!" adb push target/armv7-unknown-linux-gnueabihf/release/rootshell /tmp/ -target/x86_64-unknown-linux-gnu/release/serial "AT+SYSCMD=mv /tmp/rootshell /bin/rootshell" +target/x86_64-unknown-linux-gnu/debug/serial "AT+SYSCMD=mv /tmp/rootshell /bin/rootshell" sleep 1 -target/x86_64-unknown-linux-gnu/release/serial "AT+SYSCMD=chown root /bin/rootshell" +target/x86_64-unknown-linux-gnu/debug/serial "AT+SYSCMD=chown root /bin/rootshell" sleep 1 -target/x86_64-unknown-linux-gnu/release/serial "AT+SYSCMD=chmod 4755 /bin/rootshell" +target/x86_64-unknown-linux-gnu/debug/serial "AT+SYSCMD=chmod 4755 /bin/rootshell" echo "we have root!" -adb shell id -adb push target/armv7-unknown-linux-gnueabihf/release/rayhunter /data/rayhunter/rayhunter +adb shell /bin/rootshell -c id +./make.sh From b6a0ad6bdc1dc1e3c91e7ba3e260f1d99990dcf9 Mon Sep 17 00:00:00 2001 From: Cooper Quintin Date: Wed, 31 Jan 2024 22:00:25 -0800 Subject: [PATCH 5/6] fixing bugs in install script --- install.sh | 11 ++++++++++- make.sh | 1 + scripts/rayhunter_daemon | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 3c830df..b03e0e0 100755 --- a/install.sh +++ b/install.sh @@ -6,7 +6,7 @@ cargo build --release cd .. # Force a switch into the debug mode to enable ADB target/x86_64-unknown-linux-gnu/debug/serial AT -echo -n "device rooted, waiting for reboot" +echo -n "adb enabled, waiting for reboot" until adb shell true 2> /dev/null do echo -n . @@ -22,4 +22,13 @@ sleep 1 target/x86_64-unknown-linux-gnu/debug/serial "AT+SYSCMD=chmod 4755 /bin/rootshell" echo "we have root!" adb shell /bin/rootshell -c id +adb shell '/bin/rootshell -c "mkdir /data/rayhunter"' +adb push config.toml.example /data/rayhunter/config.toml +adb push scripts/rayhunter_daemon /tmp/rayhunter_daemon +adb push scripts/misc-daemon /tmp/misc-daemon +adb shell '/bin/rootshell -c "mv /tmp/rayhunter_daemon /etc/init.d/rayhunter_daemon"' +adb shell '/bin/rootshell -c "mv /tmp/misc-daemon /etc/init.d/misc-daemon"' +adb shell '/bin/rootshell -c "chmod 755 /etc/init.d/rayhunter_daemon"' +adb shell '/bin/rootshell -c "chmod 755 /etc/init.d/misc-daemon"' ./make.sh +adb shell '/bin/rootshell -c "/etc/init.d/rayhunter_daemon start"' diff --git a/make.sh b/make.sh index e343dde..39483f3 100755 --- a/make.sh +++ b/make.sh @@ -1,2 +1,3 @@ cargo build --release adb push target/armv7-unknown-linux-gnueabihf/release/rayhunter /data/rayhunter/rayhunter +adb shell '/bin/rootshell -c "/etc/init.d/rayhunter_daemon restart"' \ No newline at end of file diff --git a/scripts/rayhunter_daemon b/scripts/rayhunter_daemon index d190b73..90704ec 100644 --- a/scripts/rayhunter_daemon +++ b/scripts/rayhunter_daemon @@ -1,4 +1,4 @@ -#! /bin/sshell +#! /bin/bash set -e From c869353e0562ef738c9b7b7d8048e8297a684a4d Mon Sep 17 00:00:00 2001 From: Cooper Quintin Date: Wed, 31 Jan 2024 22:16:49 -0800 Subject: [PATCH 6/6] updating readme with new install instructions --- README.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c0cf67a..e7fcd25 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Rayhunter ``` - @@@@@@@ @@@@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@@@@@ @@@@@@@@ @@@@@@@ - @@! @@@ @@! @@@ @@! !@@ @@! @@@ @@! @@@ @@!@!@@@ @@! @@! @@! @@@ - @!@!!@! @!@!@!@! !@!@! @!@!@!@! @!@ !@! @!@@!!@! @!! @!!!:! @!@!!@! - !!: :!! !!: !!! !!: !!: !!! !!: !!! !!: !!! !!: !!: !!: :!! - : : : : : : .: : : : :.:: : :: : : : :: ::: : : : + @@@@@@@ @@@@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@@@@@ @@@@@@@@ @@@@@@@ + @@! @@@ @@! @@@ @@! !@@ @@! @@@ @@! @@@ @@!@!@@@ @@! @@! @@! @@@ + @!@!!@! @!@!@!@! !@!@! @!@!@!@! @!@ !@! @!@@!!@! @!! @!!!:! @!@!!@! + !!: :!! !!: !!! !!: !!: !!! !!: !!! !!: !!! !!: !!: !!: :!! + : : : : : : .: : : : :.:: : :: : : : :: ::: : : : _ _ _ _ _ _ _ _ @@ -32,12 +32,11 @@ Rayhunter is an IMSI Catcher Catcher for the Orbic mobile hotspot. Based on code Code is built and tested for the Orbic RC400L mobile hotspot, it may work on other orbics and other linux/qualcom devices but this is the only one we have tested on. Buy the orbic [using bezos bucks](https://www.amazon.com/gp/product/B09CLS6Z7X/) -Root your device on windows using the instructions here: https://xdaforums.com/t/resetting-verizon-orbic-speed-rc400l-firmware-flash-kajeet.4334899/#post-87855183 -(script to root on linux coming soon) ## Setup +### If your are on x86 linux on your linux laptop install rust the usual way and then install cross compiling dependences. run `sudo apt install build-essential libc6-armhf-cross libc6-dev-armhf-cross gcc-arm-linux-gnueabihf` @@ -47,13 +46,27 @@ rustup target add x86_64-unknown-linux-gnu rustup target add armv7-unknown-linux-gnueabihf ``` +Now you can root your device and install rayhunter by running `./install.sh` - **Note:** You will have to install the cross compile tooling below before running this. + + +### If you aren't on linux or can't run the install scripts +Root your device on windows using the instructions here: https://xdaforums.com/t/resetting-verizon-orbic-speed-rc400l-firmware-flash-kajeet.4334899/#post-87855183 + Build for arm using `cargo build` Run tests using `cargo test_pc` - Push the scripts in `scripts/` to /etc/init.d on device and make a directory called /data/rayhunter using `adb shell` (and sshell for your root shell if you followed the steps above) you also need to copy `config.toml.example` to /data/rayhunter/config.toml -Then run ./make.sh this will build the binary and push it over adb. Restart your device or run `/etc/init.d/rayhunter_daemon start` on the device and you are good to go. +Then run `./make.sh` this will build the binary and push it over adb. Restart your device or run `/etc/init.d/rayhunter_daemon start` on the device and you are good to go. + +## Development +Write your code and write tests + +Build for arm using `cargo build` + +Run tests using `cargo test_pc` + +push to the device with `./make.sh` \ No newline at end of file