Maison  >  Article  >  Opération et maintenance  >  Analyse de petits exemples de classes complexes dans l'ingénierie inverse Android

Analyse de petits exemples de classes complexes dans l'ingénierie inverse Android

WBOY
WBOYavant
2023-05-12 16:22:131537parcourir

1.classe complexe Java

Si vous ne comprenez rien, veuillez consulter : Aperçu général JAVA ou méthode de construction
Analyse de petits exemples de classes complexes dans lingénierie inverse Android

Publiez le code ici, c'est très simple et pas difficile.

2.smali code

Nous devons convertir le code java en code smali Vous pouvez faire référence à java en smali

Analyse de petits exemples de classes complexes dans lingénierie inverse Android

Analyse de petits exemples de classes complexes dans lingénierie inverse Android

Regardons-le dans les modules.

2.1 Le premier module - Module d'information


Analyse de petits exemples de classes complexes dans lingénierie inverse Android

Ce module contient des informations de base, expliquant le nom de la classe, etc. Le simple fait de le savoir n'aidera pas beaucoup dans l'analyse.

2.2 Le deuxième module - méthode de construction


Analyse de petits exemples de classes complexes dans lingénierie inverse Android

Analysons-le phrase par phrase S'il y a des parties répétées dans l'analyse précédente, nous ne les répéterons pas. Mais un lien sera fourni.

.method public constructor <init>(Ljava/lang/String;I)V</init>

Cette phrase est divisée en

.methodpublicconstructor<init>(Ljava/lang/String;I)v</init>
2.2.1 .method

means method

2.2.2 public

méthode de modification, propriété publique

2.2.3 constructeur

Le constructeur fait ici référence à cette méthode. une méthode de construction

2.2.4 <init></init><init></init>

Java在编译之后会在字节码文件中生成方法,称之为实例构造器,该实例构造器会将语句块,变量初始化,调用父类的构造器等操作收敛到方法中,收敛顺序(这里只讨论非静态变量和语句块)为:

  1. 父类变量初始化

  2. 父类语句块

  3. 父类构造函数

  4. 子类变量初始化

  5. 子类语句块

  6. 子类构造函数

所谓收敛到方法中的意思就是,将这些操作放入到中去执行

2.2.5 (Ljava/lang/String;I)

括号里的内容首先是 Ljava/lang/String,这里就是说第一个参数为String类型。
; 后面有一个I就是说同样属于 Ljava/lang这里的有一个int型参数。

2.2.6 v

最后面有一个v的含义就是void。也就是没有返回值类型。


我们来看第二句的意思。

.registers 6

寄存器 6个。这里的寄存器就是从v0-v5开始。这个很好理解。


第三句话。

.prologue

开场,意思是程序的开始。


第四句话。

.line 10

第10行代码的意思。


第五句话是:

invoke-direct {p0}, Ljava/lang/Object;-><init>()V</init>

首先先分解这句话。

invoke-direct{p0}Ljava/lang/Object;-><init>
()
V</init>
invoke-direct

就是方法调用的意思。

{p0}

p0就是说第一个参数。但是这里并没有第一个参数,这里默认就是this,我们自己传进去的参数从p1开始计数。

Ljava/lang/Object;-><init></init>

调用<init></init>方法

()里没有内容就是说没有参数。v相当于void,这里不再重复。


第六句话是

iput-object p1, p0, LPerson;->name:Ljava/lang/String;

分解一下

iput-object p1,p0LPerson;->name:Ljava/lang/String;

iput-object p1,p0的含义就是把p1的内容给p0。

LPerson;->name:Ljava/lang/String;

这句话的含义就是说把Person类里的一个名为name,类型为String的属性拿过来,这些是为了修饰p0。其实也就是this.name.


第七句话

iput p2, p0, LPerson;->age:I

这里也分解为两个部分。

iput p2, p0LPerson;->age:I

iput p2, p0,这里就是把p2的值给p0

LPerson;->age:I

说明了age这个数据类型是int。

这里可能会发现调用两个属性不一样,这里就是因为String并不是一个基本数据类型。所以使用了iput-object,如果是基本数据类型为iput。


第八句话

 sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;

分解

 sget-object v0
 Ljava/lang/System;->out:
 Ljava/io/PrintStream;

sget-object v0 就是获取到后见面的东西给v0。

Ljava/io/PrintStream;这个的含义就是说由这个类里的一个Ljava/lang/System;->out:这个方法。


第九句话

new-instance v1, Ljava/lang/StringBuilder;

新建一个StringBuilder的类给v1。


第十句话

invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V</init>

和之前的类似,从构造方法里调用v1。


第十一句话

const-string v2, "name:"

const-string 常量字符串。 v2,内容是name:


第十二句话

 invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

分解一下就是

invoke-virtual {v1, v2}Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

invoke-virtual {v1, v2} 调用虚方法,
->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

Après la compilation, Java générera une méthode dans le fichier bytecode, qui est appelée un constructeur d'instance Le constructeur d'instance Le processeur. fera converger les blocs d'instructions, l'initialisation des variables, l'appel du constructeur de la classe parent et d'autres opérations dans la méthode . L'ordre de convergence (seules les variables non statiques et les blocs d'instructions sont abordés ici) est :
  1. Initialisation de la variable de classe parent

  2. Bloc d'instructions de classe parent

  3. 🎜Constructeur de classe parent🎜
  4. 🎜Initialisation de variable de sous-classe 🎜
  5. 🎜Bloc d'instructions de sous-classe🎜
  6. 🎜Constructeur de sous-classe🎜
🎜La soi-disant convergence dans la méthode dans pour l'exécution🎜🎜2.2.5 (Ljava/lang/String;I)🎜🎜Le contenu entre parenthèses est d'abord Ljava/lang/String, ce qui signifie que le premier paramètre est de type String. 🎜; Il y a un I derrière, ce qui signifie qu'il appartient également à Ljava/lang et il y a un paramètre de type int ici. 🎜🎜2.2.6 v🎜🎜Le dernier v signifie vide. Autrement dit, il n’y a pas de type de valeur de retour. 🎜🎜🎜Regardons le sens de la deuxième phrase. 🎜
move-result-object v1
🎜Inscrivez-vous 6. Les registres ici commencent de v0 à v5. C’est facile à comprendre. 🎜🎜🎜La troisième phrase. 🎜
.method public constructor <init>()V    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method</init></init>
🎜Opening, c'est-à-dire le début du programme. 🎜🎜🎜La quatrième phrase. 🎜
public class Demo{
    public static void main(String[]args)    {
        Person p=new Person("zhuzhu",14);
    }
}
🎜La signification de la ligne 10 du code. 🎜🎜🎜La cinquième phrase est : 🎜
javac -source 1.6 -target 1.6 *.java
🎜Tout d’abord, décomposons cette phrase. 🎜
dx --dex --output=demo.dex *.class
.method public static main([Ljava/lang/String;)V
    .registers 4

    .prologue
    .line 4
    new-instance v0, LPerson;

    const-string v1, "zhuzhu"    const/16 v2, 0xe    invoke-direct {v0, v1, v2}, LPerson;-><init>(Ljava/lang/String;I)V

    .line 5    return-void.end method</init>
🎜 signifie appel de méthode. 🎜
new-instance v0, LPerson;
🎜p0 est le premier paramètre. Mais il n'y a pas de premier paramètre ici. La valeur par défaut ici est la suivante. Les paramètres que nous transmettons commencent à compter à partir de p1. 🎜
const-string v1, "zhuzhu"
🎜L'appel de la méthode <init></init> 🎜🎜() n'a pas de contenu, ce qui signifie qu'il n'y a pas de paramètres. v est équivalent à void et ne sera pas répété ici. 🎜🎜🎜La sixième phrase est 🎜
const/16 v2, 0xe
🎜Décomposez-le🎜
invoke-direct {v0, v1, v2}, LPerson;-><init>(Ljava/lang/String;I)V</init>
🎜iput-object p1, p0 signifie donner le contenu de p1 à p0. 🎜
.class public LPd;
.super Ljava/lang/Object;
.source "Pd.java"# direct methods
.method public constructor <init>()V
    .registers 1    .prologue
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void.end method

.method public static main([Ljava/lang/String;)V

    .registers 4    .prologue

    new-instance v0,LPerson;

    invoke-direct {v0}, LPerson;-><init>()V

    return-void.end method</init></init></init>
🎜Le sens de cette phrase est de prendre un attribut nommé name et de taper String de la classe Person. Il s'agit de modifier p0. En fait, il s'agit de ce.nom.🎜🎜🎜La septième phrase🎜rrreee🎜 se décompose également en deux parties. 🎜rrreee🎜iput p2, p0, voici pour donner la valeur de p2 à p0🎜rrreee🎜Cela montre que le type de données age est int. 🎜🎜Vous constaterez peut-être que l'appel des deux propriétés est différent ici. En effet, String n'est pas un type de données de base. Ainsi, iput-object est utilisé si le type de données de base est iput. 🎜🎜🎜La huitième phrase 🎜rrreee🎜Decomposition🎜rrreee🎜sget-object v0 consiste à obtenir la chose qui sera rencontrée plus tard et à la donner à v0. 🎜🎜Ljava/io/PrintStream;Cela signifie qu'il existe une méthode Ljava/lang/System;->out: dans cette classe. 🎜🎜🎜La neuvième phrase🎜rrreee🎜Créez une nouvelle classe StringBuilder pour la v1. 🎜🎜🎜La dixième phrase🎜rrreee🎜 est similaire à la précédente, appelant v1 depuis le constructeur. 🎜🎜🎜La onzième phrase🎜rrreee🎜chaîne constante const-string. v2, le contenu est nom :🎜🎜🎜La douzième phrase🎜rrreee🎜Décomposée, elle est🎜rrreee🎜invoke-virtual {v1, v2} appelle la méthode virtuelle, 🎜->append(Ljava/lang/String ; )Ljava/lang/StringBuilder;Appelez une méthode nommée append, le paramètre est de type String et la valeur de retour est de type StringBuilder. 🎜🎜🎜La treizième phrase🎜rrreee🎜 consiste à donner le résultat de la phrase précédente au registre v1. 🎜

之后的内容就是相似的了。
Analyse de petits exemples de classes complexes dans lingénierie inverse Android

有兴趣可以自己继续向下分析。

2.3 方法模块

这个模块在之前的一篇文章里已经说过了,这里就不再啰嗦了。

2.4 练习

这个练习我们就自己添加一个构造方法。

.method public constructor <init>()V    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method</init></init>

这个是我们自己写的一个构造方法。无参无返回值。

编译成jar文件进行查看。


Analyse de petits exemples de classes complexes dans lingénierie inverse Android

0x02 smali类相互调用

1. java代码

在0x01的前提上我们再写一个调用demo。

public class Demo{
    public static void main(String[]args)    {
        Person p=new Person("zhuzhu",14);
    }
}

代码很简单。

2.smali代码

这里我们要使用

javac -source 1.6 -target 1.6 *.java

编译所有.java文件

然后使用

dx --dex --output=demo.dex *.class

把所有的.class文件编译成dex文件。


Analyse de petits exemples de classes complexes dans lingénierie inverse Android

我们来主要看看main函数。

.method public static main([Ljava/lang/String;)V
    .registers 4

    .prologue
    .line 4
    new-instance v0, LPerson;

    const-string v1, "zhuzhu"    const/16 v2, 0xe    invoke-direct {v0, v1, v2}, LPerson;-><init>(Ljava/lang/String;I)V

    .line 5    return-void.end method</init>
new-instance v0, LPerson;

新建一个类,v0

const-string v1, "zhuzhu"

然后定义一个常量 v1。

const/16 v2, 0xe

定义一个16位的常量

invoke-direct {v0, v1, v2}, LPerson;-><init>(Ljava/lang/String;I)V</init>

调用Person类的构造方法,然后把v0,v1,v2当做参数传进去。

其实类之前的交互调用其实并不难。

3.总结

我们调用其他类的时候。

1.new-instance 实例化一个对象
2.invoke-direct 调用构造方法

0x03 小练习(甜点)

首先来看看我们写的程序。

Analyse de petits exemples de classes complexes dans lingénierie inverse Android

然后是手写的smali代码。

.class public LPd;
.super Ljava/lang/Object;
.source "Pd.java"# direct methods
.method public constructor <init>()V
    .registers 1    .prologue
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void.end method

.method public static main([Ljava/lang/String;)V

    .registers 4    .prologue

    new-instance v0,LPerson;

    invoke-direct {v0}, LPerson;-><init>()V

    return-void.end method</init></init></init>

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer