Charles debugging proxy – analysis and dissection

Zveřejněno , upraveno - holoubekm Přidat komentář pitváme program

From now on, I’ll sometimes add a non-Czech content. Not just to reach a bigger audience, but mainly to revamp my writing skills.

When it comes to web debugging or penetration testing, a real hacker needs a solid toolset. To a bunch of my favorite software belongs mainly The Burp suite, which I use on a daily basis, and The Charles proxy. The later one has a huge benefit of seamless system integration and HTTPS support with a neat user interface. Besides the expected features like sniffing the web traffic, filtering requests and event making new ones, there are some powerful features any advanced user should be aware of. Let’s devote this post to the Charles proxy and its examination.

The forward proxy scheme – neither user nor server is aware of it. You may already be using this concept without even noticing it.

Features for which I fell in love with a crappy software:

  • Tuned-up GUI with support for filtering, grouping and displaying info about past traffic.
  • Ability to throttle communication – similar to the Chrome Dev Tools throttle
  • Reverse proxy
  • Portfor warding
  • Whitelist – blacklist based SSL proxying
  • Support for custom certificates
  • Remote control via built-in web interface
  • Advanced automation – support for repeating, break points and much more

The suite comes as a shareware with a 30 days trial version. Obviously, the most annoying feature of the trial version is automatic shutdown after 30 minutes.

The very first window Charlie greets us with is the splash screen with text about 30 days grace period. After the 10s timeout (arghh!) the main window opens and in the helpregister you can try your luck.

Sharpen your steel and let’s dive in (and possibly drown).

The content of the installation folder. Notice the jre and lib folders.

Observant reader has already realized we’ll be dealing with the java based software today. Actually, it’s a quite common to use java in apps working within the network stack. Now we should examine the .exe file using Exeinfo PE – this brilliant piece of software provides us with worthy info about the structure of a program, tools used for its creation and more.

Exeinfo PE – 64bit application for AMD CPU built probably using GNU GCC


Actually, charles.exe is just a wrapper for java runtime environment – that’s the reason for it’s bigger size, GCC and 64bit architecture.

From the picture above it’s clear that this executable would be a tough nut to crack – unmanaged 64bit files are a bit hardcore. But soon we’ll play with some of them. Let’s find an easier way in. Using specialized software such as procmon we would recognize that the main file executed here is the charles.jar from the lib folder. If you run the file directly using java RE the result would be the same.

$ java -jar charles.jar

The second way of running program – without the boring GUI

Java – it’s so 2016! How does it even work?

So now we know that the functionality would be hidden somewhere in the .jar or in one of its dependencies. Java runtime is, similarly to the .NET, based on a virtual stack machine (JVM). This implementation of physical machine is crunching linear list of instructions called bytecode. As you may know, the .java file written by the programmer is usually compiled using the javac to the .class. This file represents a class and provides all information necessary for JVM to run it. However – single class is not what the programmer wants, it’s the program running. For such thing there is a concept of a container – a structure filled with .class files packed and compressed – with resulting extension of .jar.

Who on the Earth has a favorite archiving tool?! Just use 7zip and go outside for a walk.

Another name for .jar filetype is .zip – a plain old friend of everyone. For the modifications, you are free to use your favorite archiving tools such as 7zip of WinRAR.

Daddy, can I play?

Our further step would be to extract the charles.jar and examine its hierarchical structure. Basic knowledge of java and developers‘ website gives us a clue to the folder we need – /charles/com/xk72/charles/. For now, that folder contains just a bunch of .class files – we need a tool to read and modify these.

As always there are countless ways how to carry out that:

  • We can directly read and modify .class files. That is the most hardcore way of doing this. My favorites: jbe, reJava
  • At first, we could use deobfuscator – I forgot to mention the .class files are usually obfuscated and almost unreadable. Useful stuff: java-deobfuscator, Retroindy
  • We could try to decompile .class back to .java, gain knowledge and apply it using previous tools. Decompilers of choice are these: CFR, java decompiler

Yeah! You guessed it – we are not going to use any of these. I’ll show you the right combination for a classy cracker.

But now it’s time to decompile .jar file using CFR or similar tool with a recent java support.

Hint to keep sanity – Windows PowerShell has built-in commands completion.

Now the folder charles_decompiled should contain the tree of .java files representing the original library. Each of those files should be in plain text and should make some sense – at least in theory.

Finally! Now we’re about to focus on the licensing. For such a well-structured project it’s unnecessary to stay with a dumb text editor – you can use java IDE such as Eclipse, create a new project and import a whole folder with source files. Comfortable even while hacking – this approach allows us to use advanced refactoring, navigation and search capabilities of IDE.

After a while of digging in the /charles/com/xk72/charles/ folder, I found holy grail – a file responsible for a key management, registration and SN checking. As I promised, today we’ll avoid backdoor exploitation approach, instead of it let’s patch the file.

The direct content of the charles.jar in archiving program.

Due to applied obfuscation, its name is twisted – The class inside is a singleton – it obviously provides support for checking the key stored in the local registry, some functions serves for generating of statuses for different license types, etc. The constructors call underlying functions to check key provided as an argument.

public static String PcqR() {
        final gIbD qNfW = gIbD.QNfW;
        switch (jrCQ.xUFT[qNfW.obIG.ordinal()]) {
            case 1: { return qNfW.GyLP; }
            case 2: { return qNfW.GyLP + " - Site License"; }
            case 3: { return qNfW.GyLP + " - Multi-Site License"; }
            default: { return qNfW.GyLP; }

First of two functions returning the current licensee. Unshortened.

If you were savvy enough during the code traversal, you should have a decent outline of the code by now. For example, there is a SplashWindow class in the gui subfolder responsible for splash screen rendering. The code includes branching which depends on the current license type determined – loaded from the gIdb singleton.

To gain more insight we could have run charles in the following manner: java -Xdebug -Xrunjdwp: transport= "dt_socket, server=y, suspend=n, address=5005" -jar charles

Now you should be able to attach IDE debugger. Voila! This method enables us to debug even without the source code.

Switch back to the – two methods PcqR and LCuJ return the owner of the license. We would like to change them appropriately to return our crafted string. Furthemore there is this.PcqR – local boolean variable preset to false meaning the license status (licensed/unlicensed). We need to set it to true at all costs.

You may have noticed that the code is so-called exception driven – thus the flow of the program is determined by the exceptions. For example, in the constructors, these exceptions let know the rest of application for invalid key check. We have to silence these too.

Now open the bytecode editor and do these changes.

But, mum? Isn’t there a better way?

Of course, there is – you can change hexacode directly… Nope, just kidding.


Let’s change our decompiled to the required shape – change contents of both functions to return some sane email value, change the constructors in order to initialize this.PcqR to true and comment out all the LicenseExceptions thrown.

Here comes the god mode. If you are willing to pay some attention to imports in the beginning of the file, you should be able to recompile this .java file back to .class.

This neat command allows us to get the modified .java file and compile it in the context of the .jar file. It means the compiler can perform optimization, types checking and more fun stuff. The resulting .class file will lie next to the .class one.


In order to force the compiler to give away and crunch my crappy code, I used two different decompilers. Then I compared outputs and found the suitable way – just a slight change was necessary.

To recompile the project just use the command above. But beware of compilation errors – you may need to change the code, imports or remove new java 8 features. The javac program comes bundled in the JDK, but if you get so far, you should’ve already installed it, right?

Now grab the charles.jar file, open it in the archiver and replace the original gIdb.class with our enhanced version. Then move the result to the Charles folder and try to run.

Unfortunately, this cool splash screen now lasts for just a second. 😀

By so far, this has been the most complicated dissection.

Great you!

And as always, revert the program to its original state, go to the developers‘ website and buy it. It’s really worth it.

Tools used today:

  • Exeinfo PE – universal binary detector (free)
  • reJava – java bytecode editor and analysis tool (free)
  • Retroindy – java bytecode deobfuscator (free)
  • java decompiler – powerful java decompiler and transpiler (free)
  • javac – the original java compiler (free)
  • 7zip – opensource archiving and packing tool (free)

Vložit komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *