Android逆向-Android逆向基礎10(so文件分析大合集)
導航
博客導航戳這裏
練習資源戳這裏
說明
在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)指令將寄存器<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_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進行分析。
Android逆向-Android逆向基礎10(so文件分析大合集)