def init(self, **kwargs): from pandare import Panda arch = self.avatar.arch.qemu_name args = self.assemble_cmd_line()[1:] self.avatar.save_config(file_name=self.qemu_config_file, config=self.generate_qemu_config()) self.pypanda = Panda(arch=arch, extra_args=args, **kwargs) # adjust panda's signal handler to avatar2-standard def SigHandler(SIG, a, b): if self.state == TargetStates.RUNNING: self.stop() self.wait() self.avatar.sigint_handler() self.pypanda._setup_internal_signal_handler(signal_handler=SigHandler) self._thread = Thread(target=self.pypanda.run, daemon=True) self._thread.start() self._connect_protocols()
#!/usr/bin/env python3 ''' TODO: We don't currently have a way to unset the breakpoint so you get stuck there :( ''' from sys import argv from pandare import Panda, blocking, ffi panda = Panda(generic="i386", extra_args=["-s", "-S"]) @blocking def run_cmd(): panda.revert_sync("root") print(panda.run_serial_cmd("uname -a")) panda.end_analysis() @panda.cb_asid_changed() def asidchange(env, old_asid, new_asid): ''' On ASID change, print and enable next_bb_break fn ''' if old_asid != new_asid: print("Asid changed from %d to %d. Triggering breakpoint..." % (old_asid, new_asid)) panda.enable_callback("next_bb_break") return 0 @panda.cb_before_block_exec_invalidate_opt(enabled=False)
#!/usr/bin/env python3 # Demonstartion of using PANDA to run shellcode. Example modified from Unicorn Engine # https://github.com/unicorn-engine/unicorn/blob/master/bindings/python/sample_arm.py import capstone import os from pandare import Panda X86_CODE = b"\x40\x01\xC3\x41" # inc eax; add ebx, eax; inc ecx; ADDRESS = 0x1000 stop_addr = ADDRESS + len(X86_CODE) # Create a machine of type 'configurable' but with just a CPU specified (no peripherals or memory maps) panda = Panda("i386", extra_args=["-M", "configurable", "-nographic"]) @panda.cb_after_machine_init def setup(cpu): ''' After our CPU has been created, allocate memory and set starting state ''' # map 2MB memory for this emulation panda.map_memory("mymem", 2 * 1024 * 1024, ADDRESS) # Write code into memory panda.physical_memory_write(ADDRESS, X86_CODE) # Set up registers panda.arch.set_reg(cpu, "EAX", 0x1) panda.arch.set_reg(cpu, "EBX", 0x2)
print("Saw PASSWD - switch modes") self.set_mode("mode2") @self.panda.ppp("syscalls2", "on_sys_open_enter") @self.mode_filter("mode2") def on_open2(cpu, pc, fname_ptr, flags, mode): assert self.mode == "mode2" try: fname = self.panda.read_str(cpu, fname_ptr) except ValueError: return if fname == "/proc/cpuinfo": print("SAW CPUINFO - switch modes") self.set_mode("end") # End PANDA-decorated functions in init def run_guest(self): ''' Run guest ''' self.panda.run() if __name__ == "__main__": panda = Panda(generic="i386") test = Tester(panda) test.run_guest()
#!/usr/bin/env python3 from pandare import Panda, blocking, ffi panda = Panda(generic="x86_64") panda.load_plugin("syscalls2") panda.load_plugin("osi") @panda.ppp("syscalls2", "on_sys_read_return") def on_sys_read_return(cpu, pc, fd, buf, count): proc = panda.plugins['osi'].get_current_process(cpu) procname = ffi.string(proc.name) if proc != ffi.NULL else "error" fname_ptr = panda.plugins['osi_linux'].osi_linux_fd_to_filename(cpu, proc, fd) fname = ffi.string(fname_ptr) if fname_ptr != ffi.NULL else "error" rc = panda.plugins['syscalls2'].get_syscall_retval(cpu) print(f"[PANDA] {procname} read {rc} bytes from {fname}") @panda.ppp("syscalls2", "on_sys_execve_enter") def on_sys_execve_enter(cpu, pc, fname_ptr, argv_ptr, envp): # Log commands and arguments passed to execve unless in kernel if panda.in_kernel(cpu): return try: fname = panda.read_str(cpu, fname_ptr) argv_ptrlist = panda.virtual_memory_read(cpu, argv_ptr, 100, fmt='ptrlist') except ValueError: return argv = [] for ptr in argv_ptrlist: if ptr == 0: break try: argv.append(panda.read_str(cpu, ptr))
Retrieve ioctl that completed normally ''' return self._get_returns(self._unmodified_returns, with_buf_only) if __name__ == "__main__": ''' Bash will issue ioctls on /dev/ttys0 - this is just a simple test to make sure they're being captured ''' from pandare import blocking, Panda # No arguments, i386. Otherwise argument should be guest arch generic_type = sys.argv[1] if len(sys.argv) > 1 else "i386" panda = Panda(generic=generic_type) def print_list_elems(l): if not l: print("None") else: for e in l: print(e) @blocking def run_cmd(): # Setup faker ioctl_faker = IoctlFaker(panda, use_osi_linux=True)
''' volatility pslist two ways. By: Luke Craig ''' from pandare import Panda, blocking from sys import argv from time import time from volatility.framework.objects import utility arch = "x86_64" if len(argv) <= 1 else argv[1] extra = "-nographic -chardev socket,id=monitor,path=./monitor.sock,server,nowait -monitor chardev:monitor -serial telnet:127.0.0.1:4444,server,nowait" qcow = "/home/luke/workspace/qcows/instance-1.qcow2" panda = Panda(arch=arch, qcow=qcow, extra_args=extra, mem="1G") timechange = 5 oldtime, oldtime2 = time(), time() ''' In on_asid_change we use the fast method. It gives us back the volatility symbols and we "become" the volatility plugin. The reason this is fast is because we clear the cache between runs so we don't have to reconstruct the whole plugin again. This way we only have to run the 10+ second startup once. ''' @panda.cb_asid_changed() def on_asid_change(env, old_asid, new_asid): global oldtime if time() - oldtime > timechange: vmlinux = panda.get_volatility_symbols(debug=True) init_task = vmlinux.object_from_symbol(symbol_name="init_task")
cmd = "cd copydir/install/libxml2/.libs && LD_LIBRARY_PATH=~/copydir/install/libxml2/.libs ./xmllint ~/copydir/" + basename( inputfile) panda.type_serial_cmd(cmd) print(f"Beginning recording: {replayname}") panda.run_monitor_cmd( "begin_record {}".format(replayname)) # Begin recording result = panda.finish_serial_cmd() panda.run_monitor_cmd("end_record") print(f"Ran command `{cmd}`") print(f"Result: {result}") panda.end_analysis() panda = Panda(arch="x86_64", expect_prompt=rb"root@ubuntu:.*#", qcow=qcf, mem="1G", extra_args="-display none -nographic") panda.queue_async(record_cmds) panda.run() with open("/replay/run.log", "w") as ml: for fn in glob.glob("%s-rr-*" % replayname): ml.write("chmod %s\n" % fn) os.chmod(fn, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH)
thisdir = os.path.dirname(os.path.realpath(__file__)) os.system("mkdir -p " + os.path.join(thisdir,"cdrom")) os.system("cd ../../taint_unit_test; export TARGET=\"TARGET_X86_64\" && make; cp bin/* " + os.path.join(thisdir,"cdrom") + "; cd ../tests/taint2; cp run_all_tests.sh " + os.path.join(thisdir,"cdrom") + ";") def host_download_qcow(): if not os.path.isfile(HOST_QCOW_PATH): print("\nDownloading \'{}\'...".format(QCOW)) wget.download(QCOW_URL) assert(os.path.isfile(HOST_QCOW_PATH)) @blocking def run_in_guest(): panda.revert_sync("root") panda.copy_to_guest(os.path.join(thisdir,"cdrom")) panda.load_plugin("taint2") panda.run_serial_cmd("./cdrom/turn_on_taint; ./cdrom/run_all_tests.sh") panda.stop_run() if __name__ == "__main__": host_download_qcow() panda = Panda( arch = "x86_64", qcow = HOST_QCOW_PATH, extra_args = "-nographic", expect_prompt = rb"root@ubuntu:.*", mem = "1G" ) panda.queue_async(run_in_guest) panda.run()
from pandare import Panda panda = Panda(generic="mips") @panda.queue_blocking def driver(): panda.revert_sync("root") print(panda.run_serial_cmd("whoami")) panda.end_analysis() @panda.ppp("forcedexec", "on_branch") def on_branch(cpu, tb, idx): # Let's flip every branch in blocks with start PCs divisible by 0x30 print("Branch at", hex(tb.pc)) if (tb.pc % 0x30 == 0): print("FLIP IT") return True return False panda.run()
#!/usr/bin/env python3 ''' example_win.py This is an example for taking a recording of windows and then replaying it and using it to do analysis. ''' from pandare import Panda rec = False if rec: panda = Panda(qcow="win7pro_x86.qcow2",mem="4G", extra_args=["-vnc", "127.0.0.1:5900", "-monitor","telnet:127.0.0.1:55555,server,nowait"]) else: panda = Panda(qcow="win7pro_x86.qcow2",mem="4G", extra_args=["-nographic"],os_version="windows-32-7sp1") first = True @panda.cb_asid_changed def asidchange(cpu, old_asid, new_asid): if old_asid != new_asid: global first if first: print("processes:") for proc in panda.get_processes(cpu): print(f"{panda.ffi.string(proc.name)} {proc.pid} {proc.ppid}") first = False else: print(f"process: {panda.get_process_name(cpu)}") return 0
test_mem = "1G" # TODO: not yet supported, need hypercall update in taint.h #elif args.arch == "arm": # build_target = "TARGET_ARM" # test_expect_prompt = rb"root@ubuntu:.*" # test_qcow="/home/panda/regdir/qcows/arm_wheezy.qcow2" # test_mem = "256M" else: raise RuntimeError("Invalid architecture for taint2 unit tests!") # Panda prep panda = Panda(arch=args.arch, qcow=test_qcow, extra_args="-nographic", expect_prompt=test_expect_prompt, mem=test_mem) # Mode selection if args.mode == "record": prepare_cdrom_iso(build_target) panda.queue_async(run_in_guest_record) panda.run() elif args.mode == "replay": panda.load_plugin("taint2") panda.run_replay("taint2_tests") else: raise RuntimeError("Invalid mode for taint2 unit tests!")
import capstone import os from pandare import Panda #from pandare.ppc.helper import dump_regs, registers from ipdb import set_trace as d PPC_CODE = b"\x60\x00\x00\x00\x38\x20\x00\x10" # nop; li 1, 0x100 ADDRESS = 0 stop_addr = ADDRESS + len(PPC_CODE) # Create a machine of type 'configurable' but with just a CPU specified (no peripherals or memory maps) panda = Panda("ppc", extra_args=[ "-M", "configurable", "-nographic", "-d", "unimp,guest_errors,in_asm,cpu,int" ]) @panda.cb_after_machine_init def setup(cpu): ''' After our CPU has been created, allocate memory and set starting state ''' # map 2MB memory for this emulation panda.map_memory("mymem", 2 * 1024 * 1024, ADDRESS) # Write code into memory panda.physical_memory_write(ADDRESS, PPC_CODE)
Lastly, we use syscalls2 to monitor sys_sendto for network traffic. We must check each byte in the packet to check if it is tainted and we alert if it is tainted. ''' from sys import argv from os import path from pandare import Panda arch = "x86_64" if len(argv) <= 1 else argv[1] extra = "-nographic" qcow = argv[1] panda = Panda(arch=arch, qcow=qcow, extra_args=extra, mem="1G", expect_prompt=rb"root@ubuntu:.*") panda.set_os_name("linux-64-ubuntu") panda.load_plugin("callstack_instr", args={"stack_type": "asid"}) panda.require("syscalls2") file_info = None tainted = False @panda.ppp("syscalls2", "on_sys_read_return") def on_sys_read_return(cpustate, pc, fd, buf, count): global file_info, tainted if file_info and not tainted:
from sys import argv from pandare import Panda, ffi if len(argv) < 2: print("Usage {} <process name> <recording name>(optional)".format(argv[1])) exit(1) process_name = argv[1] rep = argv[2] if len(argv) >= 3 else False if rep: panda = Panda(arch="i386", mem='3G', os="windows", os_version="windows_32_7", extra_args=["-s", "-nographic"]) else: panda = Panda(arch="i386", mem='3G', os="windows", os_version="windows_32_7", qcow="./win7_32.img", extra_args=["--show-cursor", "-net", "none"]) # find the address of the library when the right process is started # maybe we can do this just at the first occurrence i.e. when the process starts si = 0 base = 0
NOTE: The big userland yml file is slow to load the first time. Let it do it's thing once then it will store a pickle and be fast after that. ''' from sys import argv from volatility.framework.objects import utility, Pointer from pandare import blocking, Panda, ffi import pdb, yaml, pickle, os from functools import lru_cache arch = "x86_64" image = argv[1] extra_args = "-nographic" recording_name = "/home/luke/workspace/recordings/callers" symbolfile = "./bionic-server-cloudimg-amd64-userland-symbols.yml" elfmapping = None panda = Panda(arch=arch,qcow=image,extra_args=extra_args,expect_prompt=rb"root@ubuntu:.*",mem="1G") panda.load_plugin("callstack_instr",args={"stack_type":"asid"}) if os.path.exists(symbolfile+".pickle"): with open(symbolfile+".pickle","rb") as f: print("using pickle to load elfmapping") elfmapping = pickle.load(f) if not elfmapping: if not os.path.exists(symbolfile): import urllib.request print('Beginning file download with urllib2...') url = 'http://panda-re.mit.edu/qcows/linux/ubuntu/1804/x86_64/bionic-server-cloudimg-amd64-userland-symbols.yml' urllib.request.urlretrieve(url, symbolfile)
#!/usr/bin/env python3 from sys import argv, path import time import pickle path.append("..") from pandare import Panda from pandare.helper.x86 import * # Single arg of arch, defaults to i386 arch = "i386" if len(argv) <= 1 else argv[1] extra = "-nographic -chardev socket,id=monitor,path=./monitor.sock,server,nowait -monitor chardev:monitor -serial telnet:127.0.0.1:4444,server,nowait" panda = Panda(generic=arch, extra_args=extra) with open("libc_syms.pickle", "rb") as f: libc = pickle.load(f) f = open("fwrite.out", "wb") @panda.hook_single_insn("fwrite_hook", libc["fwrite"], libraryname="libc", kernel=False) def fwrite_hook(cpustate, tb): # grab arguments ESP, arg1, arg2, arg3... ret = ffi.new("uint32_t[]", 5) size = ffi.cast("target_ptr_t", ffi.sizeof(ret)) faddr = ffi.cast("target_ptr_t", cpustate.env_ptr.regs[R_ESP]) # esp panda.virtual_memory_read(cpustate, faddr, ret, size) # XXX bad argus for virtual_memory_write string_arg = ffi.new("char[]", ret[2] * ret[3])
.end: nop """ ks = keystone.Ks(keystone.KS_ARCH_X86, keystone.KS_MODE_64) ADDRESS = 0x1000 encoding, count = ks.asm(CODE, ADDRESS) stop_addr = ADDRESS + len(encoding) buf = b"ABCD" buf_src = ADDRESS + 200 buf_dest = ADDRESS + 100 # Create a machine of type 'configurable' but with just a CPU specified (no peripherals or memory maps) panda = Panda("x86_64", extra_args=["-M", "configurable", "-nographic", "-d", "in_asm"]) panda.load_plugin("taint2") @panda.cb_after_machine_init def setup(cpu): # After our CPU has been created, allocate memory and set starting state # Setup a region of memory panda.map_memory("mymem", 2 * 1024 * 1024, ADDRESS) # Write code into memory panda.physical_memory_write(ADDRESS, bytes(encoding)) # Copy from buffer at R13 into buffer at R12
j .end nop .end: addiu $t1, 1 # t1++ """ ks = keystone.Ks(keystone.KS_ARCH_MIPS, keystone.KS_MODE_MIPS32) #ks = keystone.Ks(keystone.KS_ARCH_MIPS, keystone.KS_MODE_MIPS32 + KS_MODE_BIG_ENDIAN) ADDRESS = 0x1000 encoding, count = ks.asm(CODE, ADDRESS) stop_addr = ADDRESS + len(encoding) panda = Panda("mipsel", extra_args=["-M", "configurable", "-nographic"], raw_monitor=True) @panda.cb_after_machine_init def setup(cpu): ''' After our CPU has been created, allocate memory and set starting state ''' # map 2MB memory for this emulation panda.map_memory("mymem", 2 * 1024 * 1024, ADDRESS) # Write code into memory panda.physical_memory_write(ADDRESS, bytes(encoding)) # Set up registers
from pandare import Panda, blocking, qcows import sys import time assert (len(sys.argv) == 2) arch = "x86_64" qi = qcows.Qcows.get_qcow_info(arch) panda = Panda(arch=qi.arch, mem="1G", expect_prompt=qi.prompt, os=qi.os, qcow=sys.argv[1], extra_args="-nographic", expect_kwargs={"unansi": False}) @panda.queue_blocking def setup(): login_prompt = b"ubuntu login: "******"Password: "******"saw login prompt") panda.serial_socket.sendall(b'root\n') panda.serial_read_until(password_prompt) print("saw password prompt") panda.serial_socket.sendall(b'root\n') panda.serial_read_until(shell_prompt)
#!/usr/bin/env python3 from sys import argv from pandare import Panda, blocking, ffi panda = Panda(generic="x86_64" if len(argv) < 2 else argv[1]) @blocking def run_cmd(): panda.revert_sync("root") print(panda.run_serial_cmd("uname -a")) panda.end_analysis() @panda.cb_asid_changed() def asidchange(env, old_asid, new_asid): if old_asid != new_asid: print("Asid changed from %d to %d" % (old_asid, new_asid)) return 0 panda.queue_async(run_cmd) panda.run()
import os CODE = b""" mov x0, #1 mov x1, #64 """ ks = keystone.Ks(keystone.KS_ARCH_ARM64, keystone.KS_MODE_LITTLE_ENDIAN) ADDRESS = 0x1000 encoding, count = ks.asm(CODE, ADDRESS) stop_addr = ADDRESS + len(encoding) panda = Panda( "aarch64", extra_args=["-M", "configurable", "-nographic", "-d", "in_asm"], raw_monitor=True ) # Allows for a user to ctrl-a + c then type quit if things go wrong @panda.cb_after_machine_init def setup(cpu): ''' After our CPU has been created, allocate memory and set starting state ''' # map 2MB memory for this emulation panda.map_memory("mymem", 2 * 1024 * 1024, ADDRESS) # Write code into memory panda.physical_memory_write(ADDRESS, bytes(encoding))
def runner(generic_name): ''' Try to run a single generic image First run via CLI - load root snapshot, run a command and quit - check command output Then test via python to see if OSI works ''' from pandare import Panda data = SUPPORTED_IMAGES[generic_name] qcow_path = Qcows.get_qcow(generic_name) # Check 1 - can we load with CLI assert(os.path.isfile(qcow_path)), f"Can't find qcow for {generic_name}" # Start panda with a 10s timeout and background it # then sleep 1s, connect to the serial port via telnet, run a command and capture output # then shutdown panda via monitor and check if output matches expected value cmd = f"timeout 10s panda-system-{data.arch} -loadvm {data.snapshot} -m {data.default_mem} {qcow_path} \ {data.extra_args} -serial telnet:localhost:4321,server,nowait \ -monitor unix:/tmp/panda.monitor,server,nowait & \ sleep 2; RES=$(echo 'whoami' | nc localhost 4321) && (echo 'q' | nc -q1 -U /tmp/panda.monitor || true) && echo \"RESULT: $RES\" | grep -q 'root'" print(cmd) p = subprocess.run(cmd, shell=True) if p.returncode != 0: raise RuntimeError("Failed to run CLI panda") print("\tCLI: PASS") # Check 2 - load with python and test OSI profile if arch in osi_supported panda = Panda(generic=generic_name) assert(os.path.isdir(panda.build_dir)), f"Missing build dir {panda.build_dir}" osi_supported = ['i386', 'x86_64', 'arm'] if panda.arch in osi_supported: print(f"{panda.arch} supports OSI - loading") panda.load_plugin("osi") panda.load_plugin("osi_linux") seen = set() @panda.cb_asid_changed # Grab proc names at each asid change - AFTER we're at root (can't do OSI during boot, but asid will chage) def new_asid(cpu, oldasid, newasid): global reverted print("ASID", reverted, panda.arch) if reverted and panda.arch in osi_supported: # If osi unsupported, bail proc = panda.plugins['osi'].get_current_process(cpu) name = panda.ffi.string(proc.name) if name not in seen: seen.add(name) return 0 @panda.queue_blocking def start(): panda.revert_sync("root") global reverted reverted = True r = panda.run_serial_cmd("grep --color=no root /etc/passwd") assert("root:x" in r), "Failed to run grep command" panda.end_analysis() panda.run() if panda.arch in osi_supported: assert(len(seen)), "Didn't observe any processes" assert(b'grep' in seen), "Didn't see grep process run" print("\tPython: PASS" + (" (no OSI)" if panda.arch not in osi_supported else ""))
#!/usr/bin/env python3 from time import sleep from pandare import Panda, blocking ''' Blocking function hangs but callback can still request end_analysis and end call to panda.run ''' panda = Panda(generic='i386') sleeping_started = False sleeping_ended = False @blocking def hang(): ''' This function should start but never finish because the before block exec callback should end_analysis which preempts this ''' global sleeping_started, sleeping_ended sleeping_started = True sleep(1000) sleeping_ended = True panda.end_analysis() @panda.cb_before_block_exec def before_block_execute(cpustate, transblock): if sleeping_started:
from pandare import Panda panda = Panda(generic='x86_64') @panda.queue_blocking def driver(): panda.revert_sync('root') print(panda.run_serial_cmd("grep root /etc/passwd")) panda.end_analysis() panda.require("osi") panda.require("osi_linux") def fd_to_fname(cpu, fd): proc = panda.plugins['osi'].get_current_process(cpu) procname = panda.ffi.string( proc.name) if proc != panda.ffi.NULL else "error" fname_ptr = panda.plugins['osi_linux'].osi_linux_fd_to_filename( cpu, proc, fd) fname = panda.ffi.string( fname_ptr) if fname_ptr != panda.ffi.NULL else "error" return fname @panda.ppp("syscalls2", "on_sys_read_return") def read(cpu, tb, fd, buf, cnt): fname = fd_to_fname(cpu, fd) print(f"read {fname}")
from pandare import Panda import sys platform = sys.argv[1] panda = Panda(generic=platform) from os.path import exists if not exists(f"cool_recording_{platform}-rr-snp"): @panda.queue_blocking def do_stuff(): panda.revert_sync("root") print(panda.run_serial_cmd("echo abcdefgh | tee cool_file")) panda.run_monitor_cmd(f"begin_record cool_recording_{platform}") print(panda.run_serial_cmd("cat cool_file")) panda.run_monitor_cmd("end_record") panda.end_analysis() panda.run() print("done with iniital section") ## print out all the files we saw #@panda.ppp("syscalls2","on_sys_open_return") #def sys_open_return(cpu, pc, path, flags,mode): # print(f"File opened {panda.read_str(cpu,path)}") # #@panda.cb_asid_changed #def asid_changed(cpu, old,new): # print(f"new_asid {cpu.rr_guest_instr_count}") # return 0 #
#!/usr/bin/python3 import os from os import path from os import remove import sys import shutil from sys import argv from pandare import blocking, Panda thisdir = os.path.dirname(os.path.realpath(__file__)) if __name__ == "__main__": panda = Panda(arch="i386", qcow="/home/panda/regdir/qcows/wheezy_panda2.qcow2", extra_args="-nographic", expect_prompt=rb"root@debian-i386:.*") panda.load_plugin("taint2") panda.run_replay("taint2_tests")
#!/usr/bin/env python3 from pandare import blocking, Panda from os.path import isfile, expanduser from requests import get qcow = "https://people.debian.org/~aurel32/qemu/mips/debian_wheezy_mips_standard.qcow2" vmlinux = "https://people.debian.org/~aurel32/qemu/mips/vmlinux-3.2.0-4-4kc-malta" qcow_out = expanduser("~/.panda/debian_wheezy_mips_standard.qcow") vmlinux_out = expanduser("~/.panda/vmlinux-3.2.0-4-4kc-malta") if not isfile(qcow_out): open(qcow_out, 'wb').write(requests.get(qcow).content) if not isfile(vmlinux_out): open(vmlinux_out, 'wb').write(requests.get(vmlinux).content) panda = Panda(generic="mips", extra_args="-monitor telnet:127.0.0.1:4444,server,nowait") replay = False if replay: panda.run_replay("sample") else: @blocking def q(): panda.revert_sync("root") # panda.queue_async(q) panda.run()
''' proc_start.py Makes use of the proc_start_linux plugin to get output. Run with: python3 proc_start.py ''' from pandare import Panda from rich import print from sys import argv arch = argv[1] if len(argv) > 1 else "arm" panda = Panda(generic=arch) @panda.queue_blocking def do_stuff(): panda.revert_sync("root") for command in ["ls -la", "whoami", "sleep 1", "uname -r"]: print(panda.run_serial_cmd("LD_SHOW_AUXV=1 " + command)) panda.end_analysis() @panda.ppp("proc_start_linux", "on_rec_auxv") def rec_auxv(cpu, tb, av): print("[bold magenta][START PyPANDA on_recv_auxv][/bold magenta]") print("[bold red]Arguments: [/bold red]", end="") for i in range(av.argc): print(f'[bold red]{panda.ffi.string(av.argv[i])},[/bold red]', end="") print()
panda = Panda( arch="arm", mem="1G", extra_args=[ # Kernel "-M", "vexpress-a9", "-kernel", kernel, "-dtb", dtb, "-append", append, "-nographic", # Network "-net", "nic,netdev=net0", "-netdev", "user,id=net0,hostfwd=tcp::5443-:443,hostfwd=tcp::5580-:9080,hostfwd=tcp::2222-:22", # FS via Virtio "-drive", "if=none,file={},id=rootfs,format=raw".format(rootfs), "-device", "virtio-blk-device,drive=rootfs", # Syscalls_logger plog "-pandalog", "test_sys_logger.plog" ])