Example #1
0
def get_profile_args(args, location_base):
    """Handle all the profile file options."""
    if args.profile_file is None and len(args.profile_line) == 0:
        return []
    if args.profile_file:
        with open(args.profile_file, "rb") as prof:
            prof_magic = prof.read(4)
            if prof_magic == b'pro\0':
                # Looks like the profile-file is a binary profile. Just use it directly
                return ['--profile-file={}'.format(args.profile_file)]
    if args.debug_profman:
        profman_args = ["lldb-server", "g", ":5039", "--", args.profman]
    else:
        profman_args = [args.profman]
    if args.save_profile:
        prof_out_fd = args.save_profile.fileno()
        os.set_inheritable(prof_out_fd, True)
    else:
        prof_out_fd = os.memfd_create("reference_prof", flags=0)
    if args.debug_profman:
        profman_args.append("--reference-profile-file={}".format(
            fdfile(prof_out_fd)))
    else:
        profman_args.append(
            "--reference-profile-file-fd={}".format(prof_out_fd))
    if args.profile_file:
        profman_args.append("--create-profile-from={}".format(
            args.profile_file))
    else:
        prof_in_fd = os.memfd_create("input_prof", flags=0)
        # Why on earth does fdopen take control of the fd and not mention it in the docs.
        with os.fdopen(os.dup(prof_in_fd), "w") as prof_in:
            for l in args.profile_line:
                print(l, file=prof_in)
        profman_args.append("--create-profile-from={}".format(
            fdfile(prof_in_fd)))
    for f in args.dex_files:
        profman_args.append("--apk={}".format(f))
        profman_args.append("--dex-location={}".format(
            os.path.join(location_base, os.path.basename(f))))
    print("Running: {}".format(run_print(profman_args)))
    print("=START=======================================")
    subprocess.run(profman_args, close_fds=False).check_returncode()
    print("=END=========================================")
    if args.debug:
        return ["--profile-file={}".format(fdfile(prof_out_fd))]
    else:
        return ["--profile-file={}".format(fdfile(prof_out_fd))]
Example #2
0
def main():
    args, extra = parse_args()
    if args.arch == "host32" or args.arch == "host64":
        location_base = os.path.expandvars("${ANDROID_HOST_OUT}/framework/")
        real_arch = "x86" if args.arch == "host32" else "x86_64"
        boot_image = os.path.expandvars(
            "$ANDROID_HOST_OUT/apex/art_boot_images/javalib/boot.art")
        android_root = os.path.expandvars("$ANDROID_HOST_OUT")
        for f in args.dex_files:
            extra.append("--dex-location={}".format(
                os.path.join(location_base, os.path.basename(f))))
            extra.append("--dex-file={}".format(f))
    else:
        location_base = "/system/framework"
        real_arch = args.arch
        boot_image = os.path.expandvars(":".join([
            "${OUT}/apex/com.android.art.debug/javalib/boot.art",
            "${OUT}/system/framework/boot-framework.art"
        ]))
        android_root = os.path.expandvars("$OUT/system")
        for f in args.dex_files:
            extra.append("--dex-location={}".format(
                os.path.join(location_base, os.path.basename(f))))
            extra.append("--dex-file={}".format(f))
    extra += get_bcp_runtime_args(boot_image, args.arch)
    extra += get_profile_args(args, location_base)
    extra.append("--instruction-set={}".format(real_arch))
    extra.append("--boot-image={}".format(boot_image))
    extra.append("--android-root={}".format(android_root))
    extra += ["--runtime-arg", "-Xms64m", "--runtime-arg", "-Xmx512m"]
    if args.odex_file is not None:
        extra.append("--oat-file={}".format(args.odex_file))
    else:
        if args.debug:
            raise Exception("Debug requires a real output file. :(")
        extra.append("--oat-fd={}".format(os.memfd_create("odex_fd", flags=0)))
        extra.append("--oat-location={}".format("/tmp/odex_fd.odex"))
        extra.append("--output-vdex-fd={}".format(
            os.memfd_create("vdex_fd", flags=0)))
    pre_args = []
    if args.debug:
        pre_args = ["lldb-server", "g", ":5039", "--"]
    pre_args.append(args.dex2oat)
    print("Running: {}".format(run_print(pre_args + extra)))
    print("=START=======================================")
    subprocess.run(pre_args + extra, close_fds=False).check_returncode()
    print("=END=========================================")
Example #3
0
    def setUp(self) -> None:
        self._eicar_data = decodebytes(EICAR_DASE64)

        self._eicar_path = Path(__file__).parent.absolute() / '.eicar.com'
        with open(self._eicar_path, 'wb') as eicar_file:
            eicar_file.write(self._eicar_data)

        self._eicar_fileno = os.memfd_create('eicar')
        os.write(self._eicar_fileno, self._eicar_data)
        os.lseek(self._eicar_fileno, 0, 0)

        self._good_path = Path(__file__).parent.absolute() / '.good'
        with open(self._good_path, 'wb') as good_file:
            good_file.write(b'ClamAv cool antivirus')
Example #4
0
def _new_dl_linux(vardir):
    if hasattr(os, "memfd_create"):
        target = os.memfd_create("nle.so")
        path = "/proc/self/fd/%i" % target
        try:
            shutil.copyfile(DLPATH, path)  # Should use sendfile.
        except IOError:
            os.close(target)
            raise
        return os.fdopen(target), path

    # Otherwise, no memfd_create. Try with O_TMPFILE via the tempfile module.
    dl = tempfile.TemporaryFile(suffix="libnethack.so", dir=vardir)
    path = "/proc/self/fd/%i" % dl.fileno()
    shutil.copyfile(DLPATH, path)  # Should use sendfile.
    return dl, path
Example #5
0
def execAnonFile(args, wait_for_proc_terminate, c):
    s = ""
    for _ in range(7):
        s += random.choice(string.ascii_lowercase)

    fd = os.memfd_create(s, 0)
    if fd == -1:
        return ("Error in creating fd")
    else:
        with open("/proc/self/fd/{}".format(fd), 'wb') as f:
            f.write(c)

        child_pid = os.fork()
        if child_pid == -1:
            return ("Error executing the code")
        elif child_pid == 0:
            fname = "/proc/self/fd/{}".format(fd)
            args.insert(0, fname)
            os.execve(fname, args, dict(os.environ))
        else:
            if wait_for_proc_terminate:
                os.waitpid(child_pid, 0)
Example #6
0
def main():
    parser = get_parser()
    args = parser.parse_args()
    if args.output_source is None:
        fdnum = os.memfd_create("tempfile_profile")
        args.output_source = "/proc/{}/fd/{}".format(os.getpid(), fdnum)
    all_dexs = list()
    for f in args.apks:
        try:
            all_dexs.append(pylibdexfile.FileDexFile(f.file, f.location))
        except Exception as e1:
            try:
                all_dexs += pylibdexfile.OpenJar(f.file)
            except Exception as e2:
                parser.error(
                    "Failed to open file: {}. errors were {} and {}".format(
                        f.file, e1, e2))
    if args.input_profile is not None:
        profman_args = [
            "profmand", "--dump-classes-and-methods",
            "--profile-file={}".format(args.input_profile)
        ]
        for apk in args.apks:
            profman_args.append("--apk={}".format(apk.file))
        print(" ".join(map(shlex.quote, profman_args)))
        res = subprocess.run(profman_args,
                             capture_output=True,
                             universal_newlines=True)
        res.check_returncode()
        meth_list = list(filter(lambda a: a != "", res.stdout.split()))
    elif args.input_text_profile is not None:
        with open(args.input_text_profile, "rt") as inp:
            meth_list = list(filter(lambda a: a != "", inp.readlines()))
    else:
        all_methods = set()
        for d in all_dexs:
            for m in d.methods:
                all_methods.add(m.descriptor)
        meth_list = list(all_methods)
    print("Found {} methods. Will take ~{} iterations".format(
        len(meth_list), 1 + math.floor(math.log2(len(meth_list)))))
    print(
        "type 'yes' if the behavior you are looking for is present (i.e. the compiled code crashes "
        + "or something)")
    print("Performing single check with all methods")
    result = run_test(meth_list, args)
    if result[0].lower() != "y":
        cont = input(
            "The behavior you were looking for did not occur when run against all methods. Continue "
            + "(yes/no)? ")
        if cont[0].lower() != "y":
            print("Aborting!")
            sys.exit(1)
    needs_dump = False
    while len(meth_list) > 1:
        test_methods = list(meth_list[0:len(meth_list) // 2])
        result = run_test(test_methods, args)
        if result[0].lower() == "y":
            meth_list = test_methods
            needs_dump = False
        else:
            meth_list = meth_list[len(meth_list) // 2:]
            needs_dump = True
    if needs_dump:
        with open(args.output_source, "wt") as output:
            dump_files(meth_list, args, output)
    print("Found result!")
    print("{}".format(meth_list[0]))
    print("Leaving profile at {} and text profile at {}".format(
        args.output_file, args.output_source))
Example #7
0
def run(pov_path, target_path, *, flag=None, result=None):
    if result is None:
        result = {}

    if not flag:
        flag = os.urandom(4096)
    assert len(flag) == 4096
    flag_fd = os.memfd_create('flag')
    flag_path = f'/proc/{os.getpid()}/fd/{flag_fd}'
    os.write(flag_fd, flag)

    result['flag'] = flag.decode('latin')

    child_conn, parent_conn = multiprocessing.Pipe(duplex=True)

    def dup_child_3():
        os.dup2(child_conn.fileno(), 3, inheritable=True)

    pov_seed = str(int.from_bytes(os.urandom(3), 'little'))
    pov_popen = subprocess.Popen(
        ['qemu-cgc/i386-linux-user/qemu-i386', '-seed', pov_seed, pov_path],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.DEVNULL,
        pass_fds=(3, ),
        preexec_fn=dup_child_3)

    pov_type = b''.join(os.read(parent_conn.fileno(), 1) for _ in range(4))
    pov_type = int.from_bytes(pov_type, 'little')
    assert pov_type == 2
    os.write(parent_conn.fileno(), TYPE_2_DATA)

    def trace_me():
        libc.ptrace(PTRACE['TRACEME'], 0, 0, 0)

    target_seed = str(int.from_bytes(os.urandom(3), 'little'))
    target_popen = subprocess.Popen([
        'qemu-cgc/i386-linux-user/qemu-i386', '-magicpregen', flag_path,
        '-seed', target_seed, target_path
    ],
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.DEVNULL,
                                    preexec_fn=trace_me)

    result['interaction'] = []

    while True:
        pid, status = os.wait()

        if pid == target_popen.pid:
            sig = os.WSTOPSIG(status)
            if sig and sig != signal.SIGTRAP:
                result['signal'] = sig
                break
            if not os.WIFSTOPPED(status):
                break

        else:
            continue

        regs = user_regs_struct()
        libc.ptrace(PTRACE['GETREGS'], pid, 0, ctypes.byref(regs))

        syscall = SYSCALL_NAME[regs.orig_rax]
        syscall_start = ctypes.c_long(regs.rax).value == -errno.ENOSYS

        reading = SYSCALL_NAME[regs.orig_rax] == 'read' and regs.rdi == 0
        writing = SYSCALL_NAME[regs.orig_rax] == 'write' and regs.rdi == 1

        try:
            if reading and syscall_start:
                count = regs.rdx
                data = pov_popen.stdout.read1(
                    min(count, io.DEFAULT_BUFFER_SIZE))
                target_popen.stdin.write(data)
                target_popen.stdin.flush()
                result['interaction'].append(
                    ('read', count, data.decode('latin')))
                if not data:
                    break

            elif writing and not syscall_start:
                count = regs.rdx
                data = target_popen.stdout.read(count)
                pov_popen.stdin.write(data)
                pov_popen.stdin.flush()
                result['interaction'].append(
                    ('write', count, data.decode('latin')))

        except BrokenPipeError:
            break

        libc.ptrace(PTRACE['SYSCALL'], pid, 0, 0)

    pov_answer = b''.join(os.read(parent_conn.fileno(), 1) for _ in range(4))
    result['pov_answer'] = pov_answer.decode('latin')
    result['pov_answer_correct'] = pov_answer in flag