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))]
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=========================================")
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')
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
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)
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))
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