mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-04-26 23:49:59 -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
@@ -4,8 +4,8 @@ use clap::{Parser, Subcommand};
|
||||
mod orbic;
|
||||
mod tplink;
|
||||
|
||||
pub static CONFIG_TOML: &[u8] = include_bytes!("../../dist/config.toml.example");
|
||||
pub static RAYHUNTER_DAEMON_INIT: &[u8] = include_bytes!("../../dist/scripts/rayhunter_daemon");
|
||||
pub static CONFIG_TOML: &str = include_str!("../../dist/config.toml.example");
|
||||
pub static RAYHUNTER_DAEMON_INIT: &str = include_str!("../../dist/scripts/rayhunter_daemon");
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about)]
|
||||
@@ -42,13 +42,22 @@ struct InstallOrbic {}
|
||||
#[derive(Parser, Debug)]
|
||||
struct Util {
|
||||
#[command(subcommand)]
|
||||
command: UntilSubCommand,
|
||||
command: UtilSubCommand,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum UntilSubCommand {
|
||||
enum UtilSubCommand {
|
||||
/// Send a serial command to the Orbic.
|
||||
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)]
|
||||
@@ -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::Orbic(_) => orbic::install().await.context("Failed to install rayhunter on the Orbic RC400L")?,
|
||||
Command::Util(subcommand) => match subcommand.command {
|
||||
UntilSubCommand::Serial(serial_cmd) => {
|
||||
UtilSubCommand::Serial(serial_cmd) => {
|
||||
if serial_cmd.root {
|
||||
if !serial_cmd.command.is_empty() {
|
||||
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,
|
||||
&mut adb_device,
|
||||
"/data/rayhunter/config.toml",
|
||||
CONFIG_TOML,
|
||||
CONFIG_TOML.as_bytes(),
|
||||
)
|
||||
.await?;
|
||||
install_file(
|
||||
serial_interface,
|
||||
&mut adb_device,
|
||||
"/etc/init.d/rayhunter_daemon",
|
||||
RAYHUNTER_DAEMON_INIT,
|
||||
RAYHUNTER_DAEMON_INIT.as_bytes(),
|
||||
)
|
||||
.await?;
|
||||
install_file(
|
||||
|
||||
@@ -23,20 +23,25 @@ use crate::InstallTpLink;
|
||||
|
||||
type HttpProxyClient = hyper_util::client::legacy::Client<HttpConnector, Body>;
|
||||
|
||||
pub async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
||||
let InstallTpLink {
|
||||
pub async fn main_tplink(
|
||||
InstallTpLink {
|
||||
skip_sdcard,
|
||||
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 client = reqwest::Client::new();
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct RootResponse {
|
||||
result: u64,
|
||||
}
|
||||
|
||||
println!("Launching telnet on the device");
|
||||
|
||||
// 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 {
|
||||
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 {
|
||||
let RootResponse { result } = response.error_for_status()?.json().await?;
|
||||
let V3RootResponse { result } = response.error_for_status()?.json().await?;
|
||||
|
||||
if result != 0 {
|
||||
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!("Succeeded in rooting the device!");
|
||||
|
||||
tplink_run_install(skip_sdcard, admin_ip).await
|
||||
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."
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
@@ -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, "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")]
|
||||
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(
|
||||
addr,
|
||||
"/etc/init.d/rayhunter_daemon",
|
||||
crate::RAYHUNTER_DAEMON_INIT,
|
||||
get_rayhunter_daemon().as_bytes(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -260,7 +278,7 @@ async fn handler(state: State<AppState>, mut req: Request) -> Result<Response, S
|
||||
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 =
|
||||
hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new())
|
||||
.build(HttpConnector::new());
|
||||
@@ -270,7 +288,7 @@ async fn tplink_launch_telnet_v5(admin_ip: String) -> Result<(), Error> {
|
||||
.route("/{*path}", any(handler))
|
||||
.with_state(AppState {
|
||||
client,
|
||||
admin_ip: admin_ip.clone(),
|
||||
admin_ip: admin_ip.to_owned(),
|
||||
});
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
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