Skip to content

Instantly share code, notes, and snippets.

@enghqii
Last active February 2, 2026 12:28
Show Gist options
  • Select an option

  • Save enghqii/95df8cdeca1c0e678aeb1e183e24dc70 to your computer and use it in GitHub Desktop.

Select an option

Save enghqii/95df8cdeca1c0e678aeb1e183e24dc70 to your computer and use it in GitHub Desktop.
Amped.jar Decrypter

What this does

Loads amped.jar with the decompiled nkeel.jar loader and captures decoded class bytes via a Java agent, then writes a standard .class jar.

Required files

Download one of those single getamped zip files that includes the following:

  • amped.jar
  • keel_clazz.dll (32-bit)
  • 32-bit JRE6\

Other things we should prepare:

  • decompiled_nkeel.jar
  • 32-bit JDK 8 (ZIP install)

Install 32-bit JDK

Download and extract:

https://cdn.azul.com/zulu/bin/zulu8.90.0.19-ca-jdk8.0.472-win_i686.zip

Decompile nkeel.jar (powershell)

  1. Install JDK via winget or however you like.
winget install --id EclipseAdoptium.Temurin.21.JDK -e
  1. rename nkeel.jar to nkeel.zip then unzip.
  2. re-package the unzipped folder
jar decompiled_nkeel.jar -C .\nkeel\ .

Build (PowerShell)

$root = 'C:\path\to\project'
$jdk  = "$root\path\to\jdk\zulu8.90.0.19-ca-jdk8.0.472-win_i686\zulu8.90.0.19-ca-jdk8.0.472-win_i686"
$javac = "$jdk\bin\javac.exe"
$jar   = "$jdk\bin\jar.exe"

$src = "$root\src\main\java\amped\Decrypter.java"
$classes = "$root\build\classes"
$build = "$root\build"

$rt = "$root\JRE6\lib\rt.jar"
$cp = "$root\new_nkeel.jar"

New-Item -ItemType Directory -Force -Path $classes | Out-Null
& $javac -source 6 -target 6 -bootclasspath $rt -cp $cp -d $classes $src

$manifest = "$build\manifest.mf"
@(
"Manifest-Version: 1.0",
"Main-Class: amped.Decrypter",
"Premain-Class: amped.Decrypter",
"Can-Redefine-Classes: true",
"Can-Retransform-Classes: true",
""
) | Set-Content -Path $manifest -Encoding ASCII

$jarOut = "$build\decrypter-1.0.jar"
if (Test-Path $jarOut) { Remove-Item -Force $jarOut }
& $jar cfm $jarOut $manifest -C $classes .

Run (PowerShell)

$root = 'C:\path\to\project'
$java = "$root\JRE6\bin\java.exe"
$jar  = "$root\build\decrypter-1.0.jar"
$cp   = "$root\new_nkeel.jar"
$in   = "$root\amped.jar"
$out  = "$root\decrypted_amped.jar"

& $java "-Djava.library.path=$root" -javaagent:$jar -cp "$jar;$cp" amped.Decrypter $in $out
plugins {
id 'java'
id 'application'
}
group = 'amped'
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
implementation files('path/to/your/decompiled_nkeel.jar')
}
application {
mainClass = 'amped.Decrypter'
}
jar {
manifest {
attributes(
'Main-Class': 'amped.Decrypter',
'Premain-Class': 'amped.Decrypter',
'Can-Redefine-Classes': 'true',
'Can-Retransform-Classes': 'true'
)
}
}
rootProject.name = "decrypter"
package amped;
import backstage.runtime.ApplicationClassLoader;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
public final class Decrypter {
private static volatile Instrumentation instrumentation;
public static void premain(String agentArgs, Instrumentation inst) {
instrumentation = inst;
}
public static void main(String[] args) throws Exception {
// parse args
if (instrumentation == null) {
System.err.println("Missing -javaagent. Run with: -javaagent:<path-to-built-jar>");
System.exit(2);
}
if (args.length < 2) {
System.err.println("Usage: Decrypter <input-amped-jar> <output-jar>");
System.exit(1);
}
File inputJar = new File(args[0]);
File outputJar = new File(args[1]);
if (!inputJar.isFile()) {
System.err.println("Input jar not found: " + inputJar.getAbsolutePath());
System.exit(1);
}
final Set<String> targetClassNamesSlash = new HashSet<String>();
List<String> classNamesDot = new ArrayList<String>();
// Enumerate .clazz entries in the amped.jar so we know which classes to force-load.
JarFile jar = null;
try {
jar = new JarFile(inputJar);
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.isDirectory()) {
continue;
}
String name = entry.getName();
if (!name.endsWith(".clazz")) {
continue;
}
// name ends with '.clazz'
String slash = name.substring(0, name.length() - ".clazz".length());
targetClassNamesSlash.add(slash);
classNamesDot.add(slash.replace('/', '.'));
}
} finally {
if (jar != null) {
jar.close();
}
}
// Capture decoded bytecode as the native loader defines classes.
// class name -> decoded bytecode
final Map<String, byte[]> decodedBytesBySlashName = new ConcurrentHashMap<String, byte[]>();
ClassFileTransformer transformer = new ClassFileTransformer() {
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
if (className == null || classfileBuffer == null) {
return null;
}
if (targetClassNamesSlash.contains(className)) {
if (!decodedBytesBySlashName.containsKey(className)) {
decodedBytesBySlashName.put(className, classfileBuffer.clone());
}
}
return null;
}
};
instrumentation.addTransformer(transformer, true);
// Preparation done. now the decryption part.
// Use the nkeel ApplicationClassLoader so the native defineClass path is exercised.
ApplicationClassLoader loader = new ApplicationClassLoader("com.cyberstep.ring.client.Game");
loader.openArchive(inputJar.getAbsolutePath());
List<String> failures = new ArrayList<String>();
for (String className : classNamesDot) {
try {
// Force-load each class to trigger decoding and transformer capture.
Class.forName(className, false, loader);
} catch (Throwable t) {
failures.add(className + " -> " + t.getClass().getName() + ": " + t.getMessage());
}
}
// Class load done.
instrumentation.removeTransformer(transformer);
// Write captured decoded classes to a standard .class jar.
writeJar(outputJar, decodedBytesBySlashName);
int total = classNamesDot.size();
int decoded = decodedBytesBySlashName.size();
System.out.println("Decoded classes: " + decoded + " / " + total);
if (!failures.isEmpty()) {
System.err.println("Load failures: " + failures.size());
for (String f : failures) {
System.err.println(f);
}
}
if (decoded < total) {
System.err.println("Some classes were not captured. If needed, retry with a more complete classpath.");
}
}
private static void writeJar(File outputJar, Map<String, byte[]> classMap) throws IOException {
if (outputJar.getParentFile() != null) {
outputJar.getParentFile().mkdirs();
}
JarOutputStream jos = null;
try {
jos = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(outputJar)));
for (Map.Entry<String, byte[]> entry : classMap.entrySet()) {
String name = entry.getKey() + ".class";
JarEntry jarEntry = new JarEntry(name);
jos.putNextEntry(jarEntry);
jos.write(entry.getValue());
jos.closeEntry();
}
} finally {
if (jos != null) {
jos.close();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment