0x00前言
不知所以然,请看
Android逆向-Android基础逆向(1)
Android逆向-Android基础逆向(2)
Android逆向-Android基础逆向(2-2)
Android逆向-Android基础逆向(2-3补充篇)
Android逆向-Android基础逆向(3)
以及java系列:
Android逆向-java代码基础(1)
Android逆向-java代码基础(2)
Android逆向-java代码基础(3)
Android逆向-java代码基础(4)
Android逆向-java代码基础(5)
Android逆向-java代码基础(6)
Android逆向-java代码基础(7)
Android逆向-java代码基础(8)
内容
(1)Android 布局创建
(2)Android布局反编译
(3)反编译改变布局
(4)小工具制作
环境:
Android studio
Android killer
python
夜神模拟器
开始时间
2018年2月1日18:18:27
0x01 Android布局
1.demo
这里默认有Android开发基础,如果没有,恩。。。那我也没办法。
做一下简要的说明。
整个demo包括一个按钮,一个输入框,一个显示框。然后一个简单的逻辑。
1.1 涉及知识点
1.LinearLayout 布局
2.Button
3.TextView
4.EditText
5.监听事件
1.2 布局书写
1.2.1 更改整体布局
整体布局改成LinearLayout。
然后布局流程改成竖行。
1.2.2 添加控件
(1)EditText
(2)TextView
(3)Button
(4)代码详解
android:layout_width="wrap_content"
android:layout_height="wrap_content"
控制控件的长宽,可以使用像素单位,个人喜欢使用dp。
wrap_content的含义就是自适应,有多少就多大。
android:id="@+id/out"
这句话就是控件的name,控件的唯一标识。
1.3 布局引用
1.3.1 调用整体布局
这句代码通过Android R引用资源。也就是调用了activity_main这个名字的布局文件。等下我们看反编译后的东西。
1.3.2 定义对象
类似于int i;
1.3.3 通过id绑定控件
通过findViewById来绑定控件。
1.4 按钮监听
使用View.OnClickListener() 来写一个监听事件,因为只有一个按钮所以使用这种方式,如果以后有多个触发逻辑的话,就会使用其他的方式。
1.5 逻辑书写
这里我只写了一句代码。
out.setText(in.getText().toString());
这句包含三个知识点。
getText(),获取控件文字
setText(),书写控件文字
.toString(),转化为String类型
1.6 结束语
1.6.1 源代码
最后直接贴上全部的代码
public class MainActivity extends AppCompatActivity {
private TextView out;
private EditText in;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Binding();
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
out.setText(in.getText().toString());
}
});
}
public void Binding()
{
out= (TextView) findViewById(R.id.out);
in= (EditText) findViewById(R.id.in);
btn= (Button) findViewById(R.id.bt);
}
}
1.6.2 调试
0x02 反编译demo
1.丢在Android killer里
2. 查看layout文件
这里我们发现和Android studio中没有什么差别。
我们更改这里的就可以了。
3. 更改Android layout
我们添加这样一行
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是反编译后的按钮" />
就是加了一个按钮。
4. 反编译,查看
这里我们发现界面可以进行更改,但是没有逻辑。接下来就是我们研究逻辑的时候了。
5. smali分析
5.1 smali主要代码
.class public Lcom/example/hanlei/first_demo/MainActivity;
.super Landroid/support/v7/app/AppCompatActivity;
.source "MainActivity.java"
# instance fields
.field private btn:Landroid/widget/Button;
.field private in:Landroid/widget/EditText;
.field private out:Landroid/widget/TextView;
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 14
invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V
return-void
.end method
.method static synthetic access$000(Lcom/example/hanlei/first_demo/MainActivity;)Landroid/widget/EditText;
.locals 1
.param p0, "x0" # Lcom/example/hanlei/first_demo/MainActivity;
.prologue
.line 14
iget-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->in:Landroid/widget/EditText;
return-object v0
.end method
.method static synthetic access$100(Lcom/example/hanlei/first_demo/MainActivity;)Landroid/widget/TextView;
.locals 1
.param p0, "x0" # Lcom/example/hanlei/first_demo/MainActivity;
.prologue
.line 14
iget-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->out:Landroid/widget/TextView;
return-object v0
.end method
# virtual methods
.method public Binding()V
.locals 1
.prologue
.line 32
const v0, 0x7f0b0058
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/TextView;
iput-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->out:Landroid/widget/TextView;
.line 33
const v0, 0x7f0b0057
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/EditText;
iput-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->in:Landroid/widget/EditText;
.line 34
const v0, 0x7f0b0059
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/Button;
iput-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->btn:Landroid/widget/Button;
.line 35
return-void
.end method
.method protected onCreate(Landroid/os/Bundle;)V
.locals 2
.param p1, "savedInstanceState" # Landroid/os/Bundle;
.prologue
.line 20
invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
.line 21
const v0, 0x7f04001b
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->setContentView(I)V
.line 22
invoke-virtual {p0}, Lcom/example/hanlei/first_demo/MainActivity;->Binding()V
.line 23
iget-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->btn:Landroid/widget/Button;
new-instance v1, Lcom/example/hanlei/first_demo/MainActivity$1;
invoke-direct {v1, p0}, Lcom/example/hanlei/first_demo/MainActivity$1;-><init>(Lcom/example/hanlei/first_demo/MainActivity;)V
invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
.line 29
return-void
.end method
5.2 第一部分
这个部分就是 定义了三个变量
5.3 第二部分
这个部分应该很熟悉,在java中常见。请看java系列。
5.4 第三部分
首先找到onCreate部分,onCreate相当于c语言里的main函数
.method protected onCreate(Landroid/os/Bundle;)V
.locals 2
.param p1, "savedInstanceState" # Landroid/os/Bundle;
.prologue
.line 20
invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
.line 21
const v0, 0x7f04001b
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->setContentView(I)V
.line 22
invoke-virtual {p0}, Lcom/example/hanlei/first_demo/MainActivity;->Binding()V
.line 23
iget-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->btn:Landroid/widget/Button;
new-instance v1, Lcom/example/hanlei/first_demo/MainActivity$1;
invoke-direct {v1, p0}, Lcom/example/hanlei/first_demo/MainActivity$1;-><init>(Lcom/example/hanlei/first_demo/MainActivity;)V
invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
.line 29
return-void
.end method
我们来一句一句进行分析:
1.第一句
invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
使用oncreate方法
2.第二句
const v0, 0x7f04001b
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->setContentView(I)V
这里可以看到调用了setContentView方法,然后引用了v0这段数字,这个数字就是资源索引号。通过这个找到资源。
3.第三句
.line 22
invoke-virtual {p0}, Lcom/example/hanlei/first_demo/MainActivity;->Binding()V
调用Binding()方法
这里我们就要分析一下Binding是什么了。
4. Binding()
# virtual methods
.method public Binding()V
.locals 1
.prologue
.line 32
const v0, 0x7f0b0058
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/TextView;
iput-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->out:Landroid/widget/TextView;
.line 33
const v0, 0x7f0b0057
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/EditText;
iput-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->in:Landroid/widget/EditText;
.line 34
const v0, 0x7f0b0059
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/Button;
iput-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->btn:Landroid/widget/Button;
.line 35
return-void
.end method
来看这个函数部分的最主要部分:
const v0, 0x7f0b0058
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/TextView;
iput-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->out:Landroid/widget/TextView;
定义资源号 v0。
来看下一句
invoke-virtual {p0, v0}, Lcom/example/hanlei/first_demo/MainActivity;->findViewById(I)Landroid/view/View;
这句就是调用findViewById,然后把v0放进去相当于findViewById(v0)
下一句
move-result-object v0
就是把上一句的结果放在v0中
然后下一句
check-cast v0, Landroid/widget/TextView;
这句之前没有见过,意思就是强制转换。强制转换为TextView类型
接来下的一句
iput-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->out:Landroid/widget/TextView;
简单的说就是给out赋值。
现在我们回到onCreate
5.第四句
iget-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity;->btn:Landroid/widget/Button;
相当与使用开始btn
6第五句
new-instance v1, Lcom/example/hanlei/first_demo/MainActivity$1;
实例化了一个Lcom/example/hanlei/first_demo/MainActivity$1;变量
7.第六句
invoke-direct {v1, p0}, Lcom/example/hanlei/first_demo/MainActivity$1;-><init>(Lcom/example/hanlei/first_demo/MainActivity;)V
调用了init。我们来看下init。int在MainActivity$1中。
8. MainActivity$1
首先来看代码:
.class Lcom/example/hanlei/first_demo/MainActivity$1;
.super Ljava/lang/Object;
.source "MainActivity.java"
# interfaces
.implements Landroid/view/View$OnClickListener;
# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
value = Lcom/example/hanlei/first_demo/MainActivity;->onCreate(Landroid/os/Bundle;)V
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x0
name = null
.end annotation
# instance fields
.field final synthetic this$0:Lcom/example/hanlei/first_demo/MainActivity;
# direct methods
.method constructor <init>(Lcom/example/hanlei/first_demo/MainActivity;)V
.locals 0
.param p1, "this$0" # Lcom/example/hanlei/first_demo/MainActivity;
.prologue
.line 23
iput-object p1, p0, Lcom/example/hanlei/first_demo/MainActivity$1;->this$0:Lcom/example/hanlei/first_demo/MainActivity;
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public onClick(Landroid/view/View;)V
.locals 2
.param p1, "v" # Landroid/view/View;
.prologue
.line 26
iget-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity$1;->this$0:Lcom/example/hanlei/first_demo/MainActivity;
# getter for: Lcom/example/hanlei/first_demo/MainActivity;->out:Landroid/widget/TextView;
invoke-static {v0}, Lcom/example/hanlei/first_demo/MainActivity;->access$100(Lcom/example/hanlei/first_demo/MainActivity;)Landroid/widget/TextView;
move-result-object v0
iget-object v1, p0, Lcom/example/hanlei/first_demo/MainActivity$1;->this$0:Lcom/example/hanlei/first_demo/MainActivity;
# getter for: Lcom/example/hanlei/first_demo/MainActivity;->in:Landroid/widget/EditText;
invoke-static {v1}, Lcom/example/hanlei/first_demo/MainActivity;->access$000(Lcom/example/hanlei/first_demo/MainActivity;)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}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
.line 27
return-void
.end method
来看onClick部分
先来看看这三句。
iget-object v0, p0, Lcom/example/hanlei/first_demo/MainActivity$1;->this$0:Lcom/example/hanlei/first_demo/MainActivity;
# getter for: Lcom/example/hanlei/first_demo/MainActivity;->out:Landroid/widget/TextView;
invoke-static {v0}, Lcom/example/hanlei/first_demo/MainActivity;->access$100(Lcom/example/hanlei/first_demo/MainActivity;)Landroid/widget/TextView;
move-result-object v0
这三句在做一件事情就是用先实例化,然后把这个东西放在v0里,就是可以使用v0代替以上。
接着来看
invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
move-result-object v1
调用getText()
invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String;
调用toString()
invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
调用 setText
6.结束语
以上就是简单的smali分析,当然我们的目的不只是为了分析而已。我们还要进行一个改进才可以。还有一个目的就是可以为我们添加的控件增加一个简单的逻辑。
0x03 结尾
由于篇幅问题,其他的内容将在Android逆向-Android基础逆向(4-2)中进行剩余说明。
遗留内容
1.反编译增加一个Button,然后写一段自己的逻辑。
2.制作一个工具,辅助反编译。
收获
1.复习了Android界面编程
2.复习了Android监听事件的书写
3.反编译了一段代码,知道了smali流程
以上