Android Question Injection Reverse Engineering

Andrei E

Member
Licensed User
Longtime User
Hello dear B4a guru developers
Is anyone can explain me about activity injection of B4a project into the external package via smali code patching?

Task todo:
Inject my options activity into the onCreate method of the external package (at the smali level)

Example:
Helloworld android application (com.aide.helloworld.apk) shows toast message at first start
B4X:
# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
...
.prologue
const/4 v0, 0x1
const-string v1, "This is injected toast message"
invoke-static {p0, v1, v0}, 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
...
.end method

But when I'm trying to inject my B4a activity into the Helloworld application I'm got an error (at the start patched application, logcat in attach)

Injection code:
B4X:
# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
...
.prologue
invoke-direct {p0}, Lcom/aide/helloworld/MainActivity;->startActivity(Lcom/b4a/injectdemo/main;)V
...
.end method
 

Attachments

  • com.aide.helloworld.apk
    276.9 KB · Views: 312
  • com.aide.helloworld.toast.png
    com.aide.helloworld.toast.png
    111.4 KB · Views: 330
  • logcat.txt
    1.8 KB · Views: 242
  • com.aide.helloworld.activity.jpg
    com.aide.helloworld.activity.jpg
    128.3 KB · Views: 328
  • com.b4a.injectdemo.source.zip
    226.7 KB · Views: 214

Andrei E

Member
Licensed User
Longtime User
Hi Erel, thanks for this question, this is legal task without any breaks of software EULA
The purpose of this injection is a game application modifications like extract games prferences and graphics mods etc.

I'm already have worked examples for this task but I don't want to use them because it's hardly pointed and I don't know how to mod it for my tasks

Extraction example of internal app data:
B4X:
.method private SmartDataRestoreForYou()V
    .locals 23

    .prologue
    .line 40
    const/16 v4, 0x800

    .line 41
    .local v4, BUFFER:I
    const-string v17, "/"

    .line 42
    .local v17, t:Ljava/lang/String;
    const-string v18, "data"

    .line 44
    .local v18, t1:Ljava/lang/String;

    .line 45
    .local v23, t5:Ljava/lang/String;
    const-string v22, "zdata"

    .line 46
    .local v22, t3:Ljava/lang/String;
    invoke-virtual/range {p0 .. p0}, Lcom/miniclip/railrush/RailRushActivity;->getPackageName()Ljava/lang/String;

    move-result-object v5

    .line 47
    .local v5, aa:Ljava/lang/String;
    invoke-virtual/range {p0 .. p0}, Lcom/miniclip/railrush/RailRushActivity;->getAssets()Landroid/content/res/AssetManager;

    move-result-object v6

    .line 48
    .local v6, bb:Landroid/content/res/AssetManager;
    new-instance v20, Ljava/lang/StringBuilder;

    invoke-static/range {v17 .. v17}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object v21

    invoke-direct/range {v20 .. v21}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    move-object/from16 v0, v20

    move-object/from16 v1, v18

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v20

    move-object/from16 v0, v20

    move-object/from16 v1, v17

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v20

    move-object/from16 v0, v20

    move-object/from16 v1, v18

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v20

    move-object/from16 v0, v20

    move-object/from16 v1, v17

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v20

    move-object/from16 v0, v20

    move-object v1, v5

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v20

    move-object/from16 v0, v20

    move-object/from16 v1, v17

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v20

    invoke-virtual/range {v20 .. v20}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v16

    .line 50
    .local v16, logDir:Ljava/lang/String;
    const/4 v9, 0x0

    .line 54
    .local v9, dest:Ljava/io/BufferedOutputStream;
    :try_start_0
    move-object v0, v6

    move-object/from16 v1, v22

    invoke-virtual {v0, v1}, Landroid/content/res/AssetManager;->open(Ljava/lang/String;)Ljava/io/InputStream;

    move-result-object v15

    .line 55
    .local v15, localInputStream1:Ljava/io/InputStream;
    new-instance v19, Ljava/util/zip/ZipInputStream;

    move-object/from16 v0, v19

    move-object v1, v15

    invoke-direct {v0, v1}, Ljava/util/zip/ZipInputStream;-><init>(Ljava/io/InputStream;)V
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_1

    .local v19, zis:Ljava/util/zip/ZipInputStream;
    move-object v10, v9

    .line 58
    .end local v9          #dest:Ljava/io/BufferedOutputStream;
    .local v10, dest:Ljava/io/BufferedOutputStream;
    :cond_0
    :goto_0
    :try_start_1
    invoke-virtual/range {v19 .. v19}, Ljava/util/zip/ZipInputStream;->getNextEntry()Ljava/util/zip/ZipEntry;

    move-result-object v12

    .local v12, entry:Ljava/util/zip/ZipEntry;
    if-nez v12, :cond_1

    .line 85
    invoke-virtual/range {v19 .. v19}, Ljava/util/zip/ZipInputStream;->close()V

    .line 90
    .end local v10          #dest:Ljava/io/BufferedOutputStream;
    .end local v12          #entry:Ljava/util/zip/ZipEntry;
    .end local v15          #localInputStream1:Ljava/io/InputStream;
    .end local v19          #zis:Ljava/util/zip/ZipInputStream;
    :goto_1
    return-void

    .line 59
    .restart local v10      #dest:Ljava/io/BufferedOutputStream;
    .restart local v12      #entry:Ljava/util/zip/ZipEntry;
    .restart local v15      #localInputStream1:Ljava/io/InputStream;
    .restart local v19      #zis:Ljava/util/zip/ZipInputStream;
    :cond_1
    new-instance v13, Ljava/io/File;

    new-instance v20, Ljava/lang/StringBuilder;

    invoke-static/range {v16 .. v16}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object v21

    invoke-direct/range {v20 .. v21}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v12}, Ljava/util/zip/ZipEntry;->getName()Ljava/lang/String;

    move-result-object v21

    invoke-virtual/range {v20 .. v21}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v20

    invoke-virtual/range {v20 .. v20}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v20

    move-object v0, v13

    move-object/from16 v1, v20

    invoke-direct {v0, v1}, Ljava/io/File;-><init>(Ljava/lang/String;)V

    .line 62
    .local v13, file:Ljava/io/File;
    invoke-virtual {v13}, Ljava/io/File;->exists()Z

    move-result v20

    if-nez v20, :cond_0

    .line 66
    invoke-virtual {v12}, Ljava/util/zip/ZipEntry;->isDirectory()Z

    move-result v20

    if-eqz v20, :cond_2

    .line 67
    invoke-virtual {v13}, Ljava/io/File;->exists()Z

    move-result v20

    if-nez v20, :cond_0

    .line 68
    invoke-virtual {v13}, Ljava/io/File;->mkdirs()Z
    :try_end_1
    .catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_0

    goto :goto_0

    .line 86
    .end local v12          #entry:Ljava/util/zip/ZipEntry;
    .end local v13          #file:Ljava/io/File;
    :catch_0
    move-exception v20

    move-object/from16 v11, v20

    move-object v9, v10

    .line 88
    .end local v10          #dest:Ljava/io/BufferedOutputStream;
    .end local v15          #localInputStream1:Ljava/io/InputStream;
    .end local v19          #zis:Ljava/util/zip/ZipInputStream;
    .restart local v9      #dest:Ljava/io/BufferedOutputStream;
    .local v11, e:Ljava/lang/Exception;
    :goto_2
    invoke-virtual {v11}, Ljava/lang/Exception;->printStackTrace()V

    goto :goto_1

    .line 74
    .end local v9          #dest:Ljava/io/BufferedOutputStream;
    .end local v11          #e:Ljava/lang/Exception;
    .restart local v10      #dest:Ljava/io/BufferedOutputStream;
    .restart local v12      #entry:Ljava/util/zip/ZipEntry;
    .restart local v13      #file:Ljava/io/File;
    .restart local v15      #localInputStream1:Ljava/io/InputStream;
    .restart local v19      #zis:Ljava/util/zip/ZipInputStream;
    :cond_2
    :try_start_2
    new-array v8, v4, [B

    .line 77
    .local v8, data:[B
    new-instance v14, Ljava/io/FileOutputStream;

    invoke-direct {v14, v13}, Ljava/io/FileOutputStream;-><init>(Ljava/io/File;)V

    .line 78
    .local v14, fos:Ljava/io/FileOutputStream;
    new-instance v9, Ljava/io/BufferedOutputStream;

    invoke-direct {v9, v14, v4}, Ljava/io/BufferedOutputStream;-><init>(Ljava/io/OutputStream;I)V
    :try_end_2
    .catch Ljava/lang/Exception; {:try_start_2 .. :try_end_2} :catch_0

    .line 79
    .end local v10          #dest:Ljava/io/BufferedOutputStream;
    .restart local v9      #dest:Ljava/io/BufferedOutputStream;
    :goto_3
    const/16 v20, 0x0

    :try_start_3
    move-object/from16 v0, v19

    move-object v1, v8

    move/from16 v2, v20

    move v3, v4

    invoke-virtual {v0, v1, v2, v3}, Ljava/util/zip/ZipInputStream;->read([BII)I

    move-result v7

    .local v7, count:I
    const/16 v20, -0x1

    move v0, v7

    move/from16 v1, v20

    if-ne v0, v1, :cond_3

    .line 82
    invoke-virtual {v9}, Ljava/io/BufferedOutputStream;->flush()V

    .line 83
    invoke-virtual {v9}, Ljava/io/BufferedOutputStream;->close()V

    move-object v10, v9

    .end local v9          #dest:Ljava/io/BufferedOutputStream;
    .restart local v10      #dest:Ljava/io/BufferedOutputStream;
    goto :goto_0

    .line 80
    .end local v10          #dest:Ljava/io/BufferedOutputStream;
    .restart local v9      #dest:Ljava/io/BufferedOutputStream;
    :cond_3
    const/16 v20, 0x0

    move-object v0, v9

    move-object v1, v8

    move/from16 v2, v20

    move v3, v7

    invoke-virtual {v0, v1, v2, v3}, Ljava/io/BufferedOutputStream;->write([BII)V
    :try_end_3
    .catch Ljava/lang/Exception; {:try_start_3 .. :try_end_3} :catch_1

    goto :goto_3

    .line 86
    .end local v7          #count:I
    .end local v8          #data:[B
    .end local v12          #entry:Ljava/util/zip/ZipEntry;
    .end local v13          #file:Ljava/io/File;
    .end local v14          #fos:Ljava/io/FileOutputStream;
    .end local v15          #localInputStream1:Ljava/io/InputStream;
    .end local v19          #zis:Ljava/util/zip/ZipInputStream;
    :catch_1
    move-exception v20

    move-object/from16 v11, v20

    goto :goto_2
.end method

Usage:
B4X:
invoke-direct {p0}, Lcom/miniclip/railrush/RailRushActivity;->SmartDataRestoreForYou()V

As you can see this is class inside the entrypoint smali but I want to invoke my own activity from my smali file
 
Upvote 0

Andrei E

Member
Licensed User
Longtime User
Hmmm, so complete answer
Can you suggest me worked tool to convert my B4a project into the Eclipse?
May be then I can use my B4a converted code as a class in entrypoint smali file, because at now I can't merge duplicates smali files R$attr.smali, R$drawable.smali, R$layout.smali and R.smali of my B4a project and injectable application
 
Upvote 0
Top