java文件运行原理
注意:OpenRASP是启动前加载的,所以所有的类模块加载都是在启动前就已经换成自己想要的字节码了,每当调用关注类时,就不会调用原来的代码,而是调用编写好的代码强化的代码模块
在一个测试jar包执行前,提前执行编写好的permain函数,将原本的测试jar的字节码,替换成自己想要的字节码,然后再放回去,JVM只执行我修改好的class文件,转义后,这个代码就拥有自我监控和拦截功能,就达成了无入侵自我保护。
先说说相同点
这两个技术都是java字节码修改技术,都可以对未加入JVM的class文件,进行修改。
不同之处
ASM主要是通过字节码进行修改,而javassist是通过java代码进行修改的
直接看下他们之间代码,就懂了
同一份java代码,看下他们二者的区别
// 修改前
public void test(String args) {
System.out.println("rasp Test,正常通过!!");
}
// 修改后
public void test(String var1) {
SqlFilter var3 = new SqlFilter();
if (var3.filter(var1)) {
throw new SQLException("invalid sql because of security check");
} else {
System.out.println("rasp Test,正常通过!!");
}
}
// 添加部分
SqlFilter var3 = new SqlFilter();
if (var3.filter(var1)) {
throw new SQLException("invalid sql because of security check");
} else {
// 原本代码 XXXX
}
看下ASM进行插桩
mv.visitTypeInsn(NEW,"com/wu/javaagent01/filter/SqlFilter");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL,"com/wu/javaagent01/filter/SqlFilter","" ,"()V",false);
mv.visitVarInsn(ASTORE,3);
mv.visitVarInsn(ALOAD,3);
mv.visitVarInsn(ALOAD,1);
mv.visitMethodInsn(INVOKEVIRTUAL,"com/wu/javaagent01/filter/SqlFilter", "filter","(Ljava/lang/Object;)Z",false);
mv.visitJumpInsn(IFEQ, l92);
mv.visitTypeInsn(NEW, "java/sql/SQLException");
mv.visitInsn(DUP);
mv.visitLdcInsn("invalid sql because of security check");
mv.visitMethodInsn(INVOKESPECIAL, "java/sql/SQLException", "" , "(Ljava/lang/String;)V", false);
mv.visitInsn(ATHROW);
mv.visitLabel(l92);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
再看看javassist对这个代码如何插桩的
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.get("YourClassName"); // 替换成你的类名
CtMethod ctMethod = ctClass.getDeclaredMethod("checkListFiles");
CtClass exceptionClass = classPool.get("java.sql.SQLException");
// 创建异常抛出代码块
CtConstructor exceptionConstructor = exceptionClass.getDeclaredConstructor(new CtClass[] { classPool.get("java.lang.String") });
CtConstructor ctConstructor = ctClass.getClassInitializer();
ctConstructor.insertAfter("{" +
"if (condition) {" +
" try {" +
" throw new java.sql.SQLException(\"invalid sql because of security check\");" +
" } catch (java.sql.SQLException e) {" +
" e.printStackTrace();" +
" }" +
"}");
// 保存修改后的字节码
ctClass.writeFile();
} catch (Exception e) {
e.printStackTrace();
}