[原创]记一次基于unidbg模拟执行的去除ollvm混淆 | 宜武汇-ag真人国际厅网站

//保存指令和寄存器环境类:

    class insandctx

    {

        long addr;

        instruction ins;

        list regs;

 

        public long getaddr() {

            return addr;

        }

 

            this.addr = addr;

        }

 

        public void setins(instruction ins) {

            this.ins = ins;

        }

 

        public instruction getins() {

            return ins;

        }

 

        public void setregs(list regs) {

            this.regs = regs;

        }

 

        public list getregs() {

            return regs;

        }

    }

 

//patch类

    class patchins{

        long addr;//patch 地址

        string ins;//patch的指令

 

        public long getaddr() {

            return addr;

        }

 

            this.addr = addr;

        }

 

        public string getins() {

            return ins;

        }

 

            this.ins = ins;

        }

    }

 

 // 指令栈

  private  stack instructions;

 

  //所有需要patch的指令

  private list patchs;

 

  //保存指令寄存器环境

   public list saveregs(backend bk)

    {

       list nb = new arraylist<>();

       for(int i=0;i<29;i )

       {

            nb.add(bk.reg_read(i arm64const.uc_arm64_reg_x0));

       }

       nb.add(bk.reg_read(arm64const.uc_arm64_reg_fp));

       nb.add(bk.reg_read(arm64const.uc_arm64_reg_lr));

       return nb;

    }

 

 

  //指令hook,每条指令执行前保存环境

     public void processbr()

    {

        emulator.getbackend().hook_add_new(new codehook() {

            @override

            public void hook(backend backend, long address, int size, object user) {

                capstone capstone = new capstone(capstone.cs_arch_arm64,capstone.cs_mode_arm);

                byte[] bytes = emulator.getbackend().mem_read(address, 4);

                instruction[] disasm = capstone.disasm(bytes, 0);

                insandctx iac = new insandctx();

                iac.setins(disasm[0]);

                iac.setregs(saveregs(backend));

                iac.setaddr(address);

                instructions.push(iac);

                do_processbr();

            }

 

            @override

            public void onattach(unhook unhook) {

                system.out.println("attach");

            }

 

            @override

            public void detach() {

                system.out.println("detach");

            }

        },module.base start, module.base end,null);

    }

 

    //指令栈回溯,根据处理结果,生成patchins,供最后统一patch

        public void do_processbr()

    {

        instruction ins = instructions.peek().getins();

        if(ins.getmnemonic().equals("br") && ins.getopstr().equals("x9"))

        {

            boolean finish = false;

            long base = -1;

            long listoffset = -1;

            long cond1 = -1;

            long cond2 = -1;

            string cond = "";

            long addinstaddr = -1;

            long brinsaddr = instructions.peek().getaddr() - module.base;

            long selectaddr = -1;

            long ldaaddr = -1;

 

            try {

                while (!finish && !instructions.empty())

                {

                    instructions.pop();

                    ins = instructions.peek().getins();

                    if(ins.getmnemonic().tolowercase(locale.root).equals("add"))

                    {

                        string[] split = ins.getopstr().split(",");

                        if(split.length == 3)

                        {

                            if(split[0].tolowercase(locale.root).trim().equals("x9") && split[1].tolowercase(locale.root).trim().equals("x9"))

                            {

                                string reg = split[2].trim().tolowercase(locale.root);

                                base = getregvalue(reg,instructions.peek().getregs()).longvalue();

                                addinstaddr = instructions.peek().getaddr() - module.base;

                            }

                            else {

                                break;

                            }

                        }

                        else

                        {

                            break;

                        }

                    }

 

                    if(ins.getmnemonic().tolowercase(locale.root).equals("ldr"))

                    {

                        string[] sp = ins.getopstr().tolowercase().split(",");

                        if(sp.length == 3)

                        {

                            if(sp[0].trim().tolowercase(locale.root).equals("x9") && sp[2].trim().tolowercase(locale.root).equals("x9]"))

                            {

                                string reg = sp[1].tolowercase(locale.root).trim().substring(1);

                                listoffset = getregvalue(reg,instructions.peek().getregs()).longvalue()-module.base;

                                ldaaddr =  instructions.peek().getaddr()- module.base;

                            }

                        }

                    }

 

                    if(ins.getmnemonic().trim().tolowercase(locale.root).equals("csel"))

                    {

                        string[] sp = ins.getopstr().tolowercase(locale.root).split(",");

                        if(sp.length == 4)

                        {

                            cond = sp[3].trim();

                            if(sp[0].trim().equals("x9"))

                            {

                                string reg1 = sp[1].trim();

                                string reg2 = sp[2].trim();

                                cond1 = getregvalue(reg1,instructions.peek().getregs()).longvalue();

                                cond2 = getregvalue(reg2,instructions.peek().getregs()).longvalue();

                                selectaddr = instructions.peek().getaddr() - module.base;

                            }

                        }

                    }

 

                    if(ins.getmnemonic().trim().tolowercase(locale.root).equals("cmp"))

                    {

                        if(base == -1 || listoffset == -1 || cond1 == -1 || cond2 == -1 || cond.equals("") || addinstaddr == -1 || ldaaddr == -1 || selectaddr == -1)

                        {

                            break;

                        }

                        else

                        {

                            long offset1 = base readint64(emulator.getbackend(), module.base listoffset cond1) - module.base;

                            long offset2 = base readint64(emulator.getbackend(),module.base listoffset cond2) - module.base;

                            if( brinsaddr - addinstaddr != 4)

                            {

                                system.out.println("add ins and br ins gap more than 4 size,may make mistake");

                            }

                            string condbr = "b" cond.tolowercase(locale.root) " 0x" integer.tohexstring((int) (offset1 - addinstaddr));

                            string br = "b 0x" integer.tohexstring((int)(offset2 - brinsaddr));

                            patchins pi1 = new patchins();

                            pi1.setaddr(addinstaddr);

                            pi1.setins(condbr);

                            patchs.add(pi1);

                            patchins pi2 = new patchins();

                            pi2.setaddr(brinsaddr);

                            pi2.setins(br);

                            patchs.add(pi2);

                            patchins pi3 = new patchins();

                            pi3.setaddr(selectaddr);

                            pi3.setins("nop");

                            patchs.add(pi3);

                            patchins pi4 = new patchins();

                            pi4.setaddr(ldaaddr);

                            pi4.setins("nop");

                            patchs.add(pi4);

                            finish = true;

                        }

                    }

                }

            }catch (exception e)

            {

                e.printstacktrace();

            }

        }

    }

 

//遍历patch表,执行patch,生成新的so,使用ketstone将汇编转为机器码。

public void patch()

    {

        try {

            file f = new file(inname);

            fileinputstream fis = new fileinputstream(f);

            byte[] data = new byte[(int) f.length()];

            fis.read(data);

            fis.close();

            for(patchins pi:patchs)

            {

                system.out.println("procrss addr:" integer.tohexstring((int) pi.addr) ",code:" pi.getins());

                keystone ks = new keystone(keystonearchitecture.arm64, keystonemode.littleendian);

                keystoneencoded assemble = ks.assemble(pi.getins());

                for(int i=0;i )

                {

                    data[(int) pi.addr i] = assemble.getmachinecode()[i];

                }

            }

            file fo = new file(outname);

            fileoutputstream fos = new fileoutputstream(fo);

            fos.write(data);

            fos.flush();

            fos.close();

            system.out.println("finish");

        }

        catch (exception e)

        {

            e.printstacktrace();

        }

    }

原文链接:https://bbs.kanxue.com/thread-277086.htm

网络摘文,本文作者:15h,如若转载,请注明出处:https://www.15cov.cn/2023/08/27/原创记一次基于unidbg模拟执行的去除ollvm混淆/

发表评论

邮箱地址不会被公开。 必填项已用*标注

网站地图