This will be the first of a small series of posts on reverse engineering software and hardware.

I recently bought a thing on Gumroad. I quickly realized that said thing was uploaded as 391 items, and unless I did something, I’d be forced to hit Download and then Save on each and every one of them individually.

Firefox developer console showing 391 child items under "product files".

All projects start with a problem that you need to solve, and I really don’t want to hit Download and Save for four hours straight.

First approach

The first approach is always the simplest. Hit F12 to open the developer tools in your browser, open the Network tab and refresh the page. See if there’s any request you could use - these days there’s usually a bunch of JavaScript in the frontend that hits an API. An API is always the first stop - it’s designed for computers to make sense of, and it’s designed to not require human intervention to use.

The product page didn’t have an API, and the purchases page had an API that’s not usable for what I want - namely to get a list of links to be able to download quickly.

Second approach

The second approach is looking at native clients, which is pretty much guaranteed to be using an API. I downloaded their Android app from APKPure, and tossed it into jadx.

In general, if I need to reverse engineer a client, I go for the simplest option - start with apps in interpreted or JIT languages (Android uses Java, some Windows apps uses C#), and only move to apps in native languages (like on iOS) if you must. With Java and C# you can get readable code out of the box, while native languages require you to know some amount of assembly.

In jadx, I can see that the Android app uses a mobile API with standard REST semantics, and authentication is done through an OAuth 2.0 username/password flow. This is great - it’s easy to implement yourself. All you need to do is grab the tokens from the app.


Reverse Engineering rarely come without some engineering in the end to actually put what you’ve figured out to use. In this case, because it’s largely standards based, I can just use RestSharp to throw together something quickly in .NET 5, with great results.

Terminal showing all 391 files being downloaded through aria2c

I’ll publish the code once I finish up the auth flow and make it usable without manually looking at API requests.