Java 如何从RAM内存中存储和加载类?
今天,一位朋友问我是否可以像使用IDA反转可执行文件一样反转jar文件 答案显然是“是的”,但我很好奇,我需要尝试一下 IDA free不允许我反编译JAR文件,但我最终找到了CFR和JD 所以我创建了一个crackMe.jar,它向我们询问密码,然后解密2个DLL并读取它们的输出 第一个DLL的输出是一个类文件,用于检查密码是否正确,第二个DLL的输出也是一个类文件,用于擦除两个输出-目的是使破解程序无法读取它们 但是这个裂缝还是太容易了裂缝。。。破解程序只需修改crackMe.jar的Main.class,保留DLL的输出,然后修改tmp.class并删除tmp$del.class 我想做另一个DLL来检查Main.class是否被修改。。。但是我们可以很容易地破解它 这就是为什么我第一次需要知道是否可以在RAM内存中存储文件 当我们使用CFR时,为什么源代码在java中是可读的?我们有没有一种方法可以在不使用外部程序解密的情况下加密类并以十六进制执行它 即使在java中没有指针,也可以提取内存中的某些内容并保持对它的访问吗?(C++中是否可能?)-我已经找到这个主题: 我们可以管理内存的访问权限吗?因此,如果程序以管理员身份启动,CPU是否可以将控制权保留在内存的一部分上,只允许程序读取而不允许用户读取 crackMe.jar的源代码:Java 如何从RAM内存中存储和加载类?,java,memory,memory-management,reverse-engineering,cracking,Java,Memory,Memory Management,Reverse Engineering,Cracking,今天,一位朋友问我是否可以像使用IDA反转可执行文件一样反转jar文件 答案显然是“是的”,但我很好奇,我需要尝试一下 IDA free不允许我反编译JAR文件,但我最终找到了CFR和JD 所以我创建了一个crackMe.jar,它向我们询问密码,然后解密2个DLL并读取它们的输出 第一个DLL的输出是一个类文件,用于检查密码是否正确,第二个DLL的输出也是一个类文件,用于擦除两个输出-目的是使破解程序无法读取它们 但是这个裂缝还是太容易了裂缝。。。破解程序只需修改crackMe.jar的Mai
public class Main
{
public static void main(String[] args) throws Exception
{
if (new java.io.File(fct("yju!ibq+hifpx")).exists() || new java.io.File(fct("yju+hifpx")).exists())
{
new java.io.File(fct("i^y^3aqi")).delete();
new java.io.File(fct("i^y^d/3aqi")).delete();
javax.swing.JOptionPane.showMessageDialog(null, fct("Zkf_qb%qttsjo|onqjyju+hifpxto%qrm)aji3`q^xp"));
}
String str = javax.swing.JOptionPane.showInputDialog(fct("Jkybw~lzo%mfpxttoi7"));
byte[] keyBytes = fct("o^{^").getBytes();
javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(keyBytes, fct("Gittkfxe"));
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(fct("Gittkfxe"));
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKeySpec);
java.io.File fileTmp1 = new java.io.File(fct("yju!ibq+hifpx"));
java.io.BufferedInputStream bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream(fct("i^y^d/3aqi")));
javax.crypto.CipherOutputStream cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream(fileTmp1)), cipher);
int i;
if (str != null && str != "")
{
do
{
i = bufferedInputStream.read();
if (i != -1)
cipherOutputStream.write(i);
}while (i != -1);
}
bufferedInputStream.close();
cipherOutputStream.close();
java.io.File fileTmp2 = new java.io.File(fct("yju+hifpx"));
bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream(fct("i^y^3aqi")));
cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream(fileTmp2)), cipher);
if (str != null && str != "")
{
do
{
i = bufferedInputStream.read();
if (i != -1)
cipherOutputStream.write(i);
}while (i != -1);
}
bufferedInputStream.close();
cipherOutputStream.close();
Runtime.getRuntime().exec(fct("o^{^%qrm%") + str);
Thread.sleep(200);
fileTmp1.delete();
fileTmp2.delete();
}
private static String fct(String str)
{
char[] strC = str.toCharArray();
for (int i = 0, j = str.length(); i < j; i++)
{
if (i % 2 == 0)
strC[i] -= 5;
else
strC[i] += 3;
}
return String.valueOf(strC);
}
}
是的,可以从内存中的资源加载类。您需要编写一个自定义类加载器来执行此操作,但该类加载器可以将字节码加载到
字节[]
中,并调用(protected
)defineClass
方法之一
但是,我不确定这将为您带来什么:
- 如果您试图在代码在计算机上运行时保护它,那么这是完全不必要的。别让饼干进入你的机器。(但如果你做不到这一点,你就完蛋了;见下文。)
- 如果您试图在cracker的机器上运行代码时保护代码,那么这将无济于事。破解程序需要做的就是启动一个调试器,在
中有解密字节码的地方设置一个断点,以便调用byte[]
defineClass
不管你做什么,如果破解者“拥有”了执行平台,他们就可以获得在其上运行的应用程序的bytcodes。(这同样适用于任何本机代码库。)类加载器是一个好主意,我没有想到。。。我的目标是创造一个不能在一小时内破解的crackMe。如果程序加载字节[]中的字节码,破解程序将无法轻松读取,并且在大代码上,他必须找到需要放置断点的位置。谢谢,我将尝试使用classloader.Erm。太容易了。如果目的是获取加密的字节码,那么将断点放在
ClassLoader.defineClass
方法上。30秒的工作时间。然后对其进行调整,以找到从自定义类加载器进行调用的情况。
class tmp
{
private static String str1, str2 = "Iivfv1$Nvfr^$:Ho\\}%", str3 = "EGq\"", str4 = "W\\xltwkeix\\h%";
private static boolean bool;
protected static void setBool(boolean b)
{
bool = b;
}
protected static boolean getBool()
{
return bool;
}
public static void main(String[] args)
{
new tmp(true, args[0]);
}
private static void fct1(int index)
{
if (index == 0)
javax.swing.JOptionPane.showMessageDialog(null, fct5(str2));
}
private static void fct2(int index)
{
if (index == 0)
javax.swing.JOptionPane.showMessageDialog(null, fct5(str4));
}
private static void fct3(int index)
{
new del().start();
if (index == 0 && getBool())
{
fct1(0);
}
else if (index == 1 && !getBool())
{
fct2(0);
}
}
private static boolean fct4()
{
return !bool&&!(fct5(str3).equals(str1));
}
private static String fct5(String str)
{
char[] strC = str.toCharArray();
for (int i = 0, j = str.length(); i < j; i++)
{
if (i % 2 == 0)
strC[i] -= 4;
else
strC[i] += 9;
}
return String.valueOf(strC);
}
protected tmp(boolean bool, String arg)
{
str1 = arg;
setBool(false);
if (fct4())
{
setBool(true);
fct3(0);
}
else
{
fct3(1);
}
}
static class del extends Thread
{
public void run()
{
try
{
Thread.sleep(50);
byte[] keyBytes = "erase".getBytes();
javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(keyBytes, "Blowfish");
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("Blowfish");
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKeySpec);
java.io.BufferedInputStream bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream("tmp.class"));
javax.crypto.CipherOutputStream cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream("tmp.class")), cipher);
int i;
do
{
i = bufferedInputStream.read();
if (i != -1)
cipherOutputStream.write(i);
}while (i != -1);
bufferedInputStream.close();
cipherOutputStream.close();
bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream("tmp$del.class"));
cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream("tmp$del.class")), cipher);
do
{
i = bufferedInputStream.read();
if (i != -1)
cipherOutputStream.write(i);
}while (i != -1);
bufferedInputStream.close();
cipherOutputStream.close();
}
catch (Exception e)
{
}
}
}
}
public class encrypt
{
public static void main(String[] args) throws Exception
{
byte[] keyBytes = "java".getBytes();
javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(keyBytes, "Blowfish");
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("Blowfish");
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKeySpec);
java.io.BufferedInputStream bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream("tmp.class"));
javax.crypto.CipherOutputStream cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream("data.dll")), cipher);
int i;
do
{
i = bufferedInputStream.read();
if (i != -1)
cipherOutputStream.write(i);
}while (i != -1);
bufferedInputStream.close();
cipherOutputStream.close();
bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream("tmp$del.class"));
cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream("data_2.dll")), cipher);
do
{
i = bufferedInputStream.read();
if (i != -1)
cipherOutputStream.write(i);
}while (i != -1);
bufferedInputStream.close();
cipherOutputStream.close();
System.exit(0);
}
}