Andriod逆向

Android軟件逆向分析基礎
2-1Dalvik虛擬機基本原理

一、DVM簡介
1、DVM運行Dalvik字節碼
2、Dalvik的的可執行文件是.dex,體積小於JVM的可執行文件.class
3、DVM基於寄存器,JVM基於棧
二、Dalvik彙編語言介紹
1、命名法,如果有3個局部變量和4個參數(包括一個this)
v0,v1,v2(局部變量v打頭),p0(this),p1,p2,p3(參數p打頭)
2、類型描述符
V(void),Z(boolean),B(byte),S(short),C(char),I(int),J(long),F(float),D(double),L(java類),[(數組);
DVM寄存器都是32bit,J,D類型需要兩個寄存器;
對象類型:Ljava/lang/String;相當於java.lang.String;
一維數組[I=int[],二維數組[[I=int[][];
對對象裏面方法的調用爲 Lpackage/name/ObjectName;->MethodName(III)Z,第一個L是指package/name/ObjectName這是一個java類的類型
後面跟的是對象的名稱->後面跟的MethodName是方法名,(III)指的是方法有三個參數,都是int類型的,Z指的是方法函數的返回值是boolean
類型的;
method(I[[Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String等價於String method(int,int[],int,String,Object[])
對對象裏面變量的調用爲 Lpackage/name/ObjectName;->FieldName: Ljava/lang/String;冒號後面的Ljava/lang/String;指的是變量類型
三、程序編譯與反編譯
apk包由資源文件,dex文件AndroidManifest.xml佈局文件三個打包構成,反編譯dex文件生成smali文件,可以直接閱讀。一般用baksmali

2-2Dalvik彙編語言

.class 後面是類名
.super 後面跟的是基類名
.method 後面跟的是方法
.registers 後面的數字指的是程序使用了幾個寄存器
具體的Dalvik指令可以看《Addroid軟件安全與逆向分解》第三章

    Android控制檯可以直接執行的文件格式就是dex。我的實驗方法是

先寫一個java文件,編譯之後得到class文件,再用dx工具得到dex文件

我的java代碼是
public class helloworld{
public static void main(String[] args){
System.out.println(“Helloworld!”);
}
}

得到的dex文件經過baksmali反編譯後得到smali代碼
.class public Lhelloworld;
.super Ljava/lang/Object;
.source “helloworld.java”

direct methods

.method public constructor ()V
.registers 1

.prologue
.line 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V

return-void

.end method

.method public static main([Ljava/lang/String;)V
.registers 3

.prologue
.line 3
sget-object v0, Ljava/lang/System;->out: Ljava/io/PrintStream;

const-string v1, "Helloworld!"

invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

.line 4
return-void

.end method

2-3Dalvik版的helloworld

    編譯smali文件,可以用ApkToolBox,同時這裏面也有smali.jar文件通過指令編譯爲 java -jar smali.jar -o classes.dex(輸出的可執行文件) Helloworld.smali(源文件)使用ApktoolBox的回編譯dex功能也可以,但這時smali文件必須在一個同名的文件夾中,把文件夾拖入

ApkToolBox文件路徑中,得到dex文件。

3-1靜態分析的概念與定位關鍵代碼

靜態分析
1、定義:不運行代碼的情況下,閱讀反彙編代碼來掌握程序功能的一種技術
2、兩種方法:閱讀Dalvik字節碼(反編譯dex文件生成的smali文件)
閱讀java代碼(通過dex2jar生成jar文件,再用jd-gui閱讀jar),不過準確性不高

關鍵代碼定位
常用步驟:
1、反編譯apk,通常是反編譯成smali文件
2、通過AndroidManifest.xml查找主類Activity
3、查看程序的入口函數:主Activity的OnCreat()
4、查看Application類(全局,早於其他類啓動)的OnCreate()函數,該函數通常用作授權檢測
常用方法:
信息反饋法:運行時信息
特徵函數法:運行時行爲
順序查看法:執行流程
代碼注入法:添加Log

.class public Lcom/example/administrator/helloworld/MainActivity; //類名
.super Landroid/support/v7/app/AppCompatActivity; //基類名,說明MainActivity是繼承的AppCompatActivity
.source “MainActivity.java” //源代碼文件

instance fields //實例的成員變量,此處爲空

direct methods //直接方法

.method public constructor ()V //構造函數(constructor),返回值爲void
.locals 0 //局部變量0個

.prologue
.line 6
invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V //直接調用方法,p0存放this,當前對象

return-void

.end method

virtual methods

.method protected onCreate(Landroid/os/Bundle;)V
.locals 1
.param p1, “savedInstanceState” # Landroid/os/Bundle;

.prologue
.line 10
invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V

.line 11
const v0, 0x7f040019

invoke-virtual {p0, v0}, Lcom/example/administrator/helloworld/MainActivity;->setContentView(I)V

.line 12
return-void

.end method

smali文件
MainActivity[Math Processing Error]SNChecker.smali:成員內部類,SNChecker爲類名
MainActivity.smali:外部類

3-2Smali文件格式與分析

內部類的表示
this[Math Processing Error]0不是父類的引用,是表示對內部類所在的外部類的引用。此處外部類和父類的概念是不同的)
this$X型字段都被指定了synthetic(合成的)屬性,表明他們是被編譯器合成的,虛構的,非java代碼指定的字段
構造函數執行步驟(後兩步是任何一個類初始化都有的步驟,第一步只有內部類初始化才需要)
1、保存外部類的引用到本類的一個synthetic字段中
2、調用內部類的父類的構造函數
3、內部類自身初始化

    從屏幕截圖中可看到,在.class那行,類名是MainActivity$SNChecker,其中MainActivity是主類名,SNChecker是

內部類名,中間用[Math Processing Error]0,他是被編譯器合成的虛構
的,不是我們自己寫的,內部類SNChecker所在的外部類是MainActivity,所以this$0指向了MainActivity,存在寄存器
p0中。
smali語言中,類直接方法都是在#direct methods中,截圖裏面13-31行都是這個類的構造函數constructor,
constructor是smali構造函數的標準函數名,後面一堆是參數類型和返回值類型。
.local指的是非參數寄存器個數,.param指的是參數寄存器,.param p2,”sn”意思就是變量sn是存在p2寄存器中的。
代碼第20行對應上述步驟1,將對外部類的引用保存到本類的p1寄存器中(此處視頻中說的是保存到寄存器p1中,但我還是有些疑問,如果是保存在p1中,p1就是非參寄存器,.local後面就不應該是0。還有個問題,就是這樣操作之後p1和p0的值是不是就一樣了,都指向對外部類的引用),23行對應步驟2,27行對應步驟3,是對內部類成員變量sn的初始化(此處視頻課件有錯誤,嚴格意義上第27行的代碼只是對內部類成員變量sn的初始化,並不算是
調用SNChecker自身的構造函數)
Smali語法簡單介紹如下:
Davlik字節碼中,寄存器都是32位的,能夠支持任何類型,64位類型(Long/Double)用2個寄存器表示;
Dalvik字節碼有兩種類型:原始類型;引用類型(包括對象和數組)
原始類型:v void 只能用於返回值類型
Z boolean
B byte
S short
C char
I int
J long(64位)
F float
D double(64位)
對象類型:Lpackage/name/ObjectName; 相當於java中的package.name.ObjectName;解釋如下:
L:表示這是一個對象類型
package/name:該對象所在的包
;:表示對象名稱的結束
數組的表示形式:
[I :表示一個整形的一維數組,相當於java的int[];
對於多維數組,只要增加[ 就行了,[[I = int[][];注:每一維最多255個;
對象數組的表示形式:
[Ljava/lang/String 表示一個String的對象數組;

           方法的表示形式:
                               Lpackage/name/ObjectName;——>methodName(III)Z  詳解如下:
                               Lpackage/name/ObjectName  表示類型
                               methodName   表示方法名
                               III   表示參數(這裏表示爲3個整型參數)
                               說明:方法的參數是一個接一個的,中間沒有隔開;

             字段的表示形式:
                                Lpackage/name/ObjectName;——>FieldName: Ljava/lang/String;
                                即表示: 包名,字段名和各字段類型

              有兩種方式指定一個方法中有多少寄存器是可用的:
                                 .registers  指令指定了方法中寄存器的總數
                                 .locals        指令表明了方法中非參寄存器的總數,出現在方法中的第一行

    方法的傳參:
            當一個方法被調用的時候,方法的參數被置於最後N個寄存器中;
                      例如,一個方法有2個參數,5個寄存器(v0~v4)
                                  那麼,參數將置於最後2個寄存器(v3和v4)
             非靜態方法中的第一個參數總是調用該方法的對象;
             說明:對於靜態方法除了沒有隱含的this參數外,其他都一樣

      寄存器的命名方式:
              V命名
              P命名  第一個寄存器就是方法中的第一個參數寄存器
              比較:使用P命名是爲了防止以後如果在方法中增加寄存器,需要對參數寄存器重新進行編號的缺點
              特別說明一下:Long和Double類型是64位的,需要2個寄存器
                       例如:對於非靜態方法
                                   LMyObject——>myMethod(IJZ)V;
                                   有4個參數:LMyObject,int,long,bool;   需要5個寄存器來存儲參數;
                                                        P0    this
                                                        P1    I (int)
                                                        P2,P3  J (long)
                                                        P4    Z(bool)

相關鏈接:http://bbs.ichunqiu.com/thread-9017-1-1.html?from=csdnJG

發佈了46 篇原創文章 · 獲贊 15 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章