smali 逆向金山快盘的一个accout的文件安。此帖子只是要证明smali是可以读懂的。只要花点功夫
关于android逆向工程 smali Davlik 语法,很多写jni的同学都不陌生(Landroid/content/BroadcastReceiver对象)
简介:
原始类型:v void 只能用于返回值类型
Z boolean
B byte
S short
C char
I int
J long(64位)
F float
D double(64位)
对象类型:Lpackage/name/ObjectName; 相当于java中的package.name.ObjectName;解释如下:
L:表示这是一个对象类型
package/name:该对象所在的包
;:表示对象名称的结束
.class publicLcn/kuaipan/android/account/AuthExpiredReceiver;
.super Landroid/content/BroadcastReceiver;
( public classAuthExpiredReceiver extends BroadcastReceiver )
# direct methods
.method public constructor <init>()V
.locals 0
invoke-direct {p0},Landroid/content/BroadcastReceiver;-><init>()V
return-void
.end method
(public AuthExpiredReceiver(){}:表示该类的不带参数缺省的构造方法)
//下面按行解毒smali的编译代码
/*
有两种方式指定一个方法中有多少寄存器是可用的:.registers指令指定了方法中寄存器的总数.locals指令表明了方法中非参寄存器的总数,出现在方法中的第一行
方法的传参:当一个方法被调用的时候,方法的参数被置于最后N个寄存器中;例如,一个方法有2个参数,5个寄存器(v0~v4)那么,参数将置于最后2个寄存器(v3和v4)非静态方法中的第一个参数总是调用该方法的对象;说明:对于静态方法除了没有隐含的this参数外,其他都一样
寄存器的命名方式:V命名P命名第一个寄存器就是方法中的第一个参数寄存器比较:使用P命名是为了防止以后如果在方法中增加寄存器,需要对参数寄存器重新进行编号的缺点特别说明一下:Long和Double类型是64位的,需要2个寄存器例如:对于非静态方法LMyObject—— > myMethod(IJZ) V;有4个参数:LMyObject,
int,
long,
bool;
需要5个寄存器来存储参数;P0 this P1 I(int) P2,P3 J(long) P4 Z(bool)
*/
# virtual methods
// public voidonReceive(Context context, Intent intent)
.method publiconReceive(Landroid/content/Context;Landroid/content/Intent;)V
//locals指令表明了方法中非参寄存器的数量,4个stack
.locals 4
//第一个参数 v3
const v3,0x7f0800b6
//第二个参数
const/4 v2, 0x1
//静态调用
invoke-static {p1}, Lcn/kuaipan/android/service/ConfigFactory;->getConfig(Landroid/content/Context;)Lcn/kuaipan/android/service/Config;
//获取结果保存v0
move-result-object v0
//解释上面代码
(cn.kuaipan.android.service.Config v0= ConfigFactory. getConfig (context) )
const-string v1, "AUTH_FAILED"
invoke-virtual {v0, v1},Lcn/kuaipan/android/service/Config;->getAction(Ljava/lang/String;)Ljava/lang/String;
move-result-object v0
(final string v0 = v2.getAction( v1 );)
invoke-virtual {p2},Landroid/content/Intent;->getAction()Ljava/lang/String;
( 调用p2 intent.getAction()方法)
move-result-object v1
(返回结果给变量v1 )
invoke-virtual{v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
(v0.equals(v1) == v2.getAction( v1 ).equals( intent.getAction() ))
获取结果 v0
move-result v0
如果 v0 不等于v1 ,结束 return
if-nez v0, :cond_0
/*
if(!vo.equals(intent.getAction())) {
return;
}
*/
:goto_0
return-void
:cond_0
invoke-static {},Lcn/kuaipan/android/KuaipanApplication;->a()Lcn/kuaipan/android/KuaipanApplication;
move-result-object v0
invoke-virtual {v0}, Lcn/kuaipan/android/KuaipanApplication;->d()V
const/16 v0, 0x3ed
invoke-static {p1, v0},Lcn/kuaipan/android/notification/a;->a(Landroid/content/Context;I)V
(静态调用 KuaipanApplication.a() return Lcn/kuaipan/android/KuaipanApplication可以看出是一个单列 通过 v0 当前栈调用 d method ,然后 Lcn/kuaipan/android/notification/a的 a方法( context , int ) 可以看出来是一个窗口调用这里认为是 Notification )
new-instance v0, Landroid/content/Intent;
const-class v1, Lcn/kuaipan/android/home/LogoActivity;
invoke-direct {v0, p1, v1},Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
const-string v1, "LogoActivity.skip_logo"
invoke-virtual {v0, v1, v2},Landroid/content/Intent;->putExtra(Ljava/lang/String;Z)Landroid/content/Intent;
const-string v1, "goto_login"
invoke-virtual {v0, v1, v2},Landroid/content/Intent;->putExtra(Ljava/lang/String;Z)Landroid/content/Intent;
const/high16 v1, 0x1000
invoke-virtual {v0, v1}, Landroid/content/Intent;->setFlags(I)Landroid/content/Intent;
invoke-static {p1},Lcn/kuaipan/android/utils/l;->d(Landroid/content/Context;)Z
move-result v1
(
Intent vo = newIntent(Landroid/content/Context, LogoActivity.skip_logo);
vo.putExtra(Ljava/lang/String, Bool);
vo.putExtra(Ljava/lang/String, Bool);
vo.setFlags(Int);
Lcn/kuaipan/android/utils/l.d(Landroid/content/Context;)return bool;
)
//if 不等于 v1也就是 Lcn/kuaipan/android/utils/l.d(Landroid/content/Context;)dao cond_1
if-eqz v1, :cond_1
invoke-static {p1, v3, v2},Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
move-result-object v1
invoke-virtual {v1}, Landroid/widget/Toast;->show()V
const/high16 v1, 0x400
invoke-virtual {v0, v1},Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;
invoke-virtual {p1, v0},Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
goto :goto_0
:cond_1
const-string v1, "android.intent.action.MAIN"
invoke-virtual {v0, v1},Landroid/content/Intent;->setAction(Ljava/lang/String;)Landroid/content/Intent;
const-string v1, "android.intent.category.LAUNCHER"
invoke-virtual {v0, v1},Landroid/content/Intent;->addCategory(Ljava/lang/String;)Landroid/content/Intent;
const/4 v1, 0x0
const/high16 v2, 0x4000
invoke-static{p1, v1, v0, v2},Landroid/app/PendingIntent;->getActivity(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;
move-result-object v0
new-instance v1, Lcn/kuaipan/android/notification/a;
invoke-direct {v1, p1, v3},Lcn/kuaipan/android/notification/a;-><init>(Landroid/content/Context;I)V
invoke-virtual {v1, v0},Lcn/kuaipan/android/notification/a;->a(Landroid/app/PendingIntent;)Lcn/kuaipan/android/notification/a;
move-result-object v0
const/16 v1, 0x3e9
invoke-virtual {v0, v1},Lcn/kuaipan/android/notification/a;->c(I)Lcn/kuaipan/android/notification/a;
goto :goto_0
.end method
if (Lcn/kuaipan/android/utils/l.d(Landroid/content/Context;)) {
Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast) .show();
i.addFlags(l);
Landroid/content/Context.startActivity(Landroid/content/Intent;)V
} else {
Landroid/content/Intent;->setAction(Ljava/lang/String;)Landroid/content/Intent;
Landroid/content/Intent;->addCategory(Ljava/lang/String;)Landroid/content/Intent;
P…….
}
总结:需要对照此类里包含的L文件才能完全还原。混淆方法大概意思根据编码的流程大致能拆出来。还原个80%左右应该不是问题,问题是时间上是否允许,结合class。JAR文件还能解析出传递的参数。Jar里是int对应的R里的值String的值最终都是int类型
public class AuthExpiredReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Config xxx = ConfigFactory.getConfig(context);
final String xxx 1= xxx.getAction(IAccountServiceDef.ACTION_POSTFIX_AUTH_FAILED);
if (!xxx1.equals(intent.getAction())) {
return;
}
Lcn/kuaipan/android/KuaipanApplication.getInstance().d();
Lcn/kuaipan/android/notification/.a(Landroid/content/Context;I)V
Intent vo = new Intent(Landroid/content/Context, LogoActivity.skip_logo);
vo.putExtra(Ljava/lang/String, Bool);
vo.putExtra(Ljava/lang/String, Bool);
vo.setFlags(Int);
if (Lcn/kuaipan/android/utils/l.d(Landroid/content/Context;) ) {
Landroid/widget/Toast.makeText(Landroid/content/Context;II).show();
i.addFlags(l);
Landroid/content/Context.startActivity(Landroid/content/Intent;)
} else {
Landroid/content/Intent.setAction(Ljava/lang/String;);
Landroid/content/Intent.addCategory(Ljava/lang/String;);
P…….
}
}
}
配上一个 学习的网址 http://blog.youkuaiyun.com/caszhao/article/details/6028874