首先在Eclipse中新建一个工程,默认是HelloWorld。将bin目录下的helloworld.apk拷贝出来,然后使用命令解包:
apktool d hello.apk
参考《Android软件安全与逆向分析》,其中的代码是写在一个函数中的,这里我边写边重构了一下,拆分成两个函数:
.class public Lcom/alipay/helloworld/MainActivity;
.super Landroid/app/Activity;
.source "MainActivity.java"
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 6
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
return-void
.end method
# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
.locals 3
.parameter "savedInstanceState"
.prologue
.line 10
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
.line 11
const/high16 v0, 0x7f03
invoke-virtual {p0, v0}, Lcom/alipay/helloworld/MainActivity;->setContentView(I)V
#invoke-virtual {p0}, Lcom/alipay/helloworld/MainActivity;->getRunningListString()Ljava/lang/String;
#move-result-object v1
new-instance v1, Ljava/lang/StringBuilder;
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
const-string v2, "hello,android reverse!"
.local v2, msg:Ljava/lang/String;
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invoke-virtual {v1} , Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {p0, v1}, Lcom/alipay/helloworld/MainActivity;->showToastMessage(Ljava/lang/String;)V
invoke-virtual {p0}, Lcom/alipay/helloworld/MainActivity;->getRunningListString()Ljava/lang/String;
move-result-object v1
invoke-virtual {p0, v1}, Lcom/alipay/helloworld/MainActivity;->showToastMessage(Ljava/lang/String;)V
.line 12
return-void
.end method
.method public showToastMessage(Ljava/lang/String;)V
.locals 1
const/4 v0, 0x01
invoke-static {p0, p1, 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
return-void
.end method
.method public getRunningListString()Ljava/lang/String;
.locals 6
# get the object of ActivityManager
const-string v0, "activity"
invoke-virtual {p0, v0}, Landroid/app/Activity;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
move-result-object v1
check-cast v1, Landroid/app/ActivityManager;
.local v1, activityManager:Landroid/app/ActivityManager;
# inistantiate a string buffer to save string
new-instance v0, Ljava/lang/StringBuilder;
invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V
.local v0, results:Ljava/lang/StringBuilder;
# retrive the running app list
invoke-virtual {v1}, Landroid/app/ActivityManager;->getRunningAppProcesses()Ljava/util/List;
move-result-object v5
.local v5, psInfos:Ljava/util/List;, "Ljava/util/List<Landroid/app/ActivityManager$RunningAppProcessInfo;>;"
# travel the process list to get all the name of the running process
invoke-interface {v5}, Ljava/util/List;->iterator()Ljava/util/Iterator;
move-result-object v2
:goto_list_not_empty
invoke-interface {v2}, Ljava/util/Iterator;->hasNext()Z
move-result v3
if-eqz v3, :goto_end
invoke-interface {v2}, Ljava/util/Iterator;->next()Ljava/lang/Object;
move-result-object v3
check-cast v3, Landroid/app/ActivityManager$RunningAppProcessInfo;
.local v3, info:Landroid/app/ActivityManager$RunningAppProcessInfo;
iget-object v4, v3, Landroid/app/ActivityManager$RunningAppProcessInfo;->processName:Ljava/lang/String;
invoke-static {v4}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v4
invoke-virtual {v0, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
const-string v4, "\n"
invoke-virtual {v0, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
goto : goto_list_not_empty
:goto_end
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
return-object v0
.end method
重新打包并签名:
apktool b HelloWorld.apk hello.apk
在编写程序的时候两处地方出现了错误:
1. .locals指令用来设置当前函数使用的非参数寄存器个数,当时代码中使用了3个寄存器,结果我设置了.locals 2,于是程序在运行的时候抛出了java.lang.VerifyError异常。
2. 要区分invoke-interface、invoke-virtual、invoke-direct之间的区别。在使用的时候,好像invoke-direct就用来调用一下构造函数就可以,其余成员函数用invoke-virtual来调用,而对于一个接口类型,才使用invoke-interface.
下面是运行效果: