mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-07-17 13:28:10 -07:00
Various fixes for TP-Link
* explicitly mount the SD card to improve reliability * do not crash when the SD card is already mounted * address some review feedback
This commit is contained in:
committed by
Cooper Quintin
parent
4a7452806d
commit
c285e2ca08
Vendored
+2
@@ -5,6 +5,8 @@ set -e
|
|||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
echo -n "Starting rayhunter: "
|
echo -n "Starting rayhunter: "
|
||||||
|
# Below line may be replaced by the installer with device-specific startup commands, such as mounting the SD card.
|
||||||
|
#RAYHUNTER-PRESTART
|
||||||
start-stop-daemon -S -b --make-pidfile --pidfile /tmp/rayhunter.pid \
|
start-stop-daemon -S -b --make-pidfile --pidfile /tmp/rayhunter.pid \
|
||||||
--startas /bin/sh -- -c "RUST_LOG=info exec /data/rayhunter/rayhunter-daemon /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
|
--startas /bin/sh -- -c "RUST_LOG=info exec /data/rayhunter/rayhunter-daemon /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
|
||||||
echo "done"
|
echo "done"
|
||||||
|
|||||||
+17
-5
@@ -4,8 +4,8 @@ use clap::{Parser, Subcommand};
|
|||||||
mod orbic;
|
mod orbic;
|
||||||
mod tplink;
|
mod tplink;
|
||||||
|
|
||||||
pub static CONFIG_TOML: &[u8] = include_bytes!("../../dist/config.toml.example");
|
pub static CONFIG_TOML: &str = include_str!("../../dist/config.toml.example");
|
||||||
pub static RAYHUNTER_DAEMON_INIT: &[u8] = include_bytes!("../../dist/scripts/rayhunter_daemon");
|
pub static RAYHUNTER_DAEMON_INIT: &str = include_str!("../../dist/scripts/rayhunter_daemon");
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about)]
|
#[command(version, about)]
|
||||||
@@ -42,13 +42,22 @@ struct InstallOrbic {}
|
|||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct Util {
|
struct Util {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: UntilSubCommand,
|
command: UtilSubCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum UntilSubCommand {
|
enum UtilSubCommand {
|
||||||
/// Send a serial command to the Orbic.
|
/// Send a serial command to the Orbic.
|
||||||
Serial(Serial),
|
Serial(Serial),
|
||||||
|
/// Root the tplink and launch telnetd.
|
||||||
|
TplinkStartTelnet(TplinkStartTelnet),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
struct TplinkStartTelnet {
|
||||||
|
/// IP address for TP-Link admin interface, if custom.
|
||||||
|
#[arg(long, default_value = "192.168.0.1")]
|
||||||
|
admin_ip: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@@ -65,7 +74,7 @@ async fn run_function() -> Result<(), Error> {
|
|||||||
Command::Tplink(tplink) => tplink::main_tplink(tplink).await.context("Failed to install rayhunter on the TP-Link M7350. Make sure your computer is connected to the hotspot using USB tethering or WiFi.")?,
|
Command::Tplink(tplink) => tplink::main_tplink(tplink).await.context("Failed to install rayhunter on the TP-Link M7350. Make sure your computer is connected to the hotspot using USB tethering or WiFi.")?,
|
||||||
Command::Orbic(_) => orbic::install().await.context("Failed to install rayhunter on the Orbic RC400L")?,
|
Command::Orbic(_) => orbic::install().await.context("Failed to install rayhunter on the Orbic RC400L")?,
|
||||||
Command::Util(subcommand) => match subcommand.command {
|
Command::Util(subcommand) => match subcommand.command {
|
||||||
UntilSubCommand::Serial(serial_cmd) => {
|
UtilSubCommand::Serial(serial_cmd) => {
|
||||||
if serial_cmd.root {
|
if serial_cmd.root {
|
||||||
if !serial_cmd.command.is_empty() {
|
if !serial_cmd.command.is_empty() {
|
||||||
eprintln!("You cannot use --root and specify a command at the same time");
|
eprintln!("You cannot use --root and specify a command at the same time");
|
||||||
@@ -83,6 +92,9 @@ async fn run_function() -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UtilSubCommand::TplinkStartTelnet(options) => {
|
||||||
|
tplink::start_telnet(&options.admin_ip).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,14 +116,14 @@ async fn setup_rayhunter(
|
|||||||
serial_interface,
|
serial_interface,
|
||||||
&mut adb_device,
|
&mut adb_device,
|
||||||
"/data/rayhunter/config.toml",
|
"/data/rayhunter/config.toml",
|
||||||
CONFIG_TOML,
|
CONFIG_TOML.as_bytes(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
install_file(
|
install_file(
|
||||||
serial_interface,
|
serial_interface,
|
||||||
&mut adb_device,
|
&mut adb_device,
|
||||||
"/etc/init.d/rayhunter_daemon",
|
"/etc/init.d/rayhunter_daemon",
|
||||||
RAYHUNTER_DAEMON_INIT,
|
RAYHUNTER_DAEMON_INIT.as_bytes(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
install_file(
|
install_file(
|
||||||
|
|||||||
+54
-18
@@ -23,20 +23,25 @@ use crate::InstallTpLink;
|
|||||||
|
|
||||||
type HttpProxyClient = hyper_util::client::legacy::Client<HttpConnector, Body>;
|
type HttpProxyClient = hyper_util::client::legacy::Client<HttpConnector, Body>;
|
||||||
|
|
||||||
pub async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
pub async fn main_tplink(
|
||||||
let InstallTpLink {
|
InstallTpLink {
|
||||||
skip_sdcard,
|
skip_sdcard,
|
||||||
admin_ip,
|
admin_ip,
|
||||||
} = args;
|
}: InstallTpLink,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
start_telnet(&admin_ip).await?;
|
||||||
|
tplink_run_install(skip_sdcard, admin_ip).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct V3RootResponse {
|
||||||
|
result: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_telnet(admin_ip: &str) -> Result<(), Error> {
|
||||||
let qcmap_web_cgi_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_web_cgi");
|
let qcmap_web_cgi_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_web_cgi");
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct RootResponse {
|
|
||||||
result: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Launching telnet on the device");
|
println!("Launching telnet on the device");
|
||||||
|
|
||||||
// https://github.com/advisories/GHSA-ffwq-9r7p-3j6r
|
// https://github.com/advisories/GHSA-ffwq-9r7p-3j6r
|
||||||
@@ -48,9 +53,9 @@ pub async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
|||||||
|
|
||||||
if response.status() == 404 {
|
if response.status() == 404 {
|
||||||
println!("Got a 404 trying to run exploit for hardware revision v3, trying v5 exploit");
|
println!("Got a 404 trying to run exploit for hardware revision v3, trying v5 exploit");
|
||||||
tplink_launch_telnet_v5(admin_ip.clone()).await?;
|
tplink_launch_telnet_v5(admin_ip).await?;
|
||||||
} else {
|
} else {
|
||||||
let RootResponse { result } = response.error_for_status()?.json().await?;
|
let V3RootResponse { result } = response.error_for_status()?.json().await?;
|
||||||
|
|
||||||
if result != 0 {
|
if result != 0 {
|
||||||
anyhow::bail!("Bad result code when trying to root device: {result}");
|
anyhow::bail!("Bad result code when trying to root device: {result}");
|
||||||
@@ -59,9 +64,10 @@ pub async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
|||||||
println!("Detected hardware revision v3");
|
println!("Detected hardware revision v3");
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Succeeded in rooting the device!");
|
println!(
|
||||||
|
"Succeeded in rooting the device! Now you can use 'telnet {admin_ip}' to get a root shell. Use './installer util tplink-start-telnet' to root again without installing rayhunter."
|
||||||
tplink_run_install(skip_sdcard, admin_ip).await
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn tplink_run_install(skip_sdcard: bool, admin_ip: String) -> Result<(), Error> {
|
async fn tplink_run_install(skip_sdcard: bool, admin_ip: String) -> Result<(), Error> {
|
||||||
@@ -70,7 +76,14 @@ async fn tplink_run_install(skip_sdcard: bool, admin_ip: String) -> Result<(), E
|
|||||||
|
|
||||||
if !skip_sdcard {
|
if !skip_sdcard {
|
||||||
println!("Mounting sdcard");
|
println!("Mounting sdcard");
|
||||||
telnet_send_command(addr, "mount /dev/mmcblk0p1 /media/card", "exit code 0").await.context("Rayhunter needs a FAT-formatted SD card to function for more than a few minutes. Insert one and rerun this installer, or pass --skip-sdcard")?;
|
if telnet_send_command(addr, "mount | grep -q /media/card", "exit code 0")
|
||||||
|
.await
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
telnet_send_command(addr, "mount /dev/mmcblk0p1 /media/card", "exit code 0").await.context("Rayhunter needs a FAT-formatted SD card to function for more than a few minutes. Insert one and rerun this installer, or pass --skip-sdcard")?;
|
||||||
|
} else {
|
||||||
|
println!("sdcard already mounted");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// there is too little space on the internal flash to store anything, but the initrd script
|
// there is too little space on the internal flash to store anything, but the initrd script
|
||||||
@@ -79,7 +92,12 @@ async fn tplink_run_install(skip_sdcard: bool, admin_ip: String) -> Result<(), E
|
|||||||
telnet_send_command(addr, "mkdir -p /data", "exit code 0").await?;
|
telnet_send_command(addr, "mkdir -p /data", "exit code 0").await?;
|
||||||
telnet_send_command(addr, "ln -sf /media/card /data/rayhunter", "exit code 0").await?;
|
telnet_send_command(addr, "ln -sf /media/card /data/rayhunter", "exit code 0").await?;
|
||||||
|
|
||||||
telnet_send_file(addr, "/media/card/config.toml", crate::CONFIG_TOML).await?;
|
telnet_send_file(
|
||||||
|
addr,
|
||||||
|
"/media/card/config.toml",
|
||||||
|
crate::CONFIG_TOML.as_bytes(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
#[cfg(feature = "vendor")]
|
#[cfg(feature = "vendor")]
|
||||||
let rayhunter_daemon_bin = include_bytes!("../../rayhunter-daemon-tplink/rayhunter-daemon");
|
let rayhunter_daemon_bin = include_bytes!("../../rayhunter-daemon-tplink/rayhunter-daemon");
|
||||||
@@ -92,7 +110,7 @@ async fn tplink_run_install(skip_sdcard: bool, admin_ip: String) -> Result<(), E
|
|||||||
telnet_send_file(
|
telnet_send_file(
|
||||||
addr,
|
addr,
|
||||||
"/etc/init.d/rayhunter_daemon",
|
"/etc/init.d/rayhunter_daemon",
|
||||||
crate::RAYHUNTER_DAEMON_INIT,
|
get_rayhunter_daemon().as_bytes(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -260,7 +278,7 @@ async fn handler(state: State<AppState>, mut req: Request) -> Result<Response, S
|
|||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn tplink_launch_telnet_v5(admin_ip: String) -> Result<(), Error> {
|
async fn tplink_launch_telnet_v5(admin_ip: &str) -> Result<(), Error> {
|
||||||
let client: HttpProxyClient =
|
let client: HttpProxyClient =
|
||||||
hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new())
|
hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new())
|
||||||
.build(HttpConnector::new());
|
.build(HttpConnector::new());
|
||||||
@@ -270,7 +288,7 @@ async fn tplink_launch_telnet_v5(admin_ip: String) -> Result<(), Error> {
|
|||||||
.route("/{*path}", any(handler))
|
.route("/{*path}", any(handler))
|
||||||
.with_state(AppState {
|
.with_state(AppState {
|
||||||
client,
|
client,
|
||||||
admin_ip: admin_ip.clone(),
|
admin_ip: admin_ip.to_owned(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:4000")
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:4000")
|
||||||
@@ -295,3 +313,21 @@ async fn tplink_launch_telnet_v5(admin_ip: String) -> Result<(), Error> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_rayhunter_daemon() -> String {
|
||||||
|
// Even though TP-Link eventually auto-mounts the SD card, it sometimes does so too late. And
|
||||||
|
// changing the order in which daemons are started up seems to not work reliably.
|
||||||
|
//
|
||||||
|
// This part of the daemon dynamically generated because we may have to eventually add logic
|
||||||
|
// specific to a particular hardware revision here.
|
||||||
|
crate::RAYHUNTER_DAEMON_INIT.replace(
|
||||||
|
"#RAYHUNTER-PRESTART",
|
||||||
|
"mount /dev/mmcblk0p1 /media/card || true",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_rayhunter_daemon() {
|
||||||
|
let s = get_rayhunter_daemon();
|
||||||
|
assert!(s.contains("mount /dev/mmcblk0p1 /media/card"));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user