Brian Cassriel Brian Cassriel
6 min read
Agentic JS Deobfuscator

This project was built for the final project of my Digital Forensics course.

It spanned many of my interests and skills all at once, which was exciting. It combines my interest in security with my proficiency in JavaScript and curiosity about use cases for LLMs. This tech stack intersection places the project very nicely within my comfort zone while allowing me to play with new technologies (mainly LLM APIs to create an agent, but also recent web development tools like Astro) to learn how they work and discover their uses and shortcomings.

The result is a tool that I find genuinely useful for deobfuscating JavaScript files to reverse them into a state that closely resembles the original source. The tool is served as a webpage as a way to make the tool more easily accessible while learning more about web development.

Why Build This?

Occasionally, developers in the Minecraft Bedrock addons community like to obfuscate their code to prevent theft. I find obfuscation to be nothing more than a neusance in this context. Developers should turn to proper licensing so that they can pursue legal repercussions if they discover others using their intellectual property.

Whether code should be obfuscated can be compared directly with whether the project is open source or not. Usually, the two come hand-in-hand.

In the real world, closed source project are closed for a reason. Often, they contain business or trade secrets that give the intellectual property owners an edge in the market. Other times, they must be closed source because they implement security features that should not be easily readable to the public.

In the Minecraft Bedrock addons community, neither reason to make a project closed source are valid for independent creators.

  1. There is no market for addons outside of the Minecraft Marketplace. Studios creating for the Marketplace rightly keep their projects closed source (and their code obfuscated) to maintain their competitive edge and prevent redistribution. Creators outside of the marketplace are forced to distribute their addons for free. Redistribution also cannot be prevented outside of the marketplace.
  2. Addons are opt-in for players unless forced on a server. On a server, it makes sense to hide the source from the public to prevent exploits. On a local world, the player should retain complete control over any functionality they opt to add.

In both instances (Marketplace addons and server code), there is some kind of securty control other than obfuscation that protects the intellectual property of the owner. The obfuscation is not strictly necessary. Obfuscation only slows down someone who wants to read your source code. It does not prevent them from reading it entirely.

Obfuscation ≠ Security.

I open source all of my addon projects because I would much rather build collaboratively and allow others to learn from my projects. The quality of the project is enough to keep its compeititve edge.

Discovering the OpenAI APIs

Orignally, I wanted the LLM to do the entire JavaScript deobfuscation process. This idea stemmed from times that I’ve asked ChatGPT to deobfuscate entire JavaScript files. It historically did a reasonably good job, but didn’t generally produce a complete version of the source code in one go. Additionally, there was no way for the user to verify that the generated source code was functionally the same as the original.

The grand idea was that this would be the “deobfuscator to end all deobfuscators” in the sense that it could handle any obfuscation techniques, including novel ones. However, the LLM wouldn’t quite behave how I wanted it to. Once the agentic workflow was implemented, the LLM would consistently change entire functions at a time, blantantly modifying their functionality despite strict directions not to do so.

After much fidding, I decided that the LLM could not be trusted to maintain the original source code’s behavior and turned to more conventional techniques for functionality-preserving deobfuscation (parsing the code using context-free grammar and manipulating the resulting code tree). The agent was still kept in the final tool with only two simple abilities: naming variables, and removing dead code. The naming variables ability in particular is a nice addition and sets this tool apart from others like it.

I’m still convinced that it is technically possible for the LLM to do the entire deobfusctation process, but it requires more time and expertise than I currently have.

Future Plans

One thing that was clear throughout the development process was that the LLM clearly understood the obfuscated code much better than a human did at first glance. There must be a way to leverage this ability to produce better results. For example, I would like to try making the agent write tests for the obfuscated code, then give it more agency and see if it can produce source code with the same behavior as the orignal.

In the same vein but much more simply, I would like to add an LLM-generated summary of the code for once the deobfuscation is complete. This would help users understand the code they have deobfuscated at a glance. This is particularly useful when users don’t know whether the behavior they are looking for is defined in the file they are analyzing.

The context window of the LLM is currently an unsolved issue. Large files will throw an error when the “Rename Variables” button is pushed. This can simply be fixed using a context window that moves down the file as renaming occurs.

Takeaways

I learned quite a bit while creating this project. Not only did I ingest and work with the OpenAI API, but I also built a website from scratch by myself for the first time. I especially enjoyed working on the front end, creating a pretty and functional interface for users to interact with.