Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
kazimmt committed Sep 2, 2023
2 parents 1e79419 + bdcc780 commit eba25a6
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 34 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ Hooks libbinder with zygisk instead of applying SQL queries to database files
* Select apps you wish to detach. Changes are applied immediately, no need to reboot.

### Notes
To make the usage portable, zygisk-detach reads `detach.bin` in the magisk module folder (`/data/adb/modules/zygisk-detach/detach.bin`) which means by putting your cli generated `detach.bin` inside the module zip, you can flash and detach apps without needing to run the cli again. You can copy your generated `detach.bin` using the cli or from magisk module folder.
To make the usage portable, zygisk-detach reads `detach.bin` in the magisk module folder (`/data/adb/modules/zygisk-detach/detach.bin`) which means by putting your cli generated `detach.bin` inside the module zip, you can flash and detach apps without needing to run the cli again. You can copy your generated `detach.bin` using the cli or from magisk module folder.
Or the same way you can put a `detach.txt` with the package names inside the module and it will be serialized into a `detach.bin`.
94 changes: 78 additions & 16 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![feature(iter_intersperse, print_internals)]

use std::fmt::Display;
use std::fs;
use std::fs::{self, OpenOptions};
use std::io::{self, Seek};
use std::io::{BufWriter, Read, Write};
use std::mem::size_of;
Expand All @@ -15,29 +15,77 @@ mod colorize;
use colorize::ToColored;

mod menus;
use menus::{select_menu, select_menu_numbered, select_menu_with_input};
use menus::{cursor_hide, cursor_show, select_menu, select_menu_numbered, select_menu_with_input};

#[cfg(target_os = "android")]
const MODULE_DETACH: &str = "/data/adb/modules/zygisk-detach/detach.bin";
#[cfg(target_os = "android")]
const DETACH_TXT: &str = "/data/adb/modules/zygisk-detach/detach.txt";

#[cfg(target_os = "linux")]
const MODULE_DETACH: &str = "detach_module.txt";
const MODULE_DETACH: &str = "detach.bin";
#[cfg(target_os = "linux")]
const DETACH_TXT: &str = "detach.txt";

extern "C" {
fn kill(pid: i32, sig: i32) -> i32;
}

fn main() -> ExitCode {
match run() {
let mut args = std::env::args().skip(1);
if matches!(args.next().as_deref(), Some("--serialize")) {
match args.next() {
Some(path) => {
if let Err(err) = serialize_txt(&path) {
eprintln!("ERROR: {err}");
return ExitCode::FAILURE;
} else {
println!("Serialized detach.txt into {}", MODULE_DETACH);
return ExitCode::SUCCESS;
}
}
None => {
eprintln!("detach.txt path not supplied");
return ExitCode::FAILURE;
}
}
}

let ret = match interactive() {
Ok(_) => ExitCode::SUCCESS,
Err(err) => {
eprintln!("\rERROR: {err}");
ExitCode::FAILURE
}
};
cursor_show().unwrap();
ret
}

fn detach_bin_changed() {
let _ = fs::remove_file(DETACH_TXT);
let _ = kill_store();
}

fn serialize_txt(path: &str) -> io::Result<()> {
let detach_bin = OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(MODULE_DETACH)?;
let mut sink = BufWriter::new(detach_bin);
for app in std::fs::read_to_string(path)?
.lines()
.map(|s| s.trim())
.filter(|l| !l.is_empty() && !l.starts_with('#'))
{
bin_serialize(app, &mut sink)?;
}
Ok(())
}

fn run() -> io::Result<()> {
fn interactive() -> io::Result<()> {
cursor_hide()?;
print!("zygisk-detach cli by github.com/j-hc\r\n\n");
loop {
match main_menu()? {
Expand All @@ -55,7 +103,7 @@ fn run() -> io::Result<()> {
#[cfg(target_os = "android")]
const SDCARD_DETACH: &str = "/sdcard/detach.bin";
#[cfg(target_os = "linux")]
const SDCARD_DETACH: &str = "detach.bin";
const SDCARD_DETACH: &str = "detach_sdcard.bin";
match fs::copy(MODULE_DETACH, SDCARD_DETACH) {
Ok(_) => text!("Copied"),
Err(err) if err.kind() == io::ErrorKind::NotFound => {
Expand All @@ -71,8 +119,11 @@ fn run() -> io::Result<()> {
}

fn reattach_menu() -> io::Result<()> {
let openf = |p| fs::OpenOptions::new().write(true).read(true).open(p);
let Ok(mut detach_txt) = openf(MODULE_DETACH) else {
let Ok(mut detach_txt) = fs::OpenOptions::new()
.write(true)
.read(true)
.open(MODULE_DETACH)
else {
text!("No detach.bin was found!");
return Ok(());
};
Expand All @@ -85,17 +136,22 @@ fn reattach_menu() -> io::Result<()> {
text!("detach.bin is empty");
return Ok(());
}
text!("Select the app to re-attach ('q' to leave):");
let list = detached_apps.iter().map(|e| e.0.as_str());
let Some(i) = select_menu(list, "✖".red(), Some(Key::Char('q')))? else {
let Some(i) = select_menu(
list,
"Select the app to re-attach ('q' to leave):",
"✖".red(),
Some(Key::Char('q')),
)?
else {
return Ok(());
};

textln!("{}: {}", "re-attach".red(), detached_apps[i].0);
content.drain(detached_apps[i].1.clone());
detach_txt.set_len(0)?;
detach_txt.write_all(&content)?;
let _ = kill_store();
detach_bin_changed();
Ok(())
}

Expand Down Expand Up @@ -154,8 +210,8 @@ fn main_menu() -> io::Result<Op> {
}
}
let ops = [
OpText::new("Select app to detach", Op::DetachSelect),
OpText::new("Re-attach app", Op::ReattachSelect),
OpText::new("Detach", Op::DetachSelect),
OpText::new("Re-attach", Op::ReattachSelect),
OpText::new("Reset detached apps", Op::Reset),
OpText::new("Copy detach.bin to /sdcard", Op::CopyToSd),
];
Expand Down Expand Up @@ -204,11 +260,16 @@ fn detach_menu() -> io::Result<()> {
})
.map(|e| std::str::from_utf8(e).expect("non utf-8 package names?"))
.collect();
cursor_show()?;
let selected = select_menu_with_input(
|input| {
if input.len() > 2 {
let input = input.trim();
if !input.is_empty() {
apps.iter()
.filter(move |app| app.contains(input.trim()))
.filter(|app| {
app.to_ascii_lowercase()
.contains(&input.to_ascii_lowercase())
})
.take(5)
.collect()
} else {
Expand All @@ -219,6 +280,7 @@ fn detach_menu() -> io::Result<()> {
"- app: ",
None,
)?;
cursor_hide()?;
if let Some(detach_app) = selected {
let mut f = fs::OpenOptions::new()
.create(true)
Expand All @@ -231,7 +293,7 @@ fn detach_menu() -> io::Result<()> {
bin_serialize(detach_app, f)?;
textln!("{} {}", "detach:".green(), detach_app);
textln!("Changes are applied. No need for a reboot!");
let _ = kill_store();
detach_bin_changed();
} else {
textln!("{} {}", "already detached:".green(), detach_app);
}
Expand Down
21 changes: 16 additions & 5 deletions cli/src/menus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,29 @@ macro_rules! textln {
}};
}

pub fn cursor_hide() -> io::Result<()> {
let mut stdout = io::stdout().into_raw_mode()?;
write!(stdout, "{}", cursor::Hide)?;
Ok(())
}

pub fn cursor_show() -> io::Result<()> {
let mut stdout = io::stdout().into_raw_mode()?;
write!(stdout, "{}", cursor::Show)?;
Ok(())
}

pub fn select_menu<L: Display, I: Iterator<Item = L> + Clone>(
list: I,
title: impl Display,
prompt: impl Display,
quit: Option<Key>,
) -> io::Result<Option<usize>> {
let mut stdout = BufWriter::new(io::stdout().lock().into_raw_mode()?);
let mut select_idx = 0;
let list_len = list.clone().count();
let mut keys = io::stdin().lock().keys();
write!(stdout, "{}", cursor::Hide)?;
write!(stdout, "{}\r\n", title)?;
let ret = loop {
for (i, selection) in list.clone().enumerate() {
if i == select_idx {
Expand Down Expand Up @@ -73,7 +86,7 @@ pub fn select_menu<L: Display, I: Iterator<Item = L> + Clone>(
_ => {}
}
};
write!(stdout, "{}", cursor::Show)?;
write!(stdout, "{}{}", cursor::Up(1), clear::CurrentLine)?;
stdout.flush()?;
ret
}
Expand Down Expand Up @@ -183,7 +196,6 @@ pub fn select_menu_numbered<L: Display, I: Iterator<Item = L> + Clone>(
let mut stdout = BufWriter::new(io::stdout().lock().into_raw_mode()?);
let list_len = list.clone().count();
write!(stdout, "\r{title}\r\n")?;
write!(stdout, "{}", cursor::Hide)?;
for (i, s) in list.enumerate() {
write!(stdout, "{}. {}\r\n", (i + 1).green(), s)?;
}
Expand All @@ -197,10 +209,9 @@ pub fn select_menu_numbered<L: Display, I: Iterator<Item = L> + Clone>(
.expect("faulty keyboard?");
write!(
stdout,
"\r{}{}{}",
"\r{}{}",
cursor::Up(list_len as u16 + 2),
clear::AfterCursor,
cursor::Show
)?;
stdout.flush()?;
match key {
Expand Down
12 changes: 12 additions & 0 deletions magisk/customize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ if [ -f "$NVBASE/modules/zygisk-detach/detach.bin" ]; then
ui_print "- Preserving existing detach.bin"
cp -f "$NVBASE/modules/zygisk-detach/detach.bin" "$MODPATH/detach.bin"
fi

if [ -f "$MODPATH/detach.txt" ]; then
ui_print "- detach.txt inside module! Generating detach.bin"
APPS=$(tr -d ' \t\r' <"$MODPATH/detach.txt" | grep -v '^$')
for app in $APPS; do
ui_print " $app"
done
if ! OP=$("$MODPATH"/system/bin/detach --serialize "$MODPATH/detach.txt" 2>&1); then
ui_print "$OP"
fi
fi

ALIAS="alias detach='su -c detach'"
BASHRC="/data/data/com.termux/files/home/.bashrc"
if grep -qxF "$ALIAS" "$BASHRC" || echo "$ALIAS" >>"$BASHRC"; then
Expand Down
4 changes: 2 additions & 2 deletions update.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "v1.3",
"versionCode": 4,
"zipUrl": "https://github.com/kazimmt/zygisk-detach/releases/latest/download/zygisk-detach-v1.3.zip",
"changelog": "https://raw.githubusercontent.com/kazimmt/zygisk-detach/master/README.md"
"zipUrl": "https://github.com/j-hc/zygisk-detach/releases/latest/download/zygisk-detach-v1.3.zip",
"changelog": "https://raw.githubusercontent.com/j-hc/zygisk-detach/master/README.md"
}
17 changes: 7 additions & 10 deletions zygisk/jni/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,8 @@ int (*ioctl_orig)(int, int, char*);

#define DETACH_CAP 512
static unsigned char DETACH_TXT[DETACH_CAP] = {0};
static size_t DETACH_LEN = 0;

void handle_write(binder_transaction_data* btd) {
size_t detach_len = DETACH_LEN;
unsigned char* detach_txt = DETACH_TXT;

unsigned char* data = (unsigned char*)btd->data.ptr.buffer;
auto p = FakeParcel{data, 0};
if (!p.enforceInterface(btd->code)) return;
Expand All @@ -37,9 +33,10 @@ void handle_write(binder_transaction_data* btd) {
uint32_t pkg_len_b = pkg_len * 2 - 1;
auto pkg_ptr = p.readString16(pkg_len);

unsigned char* detach_txt = DETACH_TXT;
size_t i = 0;
while (i < detach_len) {
uint8_t dlen = detach_txt[i];
uint8_t dlen;
while ((dlen = detach_txt[i])) {
unsigned char* dptr = detach_txt + i + sizeof(dlen);
i += sizeof(dlen) + dlen;
if (dlen != pkg_len_b) continue;
Expand Down Expand Up @@ -87,9 +84,9 @@ class Sigringe : public zygisk::ModuleBase {
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);

int fd = api->connectCompanion();
DETACH_LEN = this->read_companion(fd);
size_t detach_len = this->read_companion(fd);
close(fd);
if (DETACH_LEN == 0) {
if (detach_len == 0) {
api->setOption(zygisk::Option::DLCLOSE_MODULE_LIBRARY);
return;
}
Expand Down Expand Up @@ -143,8 +140,8 @@ class Sigringe : public zygisk::ModuleBase {
if (size <= 0) {
LOGD("ERROR: detach.bin <= 0");
return 0;
} else if (size > DETACH_CAP) {
LOGD("ERROR: detach.bin > %d", DETACH_CAP);
} else if (size > DETACH_CAP - 1) { // -1 because for the null terminator
LOGD("ERROR: detach.bin > %d", DETACH_CAP - 1);
return 0;
}
int received = 0;
Expand Down

0 comments on commit eba25a6

Please sign in to comment.