1. 程式人生 > >Android逆向-java程式碼基礎(2)

Android逆向-java程式碼基礎(2)

0x00 前言

由於是對java語言的複習,所以進度會很快,而且會以smali為主,java只是順便提一下,如果對java有興趣詳細研究的,可以下載pdf仔細的看。
這篇主要涉及到基本資料型別,int,float,char,以及運算。
連結:http://download.csdn.net/download/qq_36869808/10189220

0x01 java資料型別

1.int型變數

1.1 int定義

1.2 int賦值

1.3 int型輸出

public class intbl
{
    public static void main(String[] args)
    {
        int
a;//int定義 a=520;//int賦值 System.out.println("a所儲存的是:"+a);//int輸出 } }

1.4編譯

使用javac進行編譯,但是編譯會出現一個問題。
這裡寫圖片描述

intbl.java:6: 錯誤: 編碼GBK的不可對映字元
                System.out.println("a鎵?瀛樺偍鐨勬槸錛?"+a);
                                      ^
intbl.java:6: 錯誤: 編碼GBK的不可對映字元
                System.out
.println("a鎵?瀛樺偍鐨勬槸錛?"+a); ^ 2 個錯誤

解決方案:
用記事本開啟java檔案,另存為,編碼選擇ANSI即可解決。
這裡寫圖片描述

1.5 執行

1.6 class檔案分析

1.6.1常量池說明。

這篇主要分析的是常量池。
常量池是由常量池項(cp_info)組成的。
常量池項類似於結構體,主要有兩個元素。一個是tag,還有一個是info[]陣列。tag用來判定info[]陣列的型別。下表是tag對應的型別圖。
這裡寫圖片描述
接下來就邊看二進位制檔案邊進行分析了。

1.6.2第一個cp_info

首先開啟二進位制檔案,前四位魔數,4~8位版本號,8~10長度。從11開始就是第一個cp_info了。
首先是我們的tag標誌:0A
這裡寫圖片描述
這裡我們根據上面的表進行判斷類中的方法,cp_info的結構如下。
這裡寫圖片描述
class_index: 00 0B,十進位制就是11,這裡應該提一下class_index的作用了。
class_index的作用就是指向CONSTANT_class_index,這裡是11就是指向#11塊。
順便提一下,第一個cp_info就是#1
這裡寫圖片描述
name_and_type_index:00 14,十進位制,20
name_and_type_index的作用就是指向CONSTANT_NameAndType_info。這裡指向#20塊
這裡寫圖片描述
最後總結下:

tag=10;//CONSTANT_Methodref_info
class_index=11;//CONSTANT_class_index
name_and_type_index;//CONSTANT_NameAndType_index

1.6.3第二個cp_info(#2)

首先是tag,tag的大小是09,十進位制也是09。
意味著這個cp_info的型別是 CONSTANT_Fieldref_info。
首先來看下CONSTANT_Fieldref_info的結構。
這裡寫圖片描述
感覺和CONSTANT_Methodref_info很相似。
總結一下:

tag=9;//CONSTANT_Fieldref_info
class_index=21;//#21
name_and_type_index=22;//#22

1.6.3第三個cp_info(#3)

這個就直接分析了:
tag=07,對照表就是CONSTANT_Class_info。
那麼看看CONSTANT_Class_info的結構。
這裡寫圖片描述
name_index:00 17,十進位制就是23。
總結:

tag=07;CONSTANT_Class_info
name_index:0017;#23

1.6.4第四個cp_info(#4)

tag是0A,二進位制10,之前分析過。CONSTANT_Methodref_info。

tag=0A;CONSTANT_Methodref_info
name_index=03;#3
name_and_type_index=14;#20

這裡方法類指向了#3也就是我們第三個塊,但是第三個的name_index,可能需要到#23塊,才能夠知道#3 name_index的值。

1.6.5第五個cp_info

tag=08,十進位制就是08。這裡對應的型別就是CONSTANT_String_index。
CONSTANT_String_index的基本格式如下:
這裡寫圖片描述
這裡的string_index指向的是CONSTANT_utf8_index,其實就是String的內容。
總結:

tag=08;//CONTSTANT_String_index
string_index=018;#24

1.6.6 第六個cp_info

tag=0A,又是CONSTANT_Methodref_index。不囉嗦了。

tag=0A;CONSTANT_Methodref_index
name_index=03;#3
name_and_type_index=19;#25

1.6.7結束語

到這裡有沒有對常量池有一個理解。剩下的可以自己分析了。不過這裡還有一個偷懶的方法,就是使用javap -v命令可以直接檢視我們說的這些。
這裡寫圖片描述
這樣就可以省很多時間,但是還是建議自己分析一下二進位制檔案進行測試。

1.7 smali語句

.class public Lintbl;
.super Ljava/lang/Object;
.source "intbl.java"


# direct methods
.method public constructor <init>()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 5

    .prologue
    .line 5
    const/16 v0, 0x208

    .line 6
    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    const-string v3, "a\u6240\u5b58\u50a8\u7684\u662f\uff1a"

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v0

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

    .line 8
    return-void
.end method

(1)首先我們來看smali檔案的第一個段。
這裡寫圖片描述
這段就是表示該類的不帶引數預設的構造方法,為main函式的傳參做準備。
(2)然後最主要的就是這裡的main函式裡的內容了。
(3)先來看第一句。
這裡寫圖片描述

sget-object 就是用來獲取變數值並儲存到緊接著的引數的暫存器中。
前面需要該變數所屬的類的型別,後面需要加一個冒號和該成員變數的型別,中間是“->”表示所屬關係。
那麼這句話的意思就是,System.out的值儲存在暫存器v1中。out的型別是Ljava/io/PrintStream;PrintStream是列印輸出流。

2018年1月7日15:57:35。要去寫作業。先暫停一下吧。

2018年1月7日23:05:57。作業寫完了,我的假期也就是要正式開始了。為了之後開始努力。

1.7.1 第二句分析

這裡寫圖片描述
新建一個StringBuilder 物件, new-instance

1.7.2 第三句分析

這裡寫圖片描述

invoke-direct:沒有被覆蓋方法的呼叫,即不用動態根據例項所引用的呼叫,編譯時,靜態確認的,一般是private或方法;

1.7.3 第四句分析

這裡寫圖片描述

const-string v3, "a\u6240\u5b58\u50a8\u7684\u662f\uff1a"

這句話就是定義了一個暫存器用來存放這一串字元。

1.7.4 第五句分析

這裡寫圖片描述
invoke-virtual 虛方法呼叫,呼叫的方法執行時確認實際呼叫,和例項引用的實際物件有關,動態確認的,一般是帶有修飾符protected或public的方法;
這裡就是呼叫append方法,也就是拼接的意思。

1.7.5第六句分析

這裡寫圖片描述
Move the object result of the most recent invoke-kind into the indicated register. This must be done as the instruction immediately after an invoke-kindor filled-new-array whose (object) result is not to be ignored; anywhere else is invalid.
move-result-object 就是將上一條指令的結果存放在v2暫存器中。

1.7.6第七句分析

這裡寫圖片描述

invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

這句話就是呼叫append,連線v2和v0,v2就是上一個append的結果,v0就是數字520。

1.7.7第八句分析

這裡寫圖片描述
上一句的結果給v0。

1.7.8第九句分析

這裡寫圖片描述
呼叫toString方法轉化v0

1.7.9第十一句分析

第十句很簡單就是結果給了v0。
這裡寫圖片描述
呼叫System.out.println輸出v0的結果。

2.float型變數

2.1 定義

2.2 賦值

2.3 輸出

public class floatbl
{
    public static void main(String[] args)
    {
        float a;//定義
        a=1.1f;//賦值
        System.out.println(a);//輸出
    }
}

執行結果。
這裡寫圖片描述

2.4 class檔案檢視。

這裡使用

javap -v floatbl

這裡寫圖片描述
這裡對比int型變數,發現多了一個東西就是
這裡寫圖片描述
這裡是為了給之後傳參使用的儲存資料的cp_info,為了更好的顯示引數

1.5 smali檔案檢視

這裡寫圖片描述
我們對比一下float和int的smali程式碼,可以發現都有這一塊的程式碼,我們猜測可能這就是每一個smali都有的一部分吧。在char的時候或許應該嘗試一下自己寫一個smali程式碼了。
這裡寫圖片描述
剩下的就非常簡單了,在int的時候已經非常詳細的介紹過來。可能之後也要對dex檔案進行一個分析和研究。該走的路還有很長的一段。

3.char

3.1定義

3.2賦值

3.3輸出

public class charbl{
    public static void main(String[]args)
    {
        char a;
        a='a';
        System.out.println(a);
    }
}

執行結果:
這裡寫圖片描述

3.4 class檔案分析。

這裡不贅述檢視方式,和生成方式了。
這裡寫圖片描述
這裡是對常量池進行一個展示,有興趣可以自己研究。

3.5 smali檔案分析。

先來看一下smali程式碼:
這裡寫圖片描述
這裡面發現有一個地方不一樣,全在圖裡,看圖就好。
這裡寫圖片描述

0x03 結尾

1.感悟

寫部落格會讓你對一個只是更加的融會貫通,而且在寫的同時也會進行思考,這對思路有一個提升,而且可以讓你實戰還有理論只是得到大幅度提升。

2.結束

我是不是寫的太囉嗦了,越學習越發現自己之前學的都不夠用了。