Smali - Decompiling/[Modifying]/Compiling

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Іноді цікаво змінити код додатка, щоб отримати доступ до прихованої інформації для вас (можливо, добре зашифрованих паролів або прапорців). Тоді може бути цікаво декомпілювати apk, змінити код і знову скомпілювати його.

Посилання на опкоди: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html

Швидкий спосіб

Використовуючи Visual Studio Code та розширення APKLab, ви можете автоматично декомпілювати, змінювати, скомпілювати, підписувати та встановлювати додаток без виконання будь-якої команди.

Ще один скрипт, який значно спрощує це завдання, це https://github.com/ax/apk.sh

Декомпіляція APK

Використовуючи APKTool, ви можете отримати доступ до коду smali та ресурсів:

apktool d APP.apk

Якщо apktool видає будь-яку помилку, спробуйте встановити останню версію

Деякі цікаві файли, на які варто звернути увагу:

  • res/values/strings.xml (і всі xml-файли всередині res/values/*)

  • AndroidManifest.xml

  • Будь-який файл з розширенням .sqlite або .db

Якщо apktool має проблеми з декодуванням додатка, перегляньте https://ibotpeaches.github.io/Apktool/documentation/#framework-files або спробуйте використати аргумент -r (Не декодувати ресурси). Потім, якщо проблема була у ресурсі, а не у вихідному коді, ви не матимете проблеми (ви також не розкодуєте ресурси).

Зміна коду Smali

Ви можете змінювати інструкції, змінювати значення деяких змінних або додавати нові інструкції. Я змінюю код Smali за допомогою VS Code, після чого встановлюєте розширення smalise, і редактор покаже вам, якщо будь-яка інструкція невірна. Деякі приклади можна знайти тут:

Або ви можете перевірити нижче пояснення деяких змін у Smali.

Перекомпілювати APK

Після внесення змін у код ви можете перекомпілювати код за допомогою:

apktool b . #In the folder generated when you decompiled the application

Це скомпілює новий APK всередині папки dist.

Якщо apktool видає помилку, спробуйте встановити останню версію

Підпишіть новий APK

Потім вам потрібно створити ключ (вас попросять ввести пароль та деяку інформацію, яку можна заповнити випадково):

keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>

Наостанок, підпишіть новий APK:

jarsigner -keystore key.jks path/to/dist/* <your-alias>

Оптимізація нової програми

zipalign - це інструмент для вирівнювання архіву, який забезпечує важливу оптимізацію файлів Android-додатків (APK). Додаткова інформація тут.

zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk

Підпишіть новий APK (знову?)

Якщо ви віддаєте перевагу використанню apksigner замість jarsigner, ви повинні підписати apk після застосування оптимізації з zipalign. АЛЕ ЗВЕРНІТЬ УВАГУ, ЩО ВИ ПОВИННІ ПІДПИСАТИ ДОДАТОК ОДИН РАЗ З jarsigner (перед zipalign) АБО З apksigner (після zipalign).

apksigner sign --ks key.jks ./dist/mycompiled.apk

Зміна Smali

Для наступного коду Hello World на Java:

public static void printHelloWorld() {
System.out.println("Hello World")
}

Смалі код буде:

.method public static printHelloWorld()V
.registers 2
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "Hello World"
invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
return-void
.end method

Інструкційний набір Smali доступний тут.

Легкі зміни

Зміна початкових значень змінної всередині функції

Деякі змінні визначаються на початку функції за допомогою опкоду const, ви можете змінити їх значення або визначити нові:

#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"

Основні операції

#Math
add-int/lit8 v0, v2, 0x1 #v2 + 0x1 and save it in v0
mul-int v0,v2,0x2 #v2*0x2 and save in v0

#Move the value of one object into another
move v1,v2

#Condtions
if-ge #Greater or equals
if-le #Less or equals
if-eq #Equals

#Get/Save attributes of an object
iget v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save this.o inside v0
iput v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save v0 inside this.o

#goto
:goto_6 #Declare this where you want to start a loop
if-ne v0, v9, :goto_6 #If not equals, go to: :goto_6
goto :goto_6 #Always go to: :goto_6

Великі зміни

Логування

#Log win: <number>
iget v5, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Get this.o inside v5
invoke-static {v5}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; #Transform number to String
move-result-object v1 #Move to v1
const-string v5, "wins" #Save "win" inside v5
invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I #Logging "Wins: <num>"

Рекомендації:

  • Якщо ви збираєтеся використовувати оголошені змінні всередині функції (оголошені v0, v1, v2...), розмістіть ці рядки між .local <number> та оголошеннями змінних (const v0, 0x1)

  • Якщо ви хочете вставити код журналювання посередині коду функції:

  • Додайте 2 до кількості оголошених змінних: Наприклад, з .locals 10 на .locals 12

  • Нові змінні повинні мати наступні номери після вже оголошених змінних (у цьому прикладі повинні бути v10 та v11, пам'ятайте, що вони починаються з v0).

  • Змініть код функції журналювання та використовуйте v10 та v11 замість v5 та v1.

Toasting

Не забудьте додати 3 до кількості .locals на початку функції.

Цей код готовий для вставки в середину функції (змініть кількість змінних за необхідності). Він візьме значення this.o, перетворить його на рядок і потім виведе повідомлення з його значенням.

const/4 v10, 0x1
const/4 v11, 0x1
const/4 v12, 0x1
iget v10, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I
invoke-static {v10}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
move-result-object v11
invoke-static {p0, v11, v12}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v12
invoke-virtual {v12}, Landroid/widget/Toast;->show()V
Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated