A couple of years ago I walked into a coworkers office and noticed a shelf full of about two dozen Java books. I was a bit surprised since this coworker (Bob) was a Fortran compiler engineer and didn't have much to do with Java. It turns out that when Java was introduced, Bob decided to buy every single Java book that came out. Obviously this didn't last very long. Today you can walk into practically any bookstore and pick through a selection of hundreds of Java related books. Yet, even with this glut of Java material, there are not many books about Java Internals or debugging Java programs at the runtime level. The newly published book by Alex Kalinovsky, Covert Java: Techniques for Decompiling, Patching, and Reverse Engineering attempts to delve into the backend and internals of Java programs.
Kalinovskys book consists of roughly 225 pages of content, is published by SAMS and retails for $29.99. I paid $24.95 or somewhere in that range. I'll try to go through most of the chapters and review them individually.
ISBN: 0672326388; Published: May 3, 2004; Copyright 2004; Dimensions 7-3/8" x 9-1/8" ; Pages: 288; Edition: 1st.Contents:
- Getting Started.
- Decompiling Classes.
- Obfuscating Classes.
- Hacking Non-Public Methods and Variables of a Class.
- Replacing and Patching Application Classes.
- Using Effective Tracing.
- Manipulating Java Security.
- Snooping the Runtime Environment.
- Cracking Code with Unorthodox Debuggers.
- Using Profilers for Application Runtime Analysis.
- Load-Testing to Find and Fix Scalability Problems.
- Reverse Engineering Applications.
- Eavesdropping Techniques.
- Controlling Class Loading.
- Replacing and Patching Core Java Classes.
- Intercepting Control Flow.
- Understanding and Tweaking Bytecode.
- Total Control with Native Code Patching. 19. Protecting Commercial Applications from Hacking.
The first chapter starts by laying out the rest of the book in a concise manner with the use of a more detailed table of contents, and describes what each chapter is useful for. There are a couple of paragraphs on which File Managers and IDEs are good to use. I think a little too much time is spent covering the two recommended file managers (FAR and Total Commander). Oddly enough, Kalinovsky spends more time talking about the file managers than Java IDEs. At this point the reader will start to realize that this book has very small chapters. Chapter 1 is a stretched to a total of 9 pages.
In this chapter, Kalinovsky discusses a couple of different Java decompiling tools, some commercial and some free/GPL ones. There is also an example of some Java code which is compiled and then decompiled. This example could have definitely been shortened from the 2.5 page long code listing to a 10 line code sample. Again, I got the impression that this was done to fatten up the text. The author talks briefly about Java bytecode but oddly enough never mentions the built-in 'javap' command which ships with the J2SE JDK. Kalinovsky also mentions that decompiling code is no panacea and how code obfuscators can make it very difficult to decompile code. Overall, this chapter is a decent introduction to Java decompilation for the uninitiated.
Progressing from the previous chapter, Kalinovsky goes into the concept of obfuscating Java source code for the purpose of intellectual property protection. He does a good job of explaining the different steps of obfuscation and the merits of each technique. He also compares five different popular obfuscator products available on the market. The Zelix KlassMaster product is used as a step-by-step example tutorial on how to actually obfuscate a Java class.
Hacking Non-Public Methods and Variables of a Class
This chapter discusses what many Usenet groups and online Web forums have been talking about for a while now, using the reflection API and security managers to peak into methods, variables and protected members. There is nothing new here, but the information is gathered in one location so the reader is spared having to search the net for tidbits of knowledge.
Replacing and Patching Application Classes
Chapter 5 may very well be the most interesting chapter to many readers as this is where Kalinovsky delves into the process of patching 3rd party Java classes and libraries. The author provides a small example application which he proceeds to patch without using the original source code. While the example is somewhat trivial, Kalinovsky does a good job of making his points and guides the reader through analysis, patching, and repackaging the patched Java class into the overall application.
Using Effective Tracing
The chapter on tracing is very thin and does not really provide anything that even a rookie Java programmer should not already know. There is some talk of the different tracing/logging APIs such as Apache's Log4J, and the Sun Java Logging API. Other than that, this chapter simply provides good basic advice that should be expected of any programmer in any language.
Snooping the Runtime Environment
While most of the data provided in this chapter is relatively basic, the fact is that it is very necessary. I'm somewhat surprised at how many times I've come across Java developers who don't know (or don't remember?) how to find out basic information about the runtime environment that their code is running in. Kalinovsky provides some concise code snippets which help return environment information such as JVM vendor name, version, memory consumption, number of CPUs available, and network IPs.
Cracking Code with Unorthodox Debuggers
This chapter is basically a tutorial of the Omniscient Debugger by Bil Lewis. Bil also has his own articles and user manuals for the Omniscient Debugger, but I have to thank Kalinovsky for bringing this tool to my attention. In his tutorial, the author uses the "ODB" to track through a small sample application.
Using Profilers for Application Runtime Analysis
Chapter 10 is a relatively meaty chapter which introduces some popular profiling products such as JProbe, OptimizeIt, and JProfiler. Kalinovsky uses JProbe for his examples and prefers it over the tools. This chapter also gives brief introductions to concepts such as garbage collection, references, race conditions, and deadlocks. The author goes into some detail while using JProbe to illustrate his points. Unfortunately, I was extremely disappointed to see that this decent chapter was marred at the end by the authors lack of detail on Java thread dumps! I read through the chapter nodding and thinking "I'm sure he'll soon talk about thread dumps...he must.", and finally I was greeted with a thread dump. Much to my dismay, Kalinovsky simply shows the thread dump, explains the basics of how to attain a thread dump, but never goes into the details of how to read a thread dump! This topic could have, and should have been a chapter unto itself.
Load-Testing to Find and Fix Scalability Problems
In this chapter, the author makes a very wise decision to quickly mention the high-end load testing products but settles on using Apache JMeter for all of his examples. He also shows how to load-test RMI based servers using JUnit. Kalinovsky introduces his own companies product at this point, WebCream, and while I don't mind the plug, I somewhat wish I didn't have to download yet another product to go through the steps involved in this chapter. Nevertheless, it's a small price to pay and some may find other uses for WebCream.
Reverse Engineering Applications
I expected a chapter with such a sexy name to be chock full of illicit goodies. Alas, this is not the case. The chapter is split into three very small sections, modifying text strings in Java apps, modifying images in Java apps, and hacking application configuration files. This chapter could be torn out of the book and I would have never noticed its absence.
Chapter 13 discusses methods for network sniffing HTTP, RMI, and JDBC protocols. The author uses TCPMON, EffeTechs HTTP Sniffer and Ethereal to demonstrate sniffing. The Ethereal section of the chapter could have been elaborated on with some screenshots to make the section a bit more palatable. One of the greatest things I found while reading this chapter was the JDBC sniffer tool, P6Spy. Kalinovsky shows examples of P6Spy being used to sniff SQL statements for the purpose of debugging. Maybe I'm just naive, but I had never thought there were any tools for specifically sniffing JDBC protocols. Great stuff.
Replacing and Patching Core Java Classes
This chapter is somewhat of a continuation of Chapter 5. The title of the chapter describes it all, Kalinovsky does a good job of showing the reader how to patch the java.lang.Integer class as an academic exercise. His tutorial goes through the process of writing the code, patching the Java class and then starting the JVM so that it points to the newly patched class.
Understanding and Tweaking Bytecode
The Bytecode chapter is one of the few meaty chapters in this book and does a good job of explaining the Bytecode concept and implementation in Java. Anyone interested in bytecode representations of Java class files should read this chapter. Kalinovsky gives an overview of tools such as jClassLib, BCEL, ASM library, but again fails to mention anything about the 'javap' command which ships with the J2SE JDK. Odd, but nevertheless this chapter is key.
Total Control with Native Code Patching
Kalinovsky gets deep in this chapter and explains the concepts of debugging JNI applications and tweaking native libraries with ASM. Since I'm a relative newbie when it comes to Windows based programming, this chapter is a pretty valuable to me as it introduces me to the basics of patching native code on the Windows Platform. The author goes into a good amount of detail and presents some good tools for viewing disassembled code on Windows. I'll have to read this chapter a couple of times and go through the steps before really understanding it all, but I definitely give this chapter a thumbs up.
Protecting Commercial Applications from Hacking
Chapter 19 will appeal to developers who are looking to distribute their Java programs and fear theft of intellectual property. My first thought on this chapter was that it would just be a review of different obfuscation tools, but to my surprise, there is much much more included here. Kalinovsky does a great job of introducing Java developers to protecting their applications from content modification via checksums and implementing multiple types of license verification methods. Anyone wanting to write license code into their application needs to at least read this chapter.
"Covert Java" reminds me of the computer books from the early 1990s. It is chock full of recommendations for commercial, free, and open source tools. In many cases the author provides decent tutorials on how to use many of these tools and includes screenshots of the tools in action. Maybe it's the old 1990s feel that ingratiates me to this book, but most probably it's the fact that there are certain gems of knowledge hidden in the better chapters. Uber-geek Java developers with 15 years of experience (!) may not find this book useful at all, but I think Junior to Medium level Java folks will find the book useful and a relatively easy read. There are some glaring omissions in the book, such as the total lack of explanation on how to read a thread dump, but I'm hoping the 2nd edition will cover these mistakes. So should you buy this book? Yes. I give it 7 out of 10 stars.