Android逆向-Android逆向基础10(so文件分析大合集)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36869808/article/details/79327350

0x00 前言

导航

博客导航戳这里
练习资源戳这里

说明

在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,如果有兴趣,可以去看看
博客导航戳这里

说明

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

第一步 函数书写

首先添加一个函数,然后使用 ALT+Enter进行自动创建
这里写图片描述

第二步 自动生成

在.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())));
            }
        });

第六步 测试

这里写图片描述
这里写图片描述
这里写图片描述

总结

很简单,不过多解释。

0x02 if逻辑反汇编分析

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

第一步,反编译,找到函数。

反编译,找Android Killer

这里写图片描述

找到函数之后进行反汇编。

第二步,反汇编

这里写图片描述

双击进入函数。

这里写图片描述

第三步 F5插件

这里写图片描述

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

第四步 ARM分析

首先来看下流程图

这里写图片描述

从流程图上可以看到这是一个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, [SP,#0x28+var_10]
.text:00004652                 STR             R1, [SP,#0x28+var_14]
.text:00004654                 STR             R2, [SP,#0x28+var_18]
.text:00004656                 LDR             R0, [SP,#0x28+var_18]
.text:00004658                 CMP             R0, #1
.text:0000465A                 STR             R3, [SP,#0x28+var_1C]
.text:0000465C                 STR.W           R12, [SP,#0x28+var_20]
.text:00004660                 STR.W           LR, [SP,#0x28+var_24]
.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—Stack Pointer)实现做一次调整,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, [SP,#0x28+var_10]

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

翻译一下就是 把R0这里的数据送到[SP,#0x28+var_10]中

STR             R1, [SP,#0x28+var_14]

同理

STR             R2, [SP,#0x28+var_18]

同理

 LDR             R0, [SP,#0x28+var_18]

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

 CMP             R0, #1

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

 STR             R3, [SP,#0x28+var_1C]

[SP,#0x28+var_1C] 的数据送入R3中

STR.W           R12, [SP,#0x28+var_20]

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

STR.W           LR, [SP,#0x28+var_24]
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, [SP,#0x28+var_10] ; 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, [SP,#0x28+var_C]
.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, [SP,#0x28+var_10] ; 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, [SP,#0x28+var_C]
.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, [SP,#0x28+var_C]
.text:00004686                 ADD             SP, SP, #0x20
.text:00004688                 POP             {R7,PC}

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

首先是这个,参数

这里写图片描述

调用参数,然后进行比较

这里写图片描述

根据寄存器进行跳转

这里写图片描述

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");
}

测试说明

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

总结

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

0x04 switch逻辑ARM分析

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

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

直接上IDA分析了

这里写图片描述

.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, [SP,#0x28+var_10]
.text:00004652                 STR             R1, [SP,#0x28+var_14]
.text:00004654                 STR             R2, [SP,#0x28+var_18]
.text:00004656                 LDR             R0, [SP,#0x28+var_18]
.text:00004658                 CMP             R0, #1
.text:0000465A                 STR             R3, [SP,#0x28+var_1C]
.text:0000465C                 STR.W           R12, [SP,#0x28+var_20]
.text:00004660                 STR.W           LR, [SP,#0x28+var_24]
.text:00004664                 STR             R0, [SP,#0x28+var_28]
.text:00004666                 BEQ             loc_467A
.text:00004668                 B               loc_466A

逻辑图

这里写图片描述

分析

这里写图片描述

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

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

CMP             R0, #1

用R0和#1进行比较。

BEQ             loc_467A

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

然后就跳转到这里了:

这里写图片描述

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

B               loc_466A

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

loc_466A                                ; CODE XREF: Java_com_example_hanlei_myapplication_MainActivity_panduan+24↑j
.text:0000466A                 LDR             R0, [SP,#0x28+var_28]
.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, [SP,#0x28+var_28]
.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, [SP,#0x28+var_10] ; 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, [SP,#0x28+var_C]
.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, [SP,#0x28+var_10] ; 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, [SP,#0x28+var_C]
.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, [SP,#0x28+var_10] ; 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, [SP,#0x28+var_C]

这是剩下的代码逻辑,如果有兴趣可以自己进行分析使用。

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

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");
}

测试说明

这里写图片描述

这里写图片描述

这里写图片描述

0x06 循环逻辑ARM分析

用IDA打开so文件

这里写图片描述

 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, [SP,#0x30+var_10]
.text:00004652                 STR             R1, [SP,#0x30+var_14]
.text:00004654                 STR             R2, [SP,#0x30+var_18]
.text:00004656                 MOVS            R0, #1
.text:00004658                 STR             R0, [SP,#0x30+var_20]
.text:0000465A                 LDR             R0, [SP,#0x30+var_18]
.text:0000465C                 CMP             R0, #1
.text:0000465E                 STR             R3, [SP,#0x30+var_24]
.text:00004660                 STR.W           R12, [SP,#0x30+var_28]
.text:00004664                 STR.W           LR, [SP,#0x30+var_2C]
.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, [SP,#0x30+var_10]
.text:00004652                 STR             R1, [SP,#0x30+var_14]
.text:00004654                 STR             R2, [SP,#0x30+var_18]
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, [SP,#0x30+var_20]

然后把这个值存放在 [SP,#0x30+var_20]这里

 LDR             R0, [SP,#0x30+var_18]

把[SP,#0x30+var_18]的值取出来给R0

CMP             R0, #1

然后拿出来比较

STR             R3, [SP,#0x30+var_24]
.text:00004660                 STR.W           R12, [SP,#0x30+var_28]
.text:00004664                 STR.W           LR, [SP,#0x30+var_2C]

其实我真的不知道这是什么东西,如果有人知道的话可以告诉我不。反正我忽略了。不影响分析逻辑

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, [SP,#0x30+var_10] ; 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, [SP,#0x30+var_C]
.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, [SP,#0x30+var_C]
.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, [SP,#0x30+var_18]
.text:0000467C                 CMP             R0, #2
.text:0000467E                 BNE             loc_4690
.text:00004680                 B               loc_4682

来看第一句

 LDR             R0, [SP,#0x30+var_18]

[SP,#0x30+var_18]这里的数据给R0
之前[SP,#0x30+var_18]的数据就是我们输入的数据。

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, [SP,#0x30+var_10] ; 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, [SP,#0x30+var_C]
.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, [SP,#0x30+var_1C]
.text:00004694                 B               loc_4696

来看第一句

MOVS            R0, #2

把#2的值给R0

STR             R0, [SP,#0x30+var_1C]

然后把R0的值给[SP,#0x30+var_1C]这个存储位置。

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, [SP,#0x30+var_1C]
.text:00004698                 LDR             R1, [SP,#0x30+var_18]
.text:0000469A                 CMP             R0, R1
.text:0000469C                 BGE             loc_46C0
.text:0000469E                 B               loc_46A0

第一句

LDR             R0, [SP,#0x30+var_1C]

把[SP,#0x30+var_1C]取出来给R0

LDR             R1, [SP,#0x30+var_18]

把[SP,#0x30+var_18]的数据给R1,这个[SP,#0x30+var_18]就是我们输入的数据。

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, [SP,#0x30+var_20]
.text:000046C2                 CMP             R0, #1
.text:000046C4                 BNE             loc_46D6
.text:000046C6                 B               loc_46C8
 LDR             R0, [SP,#0x30+var_20]

把[SP,#0x30+var_20]的值拿出来给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, [SP,#0x30+var_18]
.text:000046A2                 LDR             R1, [SP,#0x30+var_1C]
.text:000046A4                 BL              sub_1422C
.text:000046A8                 CMP             R1, #0
.text:000046AA                 STR             R0, [SP,#0x30+var_30]
.text:000046AC                 BNE             loc_46B6
.text:000046AE                 B               loc_46B0

第一句

 LDR             R0, [SP,#0x30+var_18]

取出[SP,#0x30+var_18]的数据给R0,[SP,#0x30+var_18]就是输入的数值。

LDR             R1, [SP,#0x30+var_1C]

去除 [SP,#0x30+var_1C]的数据给R1, [SP,#0x30+var_1C]就是在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)指令将寄存器中的值和的值执行按位“异或”操作,并将执行结果存储到目的寄存器中,同时根据指令的执行结果更新CPSR中相应的条件标志位。

IT MI

这里写图片描述

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, [SP,#0x30+var_1C]
.text:000046BA                 ADDS            R0, #1
.text:000046BC                 STR             R0, [SP,#0x30+var_1C]
.text:000046BE                 B               loc_4696
LDR             R0, [SP,#0x30+var_1C]
ADDS            R0, #1
STR             R0, [SP,#0x30+var_1C]

取出来,把变量+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, [SP,#0x30+var_20]
.text:000046B4                 B               loc_46B6

这个模块就是更改[SP,#0x30+var_20]存储的值改变为#0

然后就是继续循环。

总结

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

0x07 结束语

收获:

1.最大的收获就是对ARM汇编的理解程度变高了。
2.而且对编程还有一些流程分析有了很深的认识。
3.了解到之前学习8086有多重要了。

结束时间:

2018年2月15日16:21:05

其它说明

之后可能还要对其他的实例so进行分析。

没有更多推荐了,返回首页