美文网首页
使用unidbg

使用unidbg

作者: 静析机言 | 来源:发表于2022-02-22 11:20 被阅读0次

    一、前言

    unidbg是一个基于unicorn的逆向工具,可黑盒调用移动app中的so文件,运行时不需要模拟器或真机。有时用真机调so文件难以过反调试,而unidbg可以弥补这块缺陷。当然了,unidbg也不是万能的,怎么给unidbg补环境也是个问题。

    二、步骤

    1. 首先要将java、maven、IDEA配置好。

    https://blog.csdn.net/pan_junbiao/article/details/104264644

    2. 下载unidbg项目

    https://github.com/zhkl0228/unidbg

    3. 导入到IDEA中

    unidbg项目是java编写的,上述下载的是一个标准maven项目。

    4. 测试unidbg

    项目中的测试用例:src/test/java/com/bytedance/frameworks/core/encrypt/TTEncrypt.java,直接执行其中的main方法,会出现下述的提示

    三、实例

    看雪2021 KCTF秋季赛第8题 群狼环伺为一道安卓逆向题

    https://ctf.pediy.com/game-season_fight-187.htm

    我们可以采用unidbg模拟执行,按照正常步骤运行时,会出现如下错误

    [14:10:36 669]  WARN[com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:530) -handleInterrupt intno=2, NR=190, svcNumber=0x0, PC=RX@0x40284b5c[libc.so]0x41b5c, LR=RX@0x402725cb[libc.so]0x2f5cb, syscall=null

    [14:10:36 670]  WARN[com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:530) -handleInterrupt intno=2, NR=358, svcNumber=0x0, PC=RX@0x40284db0[libc.so]0x41db0, LR=RX@0x40272635[libc.so]0x2f635, syscall=null

    顺着该错误信息往前倒,用ida在IntelliJIDEA v23版本arm版libc.so中定位到地址0x2f5cb和0x2f635,发现是在调用popen()是出现了错误。

    从下面的帖子,说这个报错较大可能性是样本在通过popen或者system执行命令

    https://github.com/zhkl0228/unidbg/issues/342

    事实上,Unidbg目前还不支持直接跑popen,需要手动处理一下,继承和使用自己的syscallHandler

    https://blog.csdn.net/qq_38851536/article/details/118073818

    下面贴出完整的运行该so的完整unidbg代码

    crackeme.java

    package com.vprotect;

    import com.github.unidbg.AndroidEmulator;

    import com.github.unidbg.Emulator;

    import com.github.unidbg.Module;

    import com.github.unidbg.arm.context.Arm32RegisterContext;

    import com.github.unidbg.file.linux.AndroidFileIO;

    import com.github.unidbg.hook.hookzz.*;

    import com.github.unidbg.linux.android.AndroidARMEmulator;

    import com.github.unidbg.linux.android.AndroidEmulatorBuilder;

    import com.github.unidbg.linux.android.AndroidResolver;

    import com.github.unidbg.linux.android.dvm.*;

    import com.github.unidbg.memory.Memory;

    import com.github.unidbg.memory.SvcMemory;

    import com.github.unidbg.unix.UnixSyscallHandler;

    import java.io.File;

    import java.io.FileNotFoundException;

    public class crackme extends AbstractJni {

        private final AndroidEmulator emulator;

        private final Module module;

        private final VM vm;

        private final DvmClass NativeClass;

        public crackme() throws FileNotFoundException {

            AndroidEmulatorBuilder builder = new AndroidEmulatorBuilder(false) {

                @Override

                public AndroidEmulator build() {

                    return new AndroidARMEmulator(processName, rootDir, backendFactories) {

                        @Override

                        protected UnixSyscallHandler<AndroidFileIO> createSyscallHandler(SvcMemory svcMemory) {

                            return new MyARMSyscallHandler(svcMemory);

                        }

                    };

                };

            };

            emulator = builder.setProcessName("com.vprotect").build();

            final Memory memory = emulator.getMemory();

            memory.setLibraryResolver(new AndroidResolver(23));

            vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/vprotect/KCTF2021-android-crackme.apk"));

            DalvikModule dm = vm.loadLibrary("crackme", true);

            module = dm.getModule();

            vm.setVerbose(true);

            vm.setJni(this);

            dm.callJNI_OnLoad(emulator);

            NativeClass = vm.resolveClass("www/vprotect/cn/crackme");

        }

        public static void main(String[] args) {

            crackme mainActivity = null;

            try {

                mainActivity = new crackme();

            } catch (FileNotFoundException e) {

                e.printStackTrace();

            }

            String ret = mainActivity.getGoodLuck();

            System.out.println("getGoodLuck函数返回:"+ret);

        }

        public String getGoodLuck(){

            String str1 = "4DD6F06301B04D13";

            String str2 = "6461323135643835663832623133666234313635636637383266613665363961";

            String str3 = "1234567";

            StringObject stringObject = NativeClass.newObject(null).callJniMethodObject(emulator, "GoodLuck(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", str1, str2, str3);

            return stringObject.getValue();

        }

    }

    MyARMSyscallHandler.java

    package com.vprotect;

    import com.github.unidbg.Emulator;

    import com.github.unidbg.arm.context.EditableArm32RegisterContext;

    import com.github.unidbg.linux.file.ByteArrayFileIO;

    import com.github.unidbg.linux.file.DumpFileIO;

    import com.github.unidbg.memory.SvcMemory;

    import com.sun.jna.Pointer;

    import java.util.concurrent.ThreadLocalRandom;

    public class MyARMSyscallHandlerextends com.github.unidbg.linux.ARM32SyscallHandler{

    public MyARMSyscallHandler(SvcMemory svcMemory) {

    super(svcMemory);

        }

    @Override

        protected boolean handleUnknownSyscall(Emulator emulator, int NR) {

    switch (NR) {

    case 190:

    vfork(emulator);

    return true;

                case 359:

    pipe2(emulator);

    return true;

            }

    return super.handleUnknownSyscall(emulator, NR);

        }

    private void vfork(Emulator emulator) {

    EditableArm32RegisterContext context = (EditableArm32RegisterContext) emulator.getContext();

            int childPid = emulator.getPid() + ThreadLocalRandom.current().nextInt(256);

            int r0 =0;

            r0 = childPid;

            System.out.println("vfork pid=" + r0);

            context.setR0(r0);

        }

    protected int pipe2(Emulator emulator) {

    EditableArm32RegisterContext context = (EditableArm32RegisterContext) emulator.getContext();

            Pointer pipefd = context.getPointerArg(0);

            int flags = context.getIntArg(1);

            int write = getMinFd();

            this.fdMap.put(write, new DumpFileIO(write));

            int read = getMinFd();

            String stdout ="myid\n"; // getprop ro.build.id

            this.fdMap.put(read, new ByteArrayFileIO(0, "pipe2_read_side", stdout.getBytes()));

            pipefd.setInt(0, read);

            pipefd.setInt(4, write);

            System.out.println("pipe2 pipefd=" + pipefd +", flags=0x" + flags +", read=" + read +", write=" + write +", stdout=" + stdout);

            context.setR0(0);

            return 1;

        }

    }

    最终返回“输入错误”

    相关文章

      网友评论

          本文标题:使用unidbg

          本文链接:https://www.haomeiwen.com/subject/axqglrtx.html