mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-07-20 06:38:10 -07:00
@@ -4,6 +4,8 @@ rustflags = ["-C", "target-feature=+crt-static"]
|
|||||||
|
|
||||||
[alias]
|
[alias]
|
||||||
test_pc = "test --target=x86_64-unknown-linux-gnu"
|
test_pc = "test --target=x86_64-unknown-linux-gnu"
|
||||||
|
build_pc = "build --target=x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
|
||||||
[target.armv7-unknown-linux-gnueabihf]
|
[target.armv7-unknown-linux-gnueabihf]
|
||||||
linker = "arm-linux-gnueabihf-gcc"
|
linker = "arm-linux-gnueabihf-gcc"
|
||||||
|
|||||||
Generated
+21
-21
@@ -899,6 +899,27 @@ version = "0.4.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayhunter"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"axum",
|
||||||
|
"chrono",
|
||||||
|
"env_logger",
|
||||||
|
"futures-core",
|
||||||
|
"futures-macro",
|
||||||
|
"include_dir",
|
||||||
|
"log",
|
||||||
|
"mime_guess",
|
||||||
|
"orca",
|
||||||
|
"serde",
|
||||||
|
"tempdir",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rdrand"
|
name = "rdrand"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -1387,27 +1408,6 @@ version = "0.2.89"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wavehunter"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"axum",
|
|
||||||
"chrono",
|
|
||||||
"env_logger",
|
|
||||||
"futures-core",
|
|
||||||
"futures-macro",
|
|
||||||
"include_dir",
|
|
||||||
"log",
|
|
||||||
"mime_guess",
|
|
||||||
"orca",
|
|
||||||
"serde",
|
|
||||||
"tempdir",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
"tokio-util",
|
|
||||||
"toml",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|||||||
+1
-1
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
members = [
|
members = [
|
||||||
"orca",
|
"orca",
|
||||||
"wavehunter",
|
"rayhunter",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|||||||
@@ -1,22 +1,13 @@
|
|||||||
# Orca
|
# Rayhunter
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@@@@@@@ @@@@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@@@@@ @@@@@@@@ @@@@@@@
|
||||||
|
@@! @@@ @@! @@@ @@! !@@ @@! @@@ @@! @@@ @@!@!@@@ @@! @@! @@! @@@
|
||||||
|
@!@!!@! @!@!@!@! !@!@! @!@!@!@! @!@ !@! @!@@!!@! @!! @!!!:! @!@!!@!
|
||||||
|
!!: :!! !!: !!! !!: !!: !!! !!: !!! !!: !!! !!: !!: !!: :!!
|
||||||
|
: : : : : : .: : : : :.:: : :: : : : :: ::: : : :
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
u. .u .
|
|
||||||
...ue888b .d88B :@8c . u
|
|
||||||
888R Y888r ="8888f8888r .udR88N us888u.
|
|
||||||
888R I888> 4888>'88" <888'888k .@88 "8888"
|
|
||||||
888R I888> 4888> ' 9888 'Y" 9888 9888
|
|
||||||
888R I888> 4888> 9888 9888 9888
|
|
||||||
u8888cJ888 .d888L .+ 9888 9888 9888
|
|
||||||
"*888*P" ^"8888*" ?8888u../ 9888 9888
|
|
||||||
'Y" "Y" "8888P' "888*""888"
|
|
||||||
"P' ^Y" ^Y'
|
|
||||||
|
|
||||||
|
|
||||||
Orca Realtime Cellular Analysis
|
|
||||||
|
|
||||||
_ _ _ _ _ _ _ _
|
_ _ _ _ _ _ _ _
|
||||||
)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_
|
)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_
|
||||||
|
|
||||||
@@ -34,7 +25,7 @@ _ _ _ _ _ _ _ _
|
|||||||
\__;
|
\__;
|
||||||
```
|
```
|
||||||
|
|
||||||
IMSI Catcher Catcher for the Orbic mobile hotspot. Based on code from [QCSuper](https://github.com/P1sec/QCSuper)
|
Rayhunter is an IMSI Catcher Catcher for the Orbic mobile hotspot. Based on code from [QCSuper](https://github.com/P1sec/QCSuper)
|
||||||
|
|
||||||
**THIS CODE IS PROOF OF CONCEPT AND SHOULD NOT BE RELIED UPON IN HIGH RISK SITUATIONS**
|
**THIS CODE IS PROOF OF CONCEPT AND SHOULD NOT BE RELIED UPON IN HIGH RISK SITUATIONS**
|
||||||
|
|
||||||
@@ -61,8 +52,8 @@ 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/wavehunter 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/wavehunter/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 wavehunter_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.
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
# cat config.toml
|
# cat config.toml
|
||||||
qmdl_store_path = "/data/wavehunter/qmdl"
|
qmdl_store_path = "/data/rayhunter/qmdl"
|
||||||
port = 8080
|
port = 8080
|
||||||
readonly_mode = false
|
readonly_mode = false
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
cargo build --release
|
cargo build --release
|
||||||
adb push target/armv7-unknown-linux-gnueabihf/release/wavehunter /data/wavehunter/wavehunter
|
adb push target/armv7-unknown-linux-gnueabihf/release/rayhunter /data/rayhunter/rayhunter
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wavehunter"
|
name = "rayhunter"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::error::WavehunterError;
|
use crate::error::RayhunterError;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
@@ -19,21 +19,21 @@ pub struct Config {
|
|||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Config {
|
Config {
|
||||||
qmdl_store_path: "/data/wavehunter".to_string(),
|
qmdl_store_path: "/data/rayhunter/qmdl".to_string(),
|
||||||
port: 8080,
|
port: 8080,
|
||||||
readonly_mode: false,
|
readonly_mode: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_config<P>(path: P) -> Result<Config, WavehunterError> where P: AsRef<std::path::Path> {
|
pub fn parse_config<P>(path: P) -> Result<Config, RayhunterError> where P: AsRef<std::path::Path> {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
if let Ok(config_file) = std::fs::read_to_string(&path) {
|
if let Ok(config_file) = std::fs::read_to_string(&path) {
|
||||||
let parsed_config: ConfigFile = toml::from_str(&config_file)
|
let parsed_config: ConfigFile = toml::from_str(&config_file)
|
||||||
.map_err(WavehunterError::ConfigFileParsingError)?;
|
.map_err(RayhunterError::ConfigFileParsingError)?;
|
||||||
if let Some(path) = parsed_config.qmdl_store_path { config.qmdl_store_path = path }
|
if let Some(path) = parsed_config.qmdl_store_path { config.qmdl_store_path = path }
|
||||||
if let Some(port) = parsed_config.port { config.port = port }
|
if let Some(port) = parsed_config.port { config.port = port }
|
||||||
if let Some(debug_mode) = parsed_config.readonly_mode { config.readonly_mode = debug_mode }
|
if let Some(readonly_mode) = parsed_config.readonly_mode { config.readonly_mode = readonly_mode }
|
||||||
}
|
}
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@ use tokio::sync::mpsc::error::TryRecvError;
|
|||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tokio_util::task::TaskTracker;
|
use tokio_util::task::TaskTracker;
|
||||||
|
|
||||||
use crate::error::WavehunterError;
|
use crate::error::RayhunterError;
|
||||||
use crate::qmdl_store::QmdlStore;
|
use crate::qmdl_store::QmdlStore;
|
||||||
use crate::server::ServerState;
|
use crate::server::ServerState;
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ pub enum DiagDeviceCtrlMessage {
|
|||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_diag_read_thread(task_tracker: &TaskTracker, mut dev: DiagDevice, mut qmdl_file_rx: Receiver<DiagDeviceCtrlMessage>, qmdl_store_lock: Arc<RwLock<QmdlStore>>) -> JoinHandle<Result<(), WavehunterError>> {
|
pub fn run_diag_read_thread(task_tracker: &TaskTracker, mut dev: DiagDevice, mut qmdl_file_rx: Receiver<DiagDeviceCtrlMessage>, qmdl_store_lock: Arc<RwLock<QmdlStore>>) -> JoinHandle<Result<(), RayhunterError>> {
|
||||||
// mpsc channel for updating QmdlStore entry filesizes. First usize is the
|
// mpsc channel for updating QmdlStore entry filesizes. First usize is the
|
||||||
// index, second is the size in bytes
|
// index, second is the size in bytes
|
||||||
let (tx, mut rx) = mpsc::channel::<(usize, usize)>(1);
|
let (tx, mut rx) = mpsc::channel::<(usize, usize)>(1);
|
||||||
@@ -67,7 +67,7 @@ pub fn run_diag_read_thread(task_tracker: &TaskTracker, mut dev: DiagDevice, mut
|
|||||||
// returned here. Until then, the DiagDevice has already written those messages
|
// returned here. Until then, the DiagDevice has already written those messages
|
||||||
// to the QMDL file, so we can just ignore them.
|
// to the QMDL file, so we can just ignore them.
|
||||||
debug!("reading response from diag device...");
|
debug!("reading response from diag device...");
|
||||||
let _messages = dev.read_response().map_err(WavehunterError::DiagReadError)?;
|
let _messages = dev.read_response().map_err(RayhunterError::DiagReadError)?;
|
||||||
debug!("got diag response ({} messages)", _messages.len());
|
debug!("got diag response ({} messages)", _messages.len());
|
||||||
|
|
||||||
// keep track of how many bytes were written to the QMDL file so we can read
|
// keep track of how many bytes were written to the QMDL file so we can read
|
||||||
@@ -4,7 +4,7 @@ use orca::diag_device::DiagDeviceError;
|
|||||||
use crate::qmdl_store::QmdlStoreError;
|
use crate::qmdl_store::QmdlStoreError;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum WavehunterError {
|
pub enum RayhunterError{
|
||||||
#[error("Config file parsing error: {0}")]
|
#[error("Config file parsing error: {0}")]
|
||||||
ConfigFileParsingError(#[from] toml::de::Error),
|
ConfigFileParsingError(#[from] toml::de::Error),
|
||||||
#[error("Diag intialization error: {0}")]
|
#[error("Diag intialization error: {0}")]
|
||||||
@@ -12,7 +12,7 @@ use crate::qmdl_store::QmdlStore;
|
|||||||
use crate::server::{ServerState, get_qmdl, serve_static};
|
use crate::server::{ServerState, get_qmdl, serve_static};
|
||||||
use crate::pcap::get_pcap;
|
use crate::pcap::get_pcap;
|
||||||
use crate::stats::get_system_stats;
|
use crate::stats::get_system_stats;
|
||||||
use crate::error::WavehunterError;
|
use crate::error::RayhunterError;
|
||||||
|
|
||||||
use axum::response::Redirect;
|
use axum::response::Redirect;
|
||||||
use diag::{DiagDeviceCtrlMessage, start_recording, stop_recording};
|
use diag::{DiagDeviceCtrlMessage, start_recording, stop_recording};
|
||||||
@@ -73,11 +73,11 @@ async fn server_shutdown_signal(server_shutdown_rx: oneshot::Receiver<()>) {
|
|||||||
|
|
||||||
// Loads a QmdlStore if one exists, and if not, only create one if we're not in
|
// Loads a QmdlStore if one exists, and if not, only create one if we're not in
|
||||||
// readonly mode.
|
// readonly mode.
|
||||||
async fn init_qmdl_store(config: &config::Config) -> Result<QmdlStore, WavehunterError> {
|
async fn init_qmdl_store(config: &config::Config) -> Result<QmdlStore, RayhunterError> {
|
||||||
match (QmdlStore::exists(&config.qmdl_store_path).await?, config.readonly_mode) {
|
match (QmdlStore::exists(&config.qmdl_store_path).await?, config.readonly_mode) {
|
||||||
(true, _) => Ok(QmdlStore::load(&config.qmdl_store_path).await?),
|
(true, _) => Ok(QmdlStore::load(&config.qmdl_store_path).await?),
|
||||||
(false, false) => Ok(QmdlStore::create(&config.qmdl_store_path).await?),
|
(false, false) => Ok(QmdlStore::create(&config.qmdl_store_path).await?),
|
||||||
(false, true) => Err(WavehunterError::NoStoreReadonlyMode(config.qmdl_store_path.clone())),
|
(false, true) => Err(RayhunterError::NoStoreReadonlyMode(config.qmdl_store_path.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ fn run_ctrl_c_thread(
|
|||||||
diag_device_sender: Sender<DiagDeviceCtrlMessage>,
|
diag_device_sender: Sender<DiagDeviceCtrlMessage>,
|
||||||
server_shutdown_tx: oneshot::Sender<()>,
|
server_shutdown_tx: oneshot::Sender<()>,
|
||||||
qmdl_store_lock: Arc<RwLock<QmdlStore>>
|
qmdl_store_lock: Arc<RwLock<QmdlStore>>
|
||||||
) -> JoinHandle<Result<(), WavehunterError>> {
|
) -> JoinHandle<Result<(), RayhunterError>> {
|
||||||
task_tracker.spawn(async move {
|
task_tracker.spawn(async move {
|
||||||
match tokio::signal::ctrl_c().await {
|
match tokio::signal::ctrl_c().await {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
@@ -114,7 +114,7 @@ fn run_ctrl_c_thread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), WavehunterError> {
|
async fn main() -> Result<(), RayhunterError> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
let args = parse_args();
|
let args = parse_args();
|
||||||
@@ -130,9 +130,9 @@ async fn main() -> Result<(), WavehunterError> {
|
|||||||
let qmdl_file = qmdl_store_lock.write().await.new_entry().await?;
|
let qmdl_file = qmdl_store_lock.write().await.new_entry().await?;
|
||||||
let qmdl_writer = QmdlWriter::new(qmdl_file.into_std().await);
|
let qmdl_writer = QmdlWriter::new(qmdl_file.into_std().await);
|
||||||
let mut dev = DiagDevice::new(Some(qmdl_writer))
|
let mut dev = DiagDevice::new(Some(qmdl_writer))
|
||||||
.map_err(WavehunterError::DiagInitError)?;
|
.map_err(RayhunterError::DiagInitError)?;
|
||||||
dev.config_logs()
|
dev.config_logs()
|
||||||
.map_err(WavehunterError::DiagInitError)?;
|
.map_err(RayhunterError::DiagInitError)?;
|
||||||
|
|
||||||
run_diag_read_thread(&task_tracker, dev, rx, qmdl_store_lock.clone());
|
run_diag_read_thread(&task_tracker, dev, rx, qmdl_store_lock.clone());
|
||||||
}
|
}
|
||||||
+4
-4
@@ -41,9 +41,9 @@ case "$1" in
|
|||||||
/etc/init.d/start_atfwd_daemon start
|
/etc/init.d/start_atfwd_daemon start
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f /etc/init.d/wavehunter_daemon ]
|
if [ -f /etc/init.d/rayhunter_daemon ]
|
||||||
then
|
then
|
||||||
/etc/init.d/wavehunter_daemon start
|
/etc/init.d/rayhunter_daemon start
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f /etc/init.d/start_stop_qti_ppp_le ]
|
if [ -f /etc/init.d/start_stop_qti_ppp_le ]
|
||||||
@@ -72,9 +72,9 @@ case "$1" in
|
|||||||
/etc/init.d/start_loc_launcher stop
|
/etc/init.d/start_loc_launcher stop
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f /etc/init.d/wavehunter_daemon ]
|
if [ -f /etc/init.d/rayhunter_daemon ]
|
||||||
then
|
then
|
||||||
/etc/init.d/wavehunter_daemon stop
|
/etc/init.d/rayhunter_daemon stop
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f /etc/init.d/init_qcom_audio ]
|
if [ -f /etc/init.d/init_qcom_audio ]
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#! /bin/sshell
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
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 /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
|
||||||
|
echo "done"
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
echo -n "Stopping rayhunter: "
|
||||||
|
start-stop-daemon -K -p /tmp/rayhunter.pid
|
||||||
|
echo "done"
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
$0 stop
|
||||||
|
$0 start
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage rayhunter_daemon { start | stop | restart }" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#! /bin/sshell
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
start)
|
|
||||||
echo -n "Starting wavehunter: "
|
|
||||||
start-stop-daemon -S -b --make-pidfile --pidfile /tmp/wavehunter.pid \
|
|
||||||
--startas /bin/bash -- -c "exec /data/wavehunter/wavehunter /data/wavehunter/config.toml > /data/wavehunter/wavehunter.log 2>&1"
|
|
||||||
echo "done"
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
echo -n "Stopping wavehunter: "
|
|
||||||
start-stop-daemon -K -p /tmp/wavehunter.pid
|
|
||||||
echo "done"
|
|
||||||
;;
|
|
||||||
restart)
|
|
||||||
$0 stop
|
|
||||||
$0 start
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Usage atfwd_daemon{ start | stop | restart }" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
Reference in New Issue
Block a user