ksud: support set-manager (#114)
* ksud: support set-manager * ksud: rework apk sign Co-authored-by: Ylarod <me@ylarod.cn>
This commit is contained in:
103
userspace/ksud/src/apk_sign.rs
Normal file
103
userspace/ksud/src/apk_sign.rs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
use anyhow::{bail, ensure, Result};
|
||||||
|
|
||||||
|
pub fn get_apk_signature(apk: &str) -> Result<(u32, u32)> {
|
||||||
|
let mut buffer = [0u8; 0x10];
|
||||||
|
let mut size4 = [0u8; 4];
|
||||||
|
let mut size8 = [0u8; 8];
|
||||||
|
let mut size_of_block = [0u8; 8];
|
||||||
|
|
||||||
|
let mut f = std::fs::File::open(apk)?;
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
loop {
|
||||||
|
let mut n = [0u8; 2];
|
||||||
|
f.seek(SeekFrom::End(-i - 2))?;
|
||||||
|
f.read_exact(&mut n)?;
|
||||||
|
|
||||||
|
let n = u16::from_le_bytes(n);
|
||||||
|
if n as i64 == i {
|
||||||
|
f.seek(SeekFrom::Current(-22))?;
|
||||||
|
f.read_exact(&mut size4)?;
|
||||||
|
|
||||||
|
if u32::from_le_bytes(size4) ^ 0xcafebabeu32 == 0xccfbf1eeu32 {
|
||||||
|
if i > 0 {
|
||||||
|
println!("warning: comment length is {}", i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure!(n != 0xffff, "not a zip file");
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
f.seek(SeekFrom::Current(12))?;
|
||||||
|
// offset
|
||||||
|
f.read_exact(&mut size4)?;
|
||||||
|
f.seek(SeekFrom::Start(u32::from_le_bytes(size4) as u64 - 0x18))?;
|
||||||
|
|
||||||
|
f.read_exact(&mut size8)?;
|
||||||
|
f.read_exact(&mut buffer)?;
|
||||||
|
|
||||||
|
if &buffer != b"APK Sig Block 42" {
|
||||||
|
bail!("Can not found sig block");
|
||||||
|
}
|
||||||
|
|
||||||
|
let pos = u32::from_le_bytes(size4) as u64 - (u64::from_le_bytes(size8) + 0x8);
|
||||||
|
f.seek(SeekFrom::Start(pos))?;
|
||||||
|
f.read_exact(&mut size_of_block)?;
|
||||||
|
|
||||||
|
ensure!(size_of_block == size8, "not a signed apk");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut id = [0u8; 4];
|
||||||
|
let offset = 4u32;
|
||||||
|
|
||||||
|
f.read_exact(&mut size8)?; // sequence length
|
||||||
|
if size8 == size_of_block {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
f.read_exact(&mut id)?; // id
|
||||||
|
|
||||||
|
let id = u32::from_le_bytes(id);
|
||||||
|
if (id ^ 0xdeadbeefu32) == 0xafa439f5u32 || (id ^ 0xdeadbeefu32) == 0x2efed62fu32 {
|
||||||
|
f.read_exact(&mut size4)?; // signer-sequence length
|
||||||
|
f.read_exact(&mut size4)?; // signer length
|
||||||
|
f.read_exact(&mut size4)?; // signed data length
|
||||||
|
// offset += 0x4 * 3;
|
||||||
|
|
||||||
|
f.read_exact(&mut size4)?; // digests-sequcence length
|
||||||
|
let pos = u32::from_le_bytes(size4);
|
||||||
|
f.seek(SeekFrom::Current(pos as i64))?;
|
||||||
|
// offset += 0x4 + pos;
|
||||||
|
|
||||||
|
f.read_exact(&mut size4)?; // certificates length
|
||||||
|
f.read_exact(&mut size4)?; // certificate length
|
||||||
|
// offset += 0x4 * 2;
|
||||||
|
|
||||||
|
let mut hash = 1i32;
|
||||||
|
let mut c = [0u8; 1];
|
||||||
|
|
||||||
|
let j = u32::from_le_bytes(size4);
|
||||||
|
for _ in 0..j {
|
||||||
|
f.read_exact(&mut c)?;
|
||||||
|
hash = hash.wrapping_mul(31).wrapping_add(c[0] as i8 as i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// offset += j;
|
||||||
|
|
||||||
|
let out_size = j;
|
||||||
|
let out_hash = (hash as u32) ^ 0x14131211u32;
|
||||||
|
|
||||||
|
return Ok((out_size, out_hash));
|
||||||
|
}
|
||||||
|
|
||||||
|
f.seek(SeekFrom::Current(i64::from_le_bytes(size8) - offset as i64))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(anyhow::anyhow!("Unknown error"))
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use crate::{event, module};
|
use crate::{event, module, debug, apk_sign};
|
||||||
|
|
||||||
/// KernelSU userspace cli
|
/// KernelSU userspace cli
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@@ -37,7 +37,27 @@ enum Commands {
|
|||||||
/// SELinux policy Patch tool
|
/// SELinux policy Patch tool
|
||||||
Sepolicy,
|
Sepolicy,
|
||||||
|
|
||||||
/// For test
|
/// For developers
|
||||||
|
Debug {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: Debug,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
#[derive(clap::Subcommand, Debug)]
|
||||||
|
enum Debug {
|
||||||
|
/// Set the manager app, kernel CONFIG_KSU_DEBUG should be enabled.
|
||||||
|
SetManager {
|
||||||
|
/// manager apk path or package name
|
||||||
|
apk: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Get apk size and hash
|
||||||
|
GetSign {
|
||||||
|
/// apk path
|
||||||
|
apk: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// For testing
|
||||||
Test,
|
Test,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +113,18 @@ pub fn run() -> Result<()> {
|
|||||||
Commands::Install => event::install(),
|
Commands::Install => event::install(),
|
||||||
Commands::Sepolicy => todo!(),
|
Commands::Sepolicy => todo!(),
|
||||||
Commands::Services => event::on_services(),
|
Commands::Services => event::on_services(),
|
||||||
Commands::Test => event::do_systemless_mount("/data/adb/ksu/modules"),
|
|
||||||
|
Commands::Debug { command } => {
|
||||||
|
match command {
|
||||||
|
Debug::SetManager { apk } => debug::set_manager(&apk),
|
||||||
|
Debug::GetSign { apk } => {
|
||||||
|
let sign = apk_sign::get_apk_signature(&apk)?;
|
||||||
|
println!("size: {:#x}, hash: {:#x}", sign.0, sign.1);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
Debug::Test => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = &result {
|
if let Err(e) = &result {
|
||||||
|
|||||||
61
userspace/ksud/src/debug.rs
Normal file
61
userspace/ksud/src/debug.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
use anyhow::{ensure, Context, Ok, Result};
|
||||||
|
use std::{
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::apk_sign::get_apk_signature;
|
||||||
|
|
||||||
|
const KERNEL_PARAM_PATH: &str = "/sys/module/kernelsu";
|
||||||
|
|
||||||
|
fn read_u32(path: &PathBuf) -> Result<u32> {
|
||||||
|
let content = std::fs::read_to_string(path)?;
|
||||||
|
let content = content.trim();
|
||||||
|
let content = content.parse::<u32>()?;
|
||||||
|
Ok(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kernel_param(size: u32, hash: u32) -> Result<()> {
|
||||||
|
let kernel_param_path = Path::new(KERNEL_PARAM_PATH).join("parameters");
|
||||||
|
let expeced_size_path = kernel_param_path.join("ksu_expected_size");
|
||||||
|
let expeced_hash_path = kernel_param_path.join("ksu_expected_hash");
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"before size: {:#x} hash: {:#x}",
|
||||||
|
read_u32(&expeced_size_path)?,
|
||||||
|
read_u32(&expeced_hash_path)?
|
||||||
|
);
|
||||||
|
|
||||||
|
std::fs::write(&expeced_size_path, size.to_string())?;
|
||||||
|
std::fs::write(&expeced_hash_path, hash.to_string())?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"after size: {:#x} hash: {:#x}",
|
||||||
|
read_u32(&expeced_size_path)?,
|
||||||
|
read_u32(&expeced_hash_path)?
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_apk_path(package_name: &str) -> Result<String> {
|
||||||
|
let cmd = format!("pm path {}", package_name);
|
||||||
|
let output = Command::new("sh").arg("-c").arg(cmd).output()?;
|
||||||
|
|
||||||
|
// package:/data/app/<xxxx>/base.apk
|
||||||
|
let output = String::from_utf8_lossy(&output.stdout);
|
||||||
|
let path = output.trim().replace("package:", "");
|
||||||
|
Ok(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_manager(pkg: &str) -> Result<()> {
|
||||||
|
ensure!(
|
||||||
|
Path::new(KERNEL_PARAM_PATH).exists(),
|
||||||
|
"CONFIG_KSU_DEBUG is not enabled"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path = get_apk_path(pkg).with_context(|| format!("{} not exist!", pkg))?;
|
||||||
|
let sign = get_apk_signature(path.as_str())?;
|
||||||
|
set_kernel_param(sign.0, sign.1)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ mod module;
|
|||||||
mod defs;
|
mod defs;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod restorecon;
|
mod restorecon;
|
||||||
|
mod debug;
|
||||||
|
mod apk_sign;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
cli::run()
|
cli::run()
|
||||||
|
|||||||
Reference in New Issue
Block a user