<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/binary/6928

            54.15 異常 讓我們稍微修改一下,月處理的那個例子(在932頁的54.13.4)


            清單 54.10: IncorrectMonthException.java

            #!java
            public class IncorrectMonthException extends Exception
            {
               private int index;
               public IncorrectMonthException(int index)
               {
                  this.index = index;
               }
               public int getIndex()
               {
                  return index;
               }
            }
            

            清單 54.11: Month2.java

            #!java
            class Month2
            {
                public static String[] months =
                {
                "January",
                "February",
                "March",
                "April",
                "May",
                "June",
                "July",
                "August",
                "September",
                "October",
                "November",
                "December"
                };
            
                public static String get_month (int i) throws ?
                ? IncorrectMonthException
                {
                        if (i<0 || i>11)
                            throw new IncorrectMonthException(i);
                            return months[i];
                };
                public static void main (String[] args)
                {
                    try
                    {
                        System.out.println(get_month(100));
                    }
                    catch(IncorrectMonthException e)
                    {
                        System.out.println("incorrect month ?
                        ? index: "+ e.getIndex());
                        e.printStackTrace();
                    }
                };
            }
            

            本質上,IncorrectMonthExceptinClass類只是做了對象構造,還有訪問器方法。 IncorrectMonthExceptinClass是繼承于Exception類,所以,IncorrectMonth類構造之前,構造父類Exception,然后傳遞整數給IncorrectMonthException類作為唯一的屬性值。

            public IncorrectMonthException(int);
            flags: ACC_PUBLIC
            Code:
            stack=2, locals=2, args_size=2
            0: aload_0
            1: invokespecial #1 // Method java/?
            ? lang/Exception."<init>":()V
            4: aload_0
            5: iload_1
            6: putfield #2 // Field index:I
            9: return
            

            getIndex()只是一個訪問器,引用到IncorrectMothnException類,被傳到LVA的0槽(this指針),用aload_0指令取得, 用getfield指令取得對象的整數值,用ireturn指令將其返回。

            public int getIndex();
            flags: ACC_PUBLIC
            Code:
            stack=1, locals=1, args_size=1
            0: aload_0
            1: getfield #2 // Field index:I
            4: ireturn
            

            現在來看下month.class的get_month方法。

            清單 54.12: Month2.class

            public static java.lang.String get_month(int) throws ?
            ? IncorrectMonthException;
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=1, args_size=1
            0: iload_0
            1: iflt 10
            4: iload_0
            5: bipush 11
            7: if_icmple 19
            10: new #2 // class ?
            ? IncorrectMonthException
            13: dup
            14: iload_0
            15: invokespecial #3 // Method ?
            ? IncorrectMonthException."<init>":(I)V
            18: athrow
            19: getstatic #4 // Field months:[?
            ? Ljava/lang/String;
            22: iload_0
            23: aaload
            24: areturn
            949
            

            iflt 在行偏移1 ,如果小于的話,

            這種情況其實是無效的索引,在行偏移10創建了一個對象,對象類型是作為操作書傳遞指令的。(這個IncorrectMonthException的構造屆時,下標整數是被通過TOS傳遞的。行15偏移) 時間流程走到了行18偏移,對象已經被構造了,現在athrow指令取得新構對象的引用,然后發信號給JVM去找個合適的異常句柄。

            athrow指令在這個不返回到控制流,行19偏移的其他的個基本模塊,和異常無關,我們能得到到行7偏移。 句柄怎么工作? main()在inmonth2.class

            清單 54.13: Month2.class

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=3, locals=2, args_size=1
            0: getstatic #5 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            3: bipush 100
            5: invokestatic #6 // Method ?
            ? get_month:(I)Ljava/lang/String;
            8: invokevirtual #7 // Method java/io?
            ? /PrintStream.println:(Ljava/lang/String;)V
            11: goto 47
            14: astore_1
            15: getstatic #5 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            18: new #8 // class java/?
            ? lang/StringBuilder
            21: dup
            22: invokespecial #9 // Method java/?
            ? lang/StringBuilder."<init>":()V
            25: ldc #10 // String ?
            ? incorrect month index:
            27: invokevirtual #11 // Method java/?
            ? lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/?
            ? StringBuilder;
            30: aload_1
            31: invokevirtual #12 // Method ?
            ? IncorrectMonthException.getIndex:()I
            34: invokevirtual #13 // Method java/?
            ? lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
            37: invokevirtual #14 // Method java/?
            ? lang/StringBuilder.toString:()Ljava/lang/String;
            40: invokevirtual #7 // Method java/io?
            ? /PrintStream.println:(Ljava/lang/String;)V
            43: aload_1
            44: invokevirtual #15 // Method ?
            ? IncorrectMonthException.printStackTrace:()V
            47: return
            Exception table:
            from to target type
            0 11 14 Class IncorrectMonthException
            

            950 這是一個異常表,在行偏移0-11(包括)行,一個IncorrectinMonthException異常可能發生,如果發生,控制流到達14行偏移,確實main程序在11行偏移結束,在14行異常開始, 沒有進入此區域條件(condition/uncondition)設定,是不可能到打這個位置的。(PS:就是沒有異常捕獲的設定,就不會有異常流被調用執行。)

            但是JVM會傳遞并覆蓋執行這個異常case。 第一個astore_1(在行偏移14)取得,將到來的異常對象的引用,存儲在LVA的槽參數1之后。getIndex()方法(這個異常對象) 會被在31行偏移調用。引用當前的異常對象,是在30行偏移之前。 所有的這些代碼重置都是字符串操作代碼:第一個整數值使用的是getIndex()方法,被轉換成字符串使用的是toString()方法,它會和“正確月份下標”的文本字符來鏈接(像我們之前考慮的那樣)。 println()和printStackTrace(1)會被調用,PrintStackTrace(1)調用 結束之后,異常被捕獲,我們可以處理正常的函數,在47行偏移,return結束main()函數 , 如果沒有發生異常,不會執行任何的代碼。

            這有個例子,IDA是如何顯示異常范圍:

            清單54.14 我從我的計算機中找到 random.class 這個文件

            .catch java/io/FileNotFoundException from met001_335 to ?
            ? met001_360\
            using met001_360
            .catch java/io/FileNotFoundException from met001_185 to ?
            ? met001_214\
            using met001_214
            .catch java/io/FileNotFoundException from met001_181 to ?
            ? met001_192\
            using met001_195
            951
            CHAPTER 54. JAVA 54.16. CLASSES
            .catch java/io/FileNotFoundException from met001_155 to ?
            ? met001_176\
            using met001_176
            .catch java/io/FileNotFoundException from met001_83 to ?
            ? met001_129 using \
            met001_129
            .catch java/io/FileNotFoundException from met001_42 to ?
            ? met001_66 using \
            met001_69
            .catch java/io/FileNotFoundException from met001_begin to ?
            ? met001_37\
            using met001_37
            

            54.16 類 簡單類


            清單 54.15: test.java

            #!java
            public class test
            {
                public static int a;
                private static int b;
                public test()
                {
                    a=0;
                    b=0;
                }
                public static void set_a (int input)
                {
                    a=input;
                }
                public static int get_a ()
                {
                    return a;
                }
                public static void set_b (int input)
                {
                    b=input;
                }
                public static int get_b ()
                {
                    return b;
                }
            }
            

            構造函數,只是把兩個之段設置成0.

            public test();
            flags: ACC_PUBLIC
            Code:
            stack=1, locals=1, args_size=1
            0: aload_0
            1: invokespecial #1 // Method java/?
            ? lang/Object."<init>":()V
            4: iconst_0
            5: putstatic #2 // Field a:I
            8: iconst_0
            9: putstatic #3 // Field b:I
            12: return
            

            a的設定器

            public static void set_a(int);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=1, locals=1, args_size=1
            0: iload_0
            1: putstatic #2 // Field a:I
            4: return
            

            a的取得器

            public static int get_a();
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=1, locals=0, args_size=0
            0: getstatic #2 // Field a:I
            3: ireturn
            

            b的設定器

            public static void set_b(int);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=1, locals=1, args_size=1
            0: iload_0
            1: putstatic #3 // Field b:I
            4: return
            

            b的取得器

            public static int get_b();
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=1, locals=0, args_size=0
            0: getstatic #3 // Field b:I
            3: ireturn
            

            953 類中的公有和私有字段代碼沒什么區別。 但是類型信息會在in.class 文件中表示,并且,無論如何私有變量是不可以被訪問的。

            讓我們創建對象并調用方法: 清單 54.16: ex1.java

            954 新指令創建對象,但不調用構造函數(它在4行偏移被調用)set_a()方法被在16行偏移被調用,字段訪問使用的getstatic指令,在行偏移21。

            Listing 54.16: ex1.java

            #!java
            public class ex1
            {
                public static void main(String[] args)
                {
                    test obj=new test();
                    obj.set_a (1234);
                    System.out.println(obj.a);
                }
            }
            

            public static void main(java.lang.String[]);
            flags: ACC_PUBLIC, ACC_STATIC
            Code:
            stack=2, locals=2, args_size=1
            0: new #2 // class test
            3: dup
            4: invokespecial #3 // Method test."<?
            ? init>":()V
            7: astore_1
            8: aload_1
            9: pop
            10: sipush 1234
            13: invokestatic #4 // Method test.?
            ? set_a:(I)V
            16: getstatic #5 // Field java/?
            ? lang/System.out:Ljava/io/PrintStream;
            19: aload_1
            20: pop
            21: getstatic #6 // Field test.a:I
            24: invokevirtual #7 // Method java/io?
            ? /PrintStream.println:(I)V
            27: return
            

            54.17 簡單的補丁。


            54.17.1 第一個例子

            讓我們進入簡單的一個例子。

            #!java
            public class nag
            {
                public static void nag_screen()
                {
                    System.out.println("This program is not ?
                        ? registered");
                };
                public static void main(String[] args)
                {
                    System.out.println("Greetings from the mega-?
                        ? software");
                    nag_screen();
                }
            }
            

            我們如何去除打印輸出"This program is registered".

            最會在IDA中加載.class文件。

            清單54.1: IDA

            enter image description here

            我們patch到函數的第一個自己到177(返回指令操作碼) Figure 54.2 : IDA

            enter image description here

            這個在JDK1.7中不工作

            Exception in thread "main" java.lang.VerifyError: Expecting a ?
            ? stack map frame
            Exception Details:
            Location:
            nag.nag_screen()V @1: nop
            Reason:
            Error exists in the bytecode
            Bytecode:
            0000000: b100 0212 03b6 0004 b1
            at java.lang.Class.getDeclaredMethods0(Native Method)
            at java.lang.Class.privateGetDeclaredMethods(Class.java?
            ? :2615)
            at java.lang.Class.getMethod0(Class.java:2856)
            at java.lang.Class.getMethod(Class.java:1668)
            at sun.launcher.LauncherHelper.getMainMethod(?
            ? LauncherHelper.java:494)
            at sun.launcher.LauncherHelper.checkAndLoadMain(?
            ? LauncherHelper.java:486)
            

            956 也許,JVM有一些檢查,關聯到棧映射。 好的,為了讓path不同,我們使用remove call nag()

            清單:54.5 IDA NOP的操作碼是0: 現在工作起來了

            enter image description here

            54.17.2第二個例子

            現在是另外一個簡單的crackme例子。

            #!java
            public class password
            {
                public static void main(String[] args)
                {
                    System.out.println("Please enter the password")?
                        ? ;
                String input = System.console().readLine();
                if (input.equals("secret"))
                    System.out.println("password is correct?");
                else
                    System.out.println("password is not ?
                    ? correct");
                }
            }
            

            圖54.4:IDA

            enter image description here

            我們看ifeq指令是怎么工作的,他的名字的意思是如果等于。 這是不恰當的,我更愿意命名if (ifz if zero) 如果棧頂值是0,他就會跳轉,在我們這個例子,如果密碼 不正確他就跳轉。(equal方法返回的是0) 首先第一個主意是patch這個指令... iefq是兩個bytes的操作碼 編碼和跳轉偏移,讓這個指令定制,我們必須設定byte3 3byte(因為3是添加到當前地址結束總是跳轉同下一條指令) 因為ifeq的指令長度是3bytes.

            958 圖54.5IDA

            enter image description here

            這個在JDK1.7中不工作

            Exception in thread "main" java.lang.VerifyError: Expecting a ?
            ? stackmap frame at branch target 24
            Exception Details:
            Location:
            password.main([Ljava/lang/String;)V @21: ifeq
            Reason:
            Expected stackmap frame at this location.
            Bytecode:
            0000000: b200 0212 03b6 0004 b800 05b6 0006 4c2b
            0000010: 1207 b600 0899 0003 b200 0212 09b6 0004
            0000020: a700 0bb2 0002 120a b600 04b1
            Stackmap Table:
            append_frame(@35,Object[#20])
            same_frame(@43)
            at java.lang.Class.getDeclaredMethods0(Native Method)
            at java.lang.Class.privateGetDeclaredMethods(Class.java?
            ? :2615)
            at java.lang.Class.getMethod0(Class.java:2856)
            at java.lang.Class.getMethod(Class.java:1668)
            at sun.launcher.LauncherHelper.getMainMethod(?
            ? LauncherHelper.java:494)
            959
            CHAPTER 54. JAVA 54.18. SUMMARY
            at sun.launcher.LauncherHelper.checkAndLoadMain(?
            ? LauncherHelper.java:486)
            

            不用說了,它工作在JRE1.6 我也嘗試替換所有3ifeq操作嗎bytes,使用0字節(NOP),它仍然會工作,好 可能沒有更多的堆棧映射在JRE1.7中被檢查出來。

            好的,我替換整個equal調用方法,使用icore_1指令加上NOPS的爭強patch.

            enter image description here

            11總是在棧頂,當ifeq指令別執行...所以ifeq不會被執行。

            工作了。

            54.18總結

            960 和C/C+比較java少了一些什么? 結構體:使用類 聯合:使用集團類 無附加數據類型,多說一句,還有一些在Java中實現的加密算法的硬編碼。 函數指針。

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线