Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
A Software Fingerprinting Scheme for Java Using Classfiles Obfuscation Kazuhide Fukushima1 and Kouichi Sakurai2 1 2 Graduate School of Information Science and Electrical Engineering, Kyushu University, Japan, [email protected], http://itslab.csce.kyushu-u.ac.jp/\%7Efukusima/index.html Faculty of Information Science and Electrical Engineering, Kyushu University, Japan, [email protected], http://itslab.csce.kyushu-u.ac.jp/\%7Esakurai/index.html Abstract. Embedding a personal identifier as a watermark to Java classfile is effective in order to protect copyrights of them. Monden et al.[1] proposed watermarking scheme that embeds arbitrary character sequence to the target method in a Java classfiles. But the scheme can be only used to embed the same watermark to each user’s classfiles. Therefore, if we apply this scheme for embedding each user’s personal identifier, the watermarks can be specified by comparing two or more users’ Java classfiles. In this paper solve the problem by using “Classfiles Obfuscation” which is our obfuscation scheme for Java sourcecodes. By the scheme, we distribute all the methods among the all the Java classfiles at random. Evrey user’s Java classfiles will have different structures respectively by appling “Clasfiles Obfuscation”. As the result, to specify watermark by compareing classfiles will be difficult. 1 1.1 Introduction Background and Motivation Recently, Java has spread widely. Java sourcecodes are compiled to Java classfiles which are independent of machines or operating systems. And they are executed on the Java Virtual Machine (JVM). The same Java classfiles can run on different platforms without recompiling because the JVM for each platform is prepared. Java programs can run on portable phones and small information terminals such as Personal Digital Assistants (PDA) as well as PCs and Workstations. On the other hand, Java classfiles contain information such as the name of the class, the name of the super class and names of the methods and the fields defined in the class. Moreover, the description of a classfile can be divided into description of the field and the methods. Therefore, Java classfiles have high readability. As the result, an attacker can obtain Java source codes easily by decompiling Java classfiles. He can crib secret data and key algorithms by his reverse engineering of the obtained source code. K. Chae and M. Yung (Eds.): WISA 2003, LNCS 2908, pp. 303–316, 2004. c Springer-Verlag Berlin Heidelberg 2004 304 K. Fukushima and K. Sakurai Software developers are frightened by the prospect of a competitor being able to extract secret data and key algorithm in order to incorporate them into their own programs. The competitor may intercept their commercial edge by cutting development time and cost. To make matters worse, it is difficult to detect and pursue the injustice. Software obfuscation[2,3,4,5,6] is a scheme to solve the problem. Software obfuscation makes sourcecode difficult to analysis, while its functionalitys are preserved. We can apply these techniques for protecting the copyright of software. However, it is impossible to specify the person who copied software illegally. Moreover, an other attecker may steal Java classfiles in a program and create a new Java program using the Java classfiles. Software wartermarking scheme can be applied for stand up to this problem[7,1]. Even if an attacker steals Java classfiles and distributes a new program using them, the fact of the crib can be proved by extracting the watermark from the program. However in this case, since the information embedded is a developer’s identifier, it is impossible to specify the person who copied the program illegally. In this paper, we propose a digital fingerprinting scheme for Java. We improve the watermarking scheme by Monden et al. to embed user’s identifier. But, this scheme has the big problem that the embedded position of personal identifiers can be easily specified. In order to solve the problem, we apply the ‘Classfiles Obfuscation. This obfuscation make to specify the embedding position of software fingerprinting difficult, even when two or more users conspire. 1.2 Related Work Digital watermarking scheme. Most of digital watermarking schemes for pictures and sounds have been studied. However, digital watermarking schemes for software have been proposed. Digital watermarking scheme for Java is [7,1]. Kitagawa et al[7] proposed the watermarking scheme which embeds arbitrary sequences as a watermark. In this scheme, variables are prepared and sequences are stored as watermark the variables. When extracting the watermark, specific, a certain class file is change into special class file for extraction. Monden et al[1] proposed the watermarking scheme which embeds watermarks to numerical operands or opcodes in the class files. In this scheme, a dummy method is injected to the target source code as a space for a watermark. In this scheme, even if only one class file is stolen, the watermark can be extracted from the dummy method. Furthermore, the watermarking scheme is implemented as the tools “jmark” and “jdecode” [8]. However we need to embed not the developer’s identifier but the personal identifier to the program to prevent illegal copies and unjust distributions. Obfuscation schemes. On the other hand, there many researches about obfuscation schemes. Many obfuscation tool have been developed such as Don Quixote[9] and Zelix KlassMaster[10]. A Software Fingerprinting Scheme for Java Using Classfiles Obfuscation 305 Collberg and Low proposed an obfuscation scheme for Java programs by injecting dummy codes and complicating data structures and control flows[2,3]. Monden et al. proposed an obfuscation scheme for C programs contain loops . Few obfuscation schemes have basis of security. On the other hand, Myers[11] had came up with the negative result that many interprocedual Static Analysis problem are NP-complete in 1981. Later, Wang et al. proposed an obfuscation scheme based on the fact that the problem of determining precise indirect branch target addresses is NP-hard[4]. They used global arrays and pointers of C programs in their scheme. Ogiso et al[6]. extended this technique by using function pointer. If we use this technique, since neither control flow graph nor call graph of the obfuscated program settled statically, static analysis of the program becomes remarkably difficult. These technique have the basis of security. But we cannot introduce pointers to Java programs by the problem of the grammer. Then Sakabe et al[5] proposed the technique that makes static analysis of the obfuscated program much more difficult, by using method overloading and interfaced. Barak et al. show that there are no obfuscator that satisfy “virtual black box” property. (i.e. there is no obfuscator O, such that for any program P , Anything that can be efficiently computed from O(P ) can be efficiently computed given oracle access to P . Recently, many analysis tools for Java classfiles, including decompiler (such as Mocha[12] and Jad[13]), have been developed and they are improved rapidly. In the near future those scheme may be broken. On the other hand, few tools that can analyze the role of classfiles, which is abstract notion, automatically. 1.3 Challenging Issues When we apply watermarking scheme by Monden et al.[1] for embedding personal identifier, we have two problems. One is the vulnerability of watermark itself. An attacker can specify the dummy method by investigating all the methods in every Java classfiles. If he can specify dummy methods (in which a personal identifier is embedded), he can eliminate or tamper the fingerprint. The time he needs for this attack is proportional to the number of the methods in a class file. This attack is effective because the number of the methods in every class file is generally at most dozens of pieces. Actually we can specify the dummy method in which embedded watermarking from a class file by investigating the method which is not called. and we can eliminate or tamper easily. This is a fatal problem, because a personal identifier embedded in Java classfiles is used to specify the user who distribute program illegally. Another is the vulnerability over two or more user’s conspiracy. The Java classfiles distributed to users are the same when the developer’s identifier is embedded as a watermark. The dummy method of a class file will differ for every user when the personal identifier is embedded as fingerprinting. In this case, the dummy method can be specified by comparing each of class file of two or more users. Actually we can specify the dummy method by taking difference of two Java classfiles. 306 1.4 K. Fukushima and K. Sakurai Our Contribution We pointouted two problems of watermarking scheme. The first one is vulnerability over brute force attack. We can specify the dummy method embeded watermark effectively, because there are not so many methods contained in a class file. The second one is vulnerability over conspiracy attack. We can specify the dummy method by comparing two or more Javas classfiles. We improve the watermarking Monden et al to embed personal identifier to Java Program. In this paper, we solve the problem by using “Classfile Obfuscation” that is an obfuscation scheme. By the scheme, we distribute all the methods among the all the Java classfiles at random. Every user Java classfiles of different structure respectively by carrying out this scheme. As the result, to specify watermark by compareing Java classfiles comes to difficult even when two or more persons conspire. And we restrict the retern value of dummy methods to void, dummy method comes to called at any site. 2 Watermarking Scheme by Monden et al. We use the watermarking scheme by Monden et al to embed personal identifier to Java Program. In Java, verifier check bytecodes before programs are executed. Therefore, it is necessary to be careful for embed personal identifier to Java classfiles. 2.1 Encoding Procedure Their watermark encoding procedure consists of following three phases. 1. Inject of dummy methods In the first phase of watermarking, the dummy method, which will never be executed actually, is to a target Java program. Dummy method is a space for watermark codeword. Dummy method must be large enough to embed watermark. 2. Compilation In the second phase, the Java source program in which dummy method was injected, is compile with Java compiler. 3. Watermark injection In this phase they need to take account of the bytecode verifier. When execute a Java application or applet, the bytecode verifier checks the syntactical rightness and type consistency of the program. In order to keep them, they use following two approaches. (1) Overwriting numerical operands A numerical operand of an opcode that pushes a value to stack, and of an opcode that pushes a value to the stack, can be overwritten any other value without syntactical incorrectness and type inconsistency. For example, an operand xx of the opcode iinc xx can be overwritten into any single byte. A Software Fingerprinting Scheme for Java Using Classfiles Obfuscation 1. Dummy method 2. Compile 307 3. Watermarking injection injection Java sourcecode --------- 101011 Java classfiles Dummy method Fig. 1. Overview of watermarking scheme by Monden et al. On the other hand, most of other operands that indicate a position or and index of class table or location variable can not be overwritten because of syntactical incorrectness. (2) Replacing operands In odder to increase the place for watermark injection, they replace some of the opecodes into other kind of opcode. For example, an opcode iadd can be replaced to anything among isub, imul, idiv, irem,iand, ior and ixor. This indicates that above eight opcode can be replaced mutually. They can encode 3 bits information into these opecodes by assigning 000 to iadd, 001 to isub, 010 to imul, · · ·, and 111 to ixor. Such information assignment and opcode replacement can be also done in other opecodes groups. 2.2 Decoding Procedure In the watermark decoding phase, there is an assumption that they know the relation between bytecode and their assigned bits and their assigned bits, and also the relation between bit sequence and alphabet. The decoding algorithm is very simple. They simply do the exactly opposite procedure of watermark injection procedure, from top of every method. Both opcode and operand in each class method should be replaced into bit sequence, and then they should be replaced into alphabet sequence. After that, watermark will appear from the dummy method. 2.3 Our Attack to Their Scheme We can attack to their scheme by taking advantage of vulnerability of their scheme mentioned in section 1.3. We can remove or tamper, if we can specify the dummy method by brute force attack or conspiracy attack of two or more users. We attack to their sample program TEST0 that can convert midi to text. The program has one class file and twelve methods (include the one dummy method). 308 K. Fukushima and K. Sakurai #classfile: TEST0.class #key: default #algorithm: 0 (default) #begin{watermark} 1 " B2VL" 2 "))VXVXV771XV771XFIF3H3X6XF" 3 " BO" 4 "F(J1GJ" 5 "" 6 "" 7 " B,2K 4C" 8 "6BK2V 7N" 9 "0VO7" 10 "ALICE ALICE ALICE ALICE AL" 11 " B,2K I3" 12 " JHJ1J JX1V1" #end{watermark} Fig. 2. The output of ‘jdecode’ for TEST0.class Brute force attack. We assume that watermark string ALICE is embedded to the target class file, TEST0.class. The output of jdecode, that is the decode tool realizing their scheme, is shown by Fig.2. The watermark is embedded in the tenth method. We can specify the dummy method by Brute force attack. The attack consists of four phases. 1. Decompilation In the first phase of our attack, the class file(s) is decompiled to Java source code(s). We used Jad[13] that is a one of famous Java decompiler, in this Phase. 2. Extraction of methods In the second phase, we extract method from Java source code(s), obtained in first phase. And we make the list of the methods those are defined in this class. Twelve methods are defined in the class, TEST0.class. The list of method is as follows. main, TEST0, handleEvent, action, f021, m2t, check STD header, check format, write STD header,check std, check TRK header, length 3. Searching the dummy method In this phase, we investigate whether each method is used actually. We use grep command of unix. The method f021 is not the dummy method because it called the form of f021(smf0.getText(), smf1.getText()). One the other hand, we see grep check std is the dummy method, because the method is never called. 4. Attacking to the watermark Finally we can attack to the watermark by eliminating the dummy method or tampering operands and opcode in the dummy code. The output of jdecode is change into A Software Fingerprinting Scheme for Java Using Classfiles Obfuscation 309 Conspiracy attack. We assume that watermark string ALICE is embedded to the class file, TEST0 A.class and string BOB is embedded to the class file TEST0 B.class. The outputs of jdecode for TEST0 A.class and TEST0 B.class are demonstrated by Fig.5. We can attack to the scheme by conspiracy attack The attack is consisted of three phases. 1. Decompilation In the first phase of our attack, the class files is decompiled to Java source code(s). We obtain TEST0 A.Java from TEST0 A.class and TEST0 B.Java from TEST0 B.class. 2. Taking the difference of class file We take advantage of the fact that watermarks are different for every user. We take the difference of class file using diff command of UNIX. The output of diff is shown by Fig.6. According to the output, we see that position of the dummy code (from 240th line to 259th line). 3. Attacking to the watermark Finally we can attack to the watermark by eliminating the dummy method or tampering operands and opcode in the dummy code. 3 3.1 Classfiles Obfuscation for Java Our Proposed Obfuscation Scheme Data structures (fields) and procedures (methods) are defined all together in Java. This is called encapsulation. The exterior of the class doesn’t need to take into consideration the processing which is executed inside. This is called abstraction in Java. In our proposed scheme, relation during a class file can be made unclear by distributing methods between class files and destroying abstraction. By operation 1 and 2 shown bellow, we make preparations for distributing methods (operation 3) between class files. Furthermore, after distributing methods, We have to correct a call side by opration 4. 1. Destruction of encapsulation % less TEST0.JAVA | grep handleEvent f021(smf0.getText(), smf1.getText()); System.out.println("ERROR! in calling f021"); private void f021(String filename1, String filename2) throws IOException{ % less TEST0.JAVA | grep check_std private void check_std(int k){ Fig. 3. The output of grep 310 K. Fukushima and K. Sakurai ¥begin{verbatim} #classfile: TEST0.class #key: default #algorithm: 0 (default) #begin{watermark} 1 " B2VL" 2 "))VXVXV771XV771XFIF3H3X6XF" 3 " BO" 4 "F(J1GJ" 5 "" 6 "" 7 " B,2K 4C" 8 "6BK2V 7N" 9 "0VO7" 10 "BBOX XBJVS SEFE JREYU SS" 11 " B,2K I3" 12 " JHJ1J JX1V1" #end{watermark} Fig. 4. The output of grep TEST0_A.class #classfile: TEST0_A.class #key: default #algorithm: 0 (default) #begin{watermark} 1 " B2VL" 2 "))VXVXV771XV771XFIF3H3X6XF" 3 " BO" 4 "F(J1GJ" 5 "" 6 "" 7 " B,2K 4C" 8 "6BK2V 7N" 9 "0VO7" 10 "ALICE ALICE ALICE ALICE AL" 11 " B,2K I3" 12 " JHJ1J JX1V1" #end{watermark} TEST0_B.class #classfile: TEST0_B.class #key: default #algorithm: 0 (default) #begin{watermark} 1 " B2VL" 2 "))VXVXV771XV771XFIF3H3X6XF" 3 " BO" 4 "F(J1GJ" 5 "" 6 "" 7 " B,2K 4C" 8 "6BK2V 7N" 9 "0VO7" 10 "BOB BOB BOB BOB BOB BOB BO" 11 " B,2K I3" 12 " JHJ1J JX1V1" #end{watermark} Fig. 5. The output of ‘jdecode’ for TEST0 A.class and TEST0 B.class a) Publication of the fields Modifiers of all the fields of all classes are changed into public. By this change, all fields can be accessed from all the sites of the program. b) Publication of methods Modifiers of all the methods of all classes are changed into public static. By this change, all methods can be accessed from all the sites of a program. These are called in the form of (class name).(method name). A Software Fingerprinting Scheme for Java Using Classfiles Obfuscation 240c240 256c256 < for(int j = -1; j < 25; j -= 128) < for(int l = -1; l > 49; l += 25) --- --- > for(int j = 2; j >= 101; j -= 115) > for(int l = 0; l >= -42; l += 104) 242,243c242,243 258,259c258,259 < < < for(int i1 = 2; i1 >= 76; i1 += 6) i += (j - 38) % i1; --> > < 311 for(int k1 = 0; k1 < 96; k1 += 76) i |= l + 4 + (k1 + 3); --for(int i1 = 0; i1 > 1; i1 -= 98) i &= (j | 0x1a) * i1; > > for(int k1 = 1; k1 < -32; k1 += 89) i -= (l + 4) / (k1 & 4); 248c248 < for(int k = 2; k <= 100; k += 0) --> for(int k = 1; k < -32; k += 89) 250,251c250,251 < < for(int j1 = -1; j1 > 49; j1 += 25) i += (k | 3) + j1; --> > for(int j1 = 0; j1 >= -42; j1 += 104) i += (k | 4) + j1; Fig. 6. The result of diff TEST0 A.Java TEST B.Java 2. Change of the methods An instance method may be changed into a class method when encapsulation breaks in operation 1. Therefore, an instance needs to be added as a new argument of methods. An example is shown in Fig.7. class A{ private int a; public void set(int x){ a = x; } } Before Obfuscation class A{ public int a; public static void set(int x, A Obj){ Obj.a = x; } } After Obfuscation Fig. 7. The transformation of the code. After change, Methods set must newly take as a parameter Obj which is the instance of class A. Furthermore, it must be shown that the substitution to the field a is the field a of the Instance Obj. 312 K. Fukushima and K. Sakurai 3. Distribution the Methods All methods are changed into the class method which can call from anywhere by operation 1 and 2. Thereby, all methods can be placed in arbitrary classes. 4. Change of the arguments The methods are changed and distributed by operation 1, 2 and 3. We have to correct a call side for this reason. For example, the instance method of class A must have been called in the form of “obj A.setA(3);” through the instance of class A (say Obj a). However, after applying obfuscation, the instance of the class is added as a parameter and it is changed into the class method of other class (for example, class B). The method comes to be called in the form of “B.set(3,Obj A);”. 3.2 Experiments In this section we present application of our obfuscation scheme to five programs, that is, BinTree, BinSearch, HuffmanEncoding, TopologicalSort and HeapSort[14]. Table 1 shows the differences between the original programs and the obfuscated programs. We compare the number of lines, the number of classes, the number of methods, execution time [ms] and size of source code[KB]. The experiments were conducted on Intel Pentium III 1GHz with RedHat Linux 8. We can readily see from the table that the number of lines and the size of source code does not increase so much. And the number of methods never increase because we only change the position of method. Moreover, the obfuscation does not affect the execution time. Rather, it becomes better. The improvement due to change from instance methods to class methods. Table 1. The property the programs Program BinTree BinSearch HuffEnc TopSort Heapsort 4 4.1 Before Obfuscation #lines #classes #methods time 201 3 24 6100 99 2 11 4250 226 3 31 6290 156 3 18 2940 203 3 18 3010 size 3.46 1.76 3.83 2.51 3.48 After Obfuscation #lines #classes #methods time 227 14 24 5640 108 11 6 3960 280 17 31 6090 187 10 18 2870 228 12 18 2890 size 4.34 2.18 4.76 2.71 4.34 Our Proposed Scheme The Procedure Our fingerprinting encoding procedure consists of following four phase. 1. Inject of dummy method In the first phase of watermarking, the dummy method, which will never be executed actually, is inserted to a target Java program. A Software Fingerprinting Scheme for Java Using Classfiles Obfuscation 313 4. Obfuscate by distributing the methods 3. Fingerprinting injection 1. Dummy method 2. Compile injection Buyer A Java sourcecode Java classfiles Buyer B Dummy method Buyer C Fig. 8. Overview of our fingerprinting scheme 2. Compilation In the seconds phase, the Java source program (in which dummy method was injected) is compiled. We can obtain the Java class files. 3. Fingerprinting injection In the third phase, we embedded personal identifier to Java program by the same method as Monden et al. 4. Obfuscation Finally we apply our obfuscation scheme as mentioned above. The all methods in the program is distributed between the all class files. 1. Search the dummy method, to which we embedded personal identifier. 2. Decode I work in the decode to found met 4.2 Consideration of Our Proposed Method Now we consider a program which is embed personal identifier by the our proposed scheme. The dummy method, which is embedded as personal identifier, does not have an influence on the execution time, because it isn’t executed actually. And we consider that the execution time increases hardly, because the obfuscation scheme, we apply in pile, change only position where methods are placed. The following five advantages lie in changing a class file by the dispersion of the way. By changing the class files distribution of the methods, we can get the following four advantages. 1. Preventing the theft of class files. The class files before applied obfuscation conversion contains data structures and algorithms. For this reason, other users can steal some class files and use them as parts of another program. However, after applied the obfuscation, since the data structures and the algorithms will be separated, it becomes 314 K. Fukushima and K. Sakurai TEST0_A mai n TEST0 l engt h check_f or mat TEST0_A1 TEST0_A2 check_STD_header f 021 m2t check_TRK_header check_f or mat act i on wr i t e_STD_header check_s t d* Fig. 9. Classes of TEST0 A impossible to use each class file as a parts of program. Therefore, the our proposed scheme is considered to be an effective measure to theft of class files. 2. The fall of the readability of class files Since the data structures and the algorithms are separated by conversion, the readability of a program falls remarkably. Therefore, we can prevent a malicious third persons’ reverse engineering. 3. Deletion of the number of dummy methods In the scheme of Monden et al. there is a dummy method in each class file. But after conversion, some dummy method is enough for program since the surreptitious use of every class file can be prevented. Therefore, it is necessary to find one dummy method from all the methods in all the class files. 4. Preventing two or more users’ conspiracy Before applying obfuscation conversion, we were able to pinpoint the position of the dummy method (in which personal identifier are embedded) by comparing two or more users’ class files. However, after methods are distributed between class files, it becomes difficult to pinpointing of the position of the watermark by comparison. We solved two problems, the vulnerability of watermark itself and the vulnerability over two or more users’ conspiracy, in Section 1.3. We can solved these problems with advantage 3 and 4 as mention above. We summarize the above result in a table. 4.3 The Example of Application We obfuscate classes TEST0 A.class and TEST0 B.class in section 2.3. For example, we can divide TEST0 A.class into three class TEST0 A, TEST0 A1 and TEST A2 and TEST0 B.class can be divide TEST0 B and TEST B1 as following. The dummy method is chech std. Since the structures of a class file differ, the attack by comparison is not effective. A Software Fingerprinting Scheme for Java Using Classfiles Obfuscation TEST0_B TEST0_B1 mai n TEST0 act i on check_TRK_header m2t check_f or mat check_STD_header check_f or mat f 021 wr i t e_STD_header check_s t d* l engt h 315 Fig. 10. Classes of TEST0 B 5 Conclusion We proposed the scheme by which we can embed personal identifier to a Java program. It was impossible to apply existing watermarking scheme as it is, because of attack by two or more users’ conspiracy. However, we were able to not only solve this problem by applying the obfuscation scheme using class file conversion in piles, but also raise the security of the class files. Acknowledgement. This research was partly supported by the 21st Century COE Program “Reconstruction of Social Infrastructure Related to Information Science and Electrical Engineering”. References 1. Monden, A., Iida, H., Matsumoto, K., Inoue, K., Torii, K.: A practical method for watermarking java programs. In: compsac2000, 24th Computer Software and Applications Conference. (2000) 2. C.Collberg, C.Thomborson, D.Low: A taxonomy of obfuscating transformations. Technical Report of Deptartment of Computer Science 148, University of Auckland, New Zealand (1997) 3. Low, D.: Java control flow obfuscation (1998) 4. Wang, C., Hill, J., Knight, J., Davidson, J.: Software tamper resistance: Obstructing static analysis of programs. Technical Report CS-2000-12 (2000) 5. Sakabe, Y., Soshi, M., Miyaji, A.: Software obfuscation for object oriented languages. Technical report of ieice (2002) 6. Ogiso, T., Sakabe, Y., Soshi, M., Miyaji, A.: A new approach of software obfuscation based on the difficulty of interprocedural analysis. IEICE Transactions on Fundamentals E86-A (2003) 176–186 7. Kitagawa, T., Kaji, Y., Kasami, T.: Digital watermarking method for java programs. Symposium on cryptography and information security (scis1998) (1998) 8. : (jmark: A lightweight tool for watermarking java class filess) http://se.aistnara.ac.jp/jmark/. 9. : (Don quixote) http://oikaze.com/tamada/Products/DonQuixote/. 10. : (Zelix klassmaster) http://www.zelix.com/klassmaster/. 11. Myers, E.M.: A precise inter-procedural data flow algorithm. In: Proceedings of the 8th ACM SIGPLAN-SIGACT symposium on Principles of programming languages, ACM Press (1981) 219–230 316 K. Fukushima and K. Sakurai 12. : (Mocha, the java decompiler) http://www.brouhaha.com/eric/computers/mocha.html. 13. : (Jad - the fast java decompiler) http://kpdus.tripod.com/jad.html. 14. Lafore, R.: Data Structures and Algorithms in Java (2nd Edition). (Sams)