Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation #40

Merged
merged 14 commits into from
Jun 6, 2024
79 changes: 79 additions & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Build Release

on:
push:
branches: [main]

env:
CARGO_TERM_COLOR: always

jobs:
build_serial:
strategy:
matrix:
platform:
- os: ubuntu-latest
build_name: serial
- os: windows-latest
build_name: serial.exe
- os: macos-latest
build_name: serial
runs-on: ${{ matrix.platform.os }}
steps:
- uses: actions/checkout@v4
- name: Build serial
run: cargo build --bin serial --release
- uses: actions/upload-artifact@v4
with:
name: serial-${{ matrix.platform.os }}
path: ./target/release/${{ matrix.platform.build_name }}
if-no-files-found: error
build_rootshell_and_rayhunter:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: armv7-unknown-linux-gnueabihf
- name: Install cross-compilation dependencies
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: build-essential libc6-armhf-cross libc6-dev-armhf-cross gcc-arm-linux-gnueabihf
version: 1.0
- name: Build rootshell (arm32)
run: cargo build --bin rootshell --target armv7-unknown-linux-gnueabihf --release
- uses: actions/upload-artifact@v4
with:
name: rootshell
path: target/armv7-unknown-linux-gnueabihf/release/rootshell
if-no-files-found: error
- name: Build rayhunter-daemon (arm32)
run: cargo build --bin rayhunter-daemon --target armv7-unknown-linux-gnueabihf --release
- uses: actions/upload-artifact@v4
with:
name: rayhunter-daemon
path: target/armv7-unknown-linux-gnueabihf/release/rayhunter-daemon
if-no-files-found: error
build_release_zip:
needs:
- build_serial
- build_rootshell_and_rayhunter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
- name: Setup release directory
run: mv rayhunter-daemon/rayhunter-daemon rootshell/rootshell serial-* dist
- name: Archive release directory
uses: thedoctor0/[email protected]
with:
type: 'zip'
filename: 'release.zip'
directory: 'dist'
# TODO: have this create a release directly
- name: Upload release
uses: actions/upload-artifact@v4
with:
name: release.zip
path: dist/release.zip
if-no-files-found: error
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Rust
name: Check and Test

on:
push:
Expand All @@ -10,13 +10,11 @@ env:
CARGO_TERM_COLOR: always

jobs:
build:

check_and_test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
- name: Check
run: cargo check --verbose
- name: Run tests
run: cargo test --verbose
52 changes: 36 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ _ _ _ _ _ _ _ _
\ | apc '._|
\__;
```
![Tests](https://github.com/EFForg/rayhunter/actions/workflows/rust.yml/badge.svg)

Rayhunter is an IMSI Catcher Catcher for the Orbic mobile hotspot. Based on code from [QCSuper](https://github.com/P1sec/QCSuper)

Expand All @@ -32,41 +33,60 @@ 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/)

## Setup

1. Install the Android Debug Bridge (ADB) on your computer (don't worry about instructions for installing it on a phone/device yet). You can find instructions for doing so on your platform [here](https://www.xda-developers.com/install-adb-windows-macos-linux/#how-to-set-up-adb-on-your-computer).
2. Download the latest [rayhunter release bundle](https://github.com/EFForg/rayhunter/releases) and unzip it.
3. Run the install script inside the bundle corresponding to your platform (`install-linux.sh`, `install-mac.sh`).
4. Once finished, rayhunter should be running! You can verify this by visiting the web UI as described below.

## Usage

Once installed, rayhunter will run automatically whenever your Orbic device is running. It serves a web UI that provides some basic controls, such as being able to start/stop recordings, download captures, and view heuristic analyses of captures. You can access this UI in one of two ways:

1. Over wifi: Connect your phone/laptop to the Orbic's wifi network and visit `http://192.168.1.1:8080` (click past your browser warning you about the connection not being secure, rayhunter doesn't have HTTPS yet!)
* Note that you'll need the Orbic's wifi password for this, which can be retrieved by pressing the "MENU" button on the device and opening the 2.4 GHz menu.
2. Over usb: Connect the Orbic device to your laptop via usb. Run `adb forward tcp:8080 tcp:8080`, then visit `http://localhost:8080`.

## Development
* Install ADB on your computer using the instructions above.

## 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`
* 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`

set up cross compliing for rust:
* set up cross compliing for rust:
```
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
* 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`
* Build for arm using `cargo build`

Run tests using `cargo test_pc`
* 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)
* 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
* 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
* 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`

Build for arm using `cargo build`
## Documentation
* Build docs locallly using `RUSTDOCFLAGS="--cfg docsrs" cargo doc --no-deps --all-features --open`

Run tests using `cargo test_pc`
**LEGAL DISCLAIMER:** Use this program at your own risk. We beilieve running this program does not currently violate any laws or regulations in the United States. However, we are not responsible for civil or criminal liability resulting from the use of this software. If you are located outside of the US please consult with an attorney in your country to help you assess the legal risks of running this program.

push to the device with `./make.sh`
*Good Hunting!*
File renamed without changes.
61 changes: 61 additions & 0 deletions dist/install-common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/env bash

install() {
if [[ -z "${SERIAL_PATH}" ]]; then
echo "SERIAL_PATH not set, did you run this from install-linux.sh or install-mac.sh?"
exit 1
fi
check_adb
force_debug_mode
setup_rootshell
setup_rayhunter
}

check_adb() {
if ! command -v adb &> /dev/null
then
echo "adb not found, please ensure it's installed or check the README.md"
exit 1
fi
}

force_debug_mode() {
# Force a switch into the debug mode to enable ADB
$(SERIAL_PATH) AT
echo -n "adb enabled, waiting for reboot"
until adb shell true 2> /dev/null
do
echo -n .
sleep 1
done
echo
echo "it's alive!"
}

setup_rootshell() {
_adb_push rootshell /tmp/
$(SERIAL_PATH) "AT+SYSCMD=mv /tmp/rootshell /bin/rootshell"
sleep 1
$(SERIAL_PATH) "AT+SYSCMD=chown root /bin/rootshell"
sleep 1
$(SERIAL_PATH) "AT+SYSCMD=chmod 4755 /bin/rootshell"
echo "we have root!"
adb shell /bin/rootshell -c id
}

_adb_push() {
adb push "$(dirname "$0")/$1" "$2"
}

setup_rayhunter() {
adb shell '/bin/rootshell -c "mkdir /data/rayhunter"'
_adb_push config.toml.example /data/rayhunter/config.toml
_adb_push rayhunter-daemon /data/rayhunter/
_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"'
adb shell '/bin/rootshell -c "/etc/init.d/rayhunter_daemon start"'
}
6 changes: 6 additions & 0 deletions dist/install-linux.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/env bash

set -e
export SERIAL_PATH="./serial-ubuntu-latest/serial"
. "$(dirname "$0")"/install-common.sh
install
6 changes: 6 additions & 0 deletions dist/install-mac.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/env bash

set -e
export SERIAL_PATH="./serial-mac-latest/serial"
. "$(dirname "$0")"/install-common.sh
install
1 change: 1 addition & 0 deletions dist/install-windows.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ECHO TODO
File renamed without changes.
2 changes: 1 addition & 1 deletion scripts/rayhunter_daemon → dist/scripts/rayhunter_daemon
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ case "$1" in
start)
echo -n "Starting rayhunter: "
start-stop-daemon -S -b --make-pidfile --pidfile /tmp/rayhunter.pid \
--startas /bin/bash -- -c "exec /data/rayhunter/rayhunter-daemon /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
--startas /bin/bash -- -c "RUST_LOG=info exec /data/rayhunter/rayhunter-daemon /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
echo "done"
;;
stop)
Expand Down
1 change: 0 additions & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,3 @@ 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"'
5 changes: 5 additions & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ version = "0.1.0"
edition = "2021"
description = "Realtime cellular data decoding and analysis for IMSI catcher detection"


[lib]
name = "rayhunter"
path = "src/lib.rs"

[dependencies]
bytes = "1.5.0"
chrono = "0.4.31"
Expand Down
2 changes: 2 additions & 0 deletions lib/src/pcap.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Parse QMDL files and create a pcap file.
//! Creates a plausible IP header and [GSMtap](https://osmocom.org/projects/baseband/wiki/GSMTAP) header and then puts the rest of the data under that for wireshark to parse.
use crate::gsmtap::GsmtapMessage;
use crate::diag::Timestamp;

Expand Down
4 changes: 2 additions & 2 deletions make.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
cargo build --release --target="armv7-unknown-linux-gnueabihf" --bin rayhunter-daemon
adb push target/armv7-unknown-linux-gnueabihf/release/rayhunter-daemon /data/rayhunter/
cargo build --release --target="armv7-unknown-linux-gnueabihf"
adb push target/armv7-unknown-linux-gnueabihf/release/rayhunter-daemon /data/rayhunter/rayhunter-daemon
adb shell '/bin/rootshell -c "/etc/init.d/rayhunter_daemon restart"'
5 changes: 4 additions & 1 deletion rootshell/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! a simple shell for uploading to the orbic device.
//!
//! It literally just runs bash as UID/GID 0
use std::process::Command;
use std::os::unix::process::CommandExt;
use std::env;
Expand All @@ -12,4 +15,4 @@ fn main() {
.uid(0)
.gid(0)
.exec();
}
}
33 changes: 31 additions & 2 deletions serial/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
//! Serial communication with the orbic device
//!
//! This binary has two main functions, putting the orbic device in update mode which enables ADB
//! and running AT commands on the serial modem interface which can be used to upload a shell and chown it to root
//!
//! # Panics
//!
//! No device found - make sure your device is plugged in and turned on. If it is, it's possible you have a device with a different
//! usb id, file a bug with the output of `lsusb` attached.
//!
//! # Examples
//! ```
//! match rusb::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),
//! ````
use std::str;
use std::thread::sleep;
use std::time::Duration;
Expand All @@ -24,7 +45,9 @@ fn main() {
Err(e) => panic!("Failed to initialize libusb: {0}", e),
}
}

/// Sends an AT command to the usb device over the serial port
///
/// First establish a USB handle and context by calling `open_orbic(<T>)
fn send_command<T: UsbContext>(
handle: &mut DeviceHandle<T>,
command: &str,
Expand Down Expand Up @@ -55,10 +78,12 @@ fn send_command<T: UsbContext>(
}
}

/// Send a command to switch the device into generic mode, exposing serial
///
/// If the device reboots while the command is still executing you may get a pipe error here, not sure what to do about this race condition.
fn switch_device<T: UsbContext>(
handle: &mut DeviceHandle<T>,
) {
// Send a command to switch the device into generic mode, exposing serial
let timeout = Duration::from_secs(1);

if let Err(e) = handle.write_control(0x40, 0xa0, 0, 0, &[], timeout) {
Expand All @@ -71,6 +96,9 @@ fn switch_device<T: UsbContext>(
}
}

/// Get a handle and contet for the orbic device
///
/// If the device isn't already in command mode this function will call swtich_device to switch it into command mode
fn open_orbic<T: UsbContext>(
context: &mut T,
) -> Option<DeviceHandle<T>> {
Expand Down Expand Up @@ -99,6 +127,7 @@ fn open_orbic<T: UsbContext>(
panic!("No Orbic device detected")
}

/// Generic function to open a USB device
fn open_device<T: UsbContext>(
context: &mut T,
vid: u16,
Expand Down
Loading