BLOG
4 Years, 51 Packages, 3 organizations: How npm Became a Gambling Ring's Config Server
Alessandra
Rizzo
Summary
Seven npm packages under the @hd-team organization contain no code. Each one exports a single base64 encoded JSON blob: a list of API endpoints, CDN identifiers, and what look like authentication tokens and load balancing weights. These are live configuration payloads consumed by a mobile app called 斗球 (Douqiu, "Fight Ball"), a Chinese sports gambling and pirate streaming platform. The app fetches these configs from five npm registry mirrors on every launch, using them to resolve which backend servers to connect to. When a domain gets burned, the operators publish a new package version and the app picks it up automatically.
Decompiling the APK and iOS binary led to a second npm org, @yuming2022 (43 packages, four years of history), and then to a third, @elton.bfw, discovered in iOS source code pushed to GitHub in 2022. All three orgs share infrastructure: identical CDN tokens, the same bfw prefix across email addresses, Sentry hostnames, and Huawei OBS buckets.
Across the three organizations, 51 packages have been published to npm, mapping over 60 unique domains across three CDN providers (Funnull, Aliyun, Huawei), and generating over 200,000 weekly downloads on npmjs.org alone. The true download figure is higher, since the three Chinese mirrors the app primarily queries don't publish stats.
The operator is using the npm ecosystem as a free, globally distributed, highly available config server, and has been doing so under the radar since August 2022.
Analysis
The investigation started with @hd-team/app-dnpkg-beta, a package with 88,000+ weekly downloads and 990+ published versions. Its index.js contains a single base64 string that decodes to:
The base64 value ZnVubnVsbA== decodes to funnull. Funnull Technology Inc., a Philippines-based CDN administered by Chinese national Liu Lizhi, was sanctioned by the U.S. Treasury on May 29, 2025 under Executive Order 13694 for providing critical infrastructure to virtual currency investment scams, with over $200 million in reported U.S. victim losses. The FBI identified 548 unique Funnull CNAMEs linked to over 332,000 domains. Funnull was also implicated in the 2024 Polyfill.io supply chain attack (Treasury, Silent Push, OFAC SDN listing, Wiz). The cdn field identifies which CDN provider fronts each API endpoint: some are labeled funnull, others aliyun or huawei.
The package publishes a new version every five minutes in waves, each with an identical payload. The versioning scheme uses timestamps in the format 1.0.YYYYMMDDHHMMSS, and all timestamps fall within UTC+8 (China Standard Time). The rapid publishing cadence serves as a heartbeat: it keeps the package "fresh" across CDN caches on all five mirrors the app queries.
Identifying the Product
The web frontend, identified at next[.]beta[.]qiu577[.]com , confirmed the product: 斗球直播 (Douqiu Live), a pirate sports streaming platform with integrated gambling and hostess cam features. The splash screen tagline reads "斗球!爱我所赢" ("Douqiu! Love What I Win").
The site's footer claims Chinese business licenses registered in Guangxi province (桂ICP备19009876号). Customer support is handled via QQ account 3560966093.
APK Retrieval and Decompilation
The download page, located at h5down[.]qiuhui[.]com , uses a JavaScript bundle that signs API requests with a hardcoded key, and hitting the live endpoint returned the current APK:
The APK (package name com.sports.dqty, build 2610) is signed with a self signed certificate issued to CN=sports, O=sports, OU=sports , and thumbprint 6db3406e6b9b23d102dda9e0b6de548a566906ea. The internal Java namespace is com.sports.douqiu.xmsport and the project codename is com.yb.ballworld ("YB BallWorld"). The iOS build is internally called XMSport.

Figure 1: APK Launch Screen
The classes4.dex file contains five npm registry mirror URLs, all pointing to the @yuming2022 organization:
https://mirrors[.]cloud[.]tencent.com/npm/@yuming2022/app-dnpkg-*
https://r[.]cnpmjs[.]org/@yuming2022/app-dnpkg-*
https://registry.npmmirror[.]com/@yuming2022/app-dnpkg-*
https://registry.yarnpkg[.]com/@yuming2022/app-dnpkg-*
https://unpkg[.]com/@yuming2022/app-dnpkg-*
The APK requests 40+ Android permissions including ACCESS_BACKGROUND_LOCATION, CAMERA, READ_PHONE_STATE, REQUEST_INSTALL_PACKAGES, MANAGE_EXTERNAL_STORAGE, QUERY_ALL_PACKAGES, SYSTEM_ALERT_WINDOW, and DETECT_SCREEN_RECORDING. The privacy dialog at launch explicitly states the app collects IMEI, MAC address, and installed software lists.
The app integrates Alipay and WeChat Pay for payments, Alibaba's facial recognition SDK for identity verification, three redundant IM providers (RongCloud, NetEase NIM, JPush IM), push notification SDKs for every major Chinese OEM (Xiaomi, Huawei, OPPO, Vivo, Meizu), and DLNA casting for streaming to TVs.
How It Works
The iOS source code reveals the full domain resolution hierarchy.
Figure 2: Douqiu App Config Architecture
The app first calls /qiutx-support/domains/v2/pull on its current API server. If the API is down, the app fetches a static JSON file (app_prod.json) from a Huawei Cloud Object Storage bucket. Only if both the API and OBS are unreachable does the app try npm. It queries five mirrors in sequence: unpkg (proxying to npmjs.org), cnpmjs, npmmirror, Tencent Cloud, and Yarn. Each mirror fetches the latest version of @yuming2022/app-dnpkg-{environment} and returns the base64 config blob. If all of the above fail, the Android APK falls back to 13 api[.]dw*[.]app domains baked into the binary.
npm is the most interesting layer because it is the most resilient: the operator cannot be locked out of five independent npm mirrors simultaneously, the content is cached globally, and the publishing is automated.
Attribution
@yuming2022 has 43 packages on npm dating back to 2022, with byte-for-byte identical config payloads to @hd-team. The packages span three client types (app-dnpkg-* for Android, web-dnpkg-* for web, appstore-dnpkg-* for iOS) across numbered environments. Beyond Douqiu, the organization runs a decommissioned sports brand (qsty), an IM app called 聊个天 (LGT), and an SEO analytics SDK (seo-tracing) deployed on Google Sites doorway pages.
A GitHub repository (afeiaxing/Sport1) pushed four years ago contains the complete iOS source. The Xcode project identifies the developer as jsmaster, the original product as 球王体育 ("Ball King Sports"), and references a third npm org, @elton.bfw, with a single package cloud published August 16, 2022 under elton.bfw@gmail.com. That package shares the same Aliyun CDN token as today's @yuming2022 configs. The bfw prefix, present in @elton.bfw, jaxsonbfw@gmail.com, sentry.bfw14.com, and every Huawei OBS bucket, is the one constant across three npm org generations and four years of infrastructure.
Acquiring Users
The operation runs an SEO pipeline to funnel Chinese search traffic toward the app. Templated doorway pages on Google Sites and dedicated domains are stuffed with sports streaming keywords in Chinese, then redirect visitors to gambling domains like kyun9242[.]com and 38s[.]bet. The @yuming2022/seo-tracing npm package is an analytics SDK embedded in these pages to measure conversion. The doorway pages follow a consistent pattern: keyword stuffed Chinese text, a meta refresh or JavaScript redirect, and the tracing pixel. Google Sites appears to be the preferred host.
Motivation
We assess that the choice of managing the scale of this operation through NPM goes beyond infrastructure cost savings. Online gambling is completely banned in mainland China, and enforcement is severe. In 2024 alone, the Ministry of Public Security shut down over 4,500 illegal online gambling platforms, investigated 73,000 cross-border gambling cases, and arrested over 11,000 suspects. Operators of large scale gambling rings have received life sentences and death penalties. The government actively blocks access to foreign gambling websites at the network level and pursues both operators and players. For an operation like Douqiu, the existential threat is criminal prosecution.
npm registries solve this problem. Chinese npm mirrors like npmmirror.com are critical developer infrastructure used by millions of legitimate engineers. They cannot be blocked without collateral damage to China's entire software industry. A base64 blob in an index.js file is indistinguishable from a real package to any automated scanning system. Since the config is fetched at runtime rather than hardcoded in the binary, the operator can rotate blocked domains within minutes by publishing a new package version.
Conclusion
npm was designed to distribute JavaScript packages. Douqiu uses it to distribute infrastructure configuration for what we assess is an illegal gambling operation, and has been doing so for four years across 51 packages and 3 organizations.
The technique is simple: encode your config as a base64 string in index.js, publish it, and let the npm CDN handle global distribution, caching, versioning, and TLS. No C2 server to maintain. No domain to get seized. No infrastructure cost.
The implications extend beyond this one operation. Any app, malicious or otherwise, can use a package registry as a free config server. The publishing is automated, the distribution is global, the content is opaque, and the platform provides built-in redundancy through mirrors.
See it in action
Most AI closes the alert. Panther closes the loop.

Indicators
npm Packages
@elton.bfw packages
Package | Last Published |
|---|---|
@elton.bfw/cloud | 1.0.2 (2022-08-16) |
@hd-team packages
Package | Last Published |
|---|---|
@hd-team/app-dnpkg-beta | 1.0.20260424213500 (actively publishing every 5 min) |
@hd-team/app-dnpkg-prod | 1.0.20260425000003 |
@hd-team/app-dnpkg-three | 1.0.20260425000000 |
@hd-team/app-dnpkg-test | 1.0.20260424104347 |
@hd-team/app-dnpkg-eight | 1.0.20260329115708 |
@hd-team/app-dnpkg-ten | 1.0.20260408192745 |
@hd-team/app-impkg-test | 1.0.20260408143221 |
@yuming2022 packages
Package | Last Published |
|---|---|
@yuming2022/app-dnpkg | 1.0.20220822202635 |
@yuming2022/app-dnpkg-beta | 1.0.20251209150501 |
@yuming2022/app-dnpkg-prod | 1.0.20251209000002 |
@yuming2022/app-dnpkg-test | 1.0.20251110193114 |
@yuming2022/app-dnpkg-three | 1.0.20251110000000 |
@yuming2022/app-dnpkg-eight | 1.0.20251003220326 |
@yuming2022/app-dnpkg-ten | 1.0.20241227130326 |
@yuming2022/app-dnpkg-two | 1.0.20230831185202 |
@yuming2022/app-dnpkg-four | 1.0.20230806145137 |
@yuming2022/app-dnpkg-five | 1.0.20230926201832 |
@yuming2022/app-dnpkg-six | 1.0.20240510193001 |
@yuming2022/app-dnpkg-seven | 1.0.20240527152823 |
@yuming2022/app-dnpkg-nine | 1.0.20240816121214 |
@yuming2022/app-dnpkg-eight-test | 1.0.20250301132357 |
@yuming2022/app-dnpkg-xingsu | 1.0.20230628000000 |
@yuming2022/app-dnpkg-jingsu | 1.0.20230726000002 |
@yuming2022/app-dnpkg-dev | 1.0.20230630105105 |
@yuming2022/app-dnpkg-uqtest | 1.0.20250615000001 |
@yuming2022/app-dnpkg-ons-test | 1.0.20230729143242 |
@yuming2022/app-dnpkg-ons-prod | 1.0.20230729152601 |
@yuming2022/app-dnpkg-appstore | 1.0.20230725144338 |
@yuming2022/app-dnpkg-qsty--test | 1.0.20240707000002 |
@yuming2022/app-dnpkg-qsty--prod | 1.0.20240818102516 |
@yuming2022/web-dnpkg | 1.0.0 |
@yuming2022/web-dnpkg-beta | 1.0.20251121171134 |
@yuming2022/web-dnpkg-prod | 1.0.20221110132621 |
@yuming2022/web-dnpkg-test | 1.0.20250909152918 |
@yuming2022/web-dnpkg-three | 1.0.20221110133051 |
@yuming2022/web-dnpkg-two | 1.0.20220927174511 |
@yuming2022/web-dnpkg-four | 1.0.20221022193358 |
@yuming2022/web-dnpkg-five | 1.0.20220927174041 |
@yuming2022/web-dnpkg-appstore | 1.0.20221116000006 |
@yuming2022/web-dnpkg-qsty--test | 1.0.20240114182616 |
@yuming2022/web-dnpkg-qsty--prod | 1.0.20240304221144 |
@yuming2022/appstore-dnpkg-prod | 1.0.20221110132620 |
@yuming2022/appstore-dnpkg-test | 1.0.20221028192823 |
@yuming2022/appstore-dnpkg-beta | 1.0.20221118220230 |
@yuming2022/appstore-dnpkg-three | 1.0.20221110133049 |
@yuming2022/appstore-dnpkg-four | 1.0.20221022193356 |
@yuming2022/appstore-dnpkg-appstore | 1.0.20221116000004 |
@yuming2022/app-impkg-test | 1.0.20251018130310 |
@yuming2022/app-impkg-prod | 1.0.20251104163328 |
@yuming2022/seo-tracing | 1.5.0 |
APK
Field | Value |
|---|---|
Package Name | com.sports.dqty |
Version | 2.4.1 (build 2610) |
Java Namespace | com.sports.douqiu.xmsport |
Project Codename | com.yb.ballworld |
Signing Certificate Thumbprint | 6db3406e6b9b23d102dda9e0b6de548a566906ea |
Certificate Subject | CN=sports, O=sports, OU=sports |
SHA256 | 7fdcec6a71568166e8a5cff3383a7e6d6cdf87cf8c35741607217716c3d35988 |
Download URL | hXXps://sta-prod-pic-prod511[.]jiaoict[.]com/5843ea8b1f5b44cfb585e1310e60da93.apk |
AES Key (hardcoded) | 8765432112345678 |
API Signing Key (download page) | fd456406745d816a45cae554c788e754 |
OpenInstall App Key | ofv48e |
IPA (iOS)
Field | Value |
|---|---|
Bundle ID | com.app.dq202501 |
Version | 2.3.9 |
Binary Name | 斗球 |
Build Date | 2025-12-15 |
Plist URL | hXXps://sta-prod-pic-prod511[.]jiaoict[.]com/dq/iOS/prod/2.3.9/2025-12-15-16-24-54/dqty_F1.plist |
IPA URL (original, dead) | hXXps://sta-prod-pic-prod511[.]wdieijv[.]com/dq/iOS/prod/2.3.9/2025-12-15-16-24-54/dqty.ipa |
IPA URL (live mirror) | hXXps://sta-prod-pic-prod511[.]jiaoict[.]com/dq/iOS/prod/2.3.9/2025-12-15-16-24-54/dqty.ipa |
Distribution | Enterprise sideload (itms-services), not App Store |
Download Channel | F1 |
Frameworks | RongCloud IM, MobileVLCKit, HandyJSON, JGIM (JPush IM), SwiftTheme |
npm References | @yuming2022/app-dnpkg-prod |
Infrastructure
Domain | Role |
|---|---|
api[.]dq87771[.]com | API (Funnull CDN) |
apiyf[.]dq87771[.]com | API (Funnull CDN) |
api[.]dq87774[.]com | API (Funnull CDN) |
api[.]test[.]qiu577[.]com | API (Funnull CDN) |
apial[.]qiu577[.]com | API (Funnull CDN) |
apitest[.]qiu577[.]com | API (Funnull CDN) |
apial[.]yrcmza[.]com | API (Aliyun CDN) |
apial[.]bengvet[.]com | API (Aliyun CDN) |
apial[.]qaffvz[.]com | API (Aliyun CDN) |
api-al[.]wentian510[.]com | API (Aliyun CDN) |
api[.]solea76[.]com | API (Aliyun CDN) |
apial[.]cqffsj[.]top | API (Aliyun CDN) |
apihw[.]openbor[.]xyz | API (Huawei CDN) |
apihw[.]qihuaa[.]xyz | API (Huawei CDN) |
apihw[.]sdgsdggg[.]xyz | API (Huawei CDN) |
api[.]aiyno[.]cn | API (Huawei CDN) |
api[.]bbpafgv[.]cn | API (Huawei CDN) |
api[.]brackenluxy[.]cn | API (Huawei CDN) |
api[.]qiongkap[.]com | API (Huawei CDN) |
apihw[.]mlh99[.]com | API (Huawei CDN) |
apihw[.]jzsznj[.]com | API (Huawei CDN) |
api[.]yazhijian[.]com | API (Huawei CDN) |
api[.]7xingyun[.]com | API (Huawei CDN) |
api[.]dw1[.]app through api[.]dw13[.]app | Hardcoded fallback APIs |
api[.]shidaocb[.]com | Download page API (dead) |
api[.]bdxhj[.]com | Unknown API |
dqiu[.]vip | Main landing page |
dqiu[.]tv | Alternate landing |
dqiu06[.]com | Events/news |
dqiu24[.]com | Events/news |
dqiu66[.]com | Alternate landing |
dqiu99[.]com | Alternate landing |
h5down[.]qiuhui[.]com | APK download page |
h5down[.]dqiu[.]tv | APK download page |
h5down[.]bureyh[.]com | APK download page |
h5down[.]dqty[.]com | APK download page |
h5down[.]mssquabyc[.]com | APK download page |
m[.]qiutx[.]com | Mobile SSR |
m[.]ihjnhjfa[.]com | Mobile H5 |
pull[.]yaokun1985[.]com | Live stream pull (primary) |
pull[.]jycshi[.]com | Live stream pull (backup) |
video[.]shangkmo[.]com | Video player CDN |
video[.]cretebl[.]com | Video player CDN |
video[.]douphj[.]com | Video player CDN |
video[.]chnjindi[.]com | Video player CDN |
video[.]dqiu[.]com | Video stream Referer (from source) |
api[.]k396w[.]com | API (Aliyun CDN, from source) |
api-al[.]k396w[.]com | API (Aliyun CDN, from source) |
api[.]kjwinm[.]cn | API (Huawei CDN, from source) |
api-al[.]hzmgrn[.]com | API (Aliyun CDN, from source) |
api[.]hzmgrn[.]com | API (Aliyun CDN, from @elton.bfw/cloud) |
tlsapi[.]qiu994[.]com | API (Funnull CDN, App Store build, from source) |
ios[.]qiu994[.]com | API (commented out in source) |
bfw-pic-new[.]obs[.]cn-south-1[.]myhuaweicloud[.]com | Huawei OBS (Layer 2 config, from source) |
sta-prod-pic-prod511[.]jiaoict[.]com | Static assets / APK hosting |
sta-prod-pic[.]zkreen[.]com | Static assets |
sta-prod-score01-new-prod511[.]qaffvz[.]com | Score data |
sta-beta01-new-prod511[.]wbs0551[.]com | Static assets (beta) |
sta[.]5yqz2[.]com | Static assets |
sta-prod-pic[.]rtewv[.]top | iOS plist hosting |
bfw-pic-new01-prod511[.]qiuybk[.]com | Static assets |
bfw-pic-new01[.]ozljtyv[.]com | Static assets |
bfw-btd-pic-new0111[.]obs[.]ap-southeast-1[.]myhuaweicloud[.]com | Huawei OBS (Singapore) |
bfw-pic-new0111.obs[.]cn-south-1.myhuaweicloud[.]com | Huawei OBS (Guangzhou) |
d2theorj75dyet[.]cloudfront[.]net | Match animation (AWS CloudFront) |
cdn[.]topcw9d[.]com | SEO analytics C2 (active) |
cdn[.]a59[.]tv | SEO analytics C2 (burned) |
sentry[.]bfw14[.]com | Self hosted Sentry |
tcs[.]fengkuangtiyu[.]cn | "Crazy Sports" affiliate |
www[.]axd02xd[.]cfd | Customer service |
tb[.]53kf[.]com | Customer service widget |
lgt08[.]tv | IM product (聊个天) |
kyun9242[.]com | SEO doorway redirect |
ww588[.]my | SEO doorway redirect |
38s[.]bet | SEO doorway redirect |
privacy[.]xmsport[.]com | User agreement / privacy policy |
m[.]qiu80[.]com | Mobile site (qiu variant) |
issue-ap[.]qiu199[.]com | API endpoint (from OBS log.txt) |
t[.]fkhongdan[.]com | Gambling tips feature |
yumao[.]puata[.]info | Unknown infrastructure |
sta-prod-pic-prod511[.]wdieijv[.]com | iOS static assets (dead, 95[.]40[.]218[.]78) |
IP Addresses
IP | Context |
|---|---|
110[.]41[.]14[.]216:7006 | Direct connection observed in VT sandbox |
18[.]167[.]71[.]66:1510 | Customer service backend (AWS Hong Kong) |
95[.]82[.]60[.]25 | h5down[.]qiuhui[.]com hosting |
103[.]246[.]244[.]139 | Shared by lgt08[.]tv and apiyf[.]dq87771[.]com |
95[.]40[.]218[.]78 | sta-prod-pic-prod511[.]wdieijv[.]com (iOS assets, dead) |
16[.]162[.]110[.]66 | itcom888[.]com (developer registration domain, AWS Hong Kong) |
Analytics and Tracking IDs
Type | Value |
|---|---|
Baidu Analytics | 1fb727b21bee169fb069ce31cad1009c |
Baidu Analytics (download page) | 85422d97fd4bc09493777d68fe9a3430 |
CNZZ | 1281314046, 1281359148, 1279786301 |
GeeTest CAPTCHA | 8edea2293ebdda68421d99381617103e |
OpenInstall App Key | ofv48e |
Developer Identity
Field | Value |
|---|---|
Author (seo-tracing) | Jaxson <jaxsonbfw[@]gmail[.]com> |
npm Publisher (@elton.bfw) | elton[.]bfw[@]gmail[.]com |
npm Publisher (@yuming2022) | jszyhdnp[@]itcom888[.]com |
npm Publisher (@hd-team) | hd-team2026[@]outlook[.]com |
Registration Domain | itcom888[.]com (16[.]162[.]110[.]66, AWS Hong Kong) |
GitHub | afeiaxing/Sport1 |
Xcode Developer | jsmaster |
Original Product Name | 球王体育 (QWTY, "Ball King Sports") |
Apple Developer Team ID | CAWXAH3493 |
iOS Bundle ID (old) | com.dq44 |
JPush App Key (iOS) | 09986335d73a3d8569c0023b |
Umeng App Key | 5e43ceaacb23d2efa7000076 |
Funnull CDN Token | eba9b9516a601422b1c20e093f52f9a9 |
Aliyun/Huawei CDN Token | JmQ8uEKn6g96nSsWccw |
Git Commit | 2adf32b7853ee672dc2cee6a547eae705eeb397d |
QQ (customer support) | 3560966093 |
Email (customer support) | 3560966093[@]qq[.]com |
Claimed Business Licenses (unverified)
License | Value |
|---|---|
ICP Filing | 桂ICP备19009876号 |
Internet Culture License | 桂网文(2022)2794-503号 |
Telecom Business License | 桂B2-20230251 |
Share:
RESOURCES






