I have a smali code with the related source:
original_file.java:
package com.android.commands.locksettings;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
import com.android.internal.os.BaseCommand;
import com.android.internal.widget.ILockSettings;
import java.io.FileDescriptor;
import java.io.PrintStream;
public final class LockSettingsCmd extends BaseCommand {
private static final String USAGE =
"usage: locksettings set-pattern [--old OLD_CREDENTIAL] NEW_PATTERN\n" +
" locksettings set-pin [--old OLD_CREDENTIAL] NEW_PIN\n" +
" locksettings set-password [--old OLD_CREDENTIAL] NEW_PASSWORD\n" +
" locksettings clear [--old OLD_CREDENTIAL]\n" +
"\n" +
"locksettings set-pattern: sets a pattern\n" +
" A pattern is specified by a non-separated list of numbers that index the cell\n" +
" on the pattern in a 1-based manner in left to right and top to bottom order,\n" +
" i.e. the top-left cell is indexed with 1, whereas the bottom-right cell\n" +
" is indexed with 9. Example: 1234\n" +
"\n" +
"locksettings set-pin: sets a PIN\n" +
"\n" +
"locksettings set-password: sets a password\n" +
"\n" +
"locksettings clear: clears the unlock credential\n";
public static void main(String[] args) {
(new LockSettingsCmd()).run(args);
}
@Override
public void onShowUsage(PrintStream out) {
out.println(USAGE);
}
@Override
public void onRun() throws Exception {
ILockSettings lockSettings = ILockSettings.Stub.asInterface(
ServiceManager.getService("lock_settings"));
lockSettings.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out,
FileDescriptor.err, getRawArgs(), new ShellCallback(), new ResultReceiver(null) {});
}
}
original_file.smali:
.class public final Lcom/android/commands/locksettings/LockSettingsCmd;
.super Lcom/android/internal/os/BaseCommand;
.source "LockSettingsCmd.java"
# static fields
.field private static final USAGE:Ljava/lang/String; = "usage: locksettings set-pattern [--old OLD_CREDENTIAL] NEW_PATTERN\n locksettings set-pin [--old OLD_CREDENTIAL] NEW_PIN\n locksettings set-password [--old OLD_CREDENTIAL] NEW_PASSWORD\n locksettings clear [--old OLD_CREDENTIAL]\n\nlocksettings set-pattern: sets a pattern\n A pattern is specified by a non-separated list of numbers that index the cell\n on the pattern in a 1-based manner in left to right and top to bottom order,\n i.e. the top-left cell is indexed with 1, whereas the bottom-right cell\n is indexed with 9. Example: 1234\n\nlocksettings set-pin: sets a PIN\n\nlocksettings set-password: sets a password\n\nlocksettings clear: clears the unlock credential\n"
# direct methods
.method public constructor <init>()V
.registers 1
.prologue
.line 29
invoke-direct {p0}, Lcom/android/internal/os/BaseCommand;-><init>()V
return-void
.end method
.method public static main([Ljava/lang/String;)V
.registers 2
.param p0, "args" # [Ljava/lang/String;
.prologue
.line 50
new-instance v0, Lcom/android/commands/locksettings/LockSettingsCmd;
invoke-direct {v0}, Lcom/android/commands/locksettings/LockSettingsCmd;-><init>()V
invoke-virtual {v0, p0}, Lcom/android/commands/locksettings/LockSettingsCmd;->run([Ljava/lang/String;)V
const/4 v0, 0x0
invoke-virtual {v0, p0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
.line 51
return-void
.end method
# virtual methods
.method public onRun()V
.registers 10
.annotation system Ldalvik/annotation/Throws;
value = {
Ljava/lang/Exception;
}
.end annotation
.prologue
.line 61
const-string/jumbo v0, "lock_settings"
invoke-static {v0}, Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
move-result-object v0
.line 60
invoke-static {v0}, Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings;
move-result-object v7
.line 62
.local v7, "lockSettings":Lcom/android/internal/widget/ILockSettings;
invoke-interface {v7}, Lcom/android/internal/widget/ILockSettings;->asBinder()Landroid/os/IBinder;
move-result-object v0
sget-object v1, Ljava/io/FileDescriptor;->in:Ljava/io/FileDescriptor;
sget-object v2, Ljava/io/FileDescriptor;->out:Ljava/io/FileDescriptor;
.line 63
sget-object v3, Ljava/io/FileDescriptor;->err:Ljava/io/FileDescriptor;
invoke-virtual {p0}, Lcom/android/commands/locksettings/LockSettingsCmd;->getRawArgs()[Ljava/lang/String;
move-result-object v4
new-instance v5, Landroid/os/ShellCallback;
invoke-direct {v5}, Landroid/os/ShellCallback;-><init>()V
new-instance v6, Lcom/android/commands/locksettings/LockSettingsCmd$1;
const/4 v8, 0x0
invoke-direct {v6, p0, v8}, Lcom/android/commands/locksettings/LockSettingsCmd$1;-><init>(Lcom/android/commands/locksettings/LockSettingsCmd;Landroid/os/Handler;)V
.line 62
invoke-interface/range {v0 .. v6}, Landroid/os/IBinder;->shellCommand(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;[Ljava/lang/String;Landroid/os/ShellCallback;Landroid/os/ResultReceiver;)V
.line 64
return-void
.end method
.method public onShowUsage(Ljava/io/PrintStream;)V
.registers 3
.param p1, "out" # Ljava/io/PrintStream;
.prologue
.line 55
const-string/jumbo v0, "usage: locksettings set-pattern [--old OLD_CREDENTIAL] NEW_PATTERN\n locksettings set-pin [--old OLD_CREDENTIAL] NEW_PIN\n locksettings set-password [--old OLD_CREDENTIAL] NEW_PASSWORD\n locksettings clear [--old OLD_CREDENTIAL]\n\nlocksettings set-pattern: sets a pattern\n A pattern is specified by a non-separated list of numbers that index the cell\n on the pattern in a 1-based manner in left to right and top to bottom order,\n i.e. the top-left cell is indexed with 1, whereas the bottom-right cell\n is indexed with 9. Example: 1234\n\nlocksettings set-pin: sets a PIN\n\nlocksettings set-password: sets a password\n\nlocksettings clear: clears the unlock credential\n"
invoke-virtual {p1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 56
return-void
.end method
I want to edit the above smali file and add codes to main
function
So I wrote the same codes in a new java file and compiled it to class
file using javac
then using dx.jar
convert it to classes.dex
and redecompiled the dex
file and get the smali code to inject but on each time a add the code the file crached and never work.
my_code.java: (just a test to print the coming args)
public static void main(String[] args) {
for(String s : args){
System.out.println(s);
}
}
@Override
public void onShowUsage(PrintStream out) {
out.println(USAGE);
}
my_code.smali:
.method public static main([Ljava/lang/String;)V
.registers 5
.prologue
.line 50
array-length v1, p0
const/4 v0, 0x0
:goto_2
if-ge v0, v1, :cond_e
aget-object v2, p0, v0
.line 51
sget-object v3, Ljava/lang/System;->out:Ljava/io/PrintStream;
invoke-virtual {v3, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 50
add-int/lit8 v0, v0, 0x1
goto :goto_2
.line 54
:cond_e
return-void
.end method
Now how can i inject the my_code.smali
to original_file.smali
?
When you're editing smali code you should carefully take care of registers. my_code
's main method has 5 registers (i.e. 4 local and 1 param) and original_file
's main method has 2 registers (i.e. 1 local and 1 param). Before adding the my_code
to original_file
, you should decide how may registers you would need. In this example, 5 registers (i.e. 4 local and 1 param) is enough.
The final main
method (without .line
and .param
directives):
.method public static main([Ljava/lang/String;)V
.registers 5
.prologue
array-length v1, p0
const/4 v0, 0x0
:goto_2
if-ge v0, v1, :cond_e
aget-object v2, p0, v0
sget-object v3, Ljava/lang/System;->out:Ljava/io/PrintStream;
invoke-virtual {v3, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
add-int/lit8 v0, v0, 0x1
goto :goto_2
:cond_e
new-instance v0, Lcom/android/commands/locksettings/LockSettingsCmd;
invoke-direct {v0}, Lcom/android/commands/locksettings/LockSettingsCmd;-><init>()V
invoke-virtual {v0, p0}, Lcom/android/commands/locksettings/LockSettingsCmd;->run([Ljava/lang/String;)V
const/4 v0, 0x0
invoke-virtual {v0, p0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
return-void
.end method