mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-05-21 07:14:47 -07:00
Fix issues on TP-Link v9
* Fix autostart by adding another port trigger for rayhunter-daemon * Use Orbic's IOCTL params as fallback * Fix sdcard path and make it configurable * Update docs to indicate support * Add uninstalling instructions for TP-Link
This commit is contained in:
committed by
Cooper Quintin
parent
5b9dd856a8
commit
6941bc57b6
@@ -7,10 +7,10 @@ The TP-Link M7350 is supported by Rayhunter from 0.3.0 release. TP-Link M7350 su
|
||||
The TP-Link comes in many different *hardware versions*. Support for installation varies:
|
||||
|
||||
* `1.0`, `2.0`: **Not suported**, probably impossible to obtain anymore (even second-hand), however there is one report that installation is possible on `1.0` (but no reports if it is working or not)
|
||||
* `3.0`, `3.2`, `5.0`, `5.2`, `7.0`, `8.0`: **Tested, no known issues.**
|
||||
* `3.0`, `3.2`, `5.0`, `5.2`, `7.0`, `8.0`: **Tested, no known issues since 0.3.0.**
|
||||
* `6.2`: **One user reported it is working**
|
||||
* `4.0`: **Not working yet** ([issue](https://github.com/EFForg/rayhunter/issues/332)), however [it could be installed manually](https://github.com/m0veax/rayhunter-tplink-m7350/))
|
||||
* `9.0`: **Not working yet** ([issue](https://github.com/EFForg/rayhunter/issues/325), however opening/rooting works, Rayhunter could be installed manually, but does not work because of [IOCTL error](#302))
|
||||
* `4.0`: **Manual firmware downgrade required** ([issue](https://github.com/EFForg/rayhunter/issues/332))
|
||||
* `9.0`: **Working since 0.3.2.**
|
||||
|
||||
TP-Link versions newer than `3.0` have cyan packaging and a color display. Version `3.0` has a one-bit display and white packaging.
|
||||
|
||||
@@ -62,6 +62,15 @@ You can change the `port` (default is `8080`) where Rayhunter is listening for i
|
||||
By default the device will go to sleep after N minutes of no devices being connected. In that mode it will also turn off connections to cell phone towers.
|
||||
In order for Rayhunter to record continuously, you have to turn off this sleep mode in TP-Link's admin panel (go to **Advanced** - **Power Saving**) or keep e.g. your phone connectd on the TP-Link's WiFi.
|
||||
|
||||
## Port triggers
|
||||
|
||||
On hardware revisions starting with v4.0, the installer will modify settings to
|
||||
add two port triggers. You can look at `Settings > NAT Settings > Port
|
||||
Triggers` in TP-Link's admin UI to see them.
|
||||
|
||||
1. One port trigger "rayhunter-root" to launch the telnet shell. This is only needed for installation, and can be removed after upgrade. You can reinstall it using `./installer util tplink-start-telnet`.
|
||||
2. One port trigger "rayhunter-daemon" to auto-start rayhunter on boot. If you remove this, rayhunter will have to be started manually from shell.
|
||||
|
||||
## Other links
|
||||
|
||||
For more information on the device and instructions on how to install Rayhunter without an installer (i.e. manually), please see [rayhunter-tplink-m7350](https://github.com/m0veax/rayhunter-tplink-m7350/)
|
||||
|
||||
@@ -16,4 +16,9 @@ Your device is now Rayhunter-free, and should no longer be in a rooted ADB-enabl
|
||||
|
||||
## TPLink
|
||||
|
||||
TODO
|
||||
1. Run `./installer util tplink-start-telnet`
|
||||
2. Telnet into the device `telnet 192.168.0.1`
|
||||
3. `rm /data/rayhunter /etc/init.d/rayhunter_daemon`
|
||||
4. `update-rc.d rayhunter_daemon remove`
|
||||
5. (hardware revision v4.0+ only) In `Settings > NAT Settings > Port Triggers` in TP-Link's admin UI, remove any leftover port triggers.
|
||||
|
||||
|
||||
@@ -35,6 +35,17 @@ struct InstallTpLink {
|
||||
/// IP address for TP-Link admin interface, if custom.
|
||||
#[arg(long, default_value = "192.168.0.1")]
|
||||
admin_ip: String,
|
||||
|
||||
/// For advanced users: Specify the path of the SD card to be mounted explicitly.
|
||||
///
|
||||
/// The default (empty string) is to use whichever sdcard path the device would use natively to
|
||||
/// mount storage on. On most TP-Link this is /media/card, but on hardware versions 9+ this is
|
||||
/// /media/sdcard
|
||||
///
|
||||
/// Only override this when the installer does not work on your hardware version, as otherwise
|
||||
/// your custom path may conflict with the builtin storage functionality.
|
||||
#[arg(long, default_value = "")]
|
||||
sdcard_path: String,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
|
||||
@@ -27,10 +27,11 @@ pub async fn main_tplink(
|
||||
InstallTpLink {
|
||||
skip_sdcard,
|
||||
admin_ip,
|
||||
sdcard_path,
|
||||
}: InstallTpLink,
|
||||
) -> Result<(), Error> {
|
||||
start_telnet(&admin_ip).await?;
|
||||
tplink_run_install(skip_sdcard, admin_ip).await
|
||||
let is_v3 = start_telnet(&admin_ip).await?;
|
||||
tplink_run_install(skip_sdcard, admin_ip, sdcard_path, is_v3).await
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -38,7 +39,7 @@ struct V3RootResponse {
|
||||
result: u64,
|
||||
}
|
||||
|
||||
pub async fn start_telnet(admin_ip: &str) -> Result<(), Error> {
|
||||
pub async fn start_telnet(admin_ip: &str) -> Result<bool, Error> {
|
||||
let qcmap_web_cgi_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_web_cgi");
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
@@ -51,7 +52,9 @@ pub async fn start_telnet(admin_ip: &str) -> Result<(), Error> {
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if response.status() == 404 {
|
||||
let is_v3 = response.status() != 404;
|
||||
|
||||
if !is_v3 {
|
||||
println!("Got a 404 trying to run exploit for hardware revision v3, trying v5 exploit");
|
||||
tplink_launch_telnet_v5(admin_ip).await?;
|
||||
} else {
|
||||
@@ -82,20 +85,49 @@ pub async fn start_telnet(admin_ip: &str) -> Result<(), Error> {
|
||||
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(())
|
||||
Ok(is_v3)
|
||||
}
|
||||
|
||||
async fn tplink_run_install(skip_sdcard: bool, admin_ip: String) -> Result<(), Error> {
|
||||
async fn tplink_run_install(
|
||||
skip_sdcard: bool,
|
||||
admin_ip: String,
|
||||
mut sdcard_path: String,
|
||||
is_v3: bool,
|
||||
) -> Result<(), Error> {
|
||||
println!("Connecting via telnet to {admin_ip}");
|
||||
let addr = SocketAddr::from_str(&format!("{admin_ip}:23")).unwrap();
|
||||
|
||||
if !skip_sdcard {
|
||||
println!("Mounting sdcard");
|
||||
if telnet_send_command(addr, "mount | grep -q /media/card", "exit code 0")
|
||||
.await
|
||||
.is_err()
|
||||
if sdcard_path.is_empty() {
|
||||
if telnet_send_command(addr, "ls /media/card", "exit code 0")
|
||||
.await
|
||||
.is_ok()
|
||||
{
|
||||
// TP-Link hardware less than v9.0
|
||||
sdcard_path = "/media/card".to_owned();
|
||||
} else if telnet_send_command(addr, "ls /media/sdcard", "exit code 0")
|
||||
.await
|
||||
.is_ok()
|
||||
{
|
||||
// TP-Link hardware v9.0
|
||||
sdcard_path = "/media/sdcard".to_owned();
|
||||
} else {
|
||||
anyhow::bail!(
|
||||
"unable to determine sdcard path. this is a bug. please file an issue with your hardware version."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
println!("Mounting sdcard on {sdcard_path}");
|
||||
if telnet_send_command(
|
||||
addr,
|
||||
&format!("mount | grep -q {sdcard_path}"),
|
||||
"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")?;
|
||||
telnet_send_command(addr, &format!("mount /dev/mmcblk0p1 {sdcard_path}"), "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");
|
||||
}
|
||||
@@ -105,28 +137,38 @@ async fn tplink_run_install(skip_sdcard: bool, admin_ip: String) -> Result<(), E
|
||||
// expects things to be at this location
|
||||
telnet_send_command(addr, "rm -rf /data/rayhunter", "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,
|
||||
&format!("ln -sf {sdcard_path} /data/rayhunter"),
|
||||
"exit code 0",
|
||||
)
|
||||
.await?;
|
||||
|
||||
telnet_send_file(
|
||||
addr,
|
||||
"/media/card/config.toml",
|
||||
&format!("{sdcard_path}/config.toml"),
|
||||
crate::CONFIG_TOML.as_bytes(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let rayhunter_daemon_bin = include_bytes!(env!("FILE_RAYHUNTER_DAEMON_TPLINK"));
|
||||
|
||||
telnet_send_file(addr, "/media/card/rayhunter-daemon", rayhunter_daemon_bin).await?;
|
||||
telnet_send_file(
|
||||
addr,
|
||||
&format!("{sdcard_path}/rayhunter-daemon"),
|
||||
rayhunter_daemon_bin,
|
||||
)
|
||||
.await?;
|
||||
telnet_send_file(
|
||||
addr,
|
||||
"/etc/init.d/rayhunter_daemon",
|
||||
get_rayhunter_daemon().as_bytes(),
|
||||
get_rayhunter_daemon(&sdcard_path).as_bytes(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
telnet_send_command(
|
||||
addr,
|
||||
"chmod ugo+x /media/card/rayhunter-daemon",
|
||||
&format!("chmod ugo+x {sdcard_path}/rayhunter-daemon"),
|
||||
"exit code 0",
|
||||
)
|
||||
.await?;
|
||||
@@ -136,7 +178,13 @@ async fn tplink_run_install(skip_sdcard: bool, admin_ip: String) -> Result<(), E
|
||||
"exit code 0",
|
||||
)
|
||||
.await?;
|
||||
telnet_send_command(addr, "update-rc.d rayhunter_daemon defaults", "exit code 0").await?;
|
||||
|
||||
// if the device is not v3, the JS-based root exploit already added rayhunter_daemon as a
|
||||
// startup script. tplink v9 does not have update-rc.d, and it was reported that *sometimes* it
|
||||
// is unreliable on other hardware revisions too.
|
||||
if is_v3 {
|
||||
telnet_send_command(addr, "update-rc.d rayhunter_daemon defaults", "exit code 0").await?;
|
||||
}
|
||||
|
||||
println!(
|
||||
"Done. Rebooting device. After it's started up again, check out the web interface at http://{admin_ip}:8080"
|
||||
@@ -278,6 +326,7 @@ async fn handler(state: State<AppState>, mut req: Request) -> Result<Response, S
|
||||
// inject some javascript into the admin UI to get us a telnet shell.
|
||||
data.extend(br#";window.rayhunterPoll = window.setInterval(() => {
|
||||
Globals.models.PTModel.add({applicationName: "rayhunter-root", enableState: 1, entryId: 1, openPort: "2300-2400", openProtocol: "TCP", triggerPort: "$(busybox telnetd -l /bin/sh)", triggerProtocol: "TCP"});
|
||||
Globals.models.PTModel.add({applicationName: "rayhunter-daemon", enableState: 1, entryId: 2, openPort: "2400-2500", openProtocol: "TCP", triggerPort: "$(/etc/init.d/rayhunter_daemon start)", triggerProtocol: "TCP"});
|
||||
alert("Success! You can go back to the rayhunter installer.");
|
||||
window.clearInterval(window.rayhunterPoll);
|
||||
}, 1000);"#);
|
||||
@@ -324,7 +373,7 @@ async fn tplink_launch_telnet_v5(admin_ip: &str) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_rayhunter_daemon() -> String {
|
||||
fn get_rayhunter_daemon(sdcard_path: &str) -> 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.
|
||||
//
|
||||
@@ -332,12 +381,12 @@ fn get_rayhunter_daemon() -> String {
|
||||
// specific to a particular hardware revision here.
|
||||
crate::RAYHUNTER_DAEMON_INIT.replace(
|
||||
"#RAYHUNTER-PRESTART",
|
||||
"mount /dev/mmcblk0p1 /media/card || true",
|
||||
&format!("mount /dev/mmcblk0p1 {sdcard_path} || true"),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_rayhunter_daemon() {
|
||||
let s = get_rayhunter_daemon();
|
||||
let s = get_rayhunter_daemon("/media/card");
|
||||
assert!(s.contains("mount /dev/mmcblk0p1 /media/card"));
|
||||
}
|
||||
|
||||
@@ -251,6 +251,7 @@ impl DiagDevice {
|
||||
//
|
||||
// TPLINK M7350 v5 source code can be downloaded at https://www.tp-link.com/de/support/gpl-code/?app=omada
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct diag_logging_mode_param_t {
|
||||
req_mode: u32,
|
||||
peripheral_mask: u32,
|
||||
@@ -261,30 +262,41 @@ struct diag_logging_mode_param_t {
|
||||
fn enable_frame_readwrite(fd: i32, mode: u32) -> DiagResult<()> {
|
||||
unsafe {
|
||||
if libc::ioctl(fd, DIAG_IOCTL_SWITCH_LOGGING, mode, 0, 0, 0) < 0 {
|
||||
let mut params = if cfg!(feature = "tplink") {
|
||||
let try_params: &[diag_logging_mode_param_t] = &[
|
||||
// tplink M7350 HW revision 3-8 need this mode
|
||||
#[cfg(feature = "tplink")]
|
||||
diag_logging_mode_param_t {
|
||||
req_mode: mode,
|
||||
peripheral_mask: 0,
|
||||
mode_param: 1,
|
||||
}
|
||||
} else {
|
||||
},
|
||||
// tplink M7350 HW revision v9 requires the same parameters as orbic
|
||||
diag_logging_mode_param_t {
|
||||
req_mode: mode,
|
||||
peripheral_mask: u32::MAX,
|
||||
mode_param: 0,
|
||||
}
|
||||
};
|
||||
},
|
||||
];
|
||||
|
||||
let mut ret = 0;
|
||||
|
||||
for params in try_params {
|
||||
let mut params = *params;
|
||||
ret = libc::ioctl(
|
||||
fd,
|
||||
DIAG_IOCTL_SWITCH_LOGGING,
|
||||
&mut params as *mut diag_logging_mode_param_t,
|
||||
std::mem::size_of::<diag_logging_mode_param_t>(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
if ret == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let ret = libc::ioctl(
|
||||
fd,
|
||||
DIAG_IOCTL_SWITCH_LOGGING,
|
||||
&mut params as *mut _,
|
||||
std::mem::size_of::<diag_logging_mode_param_t>(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
if ret < 0 {
|
||||
let msg = format!(
|
||||
"DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code {}",
|
||||
|
||||
Reference in New Issue
Block a user