-4

我在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;
}

它工作得很好......但我需要将它重写为smali / dex,所以我可以将它编译成反编译的应用程序(通过apktool)......甚至可能吗?有人可以帮我吗?

4

2 回答 2

2

将 Java 翻译成 Smali 是:

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

如果您还没有,请下载Android SDK

来自 Eclipse

由于您的代码调用this.getAssets(),它需要在 Activity 类中。如果您还没有 Eclipse 设置来构建 Android 项目,您应该从这里开始:设置 ADT 包。设置完成后,创建一个新的 Android 项目。然后,将此代码添加到主活动中的方法中。像这样的东西:

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;
    }
}

然后,将项目导出到 APK。最后,baksmali APK 获取您的 Smali。必须将其添加到 Activity 类,或者可以访问this.getResources(). Smali 看起来像:

.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

前期工作量很大,但是一旦完成或已经安装了 Eclipse 就很容易了。

从命令行

首先,重构代码,使其可以作为静态方法独立存在。它需要一个上下文参数,才能访问getAssets(). 使用与类名相同的文件名保存它。在这种情况下,CopyAssets.java。代码如下所示:

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;
        }
    }
}

其次,确保您已经下载了带有 SDK 的 Android 平台。在这种情况下,我将 Android-18 下载到 ~/android/sdk/platforms。编译命令是:

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

然后,您将拥有一个 CopyAssets.class。使用以下命令将其转换为 Dex:

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

--no-strict告诉dx不要担心文件结构。

最后,使用 baksmali 将 Dex 文件转换为 Smali:

baksmali copyassets.dex

您将使用可以轻松添加的静态方法获得 Smali。必须通过首先获取上下文来调用它Activity.getBaseContext()。你会得到这个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

这是一个有用的别名,可以将这一切联系在一起:

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
于 2014-05-02T18:38:27.053 回答
1

用这段代码编译你自己的应用程序并反编译它以检索 smali 代码不是更容易吗?

于 2014-03-17T14:43:50.407 回答