1. 程式人生 > >Java逆向系列-基礎指令:常量入棧指令

Java逆向系列-基礎指令:常量入棧指令

                                  常量入棧指令

Java程式的反編譯工具已經十分成熟了,相對於x86平臺更底層指令的反編譯技術來說,面向VM的 bytecode更容易反編譯。這主要是因為:

  1. 位元組碼含有更為豐富的資料型別資訊。
  2. JVM記憶體模型更嚴格,因此位元組碼分析起來更為有章可循。
  3. Java編譯器不做任何優化工作(而 JVM JIT在執行時會做優化工作),因此在反編譯位元組碼之後,我們基本可以直接理解Java類檔案裡的原始指令。

反編譯有什麼用途呢?

  1. 無需重新編譯反彙編的結果,而能給類檔案做應急補丁
  2. 分析混淆程式碼。
  3. 需要編寫自己的程式碼混淆器。
  4. 建立面向JVM的、類似編譯程式的程式碼生成工具(類似 Scala,Cloture等等)。
  5. 破解研究
     

開啟Java逆向學習系列筆記,參考網上各大神的分享,有不對的請指正。

常量入棧指令有iconstbipushsipushldcldc2_w分別對應不同的使用場景

八大基本型別場景表

常量型別

常量範圍

指令

整型int

-1~5

iconst_0~ iconst_5

iconst_m1

-128~127

bipush

-32768~32767

sipush

-2147483648~2147483647

#2 = Integer 12345678

0: ldc #2 // int 12345678

布林型boolean

true

iconst_1

false

iconst_0

短整型short

-1~5

iconst_0~ iconst_5

iconst_m1

-128~127

bipush

-32768~32767

sipush

字元型char

\u0000~\u0005

iconst_0~ iconst_5

\u0000~\u00FF

bipush

\u0000~\uFFFF

sipush

位元組型byte

-1~5

iconst_0~ iconst_5

iconst_m1

-128~127

bipush

長整型long

-2^63~2^63-1

#2 = Long 1234567890123456789l

ldc2_w #2 // long 1234567890123456789l

浮點型double

8位元組

#2 = Double 123.456d

ldc2_w  #2  // double 123.456d

浮點型float

4位元組

#2 = Float 123.456f

ldc #2 // float 123.456f

指令場景表

指令

使用場景

iconst

int,short,byte,int(char a)數值在-1~5之間,boolean型別,注意不包括long

bipush

int,short,byte,int(char a)數值在-128~127之間,注意不包括long,範圍內的值在iconst之內的優先用iconst

sipush

int,short,int(char a)數值在-32768~32767之間,boolean型別,注意不包括long,範圍內的值在bipush之內的優先用bipush

ldc

int的數值-2147483648~2147483647之間(範圍內的值在sipush之內的優先用sipush),float型別

ldc2_w

long型別,double型別

以下是簡單的例子

整型常量0的例子iconst

public class ret
{
public static int main(String[] args)
{
return 0;
}
}

編譯

javac ret.java

Java標準反編譯

javap -c -verbose ret.class
...
major version: 52
...
public static int main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: iconst_0
1: ireturn
LineNumberTable:
line 5: 0

注意其中的0: iconst_0即可

整型常量123的例子bipush

public class ret
{
public static int main(String[] args)
{
return 123;
}
}

反編譯

...
major version: 52
...
public static int main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: bipush        123
2: ireturn
LineNumberTable:
line 5: 0

注意其中的0: bipush        123

整型常量1234的例子sipush

public class ret
{
public static int main(String[] args)
{
return 1234;
}
}

反編譯

...
major version: 52
...
public static int main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: sipush        1234
3: ireturn
LineNumberTable:
line 5: 0

注意其中的 0: sipush        1234

整型常量12345678的例子ldc

public class ret
{
public static int main(String[] args)
{
return 12345678;
}
}

反編譯

...
major version: 52
...
#2 = Integer            12345678
...
public static int main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: ldc           #2                  // int 12345678
2: ireturn
LineNumberTable:
line 5: 0

布林型true例子iconst

public class ret
{
public static boolean main(String[] args)
{
return true;
}
}

反編譯

...
major version: 52
...
public static boolean main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)Z
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: iconst_1
1: ireturn
LineNumberTable:
line 5: 0

注意0: iconst_1即ture用常量1表示

短整型short例子

public class ret
{
public static short main(String[] args)
{
return 1234;
}
}

反編譯

...
major version: 52
...
public static short main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)S
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: sipush        1234
3: ireturn
LineNumberTable:
line 5: 0

注意0: sipush        1234

字元型A例子

public class ret
{
public static char main(String[] args)
{
return 'A';
}
}

反編譯

...
major version: 52
...
public static char main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)C
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: bipush        65
2: ireturn
LineNumberTable:
line 5: 0

注意0: bipush        65

字元型中例子

public class ret
{
public static char main(String[] args)
{
return '中';
}
}

反編譯

...
major version: 52
...
public static char main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)C
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: sipush        20013
3: ireturn
LineNumberTable:
line 5: 0

注意0: sipush        20013

byte型別123列子

public class ret
{
public static byte main(String[] args)
{
return 123;
}
}

反編譯

...
major version: 52
...
public static byte main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)B
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: bipush        123
2: ireturn
LineNumberTable:
line 5: 0

注意 0: bipush        123

long型別1234567890123456789L例子

public class ret
{
public static long main(String[] args)
{
return 1234567890123456789l;
}
}

反編譯

...
major version: 52
...
#2 = Long               1234567890123456789l
...
public static long main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)J
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: ldc2_w        #2                  // long 1234567890123456789l
3: lreturn
LineNumberTable:
line 5: 0

注意0: ldc2_w        #2                  // long 1234567890123456789l

浮點型別123.456d的例子

public class ret
{
public static double main(String[] args)
{
return 123.456d;
}
}

反編譯

...
major version: 52
...
#2 = Double             123.456d
...
public static double main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)D
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: ldc2_w        #2                  // double 123.456d
3: dreturn
LineNumberTable:
line 5: 0

注意0: ldc2_w        #2                  // double 123.456d

浮點型別123.456f的例子

public class ret
{
public static float main(String[] args)
{
return 123.456f;
}
}

反編譯

...
major version: 52
...
#2 = Float              123.456f
...
public static float main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)F
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: ldc           #2                  // float 123.456f
2: freturn
LineNumberTable:
line 5: 0

注意0: ldc           #2                  // float 123.456f

本文參考:逆向工程權威指南.下冊.pdf 和http://blog.51cto.com/7317859/2105269

相關推薦

Java逆向系列-基礎指令常量指令

                                  常量入棧指令 Java程式的反編譯工具已經十分成熟了,相對於x86平臺更底層指令的反編譯技術來說,面向VM的 bytecode更容易反編譯。這主要是因為: 位元組碼含有更為豐富的資料型別資訊。 JVM記

Java逆向基礎常量指令

java入棧指令本文參考:http://www.vuln.cn/7115 常量入棧指令有iconst、bipush、sipush、ldc、ldc2_w分別對應不同的使用場景以下兩個表簡單總結了使用場景八大基本類型場景表常量類型常量範圍指令×××int-1~5iconst_0~ iconst_5iconst_m

Java逆向系列-基礎指令函式

例子1,方法名的定義 public class HalfRandom { public static double f() { return Math.random()/2; } } 編譯 javac HalfRandom.java 反編譯 javap -c -ve

Java逆向系列-基礎指令靜態變數存取

注意:靜態變數static可以多次賦值,不能多次賦值的是final static 線性同餘偽隨機數演算法LCG 演算法數學上基於公式: X(n+1) = (a * X(n) + c) % m 其中,各系數為: 模m, m > 0 係數a, 0 < a &

Java分析系列之四jstack生成的Thread Dump日誌執行緒狀態

前面文章中只分析了Thread Dump日誌檔案的結構,今天針對日誌檔案中 Java EE middleware, third party & custom application Threads 部分執行緒的狀態進行詳細的分析。 目錄 [隱藏] 1 Thread Dump日誌

Java分析系列之三jstat命令的使用及VM Thread分析

前面提到了一個使用jstack的shell指令碼,通過命令可以很快地定位到指定執行緒對應的堆疊資訊。 目錄 [隱藏] 1 使用jstat命令 2 JVM記憶體模型 3 JVM記憶體引數設定 3.1 堆記憶體設定 3.2 非堆記憶體設定

Java分析系列之五常見的Thread Dump日誌案例分析

目錄 [隱藏] 症狀及解決方案 下面列出幾種常見的症狀即對應的解決方案: CPU佔用率很高,響應很慢 按照《Java記憶體洩漏分析系列之一:使用jstack定位執行緒堆疊資訊》中所說的方法,先找到佔用CPU的程序,然後再定位到對應的執行緒,最後分析出對應的堆疊資訊

Java併發程式設計基礎//程序每個程序都有獨立的程式碼和資料空間(程序上下文),程序間的切換開銷比較大,一個程序包含1-n個執行緒 //執行緒同一類執行緒共享程式碼和資料空間,每個執行緒擁有獨立的執行棧和程式計

1.實現多執行緒的兩種方式: (1)繼承Thread類; (2)實現Runnable介面 //程序:每個程序都有獨立的程式碼和資料空間(程序上下文),程序間的切換開銷比較大,一個程序包含1-n個執行緒 //執行緒:同一類執行緒共享程式碼和資料空間,每個執行緒擁有獨立的執行

java開發C語言編譯器jvm的return指令以及區域性變數的操作

請結合視訊閱讀本文以便獲得更清晰的理解。 更詳細的講解和程式碼除錯演示過程,請參看視訊 用java開發C語言編譯器 如果你對機器學習感興趣,請參看一下連結: 機器學習:神經網路導論 jvm執行位元組碼時,程式碼的執行必須圍繞兩種資料結構,一種

Java分析系列之六JVM Heap Dump(堆轉儲檔案)的生成和MAT的使用

前面的文章詳細講述了分析Thread Dump檔案,實際在處理Java記憶體洩漏問題的時候,還需要分析JVM堆轉儲檔案來進行定位。 目錄 [隱藏] JVM Heap Dump(堆轉儲檔案)的生成 正如Thread Dump檔案記錄了當時JVM中執行緒執行的情況一樣,He

Java爬蟲系列之實戰爬取酷狗音樂網 TOP500 的歌曲(附原始碼)

  在前面分享的兩篇隨筆中分別介紹了HttpClient和Jsoup以及簡單的程式碼案例: Java爬蟲系列二:使用HttpClient抓取頁面HTML Java爬蟲系列三:使用Jsoup解析HTML 今天就來實戰下,用他們來抓取酷狗音樂網上的 Top500排行榜音樂。接下來的程式碼

java基礎常量的概念和使用

均可 舉例 默認 null 0.11 錯誤 pan 雙引號 bsp 常量: 在程序執行的過程中,其值不發生改變的量 分類: A:字面值常量 字符串常量 用雙引號括起來的內容。 舉例:"hello","world","HelloWorld" 整數常量

Java逆向基礎之Byteman的運行後註

java byteman 運行後註入 Byteman可以在目標程序運行後進行註入,命令如下運行後註入1.查看java進程,找到目標進程的pidjps2.安裝pidbminstall <pid>3.裝載規則腳本bmsubmit -l tracing.btm//指定監聽端口默認是9091/

Java面試系列總結 JavaSE基礎(2) 常用 API

1. Math.round(11.5)等於多少?Math.round(- 11.5) 又等於多少? Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。 四捨五入的原理是在引數上加 0.5然後進行取整。 2.

Java面試系列總結 JavaSE基礎(1) 面向物件/語法/異常

1. 面向物件都有哪些特性以及你對這些特性的理解 繼承:繼承是從已有類得到繼承資訊建立新類的過程。提供繼承資訊的類被稱為父類(超類、基類);得到繼承資訊的類被稱為子類(派生類)。繼承讓變化中的軟體系統有了一定的延續性,同時繼承也是封裝程式中可變因素的 重要

Java基礎2基本數據類型與常量

cache model ria 比較 是否 類型 misc pri pan Java基礎2:基本數據類型與常量池 基本數據類型的大小 int 32位 4字節 short 16位float 32位double 64位long 64位char 16位byte 8位boolea

Java基礎面試集合、內部類、線程

public 死鎖 exceptio read 多線程 三種 xtend arraylist 表示 package test; import java.util.Hashtable; import java.util.Map; public class test {

深入理解JAVA集合系列ArrayList源碼解讀

結束 了解 數組下標 size new 數組元素 開始 ini rem 在開始本章內容之前,這裏先簡單介紹下List的相關內容。 List的簡單介紹 有序的collection,用戶可以對列表中每個元素的插入位置進行精確的控制。用戶可以根據元素的整數索引(在列表中的位置)訪

深入理解JAVA集合系列HashMap的死循環解讀

現在 最新 star and 場景 所有 image cap 時也 由於在公司項目中偶爾會遇到HashMap死循環造成CPU100%,重啟後問題消失,隔一段時間又會反復出現。今天在這裏來仔細剖析下多線程情況下HashMap所帶來的問題: 1、多線程put操作後,get操作導

MongoDB初探系列之四MongoDB與Java共舞

ever 文件 basic query find man mongodb next() 入學 因為版本號不同,可能API也有所不同。本次學習用的是3.0版本號。 1、使用的mongodb的jdbc驅動版本號為:mongo-java-driver-3.0.0.jar