Skip to content
← All posts

FakeGit: LuaJIT malware distributed via GitHub at scale

Kirk21 min read
stealcgithubpolygonluajitinformation-stealeretherhiding

A Vietnamese-speaking operator has been distributing LuaJIT-based malware through GitHub since March 2025. The repos impersonate cracked browser extensions for SaaS tools, gaming cheats, developer utilities, and adult content. Each contains a ZIP archive with a LuaJIT loader chain. BitDefender tracks the archives as Gen:Heur.FakeGit.1 (as of March 2026). ESET tracks the Lua payloads as Lua/Agent.Z through Lua/Agent.BT (as of March 2026) -- 16 distinct obfuscator generations across the campaign.

The loader resolves its C2 by calling a getter function on a Polygon Mainnet smart contract. The operator updates the stored IP through on-chain transactions. Changing infrastructure does not require updating any deployed binary. The final payload, fetched from a GitHub dead drop and decrypted through a four-layer chain (hex, XOR, base64url, AES-ECB), is a StealC information stealer.

600+ unique malicious ZIP archives are confirmed across 47+ GitHub accounts. As of March 4, 2026, at least 25 accounts remain active. URLhaus first detected the campaign in January 2026, roughly 10 months after it started.


Sample overview

ComponentSHA256VTNotes
V1 ZIPebb0c76a03b8bb0ba246b8b31143f4462b4c3b0b3b5d581c499b4c3a484fd79220/76cracked-todoist-for-chrome.zip
V1 Lua payload8b5d6ff49034626532fbf5d2b9f4ffeee53facde63252e3c8aaa89f05029b8d416/76tcp.log
V1 executable5343326fb0b4f79c32276f08ffcc36bd88cde23aa19962bd1e8d8b80f5d339534/76luajit.exe (100KB, trojanized)
V1 DLLc7a657af5455812fb215a8888b7e3fd8fa1ba27672a3ed9021eb6004eff271ac0/76lua51.dll (3.5MB)
V2a ZIP2c5d4e26385d968570ffe8c602e431bd7fc88c3f637d0b1736ee7326c754b9ab16/76cracked-chrome-for-todoist-v3.0.zip
V2a Lua payload8cede35b80b1deaf732c2b178d908f91b3e7a0c114d06dfae9075b8a9bf78b8f3/76uix.txt
V2a executablef3e34c9e36f3be065d80d456281d31dd1cc85eb4980db7fa8c1b0eb6f29c25d831/76luajit.exe (878KB)
V2c Lua payload772ce19206d35699b4d2693c59f8c0bd1a927f287f8bf98bd14d65f1ff2488280/76icon.txt
V2e Lua payloada563a7df740bce2bda1231cebb4ed136813df43361de17c224b97af9941ee0c40/76ptd.txt
Dead drop Lua57cc3f7b14c761fcc4a3713a58c1161356fed27fb0cbc04d56bbe6a3ee43f6050/761.json / 7.txt (decrypted)
PE crypter (Feb 27)e33f444edb92a0d5f01b040dd06520092c0d52a431bbb4e6c2f9e6e71265098c15/762.json (decrypted)
PE crypter (Mar 2)e2e3768af9e40610b030644486f7434c892bf6ff273732c96f43c9e9401d3aca14/768.txt (decrypted)
StealC build0ca42898e885979196647b6e5c469461a25870c1f15ef5910d531f37f8f3f147f42/76compiled 2026-02-24
StealC build663c8cedc49339dd788dbc25f851dfce5219045aef80dd9bd17343948fb73f95441/76compiled 2026-03-01
Browser module61ab1d22949eac0582e989ae065ec4caee9ac99998276317edda96735cd311fb33/76embedded in stealer

Lure infrastructure

GitHub repos are created under a mix of purpose-built and compromised accounts. Each repo contains one ZIP archive with a fabricated name and an AI-generated README. Every link in the README -- including Documentation and Support links -- points to the same ZIP download.

The operator instructs victims to enable Chrome Developer Mode and load the extracted folder as an unpacked extension. Some repos also link to a legitimate YouTube video ("How to install unpacked extensions in chrome" by Easy Access Tech, youtube.com/watch?v=yVvvA8kaIuk) that walks through the sideloading process.

Lure categories:

  • Cracked browser extensions for SaaS tools: Jira, Asana, Todoist, Trello, Monday.com, ClickUp, Figma, Notion, Dropbox, Slack, Zoom, and others
  • Gaming cheats: Roblox executors and injectors, Fortnite XP bots and crosshair tools, CS2 radar, Valorant scripts
  • Developer tools: n8n workflows, CCNA labs, 7-Zip CVE-2025-0411 PoC, Cursor.so, Sora AI
  • Adult content and trading/crypto lures

The ZIP payload sits inside a single directory with an auto-generated name -- a rare English word or technical term. The full list of 47 confirmed names is distinctive enough to use as a hunt signal for unreported repos:

altisonous / amidofluorid / archfire / arthragra / cadetcy / circumcone / clackety / conferee / coronate / cruck / decrepitation / doddart / elegit / exclusivist / febricula / fieldworker / gastrodidymus / Guarrau / gudewife / hangworthy / harmonically / Helenus / heteropod / histometabasis / Iliadic / innkeeper / invenient / isocheim / jogglety / josh / larker / mesomorphy / nonnucleated / opisthophagic / pastoralness / Pelodytes / Phlegethontal / pteroclomorphic / Rajput / rectifiable / sketchiness / squashy / syrtic / tertiarian / textbookless / unjuvenile / ustorious

A Node.js automation toolkit found in the campaign repos (written in Vietnamese) shows the distribution workflow:

  1. Read repo name and description from a text file
  2. Rename a template directory to the repo name
  3. Compress to ZIP
  4. Create a GitHub repository
  5. Upload the ZIP and tutorial.txt

Inner payload files are byte-for-byte identical across lure categories. Extracting and hashing the contents of cracked extension ZIPs, gaming lure ZIPs, adult content ZIPs, and trading scam ZIPs targeting completely different audiences produces the same SHA256s for the executable, DLL, Lua payload, and launcher. The ZIP hashes differ because internal filenames vary per repo, but the malware binaries inside do not. This confirms single-operator attribution across all lure categories.

Accounts created specifically for this campaign typically have one public repo and a creation date anywhere from 2019 to 2025. Five accounts show signs of compromise -- existing developer accounts where a single malware repo was added alongside otherwise legitimate projects: MaybeDesxie7 (web developer, 19 legitimate repos), ShifaIshfaque (student developer, 14 legitimate repos), Mahmudul-Riad (web developer, 10 legitimate repos), sherinshamr (React project -- malware ZIP injected into src/assets/), and SYS123232 (Bannerlord modding account). Many of these compromised accounts have their legitimate repos showing a pushed_at date of 2025-10-11, suggesting a batch modification during account takeover.


Payload evolution

The first confirmed FakeGit ZIPs appear on VirusTotal on March 16, 2025, six days after the second C2 domain (aproxy.app) was registered. These earliest samples use a legitimate, unmodified 24KB LuaJIT binary from 2017 (0/76) paired with a 242KB obfuscated Lua script (conf.txt, Lua/Agent.Z, 27/76).

By May 2025, the operator replaced the clean runtime with a trojanized 100KB binary (5343326f...). The same SHA256 is present in all V1 Wave 1 ZIPs and in samples dated to May 2025, so the binary was not changed between those two points. The October 2025 jump in volume (16 to 51 ZIPs/month) was a distribution scale-up. The blockchain rotation cadence had already settled at roughly 15 days by June 2025 and did not shift in October.

In February 2026, the operator deployed a new 878KB trojanized binary alongside a second Polygon contract. Multiple EXE names appear across V2 variants: luajit.exe (878KB), vm_s390x.exe (292KB), init.exe (771KB), luad.exe (651KB), gcc.exe (651KB).

PeriodBinarySizeEXE VTLua payloadLua VTContract
Mar 2025luajit.exe (clean)24KB0/76conf.txt27/76V1 (0xd689...)
May 2025lua.exe (trojanized)100KB4/76cli.txt~16/76V1
Oct 2025 (Wave 1)luajit.exe (same binary)100KB4/76tcp.log16/76V1
Feb 2026 (Wave 2)multiple names292-878KB25-33/76uix.txt / lib_bit.txt / icon.txt / rsp.json / ptd.txt0-3/76V2 (0x1823...)

Lua payload detection has dropped from 27/76 in March 2025 to 0/76 in three of the six current variants. The operator has iterated through 16 distinct obfuscator generations.

The 600+ figure comes from querying the communicating files endpoint on all 50 C2 IPs across both contracts. URLhaus had catalogued roughly 80 of these ZIPs at time of writing -- the MISP feed captured under 15% of total distribution volume.


Lua payload internals

All six Lua payload variants use the same VM-based obfuscation scheme:

  1. Custom base64 alphabet: L07ker/2Jn4Z+b6y8hfXYVpTiDCvQKc3qRjUEBdo9MzHxtGNgWuA1FSmlaPO5wIs
  2. P table: 1,078 entries of encrypted binary constants (~114KB of encoded data per payload)
  3. Three-pass table shuffle before decoding: ranges {1,1064}, {1,658}, {659,1064}
  4. State machine dispatcher operating on encrypted bytecode from the P table
  5. All strings (URLs, API names, keys) assembled at runtime from P table entries

The FFI CDEF block is 8,514 bytes and is identical across all six variants. Declared Win32 API categories:

Screenshot capture: GetDC, CreateCompatibleDC, CreateDIBSection, SelectObject, BitBlt. Full BITMAP, BITMAPINFO, BITMAPFILEHEADER structure definitions.

Process injection / PE hollowing: IMAGE_DOS_HEADER, IMAGE_NT_HEADERS32/64, IMAGE_EXPORT_DIRECTORY, VirtualAlloc with PAGE_EXECUTE_READWRITE. PEB, LDR, and LDR_DATA_TABLE_ENTRY structures for manual DLL resolution without IAT entries.

System fingerprinting: GetComputerNameW, IsWow64Process, VerifyVersionInfoW, GetSystemMetrics, TOKEN_ELEVATION, OSVERSIONINFOEXW.

Evasion: GetConsoleWindow + ShowWindow(SW_HIDE) to suppress the console window.

The C2 backend is nginx/1.24.0 on Ubuntu with a Python FastAPI backend (Pydantic validation errors visible in HTTP responses). POST to /api/{base64_bot_id} for check-in; POST to /task/{base64_bot_id} for commands.


Blockchain C2 resolver

The loader calls a getter function on a Polygon Mainnet smart contract to retrieve the current C2 URL. This is the same EtherHiding technique documented in the OCRFix campaign, applied here to a standalone loader rather than a multi-stage botnet.

V1 contract: 0xd68910ED4D4A5A9bAdF9ec95604CAE0f3378479B

  • Function: getDomain(), selector 0xb68d1809
  • Deployed: 2025-02-21
  • Deployer: 0x6135f15449b65a962cf250258cf15c3aa16205a2
  • Transactions: 50 (48 updateDomain() + 1 destroyContract() + 1 encrypted blob test)
  • Current value: http://89.169.12.173

V2 contract: 0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc

  • Function: getData(), selector 0x3bc5de30
  • Deployed: 2025-11-15
  • Deployer: 0xdE275aD38C3352A7cb6b0d3efcBF45900c9716f2
  • Funded by: 0xF9Bd8BAD6DEB8706f63c16485F7209B8362529eA (27.82 POL from a wallet with 133,000+ transactions)
  • Transactions: 9 (all updateData())
  • Current value: http://89.169.12.241

V1 alternate contract: 0x2cbd2464dd749f5c0034fc9cddc6db2d53dea400 -- deployed 2026-01-26 by the same V1 deployer, single transaction, returns http://158.78.56.52. Never updated.

The V1 contract started with two C2 domains: layer1.icu on February 21, 2025, then aproxy.app on March 10, 2025. On March 17, 2025, the operator switched permanently to raw IPs. The aproxy.app DNS A record was 77.105.164.45, which was the next value set directly in the contract -- the domain-to-IP transition is confirmed in the blockchain record.

C2 rotation cadence averaged 5.5 days from March to May 2025 while the operator iterated on infrastructure. On May 23, 2025, six contract updates fired within 30 minutes, cycling between three IPs -- an operator manually testing C2 switching logic. From June 2025 onward the cadence settled at roughly 15 days per rotation and held that rate through the end of the V1 contract's active period.

The V2 contract was preceded by a test deployment. On November 15, 2025 the operator deployed a DataManager contract at 0xC224C02Cc0C5B5bf83538B3Db0b6f5b10a2bf6D2, stored 127.0.0.1, then destroyed it. The production V2 contract went live the same day.

On January 26, 2026, the operator called destroyContract() on the V1 contract. The call succeeded but the contract survived due to EIP-6780 -- self-destruct only removes code when called in the same transaction as contract creation. The same day, the operator tested a 128-byte encrypted blob as contract storage before reverting to plaintext IPs. Both contracts received new IP values on the same day, suggesting a planned infrastructure migration.


GitHub dead drops and decryption chain

The Lua payload fetches two encrypted blobs from GitHub repos that serve as a secondary delivery mechanism:

  • Small blob (~594KB hex-encoded): delivers an updated Lua payload for hot-patching without modifying the lure repos
  • Large blob (~2.3MB hex-encoded): delivers the PE crypter stub that decrypts and injects the final StealC payload

Current dead drop repos:

  • github.com/rd898/package (json/1.json, json/2.json) -- purpose-built account, created 2022-09-14
  • github.com/Mahmudul-Riad/www (index/7.txt, index/8.txt) -- compromised legitimate developer account

Both repos serve the same small blob (1.json and 7.txt share the same SHA256). The large blob differs between repos and across rotations.

Decryption chain for both blobs:

hex-encoded blob
  --> hex decode
  --> XOR decrypt (32-byte repeating key: ECe6VGLRJum2qYtl79OiOU7aHot7Zhbn)
       |
       +--> obfuscated Lua payload  (small blob, 297KB, 0/76)
       |
       +--> PE crypter stub         (large blob, ~1.2MB, 15/76 VT)

The XOR key is not stored as a literal in any payload file. The Lua VM assembles it at runtime from encrypted P table entries.

PE crypter:

Both observed builds are x64 GUI executables importing only KERNEL32.dll. All other APIs are resolved via PEB walking. The RCDATA section (resource ID 101) contains approximately 1MB of base64url-encoded, AES-256-ECB-encrypted content.

At RVA 0x1000, the crypter XORs two hardcoded 32-byte constants using AVX2 vpxor ymm1, ymm0, [rbp+0x20] to produce the AES-256 key at runtime. The key is stored in a global std::string, used, then zeroed out.

PE crypter buildAES-256 keyCompiled
Dead drop 2 (build0)YOYd5_dZpfW_nmA-rTxg61gpdbu_26-u2026-02-27 12:44 UTC
Dead drop 8 (build6)51AabzlG90_c_K9JZ8YXRGTOFralTd8k2026-03-02 21:10 UTC

Each build has a unique AES key (different XOR constants compiled in). Both decrypt to a 779,808-byte information stealer.

Injection: CreateProcessA (suspended) -> NtUnmapViewOfSection -> VirtualAllocEx -> WriteProcessMemory -> SetThreadContext -> ResumeThread.


StealC payload

Both decrypted inner PEs are 779,808-byte x64 GUI executables. They share 99.3% of their code and differ only in the encrypted config strings in .rdata and the build tag.

An embedded browser module (163,840 bytes) sits at .data offset 0x8DF20 and is shared across builds. SHA256: 61ab1d22949eac0582e989ae065ec4caee9ac99998276317edda96735cd311fb. VT: 33/76. Detection names include StealC, Luca Stealer, Win64/Spy.Agent.NZ. This module handles Chrome, Brave, and Edge credential extraction including App-Bound Encryption bypass. It has a .fptable PE section not commonly seen in other families.

Config encryption: RC4. The first string in the .rdata config block is the RC4 key itself. The remaining 266 strings are base64(RC4(plaintext)). All 120+ Win32 API names are encrypted and resolved at runtime via PEB walking.

BuildRC4 keyStealer C2
build0qAw6EF2z3ycMeACsJAhttp://217.119.129.110/3d9c1a1d0dc9436eb7b7.php
build6dVhllnj7MBHRDVTFDThttp://213.176.72.200/3d9c1a1d0dc9436eb7b7.php

Both stealer C2 IPs are on ASN 207957 (Serv.host Group Ltd), the same ASN as 37 of the 48 loader C2 IPs. 213.176.72.200 is in the same /23 as loader C2s 213.176.72.204 and 213.176.72.209.

Two additional StealC builds appeared on 217.119.129.110 in late February 2026 that are not from the dead drops analysed here:

Both detected as Stealer.StealC!1.133F7 / TrojanPSW:Win64/StealC. The VT filenames carry a community clustering suffix (cobalt-strike_icedid_luca-stealer_njrat_stealc) that is a tagging convention, not a malware name.

Stealer targets (from decrypted config strings):

  • Browsers: Chrome, Brave, Edge. Login Data, Cookies, Web Data, History, Extension Settings, IndexedDB. App-Bound Encryption via os_crypt/encrypted_key from Local State. Chrome v10 and v20 cookie encryption formats.
  • Firefox: NSS3 direct decryption via NSS_Init, PK11_GetInternalKeySlot, PK11SDR_Decrypt. Targets logins.json, cookies.sqlite, formhistory.sqlite, places.sqlite.
  • Email: Outlook (registry paths for Office 13.0 through 16.0 and Windows Messaging Subsystem), FoxMail.
  • SSH: WinSCP sessions (Software\Martin Prikryl\WinSCP 2\Sessions).
  • Gaming: Steam tokens and config files (ssfn*, config.vdf, DialogConfig.vdf, loginusers.vdf).
  • Loader: PowerShell iex(New-Object Net.WebClient).DownloadString('...') download-and-execute and MSI installer via msiexec /passive.

Exfiltration via JSON POST with opcode, data, and upload_file fields to the PHP endpoint. Screenshots via GDI+ (GdipCreateBitmapFromHBITMAP -> GdipSaveImageToStream -> screenshot.jpg). System fingerprint written to system_info.txt. Output directory structure: soft\Outlook\, soft\Steam\, soft\WinSCP\, soft\FoxMail\.


Full infection chain

1.  Victim extracts ZIP, runs Launcher.cmd
2.  Launcher.cmd: start luajit.exe <payload.txt>
3.  Lua VM hides console window (GetConsoleWindow + ShowWindow(SW_HIDE))
4.  eth_call to Polygon contract -> current C2 IP
5.  Fetch two hex blobs from GitHub dead drop repos
6.  Small blob: hex -> XOR -> updated Lua payload (0/76, hot-patch)
7.  Large blob: hex -> XOR -> PE crypter stub (15/76 VT)
8.  PE crypter: XOR two embedded 32-byte constants -> AES-256 key
9.  PE crypter: base64url decode RCDATA -> AES-256-ECB decrypt -> 779KB StealC
10. PE crypter: CreateProcessA (suspended) -> hollow -> inject -> resume
11. StealC: RC4-decrypt 267 config strings (API names, C2 URL, target paths)
12. StealC: collect credentials, cookies, tokens
13. StealC: JSON POST to /3d9c1a1d0dc9436eb7b7.php
14. StealC: optionally download additional payloads via PowerShell iex or msiexec

C2 infrastructure

All 52 endpoints are on bulletproof hosting providers. ASN 207957 (Serv.host Group Ltd) accounts for 37 of the 48 loader IPs and both stealer IPs. The remaining 11 loader IPs are split across four ASNs, with QWINS (AS213702) being the only other recurring provider.

ASNProviderLoader IPsPeriod
207957Serv.host Group Ltd372025-03-18 to present
213702QWINS62025-05-23 to 2025-12-22
213877u1host32025-03-31 to 2025-04-11
207043Dedik22025-12-02 to 2025-12-11
209207Digital Hosting12025-05-06
216300AbkhazMedia12025-03-17 (domain phase)

Loader C2 IPs (48 total):

IPASNCountryContractFirst seen in contract
58.64.137.6917444 (HKBN)HKlayer1.icu DNS2025-02-21
77.105.164.45216300 (AbkhazMedia)AMV1 + aproxy.app DNS2025-03-17
89.169.12.115207957DEV12025-03-18
89.169.13.30207957RUV12025-03-21
91.196.33.33207957RUV12025-03-23
89.169.12.119207957DEV12025-03-25
89.169.12.78207957DEV12025-03-28
91.196.34.17207957DEV12025-03-29
185.184.123.138213877 (u1host)NLV12025-03-31
185.184.122.38213877 (u1host)USV12025-04-02
89.169.12.42207957DEV12025-04-06
150.241.108.62213877 (u1host)USV12025-04-11
89.169.12.179207957DEV12025-04-26
193.233.126.91209207 (Digital Hosting)NLV12025-05-06
91.196.32.114207957RUV12025-05-15
95.164.53.26213702 (QWINS)DEV12025-05-23
95.164.53.153213702 (QWINS)DEV12025-05-23
185.170.153.239207957USV12025-06-03
185.170.153.243207957USV12025-06-05
185.170.153.173207957USV12025-06-08
91.196.33.27207957RUV12025-06-13
91.196.33.38207957RUV12025-06-22
89.169.13.215207957RUV12025-06-27
80.66.85.195207957DEV12025-07-07
91.196.32.121207957RUV12025-07-22
91.196.34.40207957DEV12025-08-01
94.156.155.34207957BGV12025-08-18
193.23.200.78207957SEV12025-09-06
45.149.235.146207957DEV12025-10-04
94.156.154.194207957BGV12025-10-20
185.170.154.101207957USV12025-11-09
93.123.39.74213702 (QWINS)EEV22025-11-16
84.21.189.135213702 (QWINS)DEV22025-12-11
151.243.113.70207043 (Dedik)DEV1 + V22025-12-02
151.243.113.15207043 (Dedik)DEV12025-12-11
78.40.209.225213702 (QWINS)FIV22025-12-22
93.123.39.246213702 (QWINS)EEV12025-12-22
144.31.219.13207957DEV12026-01-01
144.31.219.15207957DEV22026-01-01
213.176.72.209207957GBV12026-01-26
213.176.72.204207957GBV22026-01-26
89.169.12.173207957DEV1 (current)2026-02-08
89.169.12.160207957DEV22026-02-08
89.169.12.241207957DEV2 (current)2026-02-27
158.78.56.52--USV1 alt2026-01-26
213.176.73.151207957FRV2 sandbox--
213.176.73.163207957FRV2 sandbox--
64.188.98.20207957USV1 sandbox--

151.243.113.70 (Dedik, AS207043) appears in both V1 and V2 contracts and hosts concurrent, unrelated malware operations: ANDROMEDA/Gamarue (47-50/76), Wallstealer/luau.exe builds (37-45/76), LummaC2 (32/76), Aurora Stealer (43/76). This is shared bulletproof hosting -- the other families are not attributed to this operator.

Stealer C2 IPs:

IPASNCountryBuild
217.119.129.110207957LVbuild0
213.176.72.200207957GBbuild6

C2 domains:

DomainVTCreatedA record
layer1.icu11/942025-02-2158.64.137.69 (HK, AS17444)
aproxy.app15/942025-03-1077.105.164.45 (AM, AS216300)

IOC summary

ZIP archives

Zip hashes differ across repos because internal filenames vary per lure. The executable and Lua payload hashes inside are identical for all ZIPs sharing the same variant.

Executables

Lua payloads

Launchers

DLLs

Dead drop files (pre-decryption)

Stealer payloads

Kirk's note: If anyone knows an efficient way to bulk-report malicious GitHub repositories or accounts, please reach out to kirk@derp.ca. Reporting 25+ accounts one at a time through the web form isn't practical, and emailing support@github.com bounced.

GitHub accounts (still live as of 2026-03-03)

Cracked extension repos: teskkkkk, bibabiboreal, class1k, hamzaabiadi, jsm2raj, kayraizm3131, kukil-saikia, lazzydave, TeeeeeeeeeellKall, DARKPHATOM, MaybeDesxie7, sameeronwheels, jyng2002, ShifaIshfaque, clieez

Gaming and utility lure repos: hydrangeapaniculatabokchoi171, jorgeZdark, Masbe2117, kenshigenesis-jpg, SYS123232, blackwall0220, sherinshamr, Vitor-gf

Dead drop repos: rd898, Mahmudul-Riad

Blockchain contracts (Polygon Mainnet)

0xd68910ED4D4A5A9bAdF9ec95604CAE0f3378479B   V1 loader contract (active)
0x2cbd2464dd749f5c0034fc9cddc6db2d53dea400   V1 alternate contract (active)
0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc   V2 loader contract (active)

MITRE ATT&CK

IDTechnique
T1566.002Phishing: Spearphishing Link
T1204.002User Execution: Malicious File
T1059.007Command and Scripting Interpreter: Lua
T1036.005Masquerading: Match Legitimate Name
T1036.007Masquerading: Double File Extension
T1218Signed Binary Proxy Execution
T1027Obfuscated Files or Information
T1027.002Software Packing
T1140Deobfuscate/Decode Files
T1102.001Web Service: Dead Drop Resolver
T1053.005Scheduled Task/Job
T1055.012Process Hollowing
T1113Screen Capture
T1106Native API
T1555.003Credentials from Web Browsers
T1555Credentials from Password Stores
T1539Steal Web Session Cookie
T1586.001Compromise Accounts: Social Media
T1583.005Acquire Infrastructure: Botnet

What this analysis cannot determine: victim count, whether additional distribution platforms exist beyond GitHub, or the full extent of the operator's infrastructure beyond what the blockchain records and VT communicating files data expose. The 600+ ZIP figure is a lower bound -- repos removed before analysis would not appear in VT telemetry.

The campaign has processed 600+ distinct ZIP archives across 47+ GitHub accounts over 13 months without a sustained platform disruption. The V1 Polygon contract has rotated through 50 C2 values. Both V1 and V2 contracts are currently active.

See also: OCRFix EtherHiding botnet.


If you operate a threat intelligence platform with API access and can provide a researcher account, please reach out to kirk@derp.ca. Additional data sources directly increase the quality and coverage of the threat intel published here.

K

Kirk

I like the internet. Want to get in touch? kirk@derp.ca