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.結束
我是不是寫的太囉嗦了,越學習越發現自己之前學的都不夠用了。