This is the fourth post on one question: where do residential proxy exits actually come from?
The SYN fingerprints said the pool isn’t the crowd of real devices it’s sold as, and left off at “whichever networks the recruitment malware found most fertile.” The cracked driving game was the first attempt at naming that recruitment, and ended with an encrypted payload I couldn’t open. MediaGet was the second, and that one closed: a torrent client handing every geo it answers a proxy bundle, disclosed in the west and unlabelled everywhere else. At the end of it I wrote that the cracked game’s payload was “still sitting on the bench, still silent, still unproven,” and that the hidden channel was the one I still owed an answer on.
This is the third attempt, and the answer is no.
Not for the same sample — that one is still on the bench. But for a payload of exactly the same shape, injected by the same kind of operator into the kind of APK that fills these pools: a hidden, obfuscated, dynamically-loaded blob that looks like proxyware until you read it. It’s a cheat framework with Chinese analytics bolted on. There is no proxy relay in it, and no command-and-control server of its own, which I did not expect.
The negative result is the least interesting thing here. The statistical half of the investigation took two days and two corrections and still ended in a number I can’t interpret. Everything that survived came from an emulator and a ZIP listing.
Where it started
Same place as always. A purchased residential proxy, run through public BitTorrent attribution, and a download history that was wall-to-wall Android mod APKs. I have written before
about why that’s a map rather than a confession, and I stand by that. But this time I had a specific sample in hand, pulled off a crawler: a 933 MB Minecraft build called com-mod-minecraft-mod-apk-menu-god-modeunlocked-1-26-10-26_972601026.apk.
The first sample was clean, and that’s a real result
Repacked Minecraft Bedrock 1.26.10.26, resigned with a throwaway key:
Issuer/Subject: L=indna, C=9821
Not Before: 2024-12-06 Not After: 2049-11-30
C=9821 is not a country code. This is a keytool run by somebody who mashed the keyboard through the prompts.
The injection was three files and one hook. Two Java classes, one native library, and a single call site:
// MainActivity.java:1469
Menu.Start(this);
com.an1menu.Menu draws a floating overlay; libNotlib.so reads /proc/self/maps, finds libminecraftpe.so, calls mprotect and patches bytes. A game trainer, textbook. The toggle list comes from assets/not.json, and there is exactly one entry:
{"patch1": {"en": "Immortality", "ru": "Бессмертие"}}
libNotlib.so imports no network symbols: no socket, no connect, no getaddrinfo. It has no way to reach the network. Every manifest component — 11 activities, 6 services, 5 receivers, 3 providers — is stock Mojang, Firebase, GMS, Braze, Xbox or androidx. Nothing added.
Piracy plus a cheat, no malware. The rest of this post is about a build of the same title and same versionCode that is not clean, and the difference between them is the whole method.
The swarm was 100% one client
While the APK was decompiling I looked at who was seeding it, and the peer list was strange in a way I’d never seen: every single peer reported the same client.
37.8.138.123 -HT3334-
37.66.21.23 HyperTorrent 3.4.0
37.130.17.21 HyperTorrent 3.3.1
38.25.51.6 -HT3400-
...
60 connected, not one qBittorrent, uTorrent, Transmission or libtorrent
The -HT####- entries aren’t a different client — that’s the raw peer_id where the inspector’s lookup table didn’t have a friendly name. HT + 3400 is 3.4.0.0.
Real swarms are never homogeneous. This one was, at 100%, across four version numbers.
I initially chased “HyperTorrent” as a product, found an Android torrent client by that name on the usual download-mirror sites, and spent an hour on the wrong thing. The version numbers were what gave it away. The peers reported 3.2.6, 3.3.1, 3.3.3 and 3.4.0 — and HappyMod’s current version is 3.4.0. The older ones line up too.
HappyMod ships a BitTorrent engine:
lib/arm64-v8a/libjlibtorrent-1.2.15.2.so 7.3 MB
btdownload.services.EngineService
btdownload.services.EngineBroadcastReceiver + RECEIVE_BOOT_COMPLETED
btdownload.services.statistics.WorkService
And hyper-torrent.com turns out to be their own tracker domain, which I only found later, inside their torrent files:
http://tracker.hyper-torrent.com:8001/announce
udp://tra-pk-khi.hyper-torrent.com:8011/announce Karachi
http://tra-ph-mnl.hyper-torrent.com:8007/announce Manila
http://tra-th-bkk.hyper-torrent.com:8019/announce Bangkok
udp://tra-sa-jnb.best61.com:8002/announce Johannesburg
http://tra-ved-br.best82.com:8000/announce Brazil
http://tra-ac-ae.apktorrents.com:8001/announce UAE
Four domains, geo-coded subdomains, a distributed tracker fleet — that’s infrastructure somebody maintains.
So the “third-party torrent client” I’d been chasing was the mod store itself. There is no separate client in this story.
What HappyMod actually does to you
I put it on a rooted emulator and pulled three things from its catalogue to have samples to work on. Ninety minutes later, du -sh on its data directory:
3.7 GB.
Three downloads, and 3.7 GB of disk. The libtorrent session explains the gap:
Poppy Playtime downloaded 667,796,385 uploaded 161,288 1252/1252 pieces
Minecraft downloaded 968,965,900 uploaded 33,100,881 894/894
Car Parking downloaded 1,840,293,968 uploaded 8,565,219 871/871
───────────── ──────────
3.48 GB down 41.8 MB already served
paused: 0 auto_managed: 1
I asked for those three files. What I did not ask for is everything after completed_time: paused: 0, auto_managed: 1, and 41.8 MB already pushed back out to strangers. There is no seeding ratio, no stop-when-done, and no prompt. And btdownload.services.EngineBroadcastReceiver is registered for RECEIVE_BOOT_COMPLETED, so a reboot brings the engine back up and the seeding resumes.
Worth being exact about this, because I got it wrong on the first pass and the timestamps caught me. Two of the three were added 41 seconds apart, the third an hour later — that’s a person tapping things, not an app helping itself. HappyMod does not download what you didn’t ask for. It just never stops serving what you did.
That is still the flywheel, and it is enough of one. Every download becomes an indefinite upload, which is why the front-page items carry thousand-peer swarms, why my crawler kept hitting the same handful of APKs, and why a rented residential IP shows a torrent history full of mod APKs. The donor device has HappyMod on it, and somebody there once tapped download.
A few other things fell out of the same box:
<network-security-config>
<base-config cleartextTrafficPermitted="true"/>
</network-security-config>
Global cleartext, in an app that holds REQUEST_INSTALL_PACKAGES. Their config confirms it’s used — d_no_cdn_ip is a hardcoded http://195.154.26.56:82 fallback on Scaleway for when the CDN is unreachable.
And /sdcard/Download/HappyMod/device_id.png, 36 bytes, not a PNG:
23cfea93-3e70-4fe5-b56e-898869f5f525
A persistent identifier in public storage, disguised by extension, surviving uninstall and readable by any app with storage access.
The APK itself is packed with 360 Jiagu (com.stub.StubApp plus four libjiagu*.so in assets), which is why VirusTotal shows 1/68 with ESET calling it Android/Packed.Jiagu.D Potentially Unsafe. That’s a packer detection, not a malware detection — and on a packed sample, 1/68 exonerates nothing, because the static engines can’t see inside either.
The number that wouldn’t die
This is the part that cost me two days.
I pulled the swarm peers and ran them through IP-reputation data. The first sample: 49% flagged as residential proxy exits. Second swarm: 63%. Then I pulled 499 unique peers straight out of the emulator’s own libtorrent session — peers HappyMod itself was talking to — and got 72.8%, with a median percent_days_seen of 70% and 134 nodes sitting at 100%.
My working assumption was that a normal swarm sits in the low single digits. I never measured that, which in hindsight is the same gap as the missing control arm. I read it as the finding, and wrote it up as the finding twice.
It wasn’t, and finding out why took two corrections — the second of which I didn’t find myself.
The control I built backwards
Before writing any of it up I built what I thought was a proper control. For a sample of proxy-flagged peers I picked a random other address in the same /24 — an address I had never observed in any swarm — and looked it up.
Peers: 72.8% proxy
Random neighbours: 73.3% proxy
Identical. I concluded the flag was a property of the address range rather than the host, declared the line dead, and said so in strong terms.
That control was broken. Look at what it samples:
prox = [x for x in peers if x.proxy] # ← only already-flagged peers
sample = random.sample(prox, 60)
neighbours = [random_neighbour(ip) for ip in sample]
I drew neighbours only from /24s that were already known to contain a proxy. That conditions the control on the outcome, and of course it comes back near the peer rate. I killed a live hypothesis with a test that could not have found anything.
The correct control takes a neighbour for every peer, regardless of that peer’s own status. Pooled across six such experiments:
minecraft 893MB 33/42 = 79% 29/42 = 69% +10
gta sa up-mod 33/45 = 73% 27/45 = 60% +13
minecraft 937.5MB 24/45 = 53% 20/45 = 44% +9
minecraft 932.6MB 34/45 = 76% 26/45 = 58% +18
truckers 613MB 35/41 = 85% 28/41 = 68% +17
toca boca 868MB 14/19 = 74% 11/19 = 58% +16
────────────────────────────────────────────────────
pooled 173/237 = 73% 141/237 = 59% +14
z = 3.11 p = 0.0019 95% CI: +5.0 .. +22.0 pp
Six swarms, all six in the same direction. Peers really are more likely to be flagged than random hosts in their own neighbourhoods.
And even that measures the wrong thing
I was ready to publish that number. Then the obvious objection landed, and it wasn’t mine.
To appear in my sample at all, a peer has to be powered on, connected, and running a background service right now. Residential proxy networks recruit and use exits by exactly that criterion — they want always-on devices with stable connections. Both populations are filtered by the same hidden variable.
And what did I compare them against? A random address in the same /24, which might be a switched-off laptop or an unassigned DHCP lease. I put “definitely online” next to “maybe anything.” A +14 point excess is entirely consistent with that, with no proxyware anywhere in the picture.
So p = 0.0019 is real, and it isn’t measuring what I wanted it to.
The test that would separate them needs both arms to be live torrent peers — take a swarm from an ordinary torrent, run the same matched control, and compare the two excesses. If a Linux ISO swarm also runs +14 over its neighbours, the effect is “device is switched on” and nothing more. That arm is still missing.
Where that leaves the number, stated as plainly as I can: the correlation is real and I measured it carefully. The causality is not there, and I don’t know which way it will go when someone runs the control I’m missing. I’ve been wrong about this specific number twice already, in both directions, which is a decent argument for not making a third prediction.
Meanwhile, the boring method
While the statistics were eating two days, I noticed something in the attribution data that cost nothing:
com-mod-minecraft-mod-apk-menu-god-modeunlocked-1-26-10-26_972601026.apk 889.40 MiB
com-mod-minecraft-mod-apk-menu-god-modeunlocked1-26-10-26-972601026.apk 893.48 MiB
com-mod-minecraft-mod-apk-menu-god-modeunlocked-1-26-10-26-972601026.apk 894.09 MiB
Same title, same versionCode 972601026, three different sizes, and the names differ only in punctuation.
I had the first one. I pulled the second, and the ZIP listing diff was five lines:
+ assets/dd.json
+ assets/hs
+ assets/pg
+ assets/info
+ classes6.dex
Nothing removed. And the existing code was modified too — classes.dex grew by 14,540 bytes, AndroidManifest.xml by 512.
What’s in it
assets/dd.json is 91 bytes and explains the whole design:
{"dd": [{"host": "hs"}, {"plugin": "pg"}]}
hs and pg are complete APKs, stored as plain files under names with no extension. assets/info is a 24-character token.
The loader is in the patched classes.dex, in a package called com.dd_load, and it is not obfuscated at all:
// com.dd_load, jadx output, trimmed
InputStream is = context.getAssets().open(pluginName);
// 2. extract the matching native libs
String arch = is64Bit() ? "lib/arm64-v8a/" : "lib/armeabi-v7a/";
// 3. load it as a separate APK
new DexClassLoader(file.getAbsolutePath(), dexDir, libDir, getClass().getClassLoader());
// 4. hand over control
loadClass("com.ddmx.staticcheathost.CheatManager")
.getMethod("getInstance").invoke(null)
.init(hostContext); // at startup
.onResume(activity, "appName"); // on every resume
is64Bit() goes through reflection on dalvik.system.VMRuntime. Everything else is a stock plugin-loading framework.
hs — com.ddmx.staticcheathost, 3.58 MB:
lib/arm64-v8a/libumeng-spy.so 463 KB
lib/arm64-v8a/libcrashlytics-main.so 3.2 MB
permissions: INTERNET, CHANGE_NETWORK_STATE, storage, AD_ID
package names: oOOo00oO, IIllIIll, lIllIlIllIlIllI, _0x_a1, ﺎﻠﺎﻠﺎﻠﺎﻠ, لاإلاإلا
One of those library names is a lie. libcrashlytics-main.so is not Crashlytics — Firebase’s NDK libraries are 200–500 KB and named differently, and this one exports:
Java_android_app_settings_ActivitySettings_GL_Generate
Java_android_app_settings_ActivitySettings_GL_OnSingleTapConfirmed
Java_android_app_settings_ActivitySettings_SDK_Init / OnPause / OnResume / OnTouchEvent
Java_android_app_settings_ActivitySettings_encode / decode / sendEvent
An OpenGL overlay renderer with Crypto++ linked in, in a class tree named to look like Android system settings.
libumeng-spy.so I initially read as bespoke spyware because of the file name. It isn’t — it exports Java_com_umeng_umzid_Spy_*, and com.umeng.umzid.Spy is a real class in Alibaba’s Umeng SDK. That one’s genuine, which doesn’t make it good: Umeng is Chinese analytics that collects OAID and attempts IMEI.
pg — com.hydrozoa.emp, 761 KB, libdobby.so plus libAK.so, libAKCompat.so, libmod.so. Dobby is a well-known inline hooking framework. This is the actual cheat.
Decrypting the strings
hs has its strings encrypted, which is where I expected to hit the same wall as last time. It took one grep:
$ grep -rhoE '[A-Za-z_$][A-Za-z0-9_$]*\.[A-Za-z_$][A-Za-z0-9_$]*\("' sources/ | sort | uniq -c | sort -rn
10742 lIllIIlI.lIllIIlI("
6 sb.append("
Ten thousand calls to one two-argument method. the method is built to break decompilers — it contains byteArray[-1], a loop with length3 = "".length() + 1, and a Math.random() in the key derivation, all of which are anti-decompilation traps rather than real code. But the call sites give it away:
lIllIIlI.lIllIIlI("jJVp1pyhjmnY2H7AyO+VasA=\n", "rPgcpeiB4AY=\n")
Two base64 blobs. Decode both, XOR the first against the second repeating. That call site comes out as the string below, which is what told me the routine was right:
ct = base64.b64decode(a)
key = base64.b64decode(b)
out = bytes(ct[i] ^ key[i % len(key)] for i in range(len(ct)))
5,156 unique strings came out. Every URL among them:
ulogs.umeng.com cnlogs.umeng.com/ext_event ucc.umeng.com/v2/inn/fetch
utoken.umeng.com aspect-upush.umeng.com resolve.umeng.com
pslog.umeng.com alogus.umeng.com ulogs.umengcloud.com
Filter out Umeng, Google, Android and standard schema URLs and nothing remains. Not one third-party domain in the entire payload.
The “sensitive” keyword hits are okhttp’s own library strings — Proxy-Authorization, HTTP_PROXY_AUTH (407), exhausted proxy configurations. Stock HTTP client code, not a relay. There is no DexClassLoader inside hs, no reference to dd.json, hs or pg; the loader lives entirely in the host APK. HiddenApiBypass is present, which is a real open-source library for reaching restricted Android APIs.
So: a cheat framework with covert Chinese telemetry, camouflaged library names, five thousand encrypted strings, and no C2 of its own.
That is the answer to the question I’ve been carrying since May. For this sample, the hidden payload is ad-and-analytics-monetised cheat middleware, built to resist the kind of analysis I was doing. It is not proxyware.
The structural risk doesn’t go away, though. the delivery mechanism is a dynamic loader reading unencrypted APKs out of assets/. The same loader in tomorrow’s build will pick up whatever hs is placed next to it, the outer APK will look identical, and no app update is needed. What sits in that slot today is analytics, and I have no way to know what sits there next month.
Doing it again on purpose
If the pair-diff worked once by luck, it should work again on demand. I pulled every same-title-different-size pair I could find. Seven APKs, one script — note that it only looks for Kit A’s asset names, so a hit here means this exact kit, not “injected”:
unzip -l "$f" | grep -cE 'assets/(dd\.json|hs|pg|info)$'
One hit:
up-mod-minecraft-dream-it-build-it-...-972600201-972600201.apk 888.44 MiB ★
up-mod-minecraft-dream-it-build-it-...-972600201_972600201.apk 884.36 MiB clean
Different title. Same injection. And the payload is byte-identical:
dd.json 4fc633e9b0dfb2e5 91 B identical
hs 5c35a8b698b51a42 3,580,915 B identical
pg 18bfbf572832f35a 761,504 B identical
info d1bb18c5… vs 13600a47… different
Only info changes:
iEzQlKvNdFjOzHnUqUvMyAyS (god mode build)
gFfIfVmBhLwDuNqXpBoLnImO (dream it build it)
Twenty-four characters, alternating case. That’s a per-build identifier — the thing CheatManager reports to say which repack it’s running in. So it’s a pipeline: one fixed kit stamped onto title after title, with a fresh key each time.
Note also that classes6.dex was not present in the second one — that was multidex numbering in the first sample, not a marker. The reliable signature is the four asset files.
Two for two on the pair method, in about twenty minutes of work.
A taxonomy fell out
Eleven APKs in, the operators separate, and the signing key name is the pivot:
Kit A — ddmx (key JTWJEST, L=indna, C=9821, Dec 2024)
assets/dd.json + hs + pg + info, payload byte-identical across titles
base mod: com.an1menu.Menu + libNotlib.so
seen in: Minecraft god mode (893.5 MiB), Minecraft Dream it Build it (888.4 MiB)
Kit B — speedremoveads / magicmodapk (keys SIGNOVER, SIGN10_K)
*.speedremoveads.RMApplication + embedded Flutter UI + com.joke.speedmenu
assets/htm.txt (plaintext JSON) + assets/acf (encrypted, 22 KB)
POST -> mmk.magicmodapk.com/api/mmu.php
seen in: GTA SA x2, Truckers of Europe 3
Kit B’s config is not even hidden:
{"source":"magic","toast":0,"update_dialog":1,"openscreen":0,
"menu_speed":0,"menu":1,"adremove":1,"unlimited_resources":0}
Its strings use the same two-argument XOR scheme, and decrypting them gives a promo widget: it POSTs packageName, versionName, versionCode and a dialog version, receives three promo slots with URLs, icon and colours, and renders them in a floating menu with VISIT US and Join Telegram buttons. No device identifiers.
The interesting bit is that speedremoveads shows up under two different signing keys, so it’s a service that multiple repackers use rather than one crew. So the signing key tells you who did the repack, which is a separate question from which toolkit they used.
The truckers pair shows it directly: two builds of the same version, 30 KB apart, one signed JTWJEST and clean, one signed SIGNOVER carrying Kit B.
The seeders are not part of the crowd
One thing the IP data did produce cleanly. Every torrent I pulled off the device was created by the same client build:
CREATED BY: Transmission/3.00 (bb6b5a062e)
92.204.40.68 velia.net DE-VELIANET1 proxy=false, 0 networks
92.204.53.212 velia.net proxy=false
92.204.54.21 velia.net proxy=false
92.204.53.56 velia.net proxy=false
148.72.144.76 velia.net VIG-97 proxy=false
148.72.158.43 velia.net VIG-97 proxy=false
51.15.23.143 Online.net / Scaleway NL proxy=false
Dedicated servers at one German host plus one box at Scaleway, the same machines appearing across Minecraft, GTA and Car Parking swarms, none of them in any proxy network. That’s the seeding fleet, separate from the residential noise around it. It also works as a negative control for the reputation data, which declines to flag any of them.
What my own SYN data already said
In March I fingerprinted 319,706 residential proxy exits by their TCP handshakes. 98% Linux, and — the figure that matters here — two near-identical stock kernel defaults covering more than 70% of the pool between them, MSS 1460, window scale 12 or 6.
That is not the shape a population of recruited Android phones makes. Phones run Linux kernels too, so they land inside that 98%, but they do not handshake in lockstep: different vendors, different kernel versions, different carrier MTUs, a mess of window scales. Half a pool sharing one fingerprint on plain Ethernet is a pool of boxes. And the 6.9% sitting at MSS 1412 is tunnel overhead — wholesale gateways re-exporting somebody else’s traffic, which is a different kind of not-a-phone.
I read that post at the time as being about the pool being fake. Re-reading it against this one, it was also telling me where not to look. If mod-APK recruitment were filling these pools at any scale, the SYN distribution would have to carry a much larger and much messier Android signature than it does.
Which makes this week’s null less surprising than it felt at the time. My own composition data had already relegated the Android channel to a minority tributary in March, and I still spent two days measuring a fourteen-point correlation inside it.
The honest ledger
Proven, from direct evidence on the device:
HappyMod seeds everything it downloads, indefinitely and without asking — three requested files, 41.8 MB served back out to strangers, paused: 0 after completion and a boot receiver so it resumes after restart. It runs a global tracker fleet under four domains. It writes a persistent identifier to public storage disguised as a PNG. It permits global cleartext HTTP while holding REQUEST_INSTALL_PACKAGES, with a hardcoded plaintext fallback IP.
Not proven, and I claimed it before checking: that it downloads anything you didn’t request. The resume timestamps say otherwise and I have corrected the section above.
Proven, from the samples:
At least two builds carry a hidden dynamic loader whose payload is byte-identical between titles and keyed per build. The payload is a cheat framework with Umeng telemetry and camouflaged component names, and it has no command-and-control infrastructure of its own. Two separate repacking kits are in circulation, distinguishable by signing key and manifest entry point.
Not proven:
That any of this recruits proxy exits. The +14 point excess is a measurement without a causal arm behind it, and the arm it needs is listed under “Still open”. Nor does a clean sample today constrain tomorrow’s assets/hs.
Where the statistics went wrong
Build the control before the hypothesis gets interesting. It costs three minutes. I ran mine on day two, after I’d already invested in the answer, and then built it in the shape that confirmed what I expected.
A negative control is not the same as a matched control. Sampling neighbours of already-flagged hosts conditions on the outcome, and I did it anyway.
File names are not identity. Name, version and versionCode are all attacker-controlled and were all identical across the three builds. Size and hash were the only fields that told them apart.
And the cheap methods won. Every hour spent on IP statistics produced either nothing or a retraction. Everything that survived came from putting the app on an emulator and looking at the disk, or from unzip -l on two files whose names differ by a hyphen.
Indicators
Kit A (ddmx) — the four asset files are the signature; classes6.dex is not:
assets/dd.json 91 B {"dd":[{"host":"hs"},{"plugin":"pg"}]}
assets/hs 3,580,915 B sha256 5c35a8b6… com.ddmx.staticcheathost
assets/pg 761,504 B sha256 18bfbf57… com.hydrozoa.emp
assets/info 24 B per-build id, alternating case
Inside hs:
lib/*/libumeng-spy.so genuine Umeng UMZID
lib/*/libcrashlytics-main.so NOT Crashlytics — GL overlay + Crypto++
class tree android.app.settings.ActivitySettings
loader com.dd_load, com.ddmx.staticcheathost.CheatManager
Kit B (speedremoveads):
android:name="com.??.speedremoveads.RMApplication" prefix varies (com.hm, com.mma)
assets/htm.txt {"source":"magic",…}
assets/acf encrypted, ~22 KB
POST https://mmk.magicmodapk.com/api/mmu.php
packageName, versionName, versionCode, dialogVersion
promo target https://t.me/topfreeapks
UI class com.joke.speedmenu.widget.SpeedMenu.SpeedMenuLayout
HappyMod 3.4.0 infrastructure, from shared_prefs/launch_doman.xml:
https://app.happymodapp.com config
https://om-server.btc42.com/init ad config (POST only, Spring Boot)
https://logt.apkomega.com BT telemetry
https://log1.apkomega.com
https://log.360modbaixar.com
https://ads.appbundledownload.com
http://195.154.26.56:82 cleartext fallback, Scaleway
Trackers:
tracker.hyper-torrent.com apktorrents.com best82.com best61.com
geo-coded subdomains: tra-<region>-<city>.<domain>:80xx/announce
Seeding fleet — Transmission/3.00 (bb6b5a062e), all proxy=false:
92.204.40.68 92.204.53.212 92.204.54.21 92.204.53.56 velia.net (DE)
148.72.144.76 148.72.158.43 velia.net (VIG-97)
51.15.23.143 Online.net / Scaleway NL
Samples:
39aefb7ff70b188c0484da37183cbc5e6d6b176a829ed27b5e1fda1bb86c3804 936,886,778 ddmx
e4b09ee783e69f524b35ce16d16567788d5afb71d314b37ad0d2333a682cec47 932,606,173 clean
7165a2b3fed886c1a301fc4f55bae8cecf8210dd179d2a54bc4f7ad941f82ae7 21,021,090 HappyMod 3.4.0
Signing keys as a pivot:
JTWJEST L=indna, C=9821 2024-12-06
SIGNOVER C=ef, ST=ds, L=rtte, O=ck, OU=ywh, CN=kd 2025-06-27
SIGNOVER C=usa, ST=str, L=msk, O=O, OU=u, CN=usa 2025-07-07
SIGN10_K C=ds, ST=ds, L=sd, O=ds, OU=ds, CN=ds 2024-12-11
Still open
The live-peer control arm, which is the only thing that turns the +14 into evidence or into an artifact. assets/acf, Kit B’s 22 KB encrypted config, which should fall to the same decryptor. And the original sample from May, still sitting on the bench, still silent — though I now have a much better idea of what to expect when it opens.
Method note: all sample analysis is static, on a rooted emulator with no personal data on it. Reputation lookups are one read-only API call per address. I report ISP/ASN aggregates and sample hashes; individual addresses appear only where they are infrastructure rather than subscribers. Nothing here touched a host that didn’t offer the file.