需要将特定的smali代码插入到dex文件中起到特殊作用,但是对于smali语法一知半解,这次来总结一下,并介绍如何使用工具来讲smali代码插入dex文件中。
可以使用IDEA或者Android Studio的Java2Smali
插件来查看smali代码。
源码:
smali代码:
其中#
后面为注释
基本类型的表示很简单,int 用 I
表示即可。对象的表示,顶级父类 Object 的表示方法 Ljava/lang/Object;
,再比如 String 类型,就用 Ljava/lang/String
表示。
对于数组,DalviK 有特殊的表示方法 [
后面跟上数组元素的类型。int[]
的表示方式就是 [I
, String[]
的表示方法是 [Ljava/lang/String;
。二维数组用 [[
表示,[[Ljava/lang/String
就是指 String[][]
,以此类推。
github地址:https://github.com/JesusFreke/smali/tree/master/dexlib2/
下载地址:https://bitbucket.org/JesusFreke/smali/downloads/
dexlib2工具可以修改dex文件内容,你可以插入想要的代码或者重写一个dex文件。当然一些反编译apk的工具也引用了该工具,比如apktool。
我们可以通过 DexFileFactory 类来创建一个 DexBackedDexFile实例
一个 DexBackedDexFile 实例代表一个dex文件,通过 DexBackedDexFile 我们可以访问到所有Class
ClassDef 代表一个类,我们可以通过 DexBackedDexFile 实例来获取一个类,也可以自行创建一个类.
上面我们修改了 isFromNativeSDK 方法使其返回true,这里有关于寄存器的知识:
当一个方法被调用的时候,方法的参数被置于最后N个寄存器中。如果一个方法有2个参数,5个寄存器(v0-v4),那么参数将置于最后2个寄存器——v3和v4。 非静态方法中的第一个参数总是调用该方法的对象。
这里指定了一个寄存器,就是第一个参数this——代表EntranceActivity实例。
修改后的smali代码:
寄存器都是32位的,能够支持任何类型。64位类型(Long和Double型)用2个寄存器表示。 有两种方式指定一个方法中有多少寄存器是可用的。.registers指令指定了方法中寄存器的总数。.locals指令表明了方法中非参寄存器的数量。
MethodWrapper 类的定义:
smali就相当于汇编一样,是比较底层的语言。研究它无非是对于安卓逆向或者事安卓加固有些许帮助,并可以通过修改dex文件来获得一些特殊功能。另外,研究它也可以增加自己反编译的知识,毕竟翻译这个还是很需要时间的,一些巨人已经将自己的成果发出来供大家使用,我们只是站在巨人的肩膀上。天下没有绝对的安全。
package cn.soulapp;
import
android.os.Bundle;
import
androidx.annotation.Nullable;
import
androidx.appcompat.app.AppCompatActivity;
import
com.example.souldemo.R;
public
class
MainAcitivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
package cn.soulapp;
import
android.os.Bundle;
import
androidx.annotation.Nullable;
import
androidx.appcompat.app.AppCompatActivity;
import
com.example.souldemo.R;
public
class
MainAcitivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
.
class
public Lcn
/
soulapp
/
MainAcitivity;
.
super
Landroidx
/
appcompat
/
app
/
AppCompatActivity;
.source
"MainAcitivity.java"
.method public constructor <init>()V
.registers
1
.prologue
.line
10
invoke
-
direct {p0}, Landroidx
/
appcompat
/
app
/
AppCompatActivity;
-
><init>()V
return
-
void
.end method
.method protected onCreate(Landroid
/
os
/
Bundle;)V
.registers
3
.param p1,
"savedInstanceState"
.annotation build Landroidx
/
annotation
/
Nullable;
.end annotation
.end param
.prologue
.line
13
invoke
-
super
{p0, p1}, Landroidx
/
appcompat
/
app
/
AppCompatActivity;
-
>onCreate(Landroid
/
os
/
Bundle;)V
.line
14
const v0,
0x7f0a001c
invoke
-
virtual {p0, v0}, Lcn
/
soulapp
/
MainAcitivity;
-
>setContentView(I)V
.line
15
return
-
void
.end method
.
class
public Lcn
/
soulapp
/
MainAcitivity;
.
super
Landroidx
/
appcompat
/
app
/
AppCompatActivity;
.source
"MainAcitivity.java"
.method public constructor <init>()V
.registers
1
.prologue
.line
10
invoke
-
direct {p0}, Landroidx
/
appcompat
/
app
/
AppCompatActivity;
-
><init>()V
return
-
void
.end method
.method protected onCreate(Landroid
/
os
/
Bundle;)V
.registers
3
.param p1,
"savedInstanceState"
.annotation build Landroidx
/
annotation
/
Nullable;
.end annotation
.end param
.prologue
.line
13
invoke
-
super
{p0, p1}, Landroidx
/
appcompat
/
app
/
AppCompatActivity;
-
>onCreate(Landroid
/
os
/
Bundle;)V
.line
14
const v0,
0x7f0a001c
invoke
-
virtual {p0, v0}, Lcn
/
soulapp
/
MainAcitivity;
-
>setContentView(I)V
.line
15
return
-
void
.end method
val dexBackedDexFile
=
DexFileFactory.loadDexFile(
File
(
"classes.dex"
), Opcodes.getDefault())
val dexBackedDexFile
=
DexFileFactory.loadDexFile(
File
(
"classes.dex"
), Opcodes.getDefault())
/
/
所有classes
val classes
=
dexBackedDexFile.classes
println(classes.size)
/
/
所有classes
val classes
=
dexBackedDexFile.classes
println(classes.size)
/
/
从DexBackedDexFile获取ClassDef
val zzz
=
dexBackedDexFile.classes.find {
/
/
type
代表
class
name
it.
type
=
=
"Lcom.xxx.yyy.zzz;"
}
/
/
父类
println(zzz?.superclass)
复制代码
val
type
=
"Lcom.xxx.yyy.zzz;"
val defClass
=
ImmutableClassDef(
/
/
类名
type
,
AccessFlags.PUBLIC.value,
/
/
父类
"Ljava/lang/Object;"
,
/
/
继承的接口
null,
/
/
源文件
null,
/
/
注解
null,
/
/
静态成员变量
listOf(
ImmutableField(
/
/
所属类
type
,
/
/
成员名称
"field1"
,
/
/
成员类型
"I"
,
AccessFlags.PRIVATE.value,
/
/
初始化值
ImmutableIntEncodedValue(
666
),
null,
null
)
),
/
/
成员变量
null,
/
/
直系方法(自定义)
null,
/
/
非直系(继承重载等)
null
)
/
/
从DexBackedDexFile获取ClassDef
val zzz
=
dexBackedDexFile.classes.find {
/
/
type
代表
class
name
it.
type
=
=
"Lcom.xxx.yyy.zzz;"
}
/
/
父类
println(zzz?.superclass)
复制代码
val
type
=
"Lcom.xxx.yyy.zzz;"
val defClass
=
ImmutableClassDef(
/
/
类名
type
,
AccessFlags.PUBLIC.value,
/
/
父类
"Ljava/lang/Object;"
,
/
/
继承的接口
null,
/
/
源文件
null,
/
/
注解
null,
/
/
静态成员变量
listOf(
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!