前言
正式开始android逆向之旅,首先说一下Smali语言其实就是Davlik的寄存器语言.
语法
"#"号在smali语法中代表 注释
解析一段smali来进行实践
首先是整个activity的java代码
/**
* A login screen that offers login via email/password.
*/
public class LoginActivity extends AppCompatActivity {
private EditText mPasswordView;
private EditText email;
private View email_sign_in_button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
email = (EditText) findViewById(R.id.email);
mPasswordView = (EditText) findViewById(R.id.password);
email_sign_in_button = findViewById(R.id.email_sign_in_button);
email_sign_in_button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (email.getText().toString().equals(mPasswordView.getText().toString())) {
Toast.makeText(LoginActivity.this, R.string.title_activity_login, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(LoginActivity.this, R.string.error_incorrect_password, Toast.LENGTH_LONG).show();
}
}
});
}
}
其onClick
事件对应的smali
# virtual methods
.method public onClick(Landroid/view/View;)V
.locals 3
.param p1, "v" # Landroid/view/View;
.prologue
const/4 v2, 0x1
.line 58
iget-object v0, p0, Lcom/example/renzhendong/testtool/LoginActivity$1;->this$0:Lcom/example/renzhendong/testtool/LoginActivity;
# getter for: Lcom/example/renzhendong/testtool/LoginActivity;->email:Landroid/widget/EditText;
invoke-static {v0}, Lcom/example/renzhendong/testtool/LoginActivity;->access$100(Lcom/example/renzhendong/testtool/LoginActivity;)Landroid/widget/EditText;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String;
move-result-object v0
iget-object v1, p0, Lcom/example/renzhendong/testtool/LoginActivity$1;->this$0:Lcom/example/renzhendong/testtool/LoginActivity;
# getter for: Lcom/example/renzhendong/testtool/LoginActivity;->mPasswordView:Landroid/widget/EditText;
invoke-static {v1}, Lcom/example/renzhendong/testtool/LoginActivity;->access$000(Lcom/example/renzhendong/testtool/LoginActivity;)Landroid/widget/EditText;
move-result-object v1
invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v0
if-eqz v0, :cond_0
.line 59
iget-object v0, p0, Lcom/example/renzhendong/testtool/LoginActivity$1;->this$0:Lcom/example/renzhendong/testtool/LoginActivity;
const v1, 0x7f070033
invoke-static {v0, v1, v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
.line 63
:goto_0
return-void
.line 61
:cond_0
iget-object v0, p0, Lcom/example/renzhendong/testtool/LoginActivity$1;->this$0:Lcom/example/renzhendong/testtool/LoginActivity;
const v1, 0x7f070028
invoke-static {v0, v1, v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
goto :goto_0
.end method
由此可以看出来java代码十几行,其所对应的smali是非常之长的.
接下来进行分段分析
.method public onClick(Landroid/view/View;)V
.........
return-void
.end method
这段就是方法的开始,以及结束的表示
.method
指令,标示方法的开始. .end method
指令,标示方法的结束.
return-void
指令,就是java方法中的 return
.
.line 58
iget-object v0, p0, Lcom/example/renzhendong/testtool/LoginActivity$1;->this$0:Lcom/example/renzhendong/testtool/LoginActivity;
# getter for: Lcom/example/renzhendong/testtool/LoginActivity;-> email:Landroid/widget/EditText;
invoke-static {v0}, Lcom/example/renzhendong/testtool/LoginActivity;->access$100(Lcom/example/renzhendong/testtool/LoginActivity;)Landroid/widget/EditText;
move-result-object v0
咱们逐个分析:
iget-object v0
指令,通过了解可知,在当前位置标示为 获取LoginActivity
的实例对象,并赋值给v0
.
invoke-static {v0}
指令 和move-result-object v0
指令是配套出现的。
invoke-static {v0}
表示调用v0
寄存器中的实例中的方法.
move-result-object v0
表示方法调用的返回值,并赋值到 v0
寄存器.
了解了这些就可以看出来这段指令的意思为:
获取
LoginActivity
的实例对象,调用Activity
中的方法access$100
(本人猜测应该是findViewById
),从而得到move-result-object v0
返回,并存入v0
寄存器.
知道了invoke-static {v0}
指令 和move-result-object v0
指令所代表的意思,下面的方法调用就不必过多解释了.
invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v0
if-eqz v0, :cond_0
这段指令中有一个陌生的指令if-eqz
.它是一个比较指令,如果 目标寄存器的值为0,则跳转到cond_0
处.否则顺序往下执行.
跳转到cond_0
处的指令 如下:
.line 61
:cond_0
iget-object v0, p0, Lcom/example/renzhendong/testtool/LoginActivity$1;->this$0:Lcom/example/renzhendong/testtool/LoginActivity;
const v1, 0x7f070028
invoke-static {v0, v1, v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
goto :goto_0
goto
指令,跳转指令,后面跟要跳转的地方.
给v1
寄存器传入字符串id
.
调用android中的Tosat
方法,对v1
寄存器中的字符串进行吐司,并执行goto
指令,跳转到goto_0
.
顺序执行的指令如下:
.line 59
iget-object v0, p0, Lcom/example/renzhendong/testtool/LoginActivity$1;->this$0:Lcom/example/renzhendong/testtool/LoginActivity;
const v1, 0x7f070033
invoke-static {v0, v1, v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
.line 63
:goto_0
return-void
同上.
无论是顺序执行,还是跳转cond_0
最后都会执行goto_0
处的return-void
退出方法.
总结
到这里基本上smali语法就大致能看懂了,接下来就是进行深入的了解和学习了.