Pergunta

I got a code in java:

InputStream stream = null;
OutputStream output = null;

for(String fileName : this.getAssets().list("www"))
{
    stream = this.getAssets().open("directoryName/" + fileName);
    output = new BufferedOutputStream(new FileOutputStream("/mnt/sdcard/www/" + fileName));

    byte data[] = new byte[1024];
    int count;

    while((count = stream.read(data)) != -1)
    {
        output.write(data, 0, count);
    }

    output.flush();
    output.close();
    stream.close();

    stream = null;
    output = null;
}

It works perfect... but I need to rewrite it to smali / dex, so I could compile it into decompiled application (via apktool)... is it even possible? Could anybody help me with that?

Foi útil?

Solução

Translating Java to Smali is:

Java -(javac)-> Java bytecode -(dx)-> Dex bytecode -(baksmali)-> Smali

If you don't already have it, download the Android SDK.

From Eclipse

Since your code calls this.getAssets(), it needs to be inside of an Activity class. If you don't already have Eclipse setup to build Android projects, you should start here: Setting up the ADT Bundle. Once it's setup, create a new Android project. Then, add this code to a method in the main activity. Something like this:

public void copyAssets() throws IOException {
    InputStream stream = null;
    OutputStream output = null;

    for (String fileName : this.getAssets().list("www")) {
        stream = this.getAssets().open("directoryName/" + fileName);
        output = new BufferedOutputStream(new FileOutputStream("/mnt/sdcard/www/" + fileName));

        byte data[] = new byte[1024];
        int count;

        while ((count = stream.read(data)) != -1) {
            output.write(data, 0, count);
        }

        output.flush();
        output.close();
        stream.close();

        stream = null;
        output = null;
    }
}

Then, export the project to an APK. Finally, baksmali the APK to get your Smali. It will have to be added to an Activity class, or something with access to this.getResources(). The Smali looks like:

.method public copyAssets()V
    .registers 13
    .annotation system Ldalvik/annotation/Throws;
        value = {
            Ljava/io/IOException;
        }
    .end annotation

    .prologue
    const/4 v6, 0x0

    .line 41
    const/4 v4, 0x0

    .line 42
    .local v4, "stream":Ljava/io/InputStream;
    const/4 v3, 0x0

    .line 44
    .local v3, "output":Ljava/io/OutputStream;
    invoke-virtual {p0}, Lcom/lookout/sauronprobe/MainActivity;->getAssets()Landroid/content/res/AssetManager;

    move-result-object v5

    const-string v7, "www"

    invoke-virtual {v5, v7}, Landroid/content/res/AssetManager;->list(Ljava/lang/String;)[Ljava/lang/String;

    move-result-object v7

    array-length v8, v7

    move v5, v6

    :goto_f
    if-lt v5, v8, :cond_12

    .line 62
    return-void

    .line 44
    :cond_12
    aget-object v2, v7, v5

    .line 45
    .local v2, "fileName":Ljava/lang/String;
    invoke-virtual {p0}, Lcom/lookout/sauronprobe/MainActivity;->getAssets()Landroid/content/res/AssetManager;

    move-result-object v9

    new-instance v10, Ljava/lang/StringBuilder;

    const-string v11, "directoryName/"

    invoke-direct {v10, v11}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

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

    move-result-object v10

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

    move-result-object v10

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

    move-result-object v4

    .line 46
    new-instance v3, Ljava/io/BufferedOutputStream;

    .end local v3    # "output":Ljava/io/OutputStream;
    new-instance v9, Ljava/io/FileOutputStream;

    new-instance v10, Ljava/lang/StringBuilder;

    const-string v11, "/mnt/sdcard/www/"

    invoke-direct {v10, v11}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

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

    move-result-object v10

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

    move-result-object v10

    invoke-direct {v9, v10}, Ljava/io/FileOutputStream;-><init>(Ljava/lang/String;)V

    invoke-direct {v3, v9}, Ljava/io/BufferedOutputStream;-><init>(Ljava/io/OutputStream;)V

    .line 48
    .restart local v3    # "output":Ljava/io/OutputStream;
    const/16 v9, 0x400

    new-array v1, v9, [B

    .line 51
    .local v1, "data":[B
    :goto_48
    invoke-virtual {v4, v1}, Ljava/io/InputStream;->read([B)I

    move-result v0

    .local v0, "count":I
    const/4 v9, -0x1

    if-ne v0, v9, :cond_5d

    .line 55
    invoke-virtual {v3}, Ljava/io/OutputStream;->flush()V

    .line 56
    invoke-virtual {v3}, Ljava/io/OutputStream;->close()V

    .line 57
    invoke-virtual {v4}, Ljava/io/InputStream;->close()V

    .line 59
    const/4 v4, 0x0

    .line 60
    const/4 v3, 0x0

    .line 44
    add-int/lit8 v5, v5, 0x1

    goto :goto_f

    .line 52
    :cond_5d
    invoke-virtual {v3, v1, v6, v0}, Ljava/io/OutputStream;->write([BII)V

    goto :goto_48
.end method

.method protected onCreate(Landroid/os/Bundle;)V
    .registers 6
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;

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

    .line 25
    const/high16 v1, 0x7f030000

    invoke-virtual {p0, v1}, Lcom/lookout/sauronprobe/MainActivity;->setContentView(I)V

    .line 27
    invoke-static {}, Lcom/lookout/sauronprobe/MonitorHub;->instance()Lcom/lookout/sauronprobe/MonitorHub;

    move-result-object v0

    .line 28
    .local v0, "hub":Lcom/lookout/sauronprobe/MonitorHub;
    invoke-virtual {v0}, Lcom/lookout/sauronprobe/MonitorHub;->start()V

    .line 30
    new-instance v1, Landroid/content/Intent;

    sget-object v2, Lcom/lookout/sauronprobe/Sauron;->instance:Landroid/app/Application;

    const-class v3, Lcom/lookout/sauronprobe/telemetry/mq/MessagingService;

    invoke-direct {v1, v2, v3}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V

    invoke-virtual {p0, v1}, Lcom/lookout/sauronprobe/MainActivity;->startService(Landroid/content/Intent;)Landroid/content/ComponentName;

    .line 31
    return-void
.end method

It's a lot of work up front, but easy once you've done it or if you already have Eclipse setup.

From Command Line

First, refactor the code so it can stand alone as a static method. It will need one parameter for the context, to get access to getAssets(). Save it with a file name the same as the class name. In this case, CopyAssets.java. Code looks like this:

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;

public class CopyAssets {
    public static void copyAssets(android.content.Context ctx) throws IOException {
        InputStream stream = null;
        OutputStream output = null;

        for (String fileName : ctx.getAssets().list("www")) {
            stream = ctx.getAssets().open("directoryName/" + fileName);
            output = new BufferedOutputStream(new FileOutputStream("/mnt/sdcard/www/" + fileName));

            byte data[] = new byte[1024];
            int count;

            while ((count = stream.read(data)) != -1) {
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            stream.close();

            stream = null;
            output = null;
        }
    }
}

Second, ensure you have an Android platform downloaded with the SDK. In this case, I have Android-18 downloaded to ~/android/sdk/platforms. The command to compile is:

javac -cp ~/android/sdk/platforms/android-18/android.jar CopyAssets.java

Then, you'll have a CopyAssets.class. Convert it to a Dex with this command:

dx --dex --no-strict --output copyassets.dex CopyAssets.class

The --no-strict tells dx to not worry about file structure.

Finally, convert the Dex file to Smali with baksmali:

baksmali copyassets.dex

You will get Smali with a static method you can easily add. It must be called by first getting the context with Activity.getBaseContext(). You will get this Smali:

.class public LCopyAssets;
.super Ljava/lang/Object;
.source "CopyAssets.java"


# direct methods
.method public constructor <init>()V
    .registers 1

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

    return-void
.end method

.method public static copyAssets(Landroid/content/Context;)V
    .registers 11
    .annotation system Ldalvik/annotation/Throws;
        value = {
            Ljava/io/IOException;
        }
    .end annotation

    .prologue
    const/4 v1, 0x0

    .line 13
    .line 16
    invoke-virtual {p0}, Landroid/content/Context;->getAssets()Landroid/content/res/AssetManager;

    move-result-object v0

    const-string v2, "www"

    invoke-virtual {v0, v2}, Landroid/content/res/AssetManager;->list(Ljava/lang/String;)[Ljava/lang/String;

    move-result-object v2

    array-length v3, v2

    move v0, v1

    :goto_d
    if-ge v0, v3, :cond_64

    aget-object v4, v2, v0

    .line 17
    invoke-virtual {p0}, Landroid/content/Context;->getAssets()Landroid/content/res/AssetManager;

    move-result-object v5

    new-instance v6, Ljava/lang/StringBuilder;

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

    const-string v7, "directoryName/"

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

    move-result-object v6

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

    move-result-object v6

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

    move-result-object v6

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

    move-result-object v5

    .line 18
    new-instance v6, Ljava/io/BufferedOutputStream;

    new-instance v7, Ljava/io/FileOutputStream;

    new-instance v8, Ljava/lang/StringBuilder;

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

    const-string v9, "/mnt/sdcard/www/"

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

    move-result-object v8

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

    move-result-object v4

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

    move-result-object v4

    invoke-direct {v7, v4}, Ljava/io/FileOutputStream;-><init>(Ljava/lang/String;)V

    invoke-direct {v6, v7}, Ljava/io/BufferedOutputStream;-><init>(Ljava/io/OutputStream;)V

    .line 20
    const/16 v4, 0x400

    new-array v4, v4, [B

    .line 23
    :goto_4d
    invoke-virtual {v5, v4}, Ljava/io/InputStream;->read([B)I

    move-result v7

    const/4 v8, -0x1

    if-eq v7, v8, :cond_58

    .line 24
    invoke-virtual {v6, v4, v1, v7}, Ljava/io/OutputStream;->write([BII)V

    goto :goto_4d

    .line 27
    :cond_58
    invoke-virtual {v6}, Ljava/io/OutputStream;->flush()V

    .line 28
    invoke-virtual {v6}, Ljava/io/OutputStream;->close()V

    .line 29
    invoke-virtual {v5}, Ljava/io/InputStream;->close()V

    .line 16
    add-int/lit8 v0, v0, 0x1

    goto :goto_d

    .line 34
    :cond_64
    return-void
.end method

Here's a helpful alias for tying this all together:

function func_java2smali() {
  if [ -z "${1}" ]; then
    echo "usage: java2smali <java file>"
    return
  fi

  filename=$(basename $1 .java)
  outDir=$(shasum $1 | awk '{print $1}')

  javac -cp ~/android/sdk/platforms/android-18/android.jar $1
  dx --dex --no-strict --output=$filename.dex $filename.class
  baksmali --sequential-labels --use-locals $filename.dex -o $outDir

  cp -R $outDir/**/*.smali .

  rm -r $outDir
  rm $filename.class
  rm $filename.dex
}
alias java2smali=func_java2smali

Outras dicas

Wouldn't it be easier to compile your own application with this code and decompile it to retrieve the smali code?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top