本篇文章为大家展示了如何进行Android逆向基础中的so文件分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
在so文件的分析上,我们需要对一些ARM汇编的逻辑实现。
在代码逻辑上,只对if,switch,还有循环进行一个demo分析和创建。可能会篇幅比较大。
1.if逻辑NDK编程
2.if逻辑ARM分析
3.switch逻辑NDK编程
4.switch逻辑ARM分析
5.循环逻辑NDK编程
6.循环逻辑ARM分析
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); }
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 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()))); } });
很简单,不过多解释。
反汇编分析,当然是要丢在IDA里进行分析了。
这里有个问题就是,IDA只有32位才可以使用F5插件,我之前不知道,坑了好久。
我假装自己不知道自己的函数名称啊什么的。就按照流程进行分析。
本来第一步是要进行试玩的,demo试玩我就算了吧。
反编译,找Android Killer
找到函数之后进行反汇编。
双击进入函数。
F5插件真的比较好用,但是我们还是以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}
其中有很多是自带的东西,所以重要的东西画出来。
首先是这个参数
调用参数,然后进行比较
根据寄存器进行跳转
直接使用上次的demo来进行更改,然后直接修改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"); }
编写还是非常简单的,只要知道接口函数,在前期没有什么困难的地方。
暂停:2018年2月15日02:29:01
原因:该睡觉了。恩,要好好的睡一觉,然后起来学习。
开始时间:2018年2月15日11:33:13
原因:刚吃完午饭
.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]
这是剩下的代码逻辑,如果有兴趣可以自己进行分析使用。
感觉自己一下次大彻大悟了。
接下来就是循环逻辑了。
步骤和之前一样,我只是改变一下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"); }
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 ; 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 ; 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 ; 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 ; 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,恢复环境。程序结束。
这个是不等于#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 ; 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 ; 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 ; 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)指令将寄存器<Rn>中的值和<shifter_operand>的值执行按位“异或”操作,并将执行结果存储到目的寄存器<Rd>中,同时根据指令的执行结果更新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_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
然后就是继续循环。
上述内容就是如何进行Android逆向基础中的so文件分析,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。