Всем привет! В данном посте я солью крипту (почти полностью переписана от сертио)
добавлено:
constantPool
xor key
read method (classWriter)
minimal fix main
main:
classFileParser:
classStream:
classWriteFile:
прошу не пинать, как по мне это сильно улучшеная тема от сертио
добавлено:
constantPool
xor key
read method (classWriter)
minimal fix main
main:
Java:
package proguard.crypta;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class Main {
private static final ConcurrentHashMap<String, byte[]> files = new ConcurrentHashMap<>();
public static void main(String[] args) throws IOException {
ZipFile zip = new ZipFile("C:\\Users\\youki\\OneDrive\\Рабочий стол\\Новая папка (2)\\a.jar");
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
try {
files.put(entry.getName(), readAllBytes(zip.getInputStream(entry)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
zip.close();
files.forEach((name, data) -> {
if (isClassFileFormat(name, data)) {
ClassFileWriter classWriter = new ClassFileWriter(data);
ClassFile classFile = null;
try {
classFile = new ClassFile(new ClassFileStream(data), classWriter);
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("Processing " + name);
try {
classFile.parse_class();
} catch (IOException e) {
throw new RuntimeException(e);
}
byte[] buffer = classWriter.getByteArrayOutputStream().toByteArray();
files.put(name, buffer);
}
});
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("C:\\Users\\youki\\OneDrive\\Рабочий стол\\Новая папка (2)\\u.jar"));
zos.setLevel(9);
files.forEach((name, data) -> {
try {
zos.putNextEntry(new ZipEntry(name));
zos.write(data);
zos.closeEntry();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
zos.close();
}
private static boolean isClassFileFormat(String name, byte[] data) {
return data.length >= 8 && name.endsWith(".class");
}
private static byte[] readAllBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
inputStream.close();
return baos.toByteArray();
}
}
classFileParser:
Java:
package proguard.crypta;
import proguard.crypta.data.ConsPool;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import static proguard.crypta.data.ConsPool.*;
public class ClassFile {
private ConsPool consPool;
private Map<Integer, Object> pool;
private ClassFileStream classStream;
private final ClassFileWriter classWriter;
private int superClass;
private int flag;
private int thisFileIndex;
public ClassFile(ClassFileStream classStream, final ClassFileWriter classWriter) throws IOException {
this.classStream = classStream;
this.classWriter = classWriter;
}
int magic;
public void parse_class() throws IOException {
magic = classStream.readInt();
System.out.println("Magic number: 0x" + Integer.toHexString(magic).toUpperCase());
int minor = classStream.readShort();
System.out.println("Minor version: " + minor);
int major = classStream.readShort();
System.out.println("Major version: " + major);
classWriter.write(magic);
classWriter.writeShort(minor);
classWriter.writeShort(major);
if (magic != JAVA_CLASSFILE_MAGIC) {
throw new RuntimeException("Invalid magic number " + Integer.toHexString(magic).toUpperCase());
}
final int conspool = classStream.readUnsignedShort();
System.out.println("Constant pool count: " + conspool);
classWriter.writeShort(conspool);
this.parserConstantPool(conspool);
this.flag = classStream.readShort();
this.thisFileIndex = classStream.readUnsignedShort();
this.superClass = classStream.readShort();
System.out.println("Access flags: " + flag);
System.out.println("This class index: " + thisFileIndex);
System.out.println("Super class index: " + superClass);
classWriter.writeShort(this.flag);
classWriter.writeShort(this.thisFileIndex);
classWriter.writeShort(this.superClass);
this.parser_interface();
this.parser_fields();
this.parser_method();
this.parse_class_file_attribute();
}
private void parserConstantPool(final int length) throws IOException {
for (int i = 1; i < length; ++i) {
final int consttag = classStream.readByte();
System.out.println("Tag at index " + i + ": " + consttag);
classWriter.writeTag(consttag);
switch (consttag) {
case JVM_CONSTANT_Class:
case JVM_CONSTANT_String:
case JVM_CONSTANT_Module:
case JVM_CONSTANT_Package:
case JVM_CONSTANT_MethodType:
classWriter.writeShort(classStream.readShort());
break;
case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_Dynamic:
case JVM_CONSTANT_InvokeDynamic:
case JVM_CONSTANT_NameAndType:
classWriter.writeShort(classStream.readShort());
classWriter.writeShort(classStream.readShort());
break;
case JVM_CONSTANT_MethodHandle:
classWriter.writeByte(classStream.readByte());
classWriter.writeShort(classStream.readShort());
break;
case JVM_CONSTANT_Integer:
classWriter.write(classStream.readInt());
break;
case JVM_CONSTANT_Float:
classWriter.write(classStream.readFloat());
break;
case JVM_CONSTANT_Long:
classWriter.write(classStream.readLong());
++i;
break;
case JVM_CONSTANT_Double:
classWriter.write(classStream.readDouble());
++i;
break;
case JVM_CONSTANT_Utf8:
try {
String readUTF = classStream.readUTF();
System.out.println("UTF-8 at index " + i + ": " + readUTF);
utf(readUTF);
} catch (IOException e) {
System.err.println("Failed to read UTF-8 at index " + i + ": " + e.getMessage());
throw e;
}
break;
default:
classStream.skip(1);
classWriter.writeByte(0);
}
}
}
private void parser_interface() throws IOException {
int interfacesCount = classStream.readUnsignedShort();
classWriter.writeShort(interfacesCount);
for (int i = 0; i < interfacesCount; i++) {
int interfaceIndex = classStream.readUnsignedShort();
classWriter.writeShort(interfaceIndex);
}
}
private void parser_fields() throws IOException {
int fieldsCount = classStream.readUnsignedShort();
classWriter.writeShort(fieldsCount);
for (int i = 0; i < fieldsCount; i++) {
int accessFlags = classStream.readUnsignedShort();
int nameIndex = classStream.readUnsignedShort();
int descriptorIndex = classStream.readUnsignedShort();
int attributesCount = classStream.readUnsignedShort();
classWriter.writeShort(accessFlags);
classWriter.writeShort(nameIndex);
classWriter.writeShort(descriptorIndex);
classWriter.writeShort(attributesCount);
for (int j = 0; j < attributesCount; j++) {
int attributeNameIndex = classStream.readUnsignedShort();
int attributeLength = classStream.readInt();
byte[] attributeData = classStream.read(attributeLength);
classWriter.writeShort(attributeNameIndex);
classWriter.write(attributeLength);
classWriter.writebytes(attributeData);
}
}
}
private void parser_method() throws IOException {
int methodsCount = classStream.readUnsignedShort();
classWriter.writeShort(methodsCount);
for (int i = 0; i < methodsCount; i++) {
int accessFlags = classStream.readUnsignedShort();
int nameIndex = classStream.readUnsignedShort();
int descriptorIndex = classStream.readUnsignedShort();
int attributesCount = classStream.readUnsignedShort();
classWriter.writeShort(accessFlags);
classWriter.writeShort(nameIndex);
classWriter.writeShort(descriptorIndex);
classWriter.writeShort(attributesCount);
for (int j = 0; j < attributesCount; j++) {
int attributeNameIndex = classStream.readUnsignedShort();
int attributeLength = classStream.readInt();
byte[] attributeData = classStream.read(attributeLength);
classWriter.writeShort(attributeNameIndex);
classWriter.write(attributeLength);
classWriter.writebytes(attributeData);
}
}
}
private void parse_class_file_attribute() throws IOException {
int attributesCount = classStream.readUnsignedShort();
classWriter.writeShort(attributesCount);
for (int i = 0; i < attributesCount; i++) {
int attributeNameIndex = classStream.readUnsignedShort();
int attributeLength = classStream.readInt();
byte[] attributeData = classStream.read(attributeLength);
classWriter.writeShort(attributeNameIndex);
classWriter.write(attributeLength);
classWriter.writebytes(attributeData);
}
}
public String getUtf8(int index) {
Object value = pool.get(index);
if (value instanceof String) {
return ((String) value);
}
throw new IllegalArgumentException("No UTF-8 string at index " + index);
}
public void utf(String string) throws IOException {
byte[] data = string.getBytes(StandardCharsets.UTF_8);
String zovKey = "zov 1337";
byte[] bytes = zovKey.getBytes();
int key1 = 0x05;
int key2 = 0x39;
int obfuscator = 0xAB;
magic = (bytes[0] ^ key1) ^ obfuscator;
if ((magic) == 0) {
System.out.println("Magic numbers corrupted!");
throw new SecurityException("Tampering detected");
}
for (int i = 0; i < data.length; i++) {
data[i] += 5 ^ bytes.length;
}
this.classWriter.writeShort(data.length);
this.classWriter.writebytes(data);
}
}
classStream:
Java:
package proguard.crypta;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class ClassFileStream {
private ByteArrayOutputStream stream;
private DataOutputStream writer;
private byte[] inputData; // Store the original input data
private ByteArrayInputStream inputStream;
private DataInputStream reader;
public ClassFileStream(byte[] buf) {
this.reader = new DataInputStream(new ByteArrayInputStream(buf));
}
public int readByte() throws IOException {
return reader.read();
}
public int readShort() throws IOException {
return this.reader.readShort();
}
public int readInt() throws IOException {
return this.reader.readInt();
}
public long readLong() throws IOException {
return this.reader.readLong();
}
public float readFloat() throws IOException {
return this.reader.readFloat();
}
public double readDouble() throws IOException {
return this.reader.readDouble();
}
public String readUTF() throws IOException {
final byte[] array = new byte[this.reader.readUnsignedShort()];
this.reader.readFully(array);
return new String(array, StandardCharsets.UTF_8);
}
public DataInputStream getReader() {
return reader;
}
public int available() throws IOException {
return reader.available();
}
// Чтение заданного количества байтов в массив
public void readFully(byte[] buffer) throws IOException {
reader.readFully(buffer);
}
public void initializeConstantPool(final int init) throws IOException {
reader.read();
}
public void writeByte(final int b) throws IOException {
this.writer.write(b);
}
public void writeTag(int b) throws IOException {
this.writer.writeByte(b);
}
public void writeShort(final int v) throws IOException {
this.writer.writeShort(v);
}
public int readUnsignedShort() throws IOException {
return reader.readUnsignedShort();
}
public void write(final int v) throws IOException {
this.writer.writeInt(v);
}
public void write(final long v) throws IOException {
this.writer.writeLong(v);
}
public void write(final float v) throws IOException {
this.writer.writeFloat(v);
}
public void write(final double v) throws IOException {
this.writer.writeDouble(v);
}
public void utf(String string) throws IOException {
byte[] data = string.getBytes(StandardCharsets.UTF_8);
int xor_key = 0x78D;
for (int i = 0; i < data.length; i++) {
data[i] += 5;
}
this.writer.writeShort(data.length);
this.writer.write(data);
}
public void writeclass(ClassFileWriter classWriter) throws IOException {
writer.write(classWriter.getByteArrayOutputStream().toByteArray());
}
public void writebytes(byte[] bytes) throws IOException {
writer.write(bytes);
}
public void writebytes(byte[] bytes, int i, int is) throws IOException {
writer.write(bytes, i, is);
}
public ByteArrayOutputStream getByteArrayOutputStream() {
return this.stream;
}
public void skip(int n) throws IOException {
reader.skip(n);
}
public byte[] read(int length) throws IOException {
byte[] bytes = new byte[length];
reader.read(bytes);
return bytes;
}
}
classWriteFile:
Java:
package proguard.crypta;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class ClassFileWriter {
private final ByteArrayOutputStream stream;
private final DataOutputStream writer;
private final byte[] inputData; // Store the original input data
private ByteArrayInputStream inputStream;
private DataInputStream reader;
public ClassFileWriter(byte[] inputData) {
this.stream = new ByteArrayOutputStream();
this.writer = new DataOutputStream(stream);
this.inputData = inputData; // Initialize with input data
this.inputStream = new ByteArrayInputStream(inputData);
this.reader = new DataInputStream(inputStream);
}
public void writeByte(final int b) throws IOException {
this.writer.write(b);
}
public void writeTag(int b) throws IOException {
this.writer.writeByte(b);
}
public void writeShort(final int v) throws IOException {
this.writer.writeShort(v);
}
public int readShort() throws IOException {
return reader.readShort();
}
public int readInt() throws IOException {
return reader.readInt();
}
public int readUnsignedShort() throws IOException {
return reader.readUnsignedShort();
}
public void write(final int v) throws IOException {
this.writer.writeInt(v);
}
public void write(final long v) throws IOException {
this.writer.writeLong(v);
}
public void write(final float v) throws IOException {
this.writer.writeFloat(v);
}
public void write(final double v) throws IOException {
this.writer.writeDouble(v);
}
public void writeclass(ClassFileWriter classWriter) throws IOException {
writer.write(classWriter.getByteArrayOutputStream().toByteArray());
}
public void writebytes(byte[] bytes) throws IOException {
writer.write(bytes);
}
public void writebytes(byte[] bytes, int i, int is) throws IOException {
writer.write(bytes, i, is);
}
public ByteArrayOutputStream getByteArrayOutputStream() {
return this.stream;
}
public void skip(int n) throws IOException {
reader.skip(n);
}
public byte[] read(int length) throws IOException {
byte[] bytes = new byte[length];
reader.read(bytes);
return bytes;
}
public float readFloat() throws IOException {
return reader.readFloat();
}
public double readDouble() throws IOException {
return reader.readDouble();
}
public long readLong() throws IOException {
return reader.readLong();
}
}
прошу не пинать, как по мне это сильно улучшеная тема от сертио