#android #dex #java #dalvik

smali

一个用于读取和写入 Android 溢出 smali 文件的库

1 个不稳定版本

0.1.0 2022年9月22日

#7 in #dex

GPL-3.0-only

54KB
1K SLoC

Smali Crate

Smali 文件格式的解析器、编写器和类型集合的纯 Rust 实现。

Smali 在 Android 反向工程社区中用于检查和修改 Android APK 文件。它是一种人类可读的文本格式,表示 Dex VM 类的完整结构,包括所有指令。

使用此库,您可以将其与 apktool 结合使用,以执行 Android 应用的分析和/或修补。

examples/main.rs 中的简单示例说明了这一点。该示例将调用 apktool 来展开任何应用程序,然后解析所有 smali 文件以查找 RootBeer(一个开源的根检测框架),然后修补 RootBeer 的方法,使其始终返回 false,以便在已根设备上运行应用程序。最后,再次调用 apktool 重新打包应用程序。

以下是简单示例:

/* Expand the APK and patch RootBeer */
fn process_apk(apk_file: &str) -> Result<(), Box<dyn Error>>
{
   // Call apktool to unpack the APK
   execute_command("apktool", &["decode", "-f", apk_file, "-o", "out"])?;

   // Load all the smali classes
   let mut p = PathBuf::from_str("out")?;
   p.push("smali");
   let mut classes = find_smali_files(&p)?;
   println!("{:} smali classes loaded.", classes.len());

   // Search for the RootBeer class
   for c in classes.iter_mut()
   {
       if is_rootbeer_class(&c)
       {
           // Patch all the methods returning a boolean
           for m in c.methods.iter_mut()
           {
               if m.signature.return_type == TypeSignature::Bool && m.signature.args.len() == 0
               {
                   let mut new_instructions = vec![];
                   new_instructions.push(Instruction("const/4 v0, 0x0".to_string())); // Set v0 to false
                   new_instructions.push(Instruction("return v0".to_string()));       // return v0
                   m.instructions = new_instructions;
                   m.locals = 1;
                   println!("{} method {} successfully patched.", c.name.as_java_type(), &m.name);
               }
           }
       }
       // Save all classes, even unmodified so we can thoroughly test parser and writer
       c.save()?;
   }

   // Repack the APK
   execute_command("apktool", &["build", "out", "-o", "out.apk"])?;

   Ok(())
}

依赖项

~1MB
~19K SLoC