[JAVA] Android App dekompilieren ⇒ korrigieren ⇒ neu kompilieren

Was ist zu tun

Zu verwendende Werkzeuge

・ Apktool https://ibotpeaches.github.io/Apktool/ ・ Dex2jar https://github.com/pxb1988/dex2jar ・ Jad http://www.javadecompilers.com/jad

Überprüfungstest App

Wenn Sie das richtige Passwort (Possword) eingeben, wird der Anmeldevorgang ausgeführt. Verwenden Sie zur Überprüfung eine einfache App mit Passworteingabefeld und Anmeldeschaltfläche

Screenshot_20170701-193328.png Screenshot_20170701-193401.png

·Quellcode

MainActivity.java


package com.example.user.logintest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

    private Button mLogInButton;
    private EditText mPasswordEditText;
    private TextView mStatusTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPasswordEditText = (EditText)findViewById(R.id.editText);
        mStatusTextView = (TextView)findViewById(R.id.textView3);

        mLogInButton = (Button)findViewById(R.id.button);
        mLogInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (passwordCheck(mPasswordEditText.getText().toString())) {
                    processLogInSuccess();
                } else {
                    processLogInFail();
                }
            }
        });
    }

    private boolean passwordCheck(String password) {
        if (("possword").equals(password)) {
            return true;
        } else {
            return false;
        }
    }

    private void processLogInSuccess() {
        mStatusTextView.setText("Sie sind jetzt angemeldet");
        Toast.makeText(MainActivity.this, "Sie sind jetzt angemeldet", Toast.LENGTH_LONG).show();
    }

    private void processLogInFail() {
        mStatusTextView.setText("Das Passwort ist anders");
        Toast.makeText(MainActivity.this, "Das Passwort ist anders", Toast.LENGTH_LONG).show();
    }
}

activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.user.logintest.MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="PASSWORD : "
             />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="textPersonName"
            android:text=""
            android:ems="10"
            android:id="@+id/editText"
            android:layout_weight="1" />

    </LinearLayout>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <Button
            android:text="Einloggen"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/button"
            android:layout_weight="1" />

        <TextView
            android:text="Nicht eingeloggt"
            android:textSize="20sp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/textView3"
            android:layout_weight="1"
            android:paddingTop="10dp"
            android:gravity="center_horizontal"/>
    </LinearLayout>

</LinearLayout>

1. Dekompilieren Sie die APK-Datei in den ursprünglichen Quellcode im Java-Format

  1. Ändern Sie die Erweiterung der apk-Datei in zip und entpacken Sie sie.
  2. Konvertieren Sie classes.dex in dem in 1 entpackten Ordner in jar
> <dex2jar.Fledermausordnerpfad>\dex2jar.bat <classes.Dex-Ordnerpfad>\classes.dex
  1. Ändern Sie die Erweiterung der Ausgabe von classes-dex2jar.jar in 2, um sie zu komprimieren und zu entpacken. Konvertieren Sie die Klassendatei in dem in 4.3 entpackten Ordner in eine Java-Datei
> <Jad-Ordnerpfad>\jad -s java -d src -r classes-dex2jar\**\*.class

Die Java-Quelle wird in den durch -d angegebenen src-Ordner ausgegeben.

src\com\example\user\logintest

MainActivity.java


// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 

package com.example.user.logintest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.*;

public class MainActivity extends Activity
{

    public MainActivity()
    {
    }

    private boolean passwordCheck(String s)
    {
        return "possword".equals(s);
    }

    private void processLogInFail()
    {
        mStatusTextView.setText("\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u7570\u306A\u308A\u307E\u3059");
        Toast.makeText(this, "\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u7570\u306A\u308A\u307E\u3059", 1).show();
    }

    private void processLogInSuccess()
    {
        mStatusTextView.setText("\u30ED\u30B0\u30A4\u30F3\u3057\u307E\u3057\u305F");
        Toast.makeText(this, "\u30ED\u30B0\u30A4\u30F3\u3057\u307E\u3057\u305F", 1).show();
    }

    protected void onCreate(Bundle bundle)
    {
        super.onCreate(bundle);
        setContentView(0x7f04001a);
        mPasswordEditText = (EditText)findViewById(0x7f0b0055);
        mStatusTextView = (TextView)findViewById(0x7f0b0057);
        mLogInButton = (Button)findViewById(0x7f0b0056);
        mLogInButton.setOnClickListener(new android.view.View.OnClickListener() {

            public void onClick(View view)
            {
                if(passwordCheck(mPasswordEditText.getText().toString()))
                {
                    processLogInSuccess();
                    return;
                } else
                {
                    processLogInFail();
                    return;
                }
            }

            final MainActivity this$0;

            
            {
                this$0 = MainActivity.this;
                super();
            }
        }
);
    }

    private Button mLogInButton;
    private EditText mPasswordEditText;
    private TextView mStatusTextView;




}

2. Dekompilieren Sie die APK-Datei in neu kompilierbaren Code im Smalli-Format

> java -jar <apktoll.Der Pfad des Ordners, in dem sich das Glas befindet>/apktool.jar d <LogInTest.Der Pfad des Ordners, in dem sich apk befindet>/LogInTest.apk

Die smali-Datei wird in den Ordner mit dem gleichen Namen wie die apk-Datei ausgegeben.

LogInTest\smali\com\example\user\logintest

MainActivity.smali


.class public Lcom/example/user/logintest/MainActivity;
.super Landroid/app/Activity;
.source "MainActivity.java"


# instance fields
.field private mLogInButton:Landroid/widget/Button;

.field private mPasswordEditText:Landroid/widget/EditText;

.field private mStatusTextView:Landroid/widget/TextView;


# direct methods
.method public constructor <init>()V
    .locals 0

    .prologue
    .line 13
    invoke-direct {p0}, Landroid/app/Activity;-><init>()V

    return-void
.end method

.method static synthetic access$000(Lcom/example/user/logintest/MainActivity;)Landroid/widget/EditText;
    .locals 1
    .param p0, "x0"    # Lcom/example/user/logintest/MainActivity;

    .prologue
    .line 13
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity;->mPasswordEditText:Landroid/widget/EditText;

    return-object v0
.end method

.method static synthetic access$100(Lcom/example/user/logintest/MainActivity;Ljava/lang/String;)Z
    .locals 1
    .param p0, "x0"    # Lcom/example/user/logintest/MainActivity;
    .param p1, "x1"    # Ljava/lang/String;

    .prologue
    .line 13
    invoke-direct {p0, p1}, Lcom/example/user/logintest/MainActivity;->passwordCheck(Ljava/lang/String;)Z

    move-result v0

    return v0
.end method

.method static synthetic access$200(Lcom/example/user/logintest/MainActivity;)V
    .locals 0
    .param p0, "x0"    # Lcom/example/user/logintest/MainActivity;

    .prologue
    .line 13
    invoke-direct {p0}, Lcom/example/user/logintest/MainActivity;->processLogInSuccess()V

    return-void
.end method

.method static synthetic access$300(Lcom/example/user/logintest/MainActivity;)V
    .locals 0
    .param p0, "x0"    # Lcom/example/user/logintest/MainActivity;

    .prologue
    .line 13
    invoke-direct {p0}, Lcom/example/user/logintest/MainActivity;->processLogInFail()V

    return-void
.end method

.method private passwordCheck(Ljava/lang/String;)Z
    .locals 1
    .param p1, "password"    # Ljava/lang/String;

    .prologue
    .line 41
    const-string v0, "possword"

    invoke-virtual {v0, p1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v0

    if-eqz v0, :cond_0

    .line 42
    const/4 v0, 0x1

    .line 44
    :goto_0
    return v0

    :cond_0
    const/4 v0, 0x0

    goto :goto_0
.end method

.method private processLogInFail()V
    .locals 2

    .prologue
    .line 54
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity;->mStatusTextView:Landroid/widget/TextView;

    const-string v1, "\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u7570\u306a\u308a\u307e\u3059"

    invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 55
    const-string v0, "\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u7570\u306a\u308a\u307e\u3059"

    const/4 v1, 0x1

    invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v0

    invoke-virtual {v0}, Landroid/widget/Toast;->show()V

    .line 56
    return-void
.end method

.method private processLogInSuccess()V
    .locals 2

    .prologue
    .line 49
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity;->mStatusTextView:Landroid/widget/TextView;

    const-string v1, "\u30ed\u30b0\u30a4\u30f3\u3057\u307e\u3057\u305f"

    invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

    .line 50
    const-string v0, "\u30ed\u30b0\u30a4\u30f3\u3057\u307e\u3057\u305f"

    const/4 v1, 0x1

    invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v0

    invoke-virtual {v0}, Landroid/widget/Toast;->show()V

    .line 51
    return-void
.end method


# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 2
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;

    .prologue
    .line 21
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

    .line 22
    const v0, 0x7f04001a

    invoke-virtual {p0, v0}, Lcom/example/user/logintest/MainActivity;->setContentView(I)V

    .line 24
    const v0, 0x7f0b0055

    invoke-virtual {p0, v0}, Lcom/example/user/logintest/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/EditText;

    iput-object v0, p0, Lcom/example/user/logintest/MainActivity;->mPasswordEditText:Landroid/widget/EditText;

    .line 25
    const v0, 0x7f0b0057

    invoke-virtual {p0, v0}, Lcom/example/user/logintest/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/TextView;

    iput-object v0, p0, Lcom/example/user/logintest/MainActivity;->mStatusTextView:Landroid/widget/TextView;

    .line 27
    const v0, 0x7f0b0056

    invoke-virtual {p0, v0}, Lcom/example/user/logintest/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/example/user/logintest/MainActivity;->mLogInButton:Landroid/widget/Button;

    .line 28
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity;->mLogInButton:Landroid/widget/Button;

    new-instance v1, Lcom/example/user/logintest/MainActivity$1;

    invoke-direct {v1, p0}, Lcom/example/user/logintest/MainActivity$1;-><init>(Lcom/example/user/logintest/MainActivity;)V

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 38
    return-void
.end method

MainActivity$1.smali


.class Lcom/example/user/logintest/MainActivity$1;
.super Ljava/lang/Object;
.source "MainActivity.java"

# interfaces
.implements Landroid/view/View$OnClickListener;


# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
    value = Lcom/example/user/logintest/MainActivity;->onCreate(Landroid/os/Bundle;)V
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x0
    name = null
.end annotation


# instance fields
.field final synthetic this$0:Lcom/example/user/logintest/MainActivity;


# direct methods
.method constructor <init>(Lcom/example/user/logintest/MainActivity;)V
    .locals 0
    .param p1, "this$0"    # Lcom/example/user/logintest/MainActivity;

    .prologue
    .line 28
    iput-object p1, p0, Lcom/example/user/logintest/MainActivity$1;->this$0:Lcom/example/user/logintest/MainActivity;

    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method


# virtual methods
.method public onClick(Landroid/view/View;)V
    .locals 2
    .param p1, "view"    # Landroid/view/View;

    .prologue
    .line 31
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity$1;->this$0:Lcom/example/user/logintest/MainActivity;

    iget-object v1, p0, Lcom/example/user/logintest/MainActivity$1;->this$0:Lcom/example/user/logintest/MainActivity;

    # getter for: Lcom/example/user/logintest/MainActivity;->mPasswordEditText:Landroid/widget/EditText;
    invoke-static {v1}, Lcom/example/user/logintest/MainActivity;->access$000(Lcom/example/user/logintest/MainActivity;)Landroid/widget/EditText;

    move-result-object v1

    invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;

    move-result-object v1

    invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String;

    move-result-object v1

    # invokes: Lcom/example/user/logintest/MainActivity;->passwordCheck(Ljava/lang/String;)Z
    invoke-static {v0, v1}, Lcom/example/user/logintest/MainActivity;->access$100(Lcom/example/user/logintest/MainActivity;Ljava/lang/String;)Z

    move-result v0

    if-eqz v0, :cond_0

    .line 32
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity$1;->this$0:Lcom/example/user/logintest/MainActivity;

    # invokes: Lcom/example/user/logintest/MainActivity;->processLogInSuccess()V
    invoke-static {v0}, Lcom/example/user/logintest/MainActivity;->access$200(Lcom/example/user/logintest/MainActivity;)V

    .line 36
    :goto_0
    return-void

    .line 34
    :cond_0
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity$1;->this$0:Lcom/example/user/logintest/MainActivity;

    # invokes: Lcom/example/user/logintest/MainActivity;->processLogInFail()V
    invoke-static {v0}, Lcom/example/user/logintest/MainActivity;->access$300(Lcom/example/user/logintest/MainActivity;)V

    goto :goto_0
.end method

3. Ändern Sie den dekompilierten Smalli-Code und kompilieren Sie ihn erneut

Änderung der Smali-Datei

Hauptaktivität

                if (passwordCheck(mPasswordEditText.getText().toString())) {
                    processLogInSuccess();
                } else {
                    processLogInFail();
                }

Weil es prüft und verarbeitet, wann die Anmeldung erfolgreich ist oder fehlschlägt Durch Eliminieren der if-Urteilsverarbeitung wird es korrigiert, um zum Weg der erfolgreichen Verarbeitung überzugehen.

Wenn Sie der Smali-Quelle folgen, sehen Sie Folgendes von MainActivity $ 1.smali Es fühlt sich an wie ein Urteilsprozess.

    # invokes: Lcom/example/user/logintest/MainActivity;->passwordCheck(Ljava/lang/String;)Z
    ##Führen Sie passwordCheck aus
    invoke-static {v0, v1}, Lcom/example/user/logintest/MainActivity;->access$100(Lcom/example/user/logintest/MainActivity;Ljava/lang/String;)Z

    ##Speichern Sie passwordCheck Rückgabewert in v0
    move-result v0

    ##Wenn der Rückgabewert von passwordCheck 0 ist, wird cond_0(Verarbeitung fehlgeschlagen)Was
    if-eqz v0, :cond_0

    ##Verarbeitung zum Zeitpunkt des Erfolgs
    .line 32
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity$1;->this$0:Lcom/example/user/logintest/MainActivity;

    # invokes: Lcom/example/user/logintest/MainActivity;->processLogInSuccess()V
    ##Führen Sie processLogInSuccess aus
    invoke-static {v0}, Lcom/example/user/logintest/MainActivity;->access$200(Lcom/example/user/logintest/MainActivity;)V

    .line 36
    ##Rückkehr
    :goto_0
    return-void

    .line 34
    :cond_0
    ##Verarbeitung zum Zeitpunkt des Fehlschlags
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity$1;->this$0:Lcom/example/user/logintest/MainActivity;

    # invokes: Lcom/example/user/logintest/MainActivity;->processLogInFail()V
    ##Prozess zum Zeitpunkt von processLogInFail
    invoke-static {v0}, Lcom/example/user/logintest/MainActivity;->access$300(Lcom/example/user/logintest/MainActivity;)V

    ##Rückkehr
    goto :goto_0

Wenn-eqz der Beurteilungsprozess ist und der Prozess zum Zeitpunkt des Erfolgs direkt darunter fortgesetzt wird, kommentieren Sie den Beurteilungsprozess aus.

    invoke-static {v0, v1}, Lcom/example/user/logintest/MainActivity;->access$100(Lcom/example/user/logintest/MainActivity;Ljava/lang/String;)Z

    ##Speichern Sie passwordCheck Rückgabewert in v0
    move-result v0

    ##Wenn der Rückgabewert von passwordCheck 0 ist, wird cond_0(Verarbeitung fehlgeschlagen)Was
-    if-eqz v0, :cond_0
+    ## if-eqz v0, :cond_0

    ##Verarbeitung zum Zeitpunkt des Erfolgs
    .line 32
    iget-object v0, p0, Lcom/example/user/logintest/MainActivity$1;->this$0:Lcom/example/user/logintest/MainActivity;

neu kompilieren zu smali ⇒ apk

>java -jar <apktools.Der Pfad des Ordners, in dem sich das Glas befindet>\apktool.jar b .\LogInTest -o .\LogInTestCustom.apk

Unterschrift

> keytool -genkeypair -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 10950 -dname "CN=Android Debug,O=Android,C=US" -keystore debug.keystore -storepass android
> jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA1 -tsa http://timestamp.digicert.com -keystore debug.keystore -storepass android LogInTestCustom.apk androiddebugkey

Installation

>adb install -r LogInTestCustom1.apk

Funktionsprüfung

Screenshot_20170701-201202.png

Recommended Posts

Android App dekompilieren ⇒ korrigieren ⇒ neu kompilieren
Android Wetter App
Android App Spectrum Analyzer
Informationen zu Android-App-Komponenten
Startschuss für die persönliche Entwicklung der Android-App
ROS App Entwicklung auf Android
Erstelle eine Android App. (Tag 5)
Importieren Sie Gerätebilder mit der Android App
Erstelle eine Android App. (Erster Tag)
Hinweise zum Aufrufen von Installer in der Android App
Ich habe eine passende App erstellt (Android App)
[Android] Ich habe eine Schrittzähler-App erstellt.