smali文件格式

每个smali文件都由若干条语句组成,所有的语句都遵循着一套语法规则。在smali 文件的头3 行描述了当前类的一些信息,格式如下:

  1. .class < 访问权限> [ 修饰关键字] < 类名>
  2. .super < 父类名>
  3. .source <源文件名>

打开MainActivity.smali 文件,头3 行代码如下:

  1. .class public Lcom/droider/crackme0502/MainActivity;     //指令指定了当前类的类名。
  2. .super Landroid/app/Activity;<span style=“white-space:pre”>             </span>//指令指定了当前类的父类。
  3. .source ”MainActivity.java”<span style=“white-space:pre”>               </span>//指令指定了当前类的源文件名。

smali文件中字段的声明使用“.field”指令。字段有静态字段与实例字段两种。静态字段的声明格式如下:

  1. # static fields
  2. .field < 访问权限> static [ 修饰关键字] < 字段名>:< 字段类型>

实例字段的声明与静态字段类似,只是少了static关键字,它的格式如下:

  1. # instance fields
  2. .field < 访问权限> [ 修饰关键字] < 字段名>:< 字段类型>
  1. 比如以下的实例字段声明。
  2. # instance fields   //baksmali 生成的注释
  3. .field private btnAnno:Landroid/widget/Button;  //私有字段

smali 文件中方法的声明使用“.method ”指令,方法有直接方法与虚方法两种。

直接方法的声明格式如下:

  1. # direct methods                //添加的注释
  2. .method <访问权限> [ 修饰关键字] < 方法原型>
  3. <.locals>                 //指定了使用的局部变量的个数
  4. [.parameter]                   //指定了方法的参数
  5. [.prologue]                    //指定了代码的开始处,混淆过的代码可能去掉了该指令
  6. [.line]                    //指定了该处指令在源代码中的行号
  7. <代码体>
  8. .end method

虚方法的声明与直接方法相同,只是起始处的注释为“virtual methods”,如果一个类实现了接口,会在smali 文件中使用“.implements ”指令指出,相应的格式声明如下:

  1. # interfaces
  2. .implements < 接口名>        //接口关键字
  3. 如果一个类使用了注解,会在 smali 文件中使用“.annotation ”指令指出,注解的格式声明如下:
  4. # annotations
  5. .annotation [ 注解属性] < 注解类名>
  6. [ 注解字段 =  值]
  7. .end annotation

注解的作用范围可以是类、方法或字段。如果注解的作用范围是类,“.annotation ”指令会直接定义在smali 文件中,如果是方法或字段,“.annotation ”指令则会包含在方法或字段定义中。例如:

  1. # instance fields
  2. .field public sayWhat:Ljava/lang/String;            //String 类型 它使用了 com.droider.anno.MyAnnoField 注解,注解字段info 值为“Hello my friend”
  3. .annotation runtime Lcom/droider/anno/MyAnnoField;
  4. info = ”Hello my friend”
  5. .end annotation
  6. .end field

Android 程序中的类

1、内部类

Java 语言允许在一个类的内部定义另一个类,这种在类中定义的类被称为内部类(Inner Class)。内部类可分为成员内部类、静态嵌套类、方法内部类、匿名内部类。在反编译dex 文件的时候,会为每个类单独生成了一个 smali 文件,内部类作为一个独立的类,它也拥有自己独立的smali 文件,只是内部类的文件名形式为“[外部类]$[内部类].smali ”,例如:

  1. class Outer {
  2. class Inner{}
  3. }

反编译上述代码后会生成两个文件:Outer.smali 与Outer$Inner.smali。打开文件,代码结构如下:

  1. .class public Lcom/droider/crackme0502/MainActivitySNChecker;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;.&lt;span class=&quot;keyword&quot;&gt;super&lt;/span&gt;&lt;span&gt;&amp;nbsp;Ljava/lang/Object;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;.source&amp;nbsp;&lt;span class=&quot;string&quot;&gt;&quot;MainActivity.java&quot;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;#&amp;nbsp;annotations&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;.annotation&amp;nbsp;system&amp;nbsp;Ldalvik/annotation/EnclosingClass;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value&amp;nbsp;=&amp;nbsp;Lcom/droider/crackme0502/MainActivity;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;.end&amp;nbsp;annotation&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;.annotation&amp;nbsp;system&amp;nbsp;Ldalvik/annotation/InnerClass;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;accessFlags&amp;nbsp;=&amp;nbsp;&lt;span class=&quot;number&quot;&gt;0x1&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name&amp;nbsp;=&amp;nbsp;&lt;span class=&quot;string&quot;&gt;&quot;SNChecker&quot;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;.end&amp;nbsp;annotation&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;#&amp;nbsp;instance&amp;nbsp;fields&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;.field&amp;nbsp;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span&gt;&amp;nbsp;sn:Ljava/lang/String;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;.field&amp;nbsp;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt;&lt;span&gt;&amp;nbsp;synthetic&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;&lt;span&gt;" role="presentation">SNChecker;&nbsp;&nbsp;</span></span></li><li><span>.<span class="keyword">super</span><span>&nbsp;Ljava/lang/Object;&nbsp;&nbsp;</span></span></li><li class="alt"><span>.source&nbsp;<span class="string">"MainActivity.java"</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>#&nbsp;annotations&nbsp;&nbsp;</span></li><li><span>.annotation&nbsp;system&nbsp;Ldalvik/annotation/EnclosingClass;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;=&nbsp;Lcom/droider/crackme0502/MainActivity;&nbsp;&nbsp;</span></li><li><span>.end&nbsp;annotation&nbsp;&nbsp;</span></li><li class="alt"><span>.annotation&nbsp;system&nbsp;Ldalvik/annotation/InnerClass;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;accessFlags&nbsp;=&nbsp;<span class="number">0x1</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;=&nbsp;<span class="string">"SNChecker"</span><span>&nbsp;&nbsp;</span></span></li><li><span>.end&nbsp;annotation&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span>#&nbsp;instance&nbsp;fields&nbsp;&nbsp;</span></li><li class="alt"><span>.field&nbsp;<span class="keyword">private</span><span>&nbsp;sn:Ljava/lang/String;&nbsp;&nbsp;</span></span></li><li><span>.field&nbsp;<span class="keyword">final</span><span>&nbsp;synthetic&nbsp;</span><span class="keyword">this</span><span>SNChecker;&nbsp;&nbsp;</span></span></li><li><span>.<span class="keyword">super</span><span>&nbsp;Ljava/lang/Object;&nbsp;&nbsp;</span></span></li><li class="alt"><span>.source&nbsp;<span class="string">"MainActivity.java"</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>#&nbsp;annotations&nbsp;&nbsp;</span></li><li><span>.annotation&nbsp;system&nbsp;Ldalvik/annotation/EnclosingClass;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;=&nbsp;Lcom/droider/crackme0502/MainActivity;&nbsp;&nbsp;</span></li><li><span>.end&nbsp;annotation&nbsp;&nbsp;</span></li><li class="alt"><span>.annotation&nbsp;system&nbsp;Ldalvik/annotation/InnerClass;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;accessFlags&nbsp;=&nbsp;<span class="number">0x1</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;=&nbsp;<span class="string">"SNChecker"</span><span>&nbsp;&nbsp;</span></span></li><li><span>.end&nbsp;annotation&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span>#&nbsp;instance&nbsp;fields&nbsp;&nbsp;</span></li><li class="alt"><span>.field&nbsp;<span class="keyword">private</span><span>&nbsp;sn:Ljava/lang/String;&nbsp;&nbsp;</span></span></li><li><span>.field&nbsp;<span class="keyword">final</span><span>&nbsp;synthetic&nbsp;</span><span class="keyword">this</span><span>0:Lcom/droider/crackme0502/MainActivity;
  2. # direct methods
  3. .method public constructor
  4. <init>(Lcom/droider/crackme0502/MainActivity;Ljava/lang/String;)V
  5. ……
  6. .end method
  7. # virtual methods
  8. .method public isRegistered()Z
  9. ……
  10. .end method

发现它有两个注解定义块“Ldalvik/annotation/EnclosingClass;”与“Ldalvik/annotation/ InnerClass; ”、两个实例字段sn 与this0、一个直接方法init()、一个虚方法isRegistered()。this" role="presentation">0、一个直接方法init()、一个虚方法isRegistered()。this0、一个直接方法init()、一个虚方法isRegistered()。this0 是内部类自动保留的一个指向所在外部类的引用。左边的 this 表示为父类的引用,右边的数值0 表示引用的层数。

2、监听器

Android程序开发中大量使用到了监听器,如Button的点击事件响应OnClickListener、Button的长按事件响应OnLongClickListener、ListView列表项的点击事件响应 OnItemSelected-Listener等。

实例源码以及反编译设置按钮点击事件监听器的代码如下:

  1. public void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. setContentView(R.layout.activity_main);
  4. btnAnno = (Button) findViewById(R.id.btn_annotation);
  5. btnCheckSN = (Button) findViewById(R.id.btn_checksn);
  6. edtSN = (EditText) findViewById(R.id.edt_sn);
  7. btnAnno.setOnClickListener(new OnClickListener() {
  8. @Override
  9. public void onClick(View v) {
  10. getAnnotations();
  11. }
  12. });
  13. btnCheckSN.setOnClickListener(new OnClickListener() {
  14. @Override
  15. public void onClick(View v) {
  16. SNChecker checker = new SNChecker(edtSN.getText().toString());
  17. String str = checker.isRegistered() ? ”注册码正确” : “注册码错误”;
  18. Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
  19. }
  20. });
  21. }

  1. 反编译如下:
  2. .method public onCreate(Landroid/os/Bundle;)V
  3. .locals 2
  4. .parameter ”savedInstanceState”
  5. ……
  6. .line 32
  7. iget-object v0, p0, Lcom/droider/crackme0502/MainActivity;->btnAnno:
  8. Landroid/widget/Button;
  9. new-instance v1, Lcom/droider/crackme0502/MainActivity&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;span&gt;;&amp;nbsp;#新建一个&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MainActivity" role="presentation"></span><span class="number">1</span><span>;&nbsp;#新建一个&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;MainActivity</span><span class="number">1</span><span>;&nbsp;#新建一个&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;MainActivity1实例
  10. invoke-direct {v1, p0}, Lcom/droider/crackme0502/MainActivity&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;span&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;-&amp;gt;&amp;lt;init&amp;gt;(Lcom/droider/crackme0502/MainActivity;)V&amp;nbsp;#&amp;nbsp;初始化MainActivity" role="presentation"><span class="number">1</span><span>;&nbsp;&nbsp;</span></span></li><li><span>-&gt;&lt;init&gt;(Lcom/droider/crackme0502/MainActivity;)V&nbsp;#&nbsp;初始化MainActivity<span class="number">1</span><span>;&nbsp;&nbsp;</span></span></li><li><span>-&gt;&lt;init&gt;(Lcom/droider/crackme0502/MainActivity;)V&nbsp;#&nbsp;初始化MainActivity1
  11. 实例
  12. invoke-virtual {v0, v1}, Landroid/widget/Button;
  13. ->setOnClickListener(Landroid/view/ViewOnClickListener;)V&amp;nbsp;#&amp;nbsp;设置按钮点击事件&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;监听器&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.line&amp;nbsp;&lt;span class=&quot;number&quot;&gt;40&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;iget-object&amp;nbsp;v0,&amp;nbsp;p0,&amp;nbsp;Lcom/droider/crackme0502/MainActivity;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;-&amp;gt;btnCheckSN:Landroid/widget/Button;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span&gt;-instance&amp;nbsp;v1,&amp;nbsp;Lcom/droider/crackme0502/MainActivity" role="presentation">OnClickListener;)V&nbsp;#&nbsp;设置按钮点击事件&nbsp;&nbsp;</span></li><li><span>监听器&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">40</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;iget-object&nbsp;v0,&nbsp;p0,&nbsp;Lcom/droider/crackme0502/MainActivity;&nbsp;&nbsp;</span></li><li class="alt"><span>-&gt;btnCheckSN:Landroid/widget/Button;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>-instance&nbsp;v1,&nbsp;Lcom/droider/crackme0502/MainActivityOnClickListener;)V&nbsp;#&nbsp;设置按钮点击事件&nbsp;&nbsp;</span></li><li><span>监听器&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">40</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;iget-object&nbsp;v0,&nbsp;p0,&nbsp;Lcom/droider/crackme0502/MainActivity;&nbsp;&nbsp;</span></li><li class="alt"><span>-&gt;btnCheckSN:Landroid/widget/Button;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>-instance&nbsp;v1,&nbsp;Lcom/droider/crackme0502/MainActivity2; #新建一个
  14. MainActivity&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;span&gt;实例&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-direct&amp;nbsp;{v1,&amp;nbsp;p0},&amp;nbsp;Lcom/droider/crackme0502/MainActivity" role="presentation"><span class="number">2</span><span>实例&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-direct&nbsp;{v1,&nbsp;p0},&nbsp;Lcom/droider/crackme0502/MainActivity<span class="number">2</span><span>实例&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-direct&nbsp;{v1,&nbsp;p0},&nbsp;Lcom/droider/crackme0502/MainActivity2
  15. -><init>(Lcom/droider/crackme0502/MainActivity;)V; # 初始化MainActivity&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;span&gt;实例&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-virtual&amp;nbsp;{v0,&amp;nbsp;v1},&amp;nbsp;Landroid/widget/Button;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;-&amp;gt;setOnClickListener(Landroid/view/View" role="presentation"><span class="number">2</span><span>实例&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-virtual&nbsp;{v0,&nbsp;v1},&nbsp;Landroid/widget/Button;&nbsp;&nbsp;</span></li><li class="alt"><span>-&gt;setOnClickListener(Landroid/view/View<span class="number">2</span><span>实例&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-virtual&nbsp;{v0,&nbsp;v1},&nbsp;Landroid/widget/Button;&nbsp;&nbsp;</span></li><li class="alt"><span>-&gt;setOnClickListener(Landroid/view/ViewOnClickListener;)V#设置按钮点击事件
  16. 监听器
  17. .line 50
  18. return-void
  19. .end method

在MainActivity$1.smali 文件的开头使用了“.implements ”指令指定该类实现了按钮点击事件的监听器接口,因此,这个类实现了它的OnClick()方法,这也是我们在分析程序时关心的地方。另外,程序中的注解与监听器的构造函数都是编译器为我们自己生成的,实际分析过程中不必关心。

3、注解类

注解是Java 的语言特性,在 Android的开发过程中也得到了广泛的使用。Android系统中涉及到注解的包共有两个:一个是dalvik.annotation;另一个是 android.annotation。

例如:

  1. # annotations
  2. .annotation system Ldalvik/annotation/AnnotationDefault;
  3. value = .subannotation Lcom/droider/anno/MyAnnoClass;
  4. value = ”MyAnnoClass”
  5. .end subannotation
  6. .end annotation

除了SuppressLint与TargetApi注解,android.annotation 包还提供了SdkConstant与Widget两个注解,这两个注解在注释中被标记为“@hide”,即在 SDK 中是不可见的。SdkConstant注解指定了SDK中可以被导出的常量字段值,Widget 注解指定了哪些类是 UI类,这两个注解在分析Android程序时基本上碰不到,此处就不去探究了。

4、自动生成的类

使用 Android SDK 默认生成的工程会自动添加一些类。例如:

  1. public final class R {
  2. public static final class attr {      //属性
  3. }
  4. public static final class dimen {      //尺寸
  5. public static final int padding_large=0x7f040002;
  6. public static final int padding_medium=0x7f040001;
  7. public static final int padding_small=0x7f040000;
  8. }
  9. public static final class drawable {    //图片
  10. public static final int ic_action_search=0x7f020000;
  11. public static final int ic_launcher=0x7f020001;
  12. }
  13. public static final class id {        //id标识
  14. public static final int btn_annotation=0x7f080000;
  15. public static final int btn_checksn=0x7f080002;
  16. public static final int edt_sn=0x7f080001;
  17. public static final int menu_settings=0x7f080003;
  18. }
  19. public static final class layout {    // 布局
  20. public static final int activity_main=0x7f030000;
  21. }
  22. public static final class menu {    // 菜单
  23. public static final int activity_main=0x7f070000;
  24. }
  25. public static final class string {    // 字符串
  26. public static final int app_name=0x7f050000;
  27. public static final int hello_world=0x7f050001;
  28. public static final int menu_settings=0x7f050002;
  29. public static final int title_activity_main=0x7f050003;
  30. }
  31. public static final class style {    // 样式
  32. public static final int AppTheme=0x7f060000;
  33. }
  34. }

由于这些资源类都是R 类的内部类,因此它们都会独立生成一个类文件,在反编译出的代码中,可以发现有R.smali、Rattr.smali、R" role="presentation">attr.smali、Rattr.smali、Rdimen.smali、Rdrawable.smali、R" role="presentation">drawable.smali、Rdrawable.smali、Rid.smali、Rlayout.smali、R" role="presentation">layout.smali、Rlayout.smali、Rmenu.smali 、Rstring.smali、R" role="presentation">string.smali、Rstring.smali、Rstyle.smali 等几个文件。

阅读smali反编译的代码

smali 文件中的语句特点:

1、循环语句

在 Android开发过程中,常见的循环结构有迭代器循环、for 循环、while循环、do while 循环。我们在编写迭代器循环代码时,一般是如下形式的代码:

  1. Iterator< 对象> <对象名> = <方法返回一个对象列表>;
  2. for (< 对象> <对象名> : <对象列表>) {
  3. [处理单个对象的代码体]
  4. }
  5. 或者:
  6. Iterator< 对象> <迭代器> = <方法返回一个迭代器>;
  7. while (<迭代器>.hasNext()) {
  8. <对象> <对象名> = <迭代器>.next();
  9. [处理单个对象的代码体]
  10. }

  1. .method private iterator()V
  2. .locals 7
  3. .prologue
  4. .line 34
  5. const-string v4, “activity”
  6. invoke-virtual {p0, v4}, Lcom/droider/circulate/MainActivity;->
  7. getSystemService
  8. (Ljava/lang/String;)Ljava/lang/Object;  # 获取ActivityManager
  9. move-result-object v0
  10. check-cast v0, Landroid/app/ActivityManager;
  11. .line 35
  12. .local v0, activityManager:Landroid/app/ActivityManager;
  13. invoke-virtual {v0}, Landroid/app/ActivityManager;->getRunningAppProcesses()
  14. Ljava/util/List;
  15. move-result-object v2    #正在运行的进程列表
  16. .line 36
  17. .local v2, psInfos:Ljava/util/List;,
  18. ”Ljava/util/List<Landroid/app/ActivityManagerRunningAppProcessInfo;&amp;gt;;&quot;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span&gt;-instance&amp;nbsp;v3,&amp;nbsp;Ljava/lang/StringBuilder;&amp;nbsp;&amp;nbsp;#&amp;nbsp;新建一个StringBuilder&amp;nbsp;对象&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-direct&amp;nbsp;{v3},&amp;nbsp;Ljava/lang/StringBuilder;-&amp;gt;&amp;lt;init&amp;gt;()V&amp;nbsp;&amp;nbsp;#&amp;nbsp;调用&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StringBuilder&amp;nbsp;构造函数&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.line&amp;nbsp;&lt;span class=&quot;number&quot;&gt;37&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.local&amp;nbsp;v3,&amp;nbsp;sb:Ljava/lang/StringBuilder;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-&lt;span class=&quot;keyword&quot;&gt;interface&lt;/span&gt;&lt;span&gt;&amp;nbsp;{v2},&amp;nbsp;Ljava/util/List;-&amp;gt;iterator()Ljava/util/Iterator;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;#获取进程列表的迭代器&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;move-result-object&amp;nbsp;v4&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:goto_0&amp;nbsp;#迭代循环开始&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-&lt;span class=&quot;keyword&quot;&gt;interface&lt;/span&gt;&lt;span&gt;&amp;nbsp;{v4},&amp;nbsp;Ljava/util/Iterator;-&amp;gt;hasNext()Z&amp;nbsp;#开始迭代&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;move-result&amp;nbsp;v5&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span&gt;-nez&amp;nbsp;v5,&amp;nbsp;:cond_0&amp;nbsp;&amp;nbsp;#&amp;nbsp;如果迭代器不为空就跳走&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.line&amp;nbsp;&lt;span class=&quot;number&quot;&gt;40&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-virtual&amp;nbsp;{v3},&amp;nbsp;Ljava/lang/StringBuilder;-&amp;gt;toString()Ljava/lang/&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;move-result-object&amp;nbsp;v4&amp;nbsp;&amp;nbsp;#&amp;nbsp;StringBuilder转为字符串&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;&lt;span&gt;&amp;nbsp;v5,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;0x0&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span&gt;&amp;nbsp;{p0,&amp;nbsp;v4,&amp;nbsp;v5},&amp;nbsp;Landroid/widget/Toast;-&amp;gt;makeText&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;widget/Toast;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;move-result-object&amp;nbsp;v4&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-virtual&amp;nbsp;{v4},&amp;nbsp;Landroid/widget/Toast;-&amp;gt;show()V&amp;nbsp;#&amp;nbsp;弹出StringBuilder&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;的内容&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.line&amp;nbsp;&lt;span class=&quot;number&quot;&gt;41&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;#&amp;nbsp;方法返回&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.line&amp;nbsp;&lt;span class=&quot;number&quot;&gt;37&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:cond_0&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invoke-&lt;span class=&quot;keyword&quot;&gt;interface&lt;/span&gt;&lt;span&gt;&amp;nbsp;{v4},&amp;nbsp;Ljava/util/Iterator;-&amp;gt;next()Ljava/lang/Object;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;循环获取每一项&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;move-result-object&amp;nbsp;v1&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;check-cast&amp;nbsp;v1,&amp;nbsp;Landroid/app/ActivityManager" role="presentation">RunningAppProcessInfo;&gt;;"</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>-instance&nbsp;v3,&nbsp;Ljava/lang/StringBuilder;&nbsp;&nbsp;#&nbsp;新建一个StringBuilder&nbsp;对象&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-direct&nbsp;{v3},&nbsp;Ljava/lang/StringBuilder;-&gt;&lt;init&gt;()V&nbsp;&nbsp;#&nbsp;调用&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;构造函数&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">37</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;.local&nbsp;v3,&nbsp;sb:Ljava/lang/StringBuilder;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-<span class="keyword">interface</span><span>&nbsp;{v2},&nbsp;Ljava/util/List;-&gt;iterator()Ljava/util/Iterator;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;#获取进程列表的迭代器&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result-object&nbsp;v4&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;:goto_0&nbsp;#迭代循环开始&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-<span class="keyword">interface</span><span>&nbsp;{v4},&nbsp;Ljava/util/Iterator;-&gt;hasNext()Z&nbsp;#开始迭代&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result&nbsp;v5&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>-nez&nbsp;v5,&nbsp;:cond_0&nbsp;&nbsp;#&nbsp;如果迭代器不为空就跳走&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">40</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-virtual&nbsp;{v3},&nbsp;Ljava/lang/StringBuilder;-&gt;toString()Ljava/lang/&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;String;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result-object&nbsp;v4&nbsp;&nbsp;#&nbsp;StringBuilder转为字符串&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">const</span><span>/</span><span class="number">4</span><span>&nbsp;v5,&nbsp;</span><span class="number">0x0</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-<span class="keyword">static</span><span>&nbsp;{p0,&nbsp;v4,&nbsp;v5},&nbsp;Landroid/widget/Toast;-&gt;makeText&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;widget/Toast;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result-object&nbsp;v4&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-virtual&nbsp;{v4},&nbsp;Landroid/widget/Toast;-&gt;show()V&nbsp;#&nbsp;弹出StringBuilder&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;的内容&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">41</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>-</span><span class="keyword">void</span><span>&nbsp;&nbsp;#&nbsp;方法返回&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">37</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;:cond_0&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-<span class="keyword">interface</span><span>&nbsp;{v4},&nbsp;Ljava/util/Iterator;-&gt;next()Ljava/lang/Object;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;循环获取每一项&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result-object&nbsp;v1&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;check-cast&nbsp;v1,&nbsp;Landroid/app/ActivityManagerRunningAppProcessInfo;&gt;;"</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>-instance&nbsp;v3,&nbsp;Ljava/lang/StringBuilder;&nbsp;&nbsp;#&nbsp;新建一个StringBuilder&nbsp;对象&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-direct&nbsp;{v3},&nbsp;Ljava/lang/StringBuilder;-&gt;&lt;init&gt;()V&nbsp;&nbsp;#&nbsp;调用&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;构造函数&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">37</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;.local&nbsp;v3,&nbsp;sb:Ljava/lang/StringBuilder;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-<span class="keyword">interface</span><span>&nbsp;{v2},&nbsp;Ljava/util/List;-&gt;iterator()Ljava/util/Iterator;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;#获取进程列表的迭代器&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result-object&nbsp;v4&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;:goto_0&nbsp;#迭代循环开始&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-<span class="keyword">interface</span><span>&nbsp;{v4},&nbsp;Ljava/util/Iterator;-&gt;hasNext()Z&nbsp;#开始迭代&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result&nbsp;v5&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>-nez&nbsp;v5,&nbsp;:cond_0&nbsp;&nbsp;#&nbsp;如果迭代器不为空就跳走&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">40</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-virtual&nbsp;{v3},&nbsp;Ljava/lang/StringBuilder;-&gt;toString()Ljava/lang/&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;String;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result-object&nbsp;v4&nbsp;&nbsp;#&nbsp;StringBuilder转为字符串&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">const</span><span>/</span><span class="number">4</span><span>&nbsp;v5,&nbsp;</span><span class="number">0x0</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-<span class="keyword">static</span><span>&nbsp;{p0,&nbsp;v4,&nbsp;v5},&nbsp;Landroid/widget/Toast;-&gt;makeText&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;widget/Toast;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result-object&nbsp;v4&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-virtual&nbsp;{v4},&nbsp;Landroid/widget/Toast;-&gt;show()V&nbsp;#&nbsp;弹出StringBuilder&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;的内容&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">41</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>-</span><span class="keyword">void</span><span>&nbsp;&nbsp;#&nbsp;方法返回&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;.line&nbsp;<span class="number">37</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;:cond_0&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;invoke-<span class="keyword">interface</span><span>&nbsp;{v4},&nbsp;Ljava/util/Iterator;-&gt;next()Ljava/lang/Object;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;循环获取每一项&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;move-result-object&nbsp;v1&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;check-cast&nbsp;v1,&nbsp;Landroid/app/ActivityManagerRunningAppProcessInfo;
  19. .line 38
  20. .local v1, info:Landroid/app/ActivityManagerRunningAppProcessInfo;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span&gt;-instance&amp;nbsp;v5,&amp;nbsp;Ljava/lang/StringBuilder;&amp;nbsp;&amp;nbsp;#&amp;nbsp;新建一个临时的StringBuilder&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class=&quot;alt&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;iget-object&amp;nbsp;v6,&amp;nbsp;v1,&amp;nbsp;Landroid/app/ActivityManager" role="presentation">RunningAppProcessInfo;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>-instance&nbsp;v5,&nbsp;Ljava/lang/StringBuilder;&nbsp;&nbsp;#&nbsp;新建一个临时的StringBuilder&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;iget-object&nbsp;v6,&nbsp;v1,&nbsp;Landroid/app/ActivityManagerRunningAppProcessInfo;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>-instance&nbsp;v5,&nbsp;Ljava/lang/StringBuilder;&nbsp;&nbsp;#&nbsp;新建一个临时的StringBuilder&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;iget-object&nbsp;v6,&nbsp;v1,&nbsp;Landroid/app/ActivityManagerRunningAppProcessInfo;
  21. ->processName:Ljava/lang/String;    #获取进程的进程名
  22. invoke-static {v6}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)
  23. Ljava/lang/String;
  24. move-result-object v6
  25. invoke-direct {v5, v6}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/
  26. String;)V
  27. const/16 v6, 0xa #换行符
  28. invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(C)Ljava/
  29. lang/StringBuilder;
  30. move-result-object v5 # 组合进程名与换行符
  31. invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/
  32. String;
  33. move-result-object v5
  34. invoke-virtual {v3, v5}, Ljava/lang/StringBuilder; # 将组合后的字符串添加到
  35. StringBuilder 末尾
  36. ->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
  37. goto :goto_0  #跳转到循环开始处
  38. .end method

这段代码的功能是获取正在运行的进程列表,然后使用Toast弹出所有的进程名。

forCirculate() 方法如下:

  1. .method private forCirculate()V
  2. .locals 8
  3. .prologue
  4. .line 47
  5. invoke-virtual {p0}, Lcom/droider/circulate/MainActivity;-
  6. >getApplicationContext()Landroid/content/Context;
  7. move-result-object v6
  8. invoke-virtual {v6}, Landroid/content/Context;    #获取PackageManager
  9. ->getPackageManager()Landroid/content/pm/PackageManager;
  10. move-result-object v3
  11. .line 49
  12. .local v3, pm:Landroid/content/pm/PackageManager;
  13. const/16 v6, 0x2000
  14. .line 48
  15. invoke-virtual {v3, v6}, Landroid/content/pm/PackageManager;
  16. ->getInstalledApplications(I)Ljava/util/List;  #获取已安装的程序列表
  17. move-result-object v0
  18. .line 50
  19. .local v0, appInfos:Ljava/util/List;,”Ljava/util/List<Landroid/content/pm
  20. /ApplicationInfo;>;”
  21. invoke-interface {v0}, Ljava/util/List;->size()I  # 获取列表中ApplicationInfo
  22. 对象的个数
  23. move-result v5
  24. .line 51
  25. .local v5, size:I
  26. new-instance v4, Ljava/lang/StringBuilder;          # 新建一个
  27. StringBuilder 对象
  28. invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V  # 调用
  29. StringBuilder 的构造函数
  30. .line 52
  31. .local v4, sb:Ljava/lang/StringBuilder;
  32. const/4 v1, 0x0
  33. .local v1, i:I #初始化v1为0
  34. :goto_0 #循环开始
  35. if-lt v1, v5, :cond_0   #如果v1小于v5,则跳转到cond_0 标号处
  36. .line 56
  37. invoke-virtual {v4}, Ljava/lang/StringBuilder;->toString()Ljava/
  38. lang/String;
  39. move-result-object v6
  40. const/4 v7, 0x0
  41. invoke-static {p0, v6, v7}, Landroid/widget/Toast; #构造Toast
  42. ->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)
  43. Landroid/widget/Toast;
  44. move-result-object v6
  45. invoke-virtual {v6}, Landroid/widget/Toast;->show()V #显示已安装的程序列表
  46. .line 57
  47. return-void  # 方法返回
  48. .line 53
  49. :cond_0
  50. invoke-interface {v0, v1}, Ljava/util/List;->get(I)Ljava/lang/Object;
  51. # 单个ApplicationInfo
  52. move-result-object v2
  53. check-cast v2, Landroid/content/pm/ApplicationInfo;
  54. .line 54
  55. .local v2, info:Landroid/content/pm/ApplicationInfo;
  56. new-instance v6, Ljava/lang/StringBuilder;  # 新建一个临时StringBuilder对象
  57. iget-object v7, v2, Landroid/content/pm/ApplicationInfo;->packageName:
  58. Ljava/lang/String;
  59. invoke-static {v7}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)
  60. Ljava/lang/String;
  61. move-result-object v7  # 包名
  62. invoke-direct {v6, v7}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/
  63. String;)V
  64. const/16 v7, 0xa #换行符
  65. invoke-virtual {v6, v7}, Ljava/lang/StringBuilder;->append(C)Ljava/
  66. lang/StringBuilder;
  67. move-result-object v6  # 组合包名与换行符
  68. invoke-virtual {v6}, Ljava/lang/StringBuilder;->toString()Ljava/lang
  69. /String; #转换为字符串
  70. move-result-object v6
  71. invoke-virtual {v4, v6}, Ljava/lang/StringBuilder;-
  72. >append(Ljava/lang/String;)Ljava/lang/StringBuilder;  # 添加到循环外        的StringBuilder 中
  73. .line 52
  74. add-int/lit8 v1, v1, 0x1 #下一个索引
  75. goto :goto_0 #跳转到循环起始处
  76. .end method

这段代码的功能是获取所有安装的程序,然后使用Toast弹出所有的软件包名。

2、switch分支语句

packedSwitch()方法的代码如下:

  1. .method private packedSwitch(I)Ljava/lang/String;
  2. .locals 1
  3. .parameter ”i”
  4. .prologue
  5. .line 21
  6. const/4 v0, 0x0
  7. .line 22
  8. .local v0, str:Ljava/lang/String;  #v0为字符串,0表示null
  9. packed-switch p1, :pswitch_data_0  #packed-switch分支,pswitch_data_0指
  10. 定case区域
  11. .line 36
  12. const-string v0, “she is a person”  #default分支
  13. .line 39
  14. :goto_0      #所有case的出口
  15. return-object v0 #返回字符串v0
  16. .line 24
  17. :pswitch_0    #case 0
  18. const-string v0, “she is a baby”
  19. .line 25
  20. goto :goto_0  #跳转到goto_0标号处
  21. .line 27
  22. :pswitch_1    #case 1
  23. const-string v0, “she is a girl”
  24. .line 28
  25. goto :goto_0  #跳转到goto_0标号处
  26. .line 30
  27. :pswitch_2    #case 2
  28. const-string v0, “she is a woman”
  29. .line 31
  30. goto :goto_0  #跳转到goto_0标号处
  31. .line 33
  32. :pswitch_3    #case 3
  33. const-string v0, “she is an obasan”
  34. .line 34
  35. goto :goto_0  #跳转到goto_0标号处
  36. .line 22
  37. nop
  38. :pswitch_data_0
  39. .packed-switch 0x0    #case  区域,从0开始,依次递增
  40. :pswitch_0  #case 0
  41. :pswitch_1  #case 1
  42. :pswitch_2  #case 2
  43. :pswitch_3  #case 3
  44. .end packed-switch
  45. .end method

代码中的switch 分支使用的是 packed-switch 指令。p1为传递进来的 int 类型的数值,pswitch_data_0 为case 区域,在 case 区域中,第一条指令“.packed-switch”指定了比较的初始值为0 ,pswitch_0~ pswitch_3分别是比较结果为“case 0 ”到“case 3 ”时要跳转到的地址。

3、try/catch 语句

tryCatch()方法代码如下:

  1. .method private tryCatch(ILjava/lang/String;)V
  2. .locals 10
  3. .parameter ”drumsticks”
  4. .parameter ”peple”
  5. .prologue
  6. const/4 v9, 0x0
  7. .line 19
  8. :try_start_0  # 第1个try开始
  9. invoke-static {p2}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I
  10. #将第2个参数转换为int 型
  11. :try_end_0    # 第1个try结束
  12. .catch Ljava/lang/NumberFormatException; {:try_start_0 .. :try_end_0} :
  13. catch_1 # catch_1
  14. move-result v1  #如果出现异常这里不会执行,会跳转到catch_1标号处
  15. .line 21
  16. .local v1, i:I    #.local声明的变量作用域在.local声明与.end local 之间
  17. :try_start_1  #第2个try 开始
  18. div-int v2, p1, v1  # 第1个参数除以第2个参数
  19. .line 22
  20. .local v2, m:I    #m为商
  21. mul-int v5, v2, v1  #m * i
  22. sub-int v3, p1, v5  #v3 为余数
  23. .line 23
  24. .local v3, n:I
  25. const-string v5, ”\u5171\u6709%d\u53ea\u9e21\u817f\uff0c%d
  26. \u4e2a\u4eba\u5e73\u5206\uff0c\u6bcf\u4eba\u53ef\u5206\u5f97%d
  27. \u53ea\uff0c\u8fd8\u5269\u4e0b%d\u53ea”   # 格式化字符串
  28. const/4 v6, 0x4
  29. new-array v6, v6, [Ljava/lang/Object;
  30. const/4 v7, 0x0
  31. .line 24
  32. invoke-static {p1}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
  33. move-result-object v8
  34. aput-object v8, v6, v7
  35. const/4 v7, 0x1
  36. invoke-static {v1}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
  37. move-result-object v8
  38. aput-object v8, v6, v7
  39. const/4 v7, 0x2
  40. invoke-static {v2}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
  41. move-result-object v8
  42. aput-object v8, v6, v7
  43. const/4 v7, 0x3
  44. invoke-static {v3}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
  45. move-result-object v8
  46. aput-object v8, v6, v7
  47. .line 23
  48. invoke-static {v5, v6}, Ljava/lang/String;
  49. ->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
  50. move-result-object v4
  51. .line 25
  52. .local v4, str:Ljava/lang/String;
  53. const/4 v5, 0x0
  54. invoke-static {p0, v4, v5}, Landroid/widget/Toast;
  55. ->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)
  56. Landroid/widget/Toast;
  57. move-result-object v5
  58. invoke-virtual {v5}, Landroid/widget/Toast;->show()V  # 使用Toast 显示格
  59. 式化后的结果
  60. :try_end_1  #第2个try 结束
  61. .catch Ljava/lang/ArithmeticException; {:try_start_1 .. :try_end_1} :
  62. catch_0   # catch_0
  63. .catch Ljava/lang/NumberFormatException; {:try_start_1 .. :try_end_1} :
  64. catch_1   # catch_1
  65. .line 33
  66. .end local v1           #i:I
  67. .end local v2           #m:I
  68. .end local v3           #n:I
  69. .end local v4           #str:Ljava/lang/String;
  70. :goto_0
  71. return-void  # 方法返回
  72. .line 26
  73. .restart local v1       #i:I
  74. :catch_0
  75. move-exception v0
  76. .line 27
  77. .local v0, e:Ljava/lang/ArithmeticException;
  78. :try_start_2  #第3个try 开始
  79. const-string v5, “\u4eba\u6570\u4e0d\u80fd\u4e3a0” #“人数不能为0”
  80. const/4 v6, 0x0
  81. invoke-static {p0, v5, v6}, Landroid/widget/Toast;
  82. ->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)
  83. Landroid/widget/Toast;
  84. move-result-object v5
  85. invoke-virtual {v5}, Landroid/widget/Toast;->show()V  # 使用Toast 显示异    常原因
  86. :try_end_2    #第3个try 结束
  87. .catch Ljava/lang/NumberFormatException; {:try_start_2 .. :try_end_2} :
  88. catch_1
  89. goto :goto_0 #返回
  90. .line 29
  91. .end local v0           #e:Ljava/lang/ArithmeticException;
  92. .end local v1           #i:I
  93. :catch_1
  94. move-exception v0
  95. .line 30
  96. .local v0, e:Ljava/lang/NumberFormatException;
  97. const-string v5, “\u65e0\u6548\u7684\u6570\u503c\u5b57\u7b26\u4e32”
  98. #“无效的数值字符串”
  99. invoke-static {p0, v5, v9}, Landroid/widget/Toast;
  100. ->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)
  101. Landroid/widget/Toast;
  102. move-result-object v5
  103. invoke-virtual {v5}, Landroid/widget/Toast;->show()V  # 使用Toast 显示异
  104. 常原因
  105. goto :goto_0 #返回
  106. .end method

整段代码的功能比较简单,输入鸡腿数与人数,然后使用Toast弹出鸡腿的分配方案。传入人数时为了演示Try/Catch效果,使用了String 类型。代码中有两种情况下会发生异常:第一种是将String 类型转换成 int 类型时可能会发生 NumberFormatException异常;第二种是计算分配方法时除数为零的ArithmeticException异常。

在Dalvik 指令集中,并没有与Try/Catch相关的指令,在处理Try/Catch语句时,是通过相关的数据结构来保存异常信息的。

小结

静态分析是软件分析过程中最基础也是最重要的一种手段,我们向Android逆向破解又迈进了一大步。

smali语法详解的更多相关文章

  1. (3)Smali系列学习之Smali语法详解

    数据类型 Dalvik字节码只有两种格式:基本类型和引用类型.对象和数组属于引用类型 语法 含义 V void,只用于返回值类型 Z boolean B byte S short C char I i ...

  2. (4)Smali系列学习之Smali语法详解内部类

    在这一节,我们来介绍一下内部类.对于Java文件中的每一个内部类,都会产生一个单独的smali文件,比如ActivityThread$1.smali.这些文件的命名规范是如果是匿名内部类,则命名规则是 ...

  3. Velocity魔法堂系列二:VTL语法详解

    一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...

  4. Hive笔记--sql语法详解及JavaAPI

    Hive SQL 语法详解:http://blog.csdn.net/hguisu/article/details/7256833Hive SQL 学习笔记(常用):http://blog.sina. ...

  5. Hadoop Hive sql语法详解

    Hadoop Hive sql语法详解 Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据,可以将结构 化的数据文件 ...

  6. Thymeleaf3语法详解和实战

    Thymeleaf3语法详解 Thymeleaf是Spring boot推荐使用的模版引擎,除此之外常见的还有Freemarker和Jsp.Jsp应该是我们最早接触的模版引擎.而Freemarker工 ...

  7. Xpath语法详解

    1.简介 XPath是一门在XML和HTML文档中查找信息的语言,可以用来在XML和HTML文档中对元素和属性进行遍历 XPath的安装 Chrome插件XPath Helper 点Chrome浏览器 ...

  8. mysql用户授权、数据库权限管理、sql语法详解

    mysql用户授权.数据库权限管理.sql语法详解 —— NiceCui 某个数据库所有的权限 ALL 后面+ PRIVILEGES SQL 某个数据库 特定的权限SQL mysql 授权语法 SQL ...

  9. Java8的Stream语法详解(转载)

    1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...

随机推荐

  1. ubuntu开启慢日志

    ubuntu 开启mysql日志记录 1.找到mysql的配置文件sudo vim /etc/mysql/my.cnf将下面两行的#去掉#general_log_file = /var/log/mys ...

  2. 大数据分析引擎Apache Flink

    Apache Flink是一个高效.分布式.基于Java实现的通用大数据分析引擎,它具有分布式 MapReduce一类平台的高效性.灵活性和扩展性以及并行数据库查询优化方案,它支持批量和基于流的数据分 ...

  3. Jaxb 完全手册

    Jaxb是JavaEE的规范.全称Java Architecture for XML Binding. 可以根据XML Schema产生Java类的技术.JAXB也提供了将XML实例文档反向生成Jav ...

  4. Oracle RAC时间同步(NTP/CTSS)

    1.RAC 相关时间同步(time synchronization)Oracle Grid可用两种方式进行时间同步1)基于OS的NTP2)基于clusterware的CTSS(Cluster Time ...

  5. vue 父组件通过props向子组件传递数据/方法的方式

    参考网址:https://segmentfault.com/a/1190000010507616 下面栗子中, callback是传递父组件的方法, mutationName是传递父组件的数据, Ap ...

  6. which/whereis/locate/find的区别

    which--在$PATH目录下查找文件 whereis--在预定目录下(whereis -l查看)查找文件 locate--在数据库中查找目录或文件 find--遍历目录查找文件 说明: 1.关于w ...

  7. input实时监听

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  8. Tomcat压缩传输设置

    1.配置位于server.xml文件中的Connector节点下,具体参数如下: 参数 默认值 参数说明 compression off 是否开启压缩传输 compressableMimeType t ...

  9. zabbix3.4.7版本饼图显示问题

    问题描述 最近使用zabbix3.4.7版本,发现监控Linux的主机关联系统自带的Template OS Linux模版之后,磁盘空间饼图显示有问题,出现空白,如图所示 查看之后,确定为自带的Lem ...

  10. zabbix3.4.7触发器表达式详解

    zabbix触发器表达式详解 概述:触发器中的表达式使用很灵活,我们可以创建一个复杂的逻辑测试监控,触发器表达式形式如下: {<server>:<key>.<functi ...