smali / dex - 将目录从资产复制到SD卡

时间:2014-03-17 14:39:43

标签: android smali

我在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)......它甚至可能吗?有人可以帮我吗?

2 个答案:

答案 0 :(得分:2)

将Java翻译成Smali是:

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

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

来自Eclipse

由于您的代码调用this.getAssets(),因此它需要位于Activity类中。如果您还没有Eclipse设置来构建Android项目,那么您应该从这里开始:Setting up the ADT Bundle。设置完成后,创建一个新的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

答案 1 :(得分:1)

使用此代码编译自己的应用程序并对其进行反编译以检索smali代码会不会更容易?