MOBILE

Java Mobile Edition Security : Development and Security Testing (part 2) - Reverse Engineering and Debugging

2/15/2011 11:42:34 AM

Reverse Engineering and Debugging

Reverse engineering is a critical skill for almost every penetration tester and security engineer. Through reverse engineering, you can look at the hidden secrets of the platform and applications to find out how they really work and where the security flaws are. The goal is not to understand every instruction, but rather to understand what data the application is consuming and producing. After all, almost all security vulnerabilities result from errors when producing and consuming data.

Just as we benefit from being able to use the same development toolchain for JME, we benefit by being able to use the same debugging and reverse-engineering toolchain. Because JME code is Java, almost all of the standard Java security tools work, and there are even a couple of JME-specific tools that make reverse engineering and debugging easier.

Disassembly and Decompilation

Java application classes are compiled into Java “.class” files. These files contain Java bytecode, which is a machine-independent set of instructions for the Java virtual machine to execute. Machine-independent bytecode is what allows Java to run everywhere from ATMs to vending machines. When developers want to run Java on a new hardware platform or operating system, they create a new version of the Java virtual machine for that platform. If this virtual machine properly conforms to the Java specification, it will be able to execute Java bytecode without problems. For security reasons, Java mandates that bytecode be easily inspected at runtime. To support this, Java application bytecode must follow some conventions.

Disassembling x86 assembly code is a very painful process. Java instructions (a.k.a. opcodes) are each one byte in size. Depending on the opcode, there may or may not be instruction operands. Whether or not operands exist doesn’t matter. Every instruction will always be a predictable size. This quality is very important during runtime code inspection because it allows the virtual machine to easily traverse the application in a predictable manner. Additionally, instructions are not allowed to jump to invalid memory locations, use uninitialized data, or access private methods and data (see http://en.wikipedia.org/wiki/Java_virtual_machine). Contrast this to x86 programs, where these methods are often used to hide an application’s true behavior.

Just like the runtime does, reverse engineers can take advantage of the consistent size and variable rules to convert the program from its compiled form back into instructions—a process known as disassembly. Java is easy to disassemble—that is, it can be “decompiled” and turned back into Java source code. The results aren’t always pretty, but it is much easier to read messy Java source code than to read Java virtual machine opcodes.

Decompiling Java Applications

There are many Java decompilers to choose from. This author prefers the classic Java application decompiler (Jad). Jad was written in 2001 by Pavel Kouznetsov. It has not been changed since then, but still works remarkably well. To install Jad, download your desktop operating system’s version from the distribution source (http://www.varaneckas.com/jad) and decompress it to a folder.

To decompile code, follow these steps:

1.
JME applications come packaged as Java archive files (JAR). Within a JAR file can be lots of different file types, but we are interested in the ones that contain code. These are the “.class” files. To extract them from the JAR, simply change the JAR file’s extension to .zip and use your favorite extraction utility to extract the “.class” files. For this exercise, extract the files to the root folder \re_app\code. Keep the directory structure intact when you extract the files.

2.
Create the folder \re_app\src. This is where the decompiled source files will go.

3.
Run the following command from the \re_app\ directory:

jad -o -r -sjava -dsrc code/**/*.class

4.
Jad will decompile the application and generate the resultant Java files in the \re_app\src directory. The -r option is for recursive directory travel, and explicit output path (code/**/*.class) instructs Jad to reconstruct the packages and directories as they appeared in the input.

If you want to make a modification to the decompiled code and then recompile the application, you may be able to do so by loading the project into NetBeans. This doesn’t always work because the decompilation process is imperfect. For certain applications, some decompilers work better than others. This author has had limited success with JD-GUI (http://java.decompiler.free.fr/) and the DJ Java Decompiler (http://www.neshkov.com/dj.html).

Obfuscation

A small hurdle for reverse engineers is that many Java applications are intentionally made confusing through obfuscation. This process intentionally changes instruction paths and removes symbolic information, such as class and method names, from the compiled application. For example, an obfuscator renames the class com.isecpartners.test.MyApplication as a.a.a.C. This is not always done to confuse reverse engineers. Shorter Java class names and compressed code save memory, an important commodity on mobile devices. There are many obfuscators available, but one of the most common is ProGuard (http://proguard.sourceforge.net/). It is freely available and easy to use. Both NetBeans and the SDK bundle it with their software. For more information on obfuscators and how they work, visit the RCE forums (http://www.woodmann.com/forum/index.php).

Recovering original symbolic names after obfuscation is impossible. When reviewing obfuscated applications, look for references to core platform classes and APIs. References to these cannot be obfuscated. Reviewing between method calls can give you good insight into how the application works and is much more efficient than attempting to piece the application’s obfuscated code back together. At the very least, you will know which parts are important to analyze.

The following code is a sample decompilation of an obfuscated method. Notice that all symbolic information has been lost, so the decompiler has used alphabetic letters for class, method, variable, and parameter names. The mathematical operations are not a result of the obfuscation process.

protected final void I(int ai[], int i, int j, int k, int l, int i1, int j1)

{
int k1 = (F >> 15) - 36;
int l1 = k1 - 32;
int i2 = 512;
if(l1 > 64)
i2 = 32768 / l1;
int j2 = l1;
if(j2 > j1)
j2 = j1;
for(int k2 = l; k2 < j2; k2++)
I(ai, i, j, k, k2, i1, k2 + 1,
C(0xff3399ff, 0xff005995, (l1 - k2) * i2));


Hiding Cryptographic Secrets

Developers often use obfuscation to hide cryptographic keys and other secrets in their applications. While tempting, this is a fool’s errand. Obfuscation will slow reverse engineers down, but will never stop them. Even obfuscated code must be executed by the Java virtual machine and therefore must always be reversible.


Debugging Applications

NetBeans includes a full source debugger for stepping through application source code on real devices or on emulators. Unfortunately, you are not able to single-step through Java disassembly. To debug applications without source code, run the application through a decompiler, build it, and then debug it using NetBeans. Unfortunately, this is easier said than done because getting decompiled applications to compile again and work properly can be a challenge.

NetBeans communicates with the JVM on the machine using the KVM Debug Wire Protocol (KDWP). A specification for this protocol is available free from Sun (http://java.sun.com/javame/reference/docs/kdwp/KDWP.pdf). KDWP enables NetBeans to communicate directly with the JVM running on either the emulator or a real device. The protocol runs over a socket connection to the actual device. Not all devices are KDWP enabled, and many manufacturers require that you purchase KDWP devices directly from them. The KDWP can be used for custom debugging and reverse-engineering tasks where custom debug tools are required.

To debug an application in NetBeans, load the application project, ensure that it has no compile errors, and click the Debug Main Project button in the toolbar. This will deploy the project to the appropriate device and start the application. Breakpoints can be set up by pressing CTRL-F8 on the target source code line.

Network Monitor

Decompiling and debugging are effective tools for reverse-engineering applications, but they can be time consuming and are not always the most efficient way to approach a reversing problem. Monitoring input and output provides great insight into an application’s behavior and is significantly easier. The SDK includes a network monitor for monitoring network connections being made by a device or emulator. The best part is that it doesn’t just monitor HTTP or TCP traffic, it also monitors SMS traffic and shows SSL in cleartext.

Unlike debugging, which is enabled per invocation, network monitor logging is a configuration property of the emulator. To enable the network monitor, open a command prompt and run the following command:

c:\Java_ME_platform_SDK_3.0\bin\netmon-console.exe

This tool connects to running JME emulators and starts recording network traffic. When the netmon-console detects a new emulator, it logs a message (Output file: C:\Users\bob\netmon-9.nms) to the console. This file contains the network capture. You can also collect the capture from within NetBeans by changing the emulator’s configuration and selecting Network Monitor.

To view the network capture, follow these steps:

1.
Open the JME 3.0 SDK development environment. NetBeans does not include an option for opening saved network capture files.

2.
Select Tools | Load Network Monitor Snapshot.

3.
Browse to the file containing the snapshot (for example, C:\Users\bob\netmon-9.nms).

4.
The snapshot will load in Network Monitor and display a view similar to Figure 2.

Figure 2. Network Monitor displaying UDP and HTTP traffic

Now the fun begins. The topmost pane contains the list of network connections made by or to the application. The Protocol field lists the protocol used (arrows pointing to the right indicate the client initiated the connection; arrows pointing to the left are caused by server-generated traffic). You can dig deeper into individual packets by clicking on the connection and exploring the Hex View panels.

The Network Monitor is a great tool and has vastly improved in version 3.0 of the SDK. Use it when reverse engineering for its ease of setup and the depth of information it provides.

Profiler

Another useful application included with the SDK is the Application Profiler. Developers use this tool to help them find performance problems—a real concern for mobile applications. The Profiler records how much time is spent in each application method. This information is valuable to reverse engineers for finding the core methods of an application. It is especially useful when the application is obfuscated and you are not sure at which point to begin analysis.

Like the Network Monitor, the Profiler is more cleanly integrated into the newest version of the JME SDK than it is in NetBeans. There are some downsides: The profiler uses lots of memory and will significantly slow down your application.

It also does not provide a huge amount of detail. After all, it was built for performance analysis with well-understood applications, not for hackers.

Follow these steps to capture data using the Profiler:

1.
Open the JME SDK and load your source project. Make sure it compiles.

2.
Right-click on the emulator profile in the Device Manager pane and select Properties.

3.
Choose Enable Profiler. Record the Profiler filename listed in the properties panel (the filename will have the extension .prof).

4.
Start the project by clicking the Run arrow.

5.
Exercise the application. The goal is to figure out which code blocks are executed the most often and which system APIs are being called.

6.
Terminate the application and close the emulator.

7.
Open the Profiler log by clicking on Tools | Import JME SDK Snapshot.

8.
Browse to the stored .prof file and click Okay.

9.
The result will appear similar to Figure 3. The call graph can be expanded by clicking the plus arrow.

Figure 3. Profiler view after running the NetworkDemo application
Other  
  •  Java Mobile Edition Security : Configurations, Profiles, and JSRs
  •  Programming the Mobile Web : Performance Optimization
  •  Programming the Mobile Web : Testing and Debugging (part 3) - Client-Side Debugging
  •  Programming the Mobile Web : Testing and Debugging (part 2) - Server-Side Debugging & Markup Debugging
  •  Programming the Mobile Web : Testing and Debugging (part 1) - Remote Labs
  •  Windows Phone 7 : Working with Controls and Themes - Adding Transition Effects
  •  Windows Phone 7 : Working with Controls and Themes - Understanding Frame and Page Navigation
  •  Windows Phone 7 : Working with Controls and Themes - Panorama and Pivot Controls
  •  Programming the Mobile Web : Widgets and Offline Webapps - Platforms (part 5) - Windows Mobile & BlackBerry
  •  Programming the Mobile Web : Widgets and Offline Webapps - Platforms (part 4) - Windows Mobile & BlackBerry
  •  Programming the Mobile Web : Widgets and Offline Webapps - Platforms (part 3) - webOS & Android
  •  Programming the Mobile Web : Widgets and Offline Webapps - Platforms (part 2) - iPhone, iPod, and iPad
  •  Programming the Mobile Web : Widgets and Offline Webapps - Platforms (part 1) - Symbian/Nokia
  •  Programming the Mobile Web : Widgets and Offline Webapps - Standards
  •  Mobile Application Security : BlackBerry Security - Networking
  •  Mobile Application Security : BlackBerry Security - Local Data Storage
  •  Themes on Windows Phone 7 Devices (part 2) - Changing the Theme & Detecting the Currently Selected Theme
  •  Themes on Windows Phone 7 Devices (part 1) - Applying a Theme
  •  Programming the Mobile Web : Mobile Widget Platforms
  •  Programming the Mobile Web : Geolocation and Maps - Showing a Map
  •  
    Top 10
    The Return Of The Mini PC
    Zotac Z77-ITX Wi-Fi – A Fierce Competition
    Roll Your Own Home Server (Part 2)
    Roll Your Own Home Server (Part 1)
    How-To Imaging: Landscapes
    The Digital Economy Act: Back From The Grave
    Plug-in Of the Month - November 2012 : Audacity for Windows 2.0.2 RC4, Firefox 15 Beta 5, Comment Blocker
    Fractal Design Node 304
    Lian Li PC-TU200 - Gorgeous And Well-Built
    Miniature Marvels - Decent-Spec Mini-ITX Cases
    Most View
    Windows Server 2008 and Windows Vista : GPO Replication (part 1) - Group Policy Template and SYSVOL Replication, Active Directory Replication
    Birds Of Prey (Part 3) - Behind the scenes
    The Android Phone computer (Part 2) - The world of OTG & Big screen entertainment
    Synology DiskStation DS212j
    PNY NVidia GeForce GTX 660 Ti 2GB
    $150 Android HD/3D Player
    Programming the iPhone : Tables and Embedded Controls
    Programming .NET Components : Building a Distributed Application (part 6) - Remote Callbacks
    Sand, Sea And Samsung (Part 1)
    Top 10 Video Streaming : D-Link Boxee Box, Sony SMP-N200, Western Digital WD TV Live, Roku 2 NX
    AC Ryan Playon! HD2 Mini
    Integrating Applications with the Windows Phone OS : Working with Launchers and Choosers
    SQL Server 2008 : Performance Tuning - Tracing with SQL Profiler
    Windows Vista : Migrating User State Data - Evaluating Migration Technologies, Using Windows Easy Transfer
    Building Your First Windows Phone 7 Application (part 3) - Writing Your First Windows Phone Code
    Algorithms for Compiler Design: EXAMPLES for Bottom-up Parsing
    Plum Crazy Trooper – “‘70s-Era Muscle Cars”
    Windows Server 2003 : Implementing a GPO (part 1)
    Resolve a Hostname to an IP Address
    Programming the Mobile Web : HTML 5 (part 1)