sw-cache-forge: Polymorphic Payload Evolution on Top of GAP
sw-cache-forge is a small standalone tool that rewrites the cached JavaScript of a Chromium service worker. It has zero dependency on GAP and works on any SW cache entry you can write to, but itβs the missing second half of the GAP chain.
Persistence, then evolution
GAP gives you persistence: a service worker that keeps executing even after its extension folder is deleted. The catch is that the payload you injected at install time is frozen. sw-cache-forge lets you change that payload later, directly on disk, by rewriting the cache - swap the C2, add modules, pivot from a collector to an RCE agent - without redeploying and without dropping a new malicious artifact.
1
2
3
4
5
GAP (persistence) sw-cache-forge (evolution)
ββββββββββββββββββββ ββββββββββββββββββββββββββ
secure prefs + SW DB rewrite _0 stream1 + CRC32
β β
ββββββΊ persistent SW βββββββββββ β new payload, recompiled by V8
The kill-chain
- Install a minimal extension with GAP (or anchor an existing one) β persistent SW.
- Evolve later, from a foothold: locate the SWβs
_0cache entry and patch it. - V8 sees the stale
source_hash, drops the code cache, and recompiles your new source. No re-signing, no new file.
Why itβs that easy
A SW script is a SimpleCache _0 entry:
1
header | key | stream1 (JS) | EOF1 | stream0 (headers) | ...
sw-cache-forge rewrites only stream1 and recomputes the EOF1 CRC32. Two Chromium details do the rest: content_length is recomputed from the actual stream size (thereβs no stored size to mismatch), and the V8 code cache self-invalidates on a source_hash mismatch.
1
2
3
4
5
6
7
8
# find where your payload ends up
python3 sw_cache_forge.py dump <hash>_0 --find "AGENTID"
# append a payload (the reliable pattern β idempotent)
python3 sw_cache_forge.py patch <hash>_0 --append-file agent.js --output <hash>_0.patched
# confirm CRCs + marker
python3 sw_cache_forge.py verify <hash>_0.patched --contains "AGENTID"
Demo
You can also use this tool to inject unexpected code into legitimate browser extension.
One pitfall: the source must be complete, valid JS. Append a self-contained agent to the end; a fragment cut mid-bundle wonβt compile and the worker shows up empty.
- Tool: Fir3n0x/sw-cache-forge
- Persistence primitive: Fir3n0x/GAP
For authorized security testing and research only.
