Objects and Methods
Objects and methods provide the ability to modify or insert code, enabling dynamic changes to the behavior of an application.
In SMALI
invoke-virtual
: Indicates that the method being called is a public method.invoke-direct
: Refers to constructors or private methods.new-instance vx, type
: Creates a new instance of a specified type (e.g.,java.io.FileInputStream
) and stores it in a register (e.g.,v0
).This is particularly powerful because it allows the use of classes like
FileOutputStream
to interact with files, enabling the search for or manipulation of sensitive information.
Important Blocks
Java code
public void helloWorld() { String text = "Hello World!"; System.out.println(text); }
SMALI Code:
const-string v0, "Hello World!" sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
const-string v0, "Hello World!"
: This loads the string"Hello World!"
into the registerv0
.sget-object
: It retrieves the static fieldSystem.out
(which is aPrintStream
) and stores it in registerv1
.invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
: This invokes theprintln
method on thePrintStream
object inv1
, passing the string inv0
as an argument.
Useful SMALI snippets
Printing Variables/Return Values via
System.out.println
Java Code:
String password = "Pa%%w0rd!"; System.out.println(password);
Corresponding SMALI Code:
.line 14 const-string v0, "Pa%%w0rd!" # Load the string "Pa%%w0rd!" into register v0 .line 15 .local v0, "password":Ljava/lang/String; # Declare v0 as a local variable named "password" of type String sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; # Retrieve the static field System.out (PrintStream) and store it in v1 invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V # Invoke the println method on System.out, passing the string in v0
Usage:
To print any variable or return value, place the object or value you want to print into
v0
(or another register), then usesget-object
andinvoke-virtual
as shown above.After modifying the SMALI code, run the app and check the
logcat
output to see the printed value:$ adb logcat
Printing Byte Values as Base64 Encoded Strings
When working with cryptographic functions, keys or initialization vectors (IVs) are often stored as byte arrays. To print these byte arrays in a readable text format, you can encode them as Base64 strings. Here's how you can achieve this in both Java and SMALI:
Java Code:
System.out.println(Base64.encodeToString(<byteArray>, 0));
Corresponding SMALI Code:
const/4 v5, 0x0 invoke-static {v2, v5}, Landroid/util/Base64;->encodeToString([BI)Ljava/lang/String; # Encode the byte array in v2 to a Base64 string move-result-object v5 # Store the resulting Base64 string in v5 sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; # Get the System.out PrintStream object invoke-virtual {v1, v5}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V # Print the Base64 string
Usage:
Insert this SMALI snippet into the existing SMALI code of the application at the point where you want to print the byte array as a Base64 string.
Adjust the register
v2
to point to the byte array you want to encode and print.After running the app, check the logcat output to see the printed Base64 string:
$ adb logcat
📍We have an encrypted message, and we aim to display it as plain text.

There are two approaches to achieve this:
Use
System.out.println()
to Display the Decrypted Message in Logcat:By inserting
System.out.println()
in the code, we can print the decrypted message to the logcat output. This is useful for debugging and verifying the decryption process.
Identify the Register Containing the Decrypted Message:
Determine which register holds the decrypted message and use it to display the message on the screen. For example, if register
v0
contains the decrypted message and registerv2
contains the encrypted message, we can modify the code to invokev0
instead ofv2
to show the decrypted message on the screen.
To achieve the first approach
Identify the Register Holding the Decrypted Message
Insert SMALI Code to Print the Message:
Use
sget-object
to get theSystem.out
PrintStream
object.Use
invoke-virtual
to callprintln
and print the decrypted message.
Place the Code in the Correct Location:
Insert the SMALI code immediately after the decryption logic to ensure the decrypted message is printed.
Example in SMALI
# Assume v0 contains the decrypted message .line 42 .local v0, "decryptedMessage":Ljava/lang/String; # Declare v0 as the decrypted message # Print the decrypted message to Logcat sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; # Get System.out invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V # Print v0
How to Test:
Rebuild the APK with the modified SMALI code.
Install the APK on a device or emulator.
Run the app and monitor the Logcat output:
adb logcat
Look for the decrypted message in the logs.
Last updated