使用ASM直接修改字節(jié)碼Hacker

  • 直接修改字節(jié)碼,其實就是在很多問題上的降維打擊;在許多領域有著廣發(fā)應用,尤其是在AOP框架設計領域,它擁有著 反射調(diào)用 所無法比擬的性能優(yōu)勢;
  • ASM即為一種直接修改字節(jié)碼技術手段,它降低了開發(fā)者修改字節(jié)碼的技術門檻, 但是實際上依然需要開發(fā)者對Java Class文件有著比較深刻的理解;

此前因為工作關系,使用了ASM去破解一個Java程序的驗證,Hack也是直接修改字節(jié)碼技術手段的一個應用(當然, 這是很低級的Hack, 防范的方法也很多);

下面舉一個簡單的例子,表述一下Hacker的核心過程;
要hack的類為Person.class, 從這個代碼可以看出, 該方法的返回值應該永遠是false;

public class Person {

    private  boolean passAuth = false;
    
    public boolean validation() {
        if(passAuth) {
            System.out.println("pass auth");
        } else {
            System.out.println("fail auth");
        }
        return passAuth;
    }
}

下面開始hack ,使用ASM 篡改字節(jié)碼的過程;

  • 從原始字節(jié)碼, 修改為被偽造字節(jié)碼的整個過程;
        //讀取編譯ok的字節(jié)碼;
        Path p = Paths.get("F:\\src2020\\asmtest\\bin\\asmtest\\Person.class");
        ClassReader cr = new ClassReader(Files.newInputStream(p));
      //輸出字節(jié)碼的writer;
        ClassWriter cw = new ClassWriter(cr, Opcodes.ASM4);
      //構造一個責任鏈,ChangeClassAdapter是具體修改Class文件
        ClassVisitor cv = new ChangeClassAdapter(cw);
      //開始了鏈式調(diào)用,最后的結果會存在鏈條的最后一個,即cr;
        cr.accept(cv, 0);
      //輸出偽造后的字節(jié)碼
                byte[] data = cw.toByteArray();

下面是具體修改字節(jié)碼的核心類ChangeClassAdapter;

public class ChangeClassAdapter extends ClassVisitor {

    public ChangeClassAdapter(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
        // TODO Auto-generated constructor stub
    }
    
    public ChangeClassAdapter(ClassVisitor cv) {
        super(Opcodes.ASM4);
        this.cv = cv;
    }
    

    public ChangeClassAdapter(int asm7) {
        // TODO Auto-generated constructor stub
        super(asm7);
    }
    
    @Override
    public MethodVisitor visitMethod(
        int access,
        String name,
        String desc,
        String signature,
        String[] exceptions)
    {
        //這里mv實際最終拿到的是MethodWriter
        MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
        if (cv != null && "validation".equals(name)) {
            //validation方法重新構造
            mv.visitCode();
            mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            mv.visitLdcInsn("i am hacker");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
            mv.visitInsn(Opcodes.ICONST_1);
            mv.visitInsn(Opcodes.IRETURN);
            mv.visitMaxs(2, 1);
            mv.visitEnd();
            //注意這里的返回值;只有返回null,才意味著修改是生效的;具體可以看一下源碼,方法里直接有說明;
            return null;
        }
        return mv;
    }
}

將新的字節(jié)碼保存到本地,并用JAD反編譯出來看一下結果;

public class Person
{

    public Person()
    {
        correct = false;
    }

    public boolean validation()
    {
        //成功hacker
        System.out.println("i am hacker");
        return true;
    }

    private boolean correct;
}

從ChangeClassAdapter 的例子可以看出, 對于復雜的邏輯修改,即使使用ASM,去在字節(jié)碼層面重寫代碼,依然是一件并不容易的事情;
個人經(jīng)驗是使用ASM 的ASMifier,生成一個參考的模板代碼;然后摘抄一些自己需要的部分;

  • 寫出自己期待的方法并編譯;
  • 用ASMifer生成構造該方法字節(jié)碼的樣板代碼;
  • 參考,摘抄自己需要的部分;
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 前言 很早之前就寫過面向切面的編程思想,主要學習了AOP的思想(參考:AOP簡介)以及使用 AspectJ 實現(xiàn)簡...
    Whyn閱讀 11,174評論 4 40
  • 1. 概述 AOP(面向切面編程)的概念現(xiàn)在已經(jīng)應用的非常廣泛了,下面是從百度百科上摘抄的一段解釋,比較淺顯易懂 ...
    lijiankun24閱讀 18,236評論 4 33
  • 簡述 本文內(nèi)容將介紹 Java 字節(jié)碼相關知識,以及如何通過 javaagent 技術加上 ASM 框架進行插樁。...
    毒死預言家的女巫閱讀 1,499評論 1 6
  • 最近進行組內(nèi)分享時選擇了這個Java字節(jié)碼處理這個主題,特此記錄下來。眾所周知,Java是一門運行在虛擬機上的語言...
    sheepm閱讀 16,684評論 1 71
  • 第一步:將下載的sra格式的數(shù)據(jù)轉(zhuǎn)換成fastq格式的數(shù)據(jù)輸出到./project 這一部免費的云服務器就已經(jīng)扛不...
    陳宇喬閱讀 570評論 0 1

友情鏈接更多精彩內(nèi)容