1. 程式人生 > >Java逆向基礎之字符串

Java逆向基礎之字符串

java 字符串

本文參考:http://www.vuln.cn/7116

本文參考:《Reverse Engineering for Beginners》Dennis Yurichev著

字符串

字符串也是對象,和其他對象的構造方式相同。(包括數組)

第一個例子

public class stringhello {
	public static void main(String[] args) {
		System.out.println("What is your name?");
		String input = System.console().readLine();
		System.out.println("Hello, " + input);
	}
}

編譯

javac stringhello.java

反編譯

javap -c -verbose stringhello.class
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String What is your name?
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: invokestatic  #5                  // Method java/lang/System.console:()Ljava/io/Console;
        11: invokevirtual #6                  // Method java/io/Console.readLine:()Ljava/lang/String;
        14: astore_1
        15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        18: new           #7                  // class java/lang/StringBuilder
        21: dup
        22: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
        25: ldc           #9                  // String Hello,
        27: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        30: aload_1
        31: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        34: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        37: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        40: return

部分指令解釋

11: invokevirtual #6 // Method java/io/Console.readLine:()Ljava/lang/String; //調用了readline()方法,字符串引用(由用戶提供)被存儲在棧頂

14: astore_1 //將字符串引用從操作數棧中彈出,保存在索引為1的局部變量中(即input)

25: ldc #9 // String Hello, //將字符串String Hello,壓入棧

27: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; //使用StringBuilder.append方法,返回一個StringBuilder對象的引用壓入棧頂,需要從棧頂彈出兩個值,一個是StringBuilder的引用,一個是字符串String Hello,

30: aload_1 //將索引為1的局部變量(即input)壓入操作數棧

31: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; //使用StringBuilder.append方法,返回一個StringBuilder對象的引用壓入棧頂,需要從棧頂彈出兩個值,一個是StringBuilder的引用,一個是字符串input變量值

34: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; //使用StringBuilder.toString方法,返回一個String對象的引用壓入棧頂,需要從棧頂彈出一個值,是StringBuilder的引用

37: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V //使用PrintStream.println方法,需要從棧頂彈出一個值,是System.out的引用

可以看到字符串的鏈接由StringBuilder完成


另外一個例子

public class strings {
	public static char test(String a) {
		return a.charAt(3);
	};

	public static String concat(String a, String b) {
		return a + b;
	}
}

反編譯

test方法

  public static char test(java.lang.String);
    descriptor: (Ljava/lang/String;)C
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: iconst_3
         2: invokevirtual #2                  // Method java/lang/String.charAt:(I)C
         5: ireturn

concat方法

  public static java.lang.String concat(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=2
         0: new           #3                  // class java/lang/StringBuilder
         3: dup
         4: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
         7: aload_0
         8: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        11: aload_1
        12: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        15: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        18: areturn

這裏的字符串的連接也使用StringBuilder類完成

部分指令解釋

0: new #3 // class java/lang/StringBuilder //創建StringBuilder的引用並壓入棧頂

3: dup //復制棧頂值,即StringBuilder的引用

4: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V //彈出1個棧頂值,調用<init>方法初始化


另外一個例子

public class stringhellotwo {
	public static void main(String[] args) {
		String s = "Hello!";
		int n = 123;
		System.out.println("s=" + s + " n=" + n);
	}
}

反編譯

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=1
         0: ldc           #2                  // String Hello!
         2: astore_1
         3: bipush        123
         5: istore_2
         6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         9: new           #4                  // class java/lang/StringBuilder
        12: dup
        13: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
        16: ldc           #6                  // String s=
        18: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        21: aload_1
        22: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        25: ldc           #8                  // String  n=
        27: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        30: iload_2
        31: invokevirtual #9                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        34: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        37: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        40: return

這裏的字符串的連接也使用StringBuilder類進行拼接

Java逆向基礎之字符串