BubblePig 发表于 2018-2-15 16:26

Android逆向-Android逆向基础10(so逻辑分析)

新年快乐呀
# 0x00 前言
## 导航
博客导航[戳这里](http://blog.csdn.net/qq_36869808/article/details/79270225)
练习资源[戳这里](http://blog.csdn.net/qq_36869808/article/details/79290420)

## 说明

在so文件的分析上,我们需要对一些ARM汇编的逻辑实现。
在代码逻辑上,只对if,switch,还有循环进行一个demo分析和创建。可能会篇幅比较大。

## 内容
1.if逻辑NDK编程
2.if逻辑ARM分析
3.switch逻辑NDK编程
4.switch逻辑ARM分析
5.循环逻辑NDK编程
6.循环逻辑ARM分析

# 0x01 if逻辑NDK编程
demo使用之前的demo,如果有兴趣,可以去看看
博客导航[戳这里](http://blog.csdn.net/qq_36869808/article/details/79270225)

## 说明
demo主要实现一个输入,然后根据输入的内容返回不同的内容。在Native层进行实现。

## 第一步 函数书写
首先添加一个函数,然后使用 ALT+Enter进行自动创建
![这里写图片描述](http://t1.aixinxi.net/o_1c6a98p72mpa1gmi1e601f4p8nsa.png-j.jpg)

## 第二步 自动生成
在.cpp文件里会自动生成一个函数

```
JNIEXPORT jstring JNICALL
Java_com_example_hanlei_myapplication_MainActivity_panduan(JNIEnv *env, jobject instance, jint i) {

    // TODO


    return env->NewStringUTF(returnValue);
}

```

## 第三步 编写c语言代码

```
JNIEXPORT jstring JNICALL
Java_com_example_hanlei_myapplication_MainActivity_panduan(JNIEnv *env, jobject instance, jint i) {

    if (i==1)
    {
      return env->NewStringUTF("I LOVE YOU!");
    }
    return env->NewStringUTF("Sorrry");
}
```

## 第四步 编写xml

```
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.hanlei.myapplication.MainActivity">

    <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/et"
      android:hint="请输入数字"
      android:numeric="integer"
      />
    <TextView
      android:id="@+id/sample_text"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Hai ,my Love"
         />
    <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Go"
      android:id="@+id/btn"/>

</LinearLayout>

```

## 第五步,逻辑编写

这个是MainActivity的代码。
```
package com.example.hanlei.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
private TextView tv;
private EditText et;
    // Used to load the 'native-lib' library on application startup.
    static {
      System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      // Example of a call to a native method
         tv = (TextView) findViewById(R.id.sample_text);
         et=findViewById(R.id.et);
      findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv.setText(panduan(Integer.parseInt(et.getText().toString())));
            }
      });
    }

    /**
   * A native method that is implemented by the 'native-lib' native library,
   * which is packaged with this application.
   */
    public native String stringFromJNI();
    public native String getHelloJni();
    public native void updateFile(String path);
    public native String panduan(int i);
}

```

这个是主要的代码。

```
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv.setText(panduan(Integer.parseInt(et.getText().toString())));
            }
      });
```

## 第六步 测试
![这里写图片描述](http://t1.aixinxi.net/o_1c6agabnf6rt1h831ld21ec1nkoa.png-j.jpg)
![这里写图片描述](http://t1.aixinxi.net/o_1c6agc2uf1skt16gdvnk1gb91er1a.png-j.jpg)
![这里写图片描述](http://t1.aixinxi.net/o_1c6agee5g1cqn10o026a1cu96f5a.png-j.jpg)

## 总结
很简单,不过多解释。

# 0x02 if逻辑反汇编分析
反汇编分析,当然是要丢在IDA里进行分析了。
这里有个问题就是,IDA只有32位才可以使用F5插件,我之前不知道,坑了好久。
我假装自己不知道自己的函数名称啊什么的。就按照流程进行分析。
本来第一步是要进行试玩的,demo试玩我就算了吧。
## 第一步,反编译,找到函数。
反编译,找Android Killer

![这里写图片描述](http://t1.aixinxi.net/o_1c6ai60fd8mn1n1cbk5hcg1067a.png-j.jpg)

找到函数之后进行反汇编。
## 第二步,反汇编

![这里写图片描述](http://t1.aixinxi.net/o_1c6aitoej7vp167jjjkgb6u46a.png-j.jpg)

双击进入函数。

![这里写图片描述](http://t1.aixinxi.net/o_1c6aj294hs6719h1ga376q1cmqa.png-j.jpg)

## 第三步 F5插件

![这里写图片描述](http://t1.aixinxi.net/o_1c6aj5c951ncc1csf3i7eqgiq7a.png-j.jpg)

F5插件真的比较好用,但是我们还是以ARM为主。

## 第四步 ARM分析
首先来看下流程图

![这里写图片描述](http://t1.aixinxi.net/o_1c6ajd8471v6j1tqrblq7njf7qa.png-j.jpg)

从流程图上可以看到这是一个if逻辑的流程图。


我们来看主要代码

```
.text:00004644               PUSH            {R7,LR}
.text:00004646               MOV             R7, SP
.text:00004648               SUB             SP, SP, #0x20
.text:0000464A               MOV             R3, R2
.text:0000464C               MOV             R12, R1
.text:0000464E               MOV             LR, R0
.text:00004650               STR             R0,
.text:00004652               STR             R1,
.text:00004654               STR             R2,
.text:00004656               LDR             R0,
.text:00004658               CMP             R0, #1
.text:0000465A               STR             R3,
.text:0000465C               STR.W         R12,
.text:00004660               STR.W         LR,
.text:00004664               BNE             loc_4676
.text:00004666               B               loc_4668
```

```
PUSH            {R7,LR}
```
PUSH 是入栈的意思
R7是通用寄存器
LR就是:R14:链接寄存器(LR) LR是链接寄存器,是ARM处理器中一个有特殊用途的寄存器,当调用函数时,返回地址即PC的值被保存到LR中(mov lr,pc)。

那么这句话的意思就是把R7 和LR入栈


```
MOV             R7, SP
```
这句话好理解,就是把sp的值给R7。
在随机存储器区划出一块区域作为堆栈区,数据可以一个个顺序地存入(压入)到这个区域之中,这个过程称为‘压栈’(push )。通常用一个指针(堆栈指针 SP---StackPointer)实现做一次调整,SP总指向最后一个压入堆栈的数据所在的数据单元(栈顶)。


```
SUB             SP, SP, #0x20
```
SUB 是减法运算。
简单的翻译一下就是:sp=sp-#0x20
这里的#0x20就是十六进制的意思。

```
MOV             R3, R2
```
R3=R2

```
MOV             R12, R1
```
R12=R1

```
MOV             LR, R0
```
LR=R0

```
STR             R0,
```
STR{条件}源寄存器,<存储器地址>
STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用。

翻译一下就是 把R0这里的数据送到中

```
STR             R1,
```
同理

```
STR             R2,
```
同理

```
LDR             R0,
```
LDR 伪指令用于加载立即数或一个地址值到指定寄存器.

```
CMP             R0, #1
```
CMP是比较命令,R0和#1进行比较
CF=1,因为有借位
OF=0,未溢出
SF=1,结果是负数
ZF=0,结果不全是零

```
STR             R3,
```
的数据送入R3中

```
STR.W         R12,
```
.W 是wide。指定汇编器必须为这条指令选择一个32位的编码模式。如果办不到,汇编器报错。

```
STR.W         LR,
```

```
BNE             loc_4676
```
bne: 数据跳转指令,标志寄存器中Z标志位不等于零时, 跳转到BNE后标签处
也就是说当Z不等于0的时候也就是不相等的时候就会跳转到loc_4676

```
B               loc_4668
```
无条件跳转

恩,我大概懂了。

如果不满足就跳转到这里。
```
loc_4668                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+22↑j
.text:00004668               LDR             R0, ; this
.text:0000466A               LDR             R1, =(aILoveYou - 0x4670)
.text:0000466C               ADD             R1, PC; "I LOVE YOU!"
.text:0000466E               BLX             j__ZN7_JNIEnv12NewStringUTFEPKc ; _JNIEnv::NewStringUTF(char const*)
.text:00004672               STR             R0,
.text:00004674               B               loc_4684
```
如果满足的话,叫跳转到这里

```
.text:00004676
.text:00004676 loc_4676                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+20↑j
.text:00004676               LDR             R0, ; this
.text:00004678               LDR             R1, =(aSorrry - 0x467E)
.text:0000467A               ADD             R1, PC; "Sorrry"
.text:0000467C               BLX             j__ZN7_JNIEnv12NewStringUTFEPKc ; _JNIEnv::NewStringUTF(char const*)
.text:00004680               STR             R0,
.text:00004682               B               loc_4684
```

最后就会归结在这里:

```
oc_4684                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+30↑j
.text:00004684                                       ; Java_com_example_hanlei_myapplication_MainActivity_panduan+3E↑j
.text:00004684               LDR             R0,
.text:00004686               ADD             SP, SP, #0x20
.text:00004688               POP             {R7,PC}
```

其中有很多是自带的东西,所以重要的东西画出来。

首先是这个,参数

![这里写图片描述](http://t1.aixinxi.net/o_1c6an3mqinq1531aogdqc4rga.png-j.jpg)

调用参数,然后进行比较

![这里写图片描述](http://t1.aixinxi.net/o_1c6an5imsbo761e3do16to1he3a.png-j.jpg)

根据寄存器进行跳转

![这里写图片描述](http://t1.aixinxi.net/o_1c6andh7j80i1l96d671m01ek0a.png-j.jpg)

# 0x03 switch逻辑NDK编程

## 说明

直接使用上次的demo来进行更改,然后直接修改c语言程序就可以了。

## c文件编写

```
JNIEXPORT jstring JNICALL
Java_com_example_hanlei_myapplication_MainActivity_panduan(JNIEnv *env, jobject instance, jint i) {

    switch(i)
    {
      case 1:
            return env->NewStringUTF("Love");
            break;
      case 2:
            return env->NewStringUTF("ZHUZHU");
            break;
      case 3:
            return env->NewStringUTF("Life");
            break;
    }
    return env->NewStringUTF("Sorrry");
}
```

## 测试说明

![这里写图片描述](http://t1.aixinxi.net/o_1c6aovsov1nns7nm19n8pm0laja.png-j.jpg)

![这里写图片描述](http://t1.aixinxi.net/o_1c6ap145l12s23i91vhcdd1pena.png-j.jpg)

![这里写图片描述](http://t1.aixinxi.net/o_1c6ap23jl1hi51ghf14k61j55nta.png-j.jpg)

![这里写图片描述](http://t1.aixinxi.net/o_1c6ap31n4tp1d6ojt317ms1jfca.png-j.jpg)

## 总结

编写还是非常简单的,只要知道接口函数,在前期没有什么困难的地方。


# 0x04switch逻辑ARM分析

暂停:2018年2月15日02:29:01
原因:该睡觉了。恩,要好好的睡一觉,然后起来学习。

开始时间:2018年2月15日11:33:13
原因:刚吃完午饭

## 直接上IDA分析了
![这里写图片描述](http://t1.aixinxi.net/o_1c6bpb4om54dio1il6rr11oana.png-j.jpg)

```
.text:00004644 ; __unwind {
.text:00004644               PUSH            {R7,LR}
.text:00004646               MOV             R7, SP
.text:00004648               SUB             SP, SP, #0x20
.text:0000464A               MOV             R3, R2
.text:0000464C               MOV             R12, R1
.text:0000464E               MOV             LR, R0
.text:00004650               STR             R0,
.text:00004652               STR             R1,
.text:00004654               STR             R2,
.text:00004656               LDR             R0,
.text:00004658               CMP             R0, #1
.text:0000465A               STR             R3,
.text:0000465C               STR.W         R12,
.text:00004660               STR.W         LR,
.text:00004664               STR             R0,
.text:00004666               BEQ             loc_467A
.text:00004668               B               loc_466A
```

## 逻辑图
![这里写图片描述](http://t1.aixinxi.net/o_1c6bsbll63jf1ps81689cls1v3ha.png-j.jpg)

## 分析

![这里写图片描述](http://t1.aixinxi.net/o_1c6bpd7ku1a073bu1msn1g419fma.png-j.jpg)

首先来说,这些ARM代码,个人理解,就是在进行函数以及函数内参数的初始化过程,也可以理解为在构建一个我们主要ARM进行逻辑运算的环境或者是平台,之后也有一相对应的环境释放。

我们来看一下主要的逻辑判断部分。

```
CMP             R0, #1
```

用R0和#1进行比较。

```
BEQ             loc_467A
```

标志寄存器中Z标志位等于零时, 跳转到BEQ后标签处。

然后就跳转到这里了:

![这里写图片描述](http://t1.aixinxi.net/o_1c6bt25srbkh8nc4ed1pqa1586a.png-j.jpg)

突然发现判断逻辑好简单,可能是我太无知了。

```
B               loc_466A
```
无条件跳转到下一个判断。
之前还在想多个if怎么实现,现在发现还是按照一个块一个来进行运行。
现在知道了那两周学习8086不是白学习的了。

```
loc_466A                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+24↑j
.text:0000466A               LDR             R0,
.text:0000466C               CMP             R0, #2
.text:0000466E               BEQ             loc_4688
.text:00004670               B               loc_4672
.text:00004672 ; ---------------------------------------------------------------------------
.text:00004672
.text:00004672 loc_4672                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+2C↑j
.text:00004672               LDR             R0,
.text:00004674               CMP             R0, #3
.text:00004676               BEQ             loc_4696
.text:00004678               B               loc_46A4
.text:0000467A ; ---------------------------------------------------------------------------
.text:0000467A
.text:0000467A loc_467A                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+22↑j
.text:0000467A               LDR             R0, ; this
.text:0000467C               LDR             R1, =(aLove - 0x4682)
.text:0000467E               ADD             R1, PC; "Love"
.text:00004680               BLX             j__ZN7_JNIEnv12NewStringUTFEPKc ; _JNIEnv::NewStringUTF(char const*)
.text:00004684               STR             R0,
.text:00004686               B               loc_46B2
.text:00004688 ; ---------------------------------------------------------------------------
.text:00004688
.text:00004688 loc_4688                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+2A↑j
.text:00004688               LDR             R0, ; this
.text:0000468A               LDR             R1, =(aZhuzhu - 0x4690)
.text:0000468C               ADD             R1, PC; "ZHUZHU"
.text:0000468E               BLX             j__ZN7_JNIEnv12NewStringUTFEPKc ; _JNIEnv::NewStringUTF(char const*)
.text:00004692               STR             R0,
.text:00004694               B               loc_46B2
.text:00004696 ; ---------------------------------------------------------------------------
.text:00004696
.text:00004696 loc_4696                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+32↑j
.text:00004696               LDR             R0, ; this
.text:00004698               LDR             R1, =(aLife - 0x469E)
.text:0000469A               ADD             R1, PC; "Life"
.text:0000469C               BLX             j__ZN7_JNIEnv12NewStringUTFEPKc ; _JNIEnv::NewStringUTF(char const*)
.text:000046A0               STR             R0,
```
这是剩下的代码逻辑,如果有兴趣可以自己进行分析使用。

感觉自己一下次大彻大悟了。
接下来就是循环逻辑了。

# 0x05 循环逻辑NDK编程

步骤和之前一样,我只是改变一下c代码。

## c代码编写

写一个简单的逻辑。
就是判断质数。

```
JNIEXPORT jstring JNICALL
Java_com_example_hanlei_myapplication_MainActivity_panduan(JNIEnv *env, jobject instance, jint i) {

    int j;
    int t=1;
    if(i==1)
    {
      return env->NewStringUTF("Sorrry");
    }
    if(i==2)
    {
      return env->NewStringUTF("ZHUZHU I Love YOU");
    }
    for(j=2;j<i;j++)
    {
      if(i%j==0)
      {
            t=0;
      }
    }
    if(t==1)
    {
      return env->NewStringUTF("ZHUZHU I Love YOU");
    }
    return env->NewStringUTF("Sorrry");
}
```

## 测试说明

![这里写图片描述](http://t1.aixinxi.net/o_1c6buvpqm43b1lvgqg9igs10vca.png-j.jpg)

![这里写图片描述](http://t1.aixinxi.net/o_1c6bva6cd1spj4t2qh2og3rqva.png-j.jpg)

![这里写图片描述](http://t1.aixinxi.net/o_1c6bvb1bk14pmlq8p2nq8017qa.png-j.jpg)

# 0x06 循环逻辑ARM分析

## 用IDA打开so文件

![这里写图片描述](http://t1.aixinxi.net/o_1c6bvq3c0ufvtrm1d941g3v1f37a.png-j.jpg)

```
PUSH            {R7,LR}
.text:00004646               MOV             R7, SP
.text:00004648               SUB             SP, SP, #0x28
.text:0000464A               MOV             R3, R2
.text:0000464C               MOV             R12, R1
.text:0000464E               MOV             LR, R0
.text:00004650               STR             R0,
.text:00004652               STR             R1,
.text:00004654               STR             R2,
.text:00004656               MOVS            R0, #1
.text:00004658               STR             R0,
.text:0000465A               LDR             R0,
.text:0000465C               CMP             R0, #1
.text:0000465E               STR             R3,
.text:00004660               STR.W         R12,
.text:00004664               STR.W         LR,
.text:00004668               BNE             loc_467A
.text:0000466A               B               loc_466C
```

这里是主体部分,类似于main的开头

## 开始逻辑分析
这些ARM代码就是在搭建环境。
```
PUSH            {R7,LR}
.text:00004646               MOV             R7, SP
.text:00004648               SUB             SP, SP, #0x28
.text:0000464A               MOV             R3, R2
.text:0000464C               MOV             R12, R1
.text:0000464E               MOV             LR, R0
.text:00004650               STR             R0,
.text:00004652               STR             R1,
.text:00004654               STR             R2,
```

```
MOVS            R0, #1
```

MOV一般不影响CPSR, 除非执行类似MOV pc, lr,效果上等同于BX lr,可能会影响到T标志位
MOVS总是会影响CPSR, 包括N,Z,C标志位,执行MOVS pc, lr时,CPSR会被SPSR覆盖(内核态,USER和SYSTEM模式下没有SPSR)

再简单的说就是 R0=#1

```
STR             R0,
```
然后把这个值存放在 这里

```
LDR             R0,
```
把的值取出来给R0


```
CMP             R0, #1
```
然后拿出来比较

```
STR             R3,
.text:00004660               STR.W         R12,
.text:00004664               STR.W         LR,
```
其实我真的不知道这是什么东西,如果有人知道的话可以告诉我不。反正我忽略了。不影响分析逻辑

```
BNE             loc_467A
```
bne: 数据跳转指令,标志寄存器中Z标志位不等于零时, 跳转到BNE后标签处

如果不等于#1的话就会进行跳转

```
B               loc_466C
```
如果相等,就会执行无条件跳转。


我们现在来看loc_466C这一个块

## loc_466C块分析

```
loc_466C                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+26↑j
.text:0000466C               LDR             R0, ; this
.text:0000466E               LDR             R1, =(aSorrry - 0x4674)
.text:00004670               ADD             R1, PC; "Sorrry"
.text:00004672               BLX             j__ZN7_JNIEnv12NewStringUTFEPKc ; _JNIEnv::NewStringUTF(char const*)
.text:00004676               STR             R0,
.text:00004678               B               loc_46E4
```

调用接口函数,返回一个字符串。"Sorrry";
程序最后跳转到 loc_46E4

##loc_46E4块分析

```
loc_46E4                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+34↑j
.text:000046E4                                       ; Java_com_example_hanlei_myapplication_MainActivity_panduan+4A↑j ...
.text:000046E4               LDR             R0,
.text:000046E6               ADD             SP, SP, #0x28
.text:000046E8               POP             {R7,PC}
```
这个就是拆环境的部分。

##loc_467A块分析

```
loc_467A                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+24↑j
.text:0000467A               LDR             R0,
.text:0000467C               CMP             R0, #2
.text:0000467E               BNE             loc_4690
.text:00004680               B               loc_4682
```

来看第一句

```
LDR             R0,
```
这里的数据给R0       
之前的数据就是我们输入的数据。

```
CMP             R0, #2
BNE             loc_4690
B               loc_4682
```

如果等于#2 就跳转到loc_4682,如果不等于#2就跳转到loc_4690。如果等于就会跳转到loc_4682

## loc_4682块分析

```
loc_4682                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+3C↑j
.text:00004682               LDR             R0, ; this
.text:00004684               LDR             R1, =(aZhuzhuILoveYou - 0x468A)
.text:00004686               ADD             R1, PC; "ZHUZHU I Love YOU"
.text:00004688               BLX             j__ZN7_JNIEnv12NewStringUTFEPKc ; _JNIEnv::NewStringUTF(char const*)
.text:0000468C               STR             R0,
.text:0000468E               B               loc_46E4
```
这一块就是返回"ZHUZHU I Love YOU"这个字符串,然后到loc_46E4,恢复环境。程序结束。
## loc_4690块

这个是不等于#2时进行跳转的


```
loc_4690                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+3A↑j
.text:00004690               MOVS            R0, #2
.text:00004692               STR             R0,
.text:00004694               B               loc_4696
```
来看第一句
```
MOVS            R0, #2
```

把#2的值给R0

```
STR             R0,
```
然后把R0的值给这个存储位置。

```
B               loc_4696
```
跳转到 loc_4696块。

## loc_4696块分析

```
loc_4696                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+50↑j
.text:00004696                                       ; Java_com_example_hanlei_myapplication_MainActivity_panduan+7A↓j
.text:00004696               LDR             R0,
.text:00004698               LDR             R1,
.text:0000469A               CMP             R0, R1
.text:0000469C               BGE             loc_46C0
.text:0000469E               B               loc_46A0
```

第一句

```
LDR             R0,
```
把取出来给R0

```
LDR             R1,
```
把的数据给R1,这个就是我们输入的数据。

```
CMP             R0, R1
```
R0和R1比较

```
BGE             loc_46C0
```

跳转的意思,BGE就是大于或等于才跳。也就是说当R0>=R1就跳转到loc_46C0


```
B               loc_46A0
```
其他情况跳转到 loc_46A0

## loc_46C0 块分析

```
loc_46C0                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+58↑j
.text:000046C0               LDR             R0,
.text:000046C2               CMP             R0, #1
.text:000046C4               BNE             loc_46D6
.text:000046C6               B               loc_46C8
```

```
LDR             R0,
```
把的值拿出来给R0

```
CMP             R0, #1
```
然后进行比较。

```
BNE             loc_46D6
```
不相等就跳转到loc_46D6,loc_46D6返回sorry

```
B               loc_46C8
```
相等就跳转到loc_46C8,返回 "ZHUZHU I Love YOU"



## loc_46A0块分析

```
loc_46A0                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+5A↑j
.text:000046A0               LDR             R0,
.text:000046A2               LDR             R1,
.text:000046A4               BL            sub_1422C
.text:000046A8               CMP             R1, #0
.text:000046AA               STR             R0,
.text:000046AC               BNE             loc_46B6
.text:000046AE               B               loc_46B0
```

第一句

```
LDR             R0,
```
取出的数据给R0,就是输入的数值。

```
LDR             R1,
```
去除 的数据给R1, 就是在loc_4690中存取的数据,现在是#2

```
BL            sub_1422C
```

跳转到 sub_1422C

我们来看看 sub_1422C

```
sub_1422C                               ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+60↑p
.text:0001422C
.text:0001422C ; FUNCTION CHUNK AT .text:0001421A SIZE 00000012 BYTES
.text:0001422C
.text:0001422C               CMP             R1, #0
.text:0001422E               BEQ             loc_1421A
.text:00014230               PUSH.W          {R0,R1,LR}
.text:00014234               BL            sub_1416C
.text:00014238               POP.W         {R1,R2,LR}
.text:0001423C               MUL.W         R3, R2, R0
.text:00014240               SUB.W         R1, R1, R3
.text:00014244               BX            LR
.text:00014244 ; End of function sub_1422C
```

```
CMP             R1, #0
```
比较R1和0,之前的R1就是#2

```
BEQ             loc_1421A
```
相等则进行跳转

```
PUSH.W          {R0,R1,LR}
```
入栈

```
BL            sub_1416C
```
跳转到sub_1416c


sub_1416c

```
sub_1416C                               ; CODE XREF: sub_1422C+8↓p
.text:0001416C               EOR.W         R12, R0, R1
.text:00014170               IT MI
.text:00014172               NEGMI         R1, R1
.text:00014174               SUBS            R2, R1, #1
.text:00014176               BEQ             loc_141EA
.text:00014178               MOVS            R3, R0
.text:0001417A               IT MI
.text:0001417C               NEGMI         R3, R0
.text:0001417E               CMP             R3, R1
.text:00014180               BLS             loc_141F4
.text:00014182               TST             R1, R2
.text:00014184               BEQ             loc_14204
.text:00014186               CLZ.W         R2, R1
.text:0001418A               CLZ.W         R0, R3
.text:0001418E               SUB.W         R0, R2, R0
.text:00014192               MOV.W         R2, #1
.text:00014196               LSL.W         R1, R1, R0
.text:0001419A               LSL.W         R2, R2, R0
.text:0001419E               MOV.W         R0, #0
```

```
EOR.W         R12, R0, R1
```

逻辑异或EOR(Exclusive OR)指令将寄存器<Rn>中的值和<shifter_operand>的值执行按位“异或”操作,并将执行结果存储到目的寄存器<Rd>中,同时根据指令的执行结果更新CPSR中相应的条件标志位。

```
IT MI
```
![这里写图片描述](http://t1.aixinxi.net/o_1c6c6sqsi11ht1vbr12pafq21jmua.png-j.jpg)

```
SUBS            R2, R1, #1
```
SUBS中S表示把进位结果写入CPSR

R2=R1-#1然后写入CPSR

之后还有很多。

我们继续来看
loc_46A0

```
BL            sub_1422C
```
这一句的逻辑就是计算R1被整除之后的内容

```
CMP             R1, #0
```
比较是不是相等


```
BNE             loc_46B6
```
不相等跳转到loc_46B6模块

如果相等的话。

## loc_46B6模块分析

```
loc_46B8                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan:loc_46B6↑j
.text:000046B8               LDR             R0,
.text:000046BA               ADDS            R0, #1
.text:000046BC               STR             R0,
.text:000046BE               B               loc_4696
```

```
LDR             R0,
ADDS            R0, #1
STR             R0,
```
取出来,把变量+1然后存进去

```
B               loc_4696
```

跳转到 loc_4696

这里就是整个循环了。


##loc_46B0模块分析

```
loc_46B0                              ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+6A↑j
.text:000046B0               MOVS            R0, #0
.text:000046B2               STR             R0,
.text:000046B4               B               loc_46B6
```

这个模块就是更改存储的值改变为#0

然后就是继续循环。

## 总结

终于分析完了。但是收获还是很明显的。你和ARM玩的越久,ARM就越喜欢你。

# 0x07 结束语

## 收获:
1.最大的收获就是对ARM汇编的理解程度变高了。
2.而且对编程还有一些流程分析有了很深的认识。
3.了解到之前学习8086有多重要了。
## 结束时间:
2018年2月15日16:21:05
## 其它说明
之后可能还要对其他的实例so进行分析。

chenty 发表于 2018-2-15 18:08

只能说好牛逼啊

ABB327 发表于 2018-2-15 22:33

祝大家新春快乐!

chenjingyes 发表于 2018-2-16 00:28

楼主新春快乐谢谢分享

yhxi1714 发表于 2018-2-16 22:39

楼主的工具能否共享一份,谢谢啊,看了收获很大

王珞丹 发表于 2018-2-17 19:14

学习一下了。。。。

惘然记 发表于 2018-2-19 14:43

很不错,虽然看不太懂!!

BubblePig 发表于 2018-2-19 16:37

惘然记 发表于 2018-2-19 14:43
很不错,虽然看不太懂!!

如果自己搞一遍的话就简单啦

ezsf 发表于 2018-3-13 19:54

很好的so逆向学习demo,感谢分享

Ouyang520 发表于 2018-3-14 11:56

什么时候来一系列安卓脱壳教程,那就更好了
页: [1] 2
查看完整版本: Android逆向-Android逆向基础10(so逻辑分析)