I'm Building a Browser for Reverse Engineers
Mon Oct 06 2025 authored by veritas
Preamble
In the expanding world of AI my heart still lies in AST transforms, browser fingerprinting, and anti-bot circumvention. In fact, that's the majority of this blog's content. But my workflow always felt... primitive. I was still manually sifting through page scripts, pasting suspicious snippets into an editor, and writing bespoke deobfuscators by hand. Tools like Webcrack and deobfuscate.io help, but the end-to-end loop still felt slow and manual. I wanted to build a tool that would be my web reverse-engineering Swiss Army knife
If you're just curious about what it looks like and don't care about how it works then here's a quick showcase:
Your browser does not support the video tag.
Humble Beginnings
My first idea was simple: make a browser extension. For an MVP I wanted to hook an arbitrary function like Array.prototype.push as early as possible and log every call to it.
Hooking functions in JavaScript
In JavaScript, it's trivial to hook into and override existing functions because you can reassign references at runtime. A common pattern is to stash the original function, replace it with a wrapper that does whatever instrumentation you want, and then call the original so the page keeps behaving normally:
const _origPush = Array . prototype . push ; Array . prototype . push = function ( ... args ) { console . log ( 'Array.push called on' , this , 'with' , args ) ; return _origPush . apply ( this , args ) ; } ;
Here's what that looks like in Chrome's devtools:
Hooking Array.prototype.push inside the Chrome Devtools
This technique should make it pretty straightforward to build a Chrome extension that hooks arbitrary global functions on page load and surfaces calls in a small UI.
Content Scripts
Chrome's content scripts are files that run in the context of web pages, which we can use to install our hooks early.
The idea is simple, we create a content script that runs at document_start that injects a tiny bit of code that replaces Array.prototype.push with a wrapper that logs and then calls the original.
{ "name" : "My extension" , "content_scripts" : [ { "run_at" : "document_start" , "matches" : [ "" ] , "js" : [ "content-script.js" ] } ] }
const _origPush = Array . prototype . push ; Array . prototype . push = function ( ... args ) { console . log ( 'Array.push called on' , this , 'with' , args ) ; return _origPush . apply ( this , args ) ; } ;
Running this on a page that clearly used Array.push gave me... absolutely nothing. At first, I thought it had to be an execution order issue. Maybe my hook was loading too late? But after another read through the docs, I found this painfully obvious note staring me right in the face:
“Content scripts live in an isolated world, allowing a content script to make changes to its JavaScript environment without conflicting with the page or other extensions’ content scripts.”
In hindsight, of course that makes sense. Still, it sucked. I wasn’t ready to give up yet, though. I had a potentially clever workaround: injecting a