[原创]记一次基于unidbg模拟执行的去除ollvm混淆
2023-5-4 18:35:0 Author: bbs.pediy.com(查看原文) 阅读量:11 收藏

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

    class InsAndCtx

    {

        long addr;

        Instruction ins;

        List<Number> regs;

        public long getAddr() {

            return addr;

        }

        public void setAddr(long addr) {

            this.addr = addr;

        }

        public void setIns(Instruction ins) {

            this.ins = ins;

        }

        public Instruction getIns() {

            return ins;

        }

        public void setRegs(List<Number> regs) {

            this.regs = regs;

        }

        public List<Number> getRegs() {

            return regs;

        }

    }

//patch类

    class PatchIns{

        long addr;//patch 地址

        String ins;//patch的指令

        public long getAddr() {

            return addr;

        }

        public void setAddr(long addr) {

            this.addr = addr;

        }

        public String getIns() {

            return ins;

        }

        public void setIns(String ins) {

            this.ins = ins;

        }

    }

 // 指令栈

  private  Stack<InsAndCtx> instructions;

  //所有需要patch的指令

  private List<PatchIns> patchs;

  //保存指令寄存器环境

   public List<Number> saveRegs(Backend bk)

    {

       List<Number> 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<assemble.getMachineCode().length;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.pediy.com/thread-277086.htm
如有侵权请联系:admin#unsafe.sh