本文章首发于i春秋
请学好smali代码,对之后的学习有很大的帮助,当然也在这里等待你们回来复习
很多人都问学逆向需不需要有编程基础?需要是需要一点吧,只要最基础的就可以了。当然建议在学逆向的时候一起学习编程。
0x00 前言
1.建议食用者
1.想要学习Android逆向的小白,但是没有思路的。
2.入门了Android逆向觉得根基不稳的。
2.说明
由浅到深学习smali,强化分析能力。
另外,请参考HAI_手册,里面有之前总结的文章,还有一些练习题目,还有一些收集的文章。
3.内容说明
语言都是从HelloWorld的开始的,smali当然这样也可以这样学。所以我们就从HelloWorld开始学习。
4.内容安排
1.HelloWorld(开胃菜)
从一个helloworld,让你摆脱jd-gui。
2.smali与类(主菜)
从java类的呈现形式与smali类的呈现形式对比,从根本了解二者的关系。
3.smali改写一个类(饭后甜点)
通过用smali编写程序,更容易理解到smali代码的编写方法,从模仿开始,到轻车熟路。
4.小玩具(连载)
一个python写的小玩具,有兴趣可以当做一个练习。
0x01 HelloWorld
1.java编写HelloWord
package smali;
public class Hello {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
然后运行。
好了,这个就是我们的java代码,难度为0。
2.smali 的HelloWorld
生成一个dex文件,然后进行反编译,就会变成了smali代码了。
.class public LHello;
.super Ljava/lang/Object;
.source "Hello.java"
# direct methods
.method public constructor <init>()V
.registers 1
.prologue
.line 2
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
.method public static main([Ljava/lang/String;)V
.registers 3
.prologue
.line 6
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "HelloWorld"
invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 7
return-void
.end method
3.smali分析
3.1 画块分析
主要我们把smali代码分成3块。
第一块就是信息说明部分。我直接在图中标明信息。
第二块就是init块。
也就是构造方法块,这里的是java虚拟机自己添加了一个默认的构造方法。
第三块是方法块,也就是说不管是main方法还是其他的方法都会在这一块里平行列出来。
3.2 单句分析
这次我们主要看main函数。
也就是这一块
.method public static main([Ljava/lang/String;)V
.registers 3
.prologue
.line 6
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "HelloWorld"
invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 7
return-void
.end method
.registers 3
,可以使用的寄存器个数,v0,v1,v2。
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
,简单来说就是 v0=System.out
const-string v1, "HelloWorld"
,v1=”HelloWorld”
invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
,把v0,和v1,当参数传进去。相当于是println(v0,v1)
;,也就是println(System.out,"HelloWorld");
普遍helloworld是最简单的,当然也是必须要走的过程。
0x02 smali与类
该上我们的主菜了。
类,很简单的东西,我们主要包含两个内容,属性和方法。
1.java类
我们来写一个简单的类,一个属性,两个方法。
如果觉得有点困难的话。
请戳这里。
public class Person{
private String name;
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
}
2.smali类
这个就是smali类。
是不是感觉比Helloworld多一块。
# instance fields
.field private name:Ljava/lang/String;
这里多了一个属性定义的部分。
那我们就从属性定义这里开始吧。
.field
,这个就是属性的标志。 private
私有的,name
,名字,Ljava/lang/String
,String类型的变量。
和java恰恰相反,smali是先写出名字,在最后带上类型,java就是先类型后名字。
构造方法没有变。
我们来看看写的两个封装方法。
.registers 2
,两个寄存器,v0,v1。
iget-object v0, p0, LPerson;->name:Ljava/lang/String
,这里p0的意思是第一个传入的参数。这里就好奇了,明明java里没有参数,为什么这里会有呢。在虚拟机里,this就算是一个参数,所以这里才会是p0。iget-object v0,把p0的内容给v0。get,应该很好理解。
LPerson;->name:Ljava/lang/String`,这里就是对p0做一个解释。
iput-object p1, p0, LPerson;->name:Ljava/lang/String;
核心的代码就是这一句。iput-object p1,p0,就是把p1的内容给p0。put,给,get拿到,刚好和之前的那个相反。这里的p1就是传入的参数。p0就是this。
分析透了其实很好理解。
0x03 smali改写一个类
这里算是一个小练习吧。
题目:
用smali代码为之前的Person类添加一个age属性,然后写出get,set方法。
建议自己写完了之后,来进行对照。
解:
首先第一步,添加属性。
第二步,添加setAge方法。
第三步,添加getAge方法。
最后一步,大功告成
最后源码:
.class public LPerson;
.super Ljava/lang/Object;
.source "Person.java"
# instance fields
.field private name:Ljava/lang/String;
.field private age:Ljava/lang/int;
# direct methods
.method public constructor <init>()V
.registers 1
.prologue
.line 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public getName()Ljava/lang/String;
.registers 2
.prologue
.line 10
iget-object v0, p0, LPerson;->name:Ljava/lang/String;
return-object v0
.end method
.method public setName(Ljava/lang/String;)V
.registers 2
.prologue
.line 6
iput-object p1, p0, LPerson;->name:Ljava/lang/String;
.line 7
return-void
.end method
.method public setAge(Ljava/lang/int;)V
.registers 2
.prologue
iput-object p1,p0,LPerson;->age:Ljava/lang/int;
return-void
.end method
.method public getAge()Ljava/lang/int;
.registers 2
.prologue
iget-object v0,p0,LPerson;->age:Ljava/lang/int;
return-object v0
.end method
0x04 一个小玩具
一个python小玩具。
用途:
自动分析smali代码内容。
涉及知识点:
1.sys
2.while
3.str…split
4.if,elif
使用方法:
smali代码放在txt文件中。
简要说明:
暂时只对开始的一块进行分析。
第一个部分,读取txt内容。
然后进行判断字段。
.class字段
.super字段
.source字段