예제 #1
0
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}")
예제 #2
0
    def __init__(self, panda, cpu, fd, cmd, guest_ptr, use_osi_linux = False):

        '''
        Do unpacking, optionally using OSI for process and file name info.
        '''

        do_ioctl_init(panda.arch_name)
        self.cmd = ffi.new("union IoctlCmdUnion*")
        self.cmd.asUnsigned32 = cmd
        self.original_ret_code = None
        self.osi = use_osi_linux

        # Optional syscall argument: pointer to buffer
        if (self.cmd.bits.arg_size > 0):
            try:
                self.has_buf = True
                self.guest_ptr = guest_ptr
                self.guest_buf = panda.virtual_memory_read(cpu, self.guest_ptr, self.cmd.bits.arg_size)
            except ValueError:
                raise RuntimeError("Failed to read guest buffer: ioctl({})".format(str(self.cmd)))
        else:
            self.has_buf = False
            self.guest_ptr = None
            self.guest_buf = None

        # Optional OSI usage: process and file name
        if self.osi:
            proc = panda.plugins['osi'].get_current_process(cpu)
            proc_name_ptr = proc.name
            file_name_ptr = panda.plugins['osi_linux'].osi_linux_fd_to_filename(cpu, proc, panda.ffi.cast("int", fd))
            self.proc_name = ffi.string(proc_name_ptr).decode() if proc_name_ptr != ffi.NULL else "unknown"
            self.file_name = ffi.string(file_name_ptr).decode() if file_name_ptr != ffi.NULL else "unknown"
        else:
            self.proc_name = None
            self.file_name = None
예제 #3
0
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"
    print(f"[PANDA] {procname} read from {fname}")
    if b"cat" in procname:
        populate_ghidra(cpu, pc)
        import ipdb
        ipdb.set_trace()
예제 #4
0
def virt_mem_after_read(cpustate, pc, addr, size, buf):
	curbuf = ffi.cast("char*", buf)
	current = panda.get_current_process(cpustate)
	if current != ffi.NULL:
		if size >= 5:
			buf_addr = hex(int(ffi.cast("uint64_t", buf)))
			buf_str = ffi.string(ffi.cast("char*",buf)).decode(errors='ignore')
			print("Read buf: %s, size: %x, at pc: %x %s" %(buf_addr[2:], size, addr, buf_str))
예제 #5
0
 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 = ffi.string(proc.name)
         if name not in seen:
             seen.add(name)
     return 0
예제 #6
0
def get_calltree(cpu):
    # Print the calltree to the current process
    proc = panda.plugins['osi'].get_current_process(cpu)
    if proc == ffi.NULL:
        print("Error determining current process")
        return
    procs = panda.get_processes_dict(cpu)

    chain = [{'name': ffi.string(proc.name).decode('utf8', 'ignore'),
              'pid': proc.pid, 'parent_pid': proc.ppid}]
    while chain[-1]['pid'] > 1 and chain[-1]['parent_pid'] in procs.keys():
        chain.append(procs[chain[-1]['parent_pid']])
    return " -> ".join(f"{item['name']} ({item['pid']})" for item in chain[::-1])
예제 #7
0
    def __str__(self):

        if self.osi:
            self_str = "\'{}\' using \'{}\' - ".format(self.proc_name, self.file_name)
        else:
            self_str = ""

        bits = self.cmd.bits
        direction = ffi.string(ffi.cast("enum ioctl_direction", bits.direction))
        ioctl_desc = f"dir={direction},arg_size={bits.arg_size:x},cmd=0x{bits.cmd_num:x},type=0x{bits.type_num:x}"
        if (self.guest_ptr == None):
            self_str += f"ioctl({ioctl_desc}) -> {self.original_ret_code}"
        else:
            self_str += f"ioctl({ioctl_desc},ptr={self.guest_ptr:08x},buf={self.guest_buf}) -> {self.original_ret_code}"
        return self_str
예제 #8
0
def ntmap(cpu, pc, SectionHandle, ProcessHandle, BaseAddress, ZeroBits,
          CommitSize, SectionOffset, ViewSize, InheritDisposition,
          AllocationType, Win32Protect):
    proc = panda.get_process_name(cpu)
    #print("PC 0x{:x}".format(pc))
    print(proc)
    if proc == process_name:

        mappings = panda.get_mappings(cpu)
        for mapping in mappings:
            print(
                "Name: " + ffi.string(mapping.name).decode(),
                "Base: 0x{:x} Size: 0x{:x}".format(mapping.base, mapping.size))
            if ffi.string(mapping.name).decode().lower() == "kernel32.dll":
                global base
                base = mapping.base
                global si
                si = mapping.size
                print("Enabling memory callback")
                panda.enable_callback("cb1")
                print("Enabling hypercall callback")
                panda.enable_callback("hyper")
                print("Disabling MapViewOfSections hook")
                panda.disable_ppp("ntmap")
예제 #9
0
def bbe(cpu, tb, exit_code):

    global bb_ctr

    if (not panda.in_kernel(cpu)) and (exit_code <= 1):
        bb_ctr += 1

        if (bb_ctr % 1000) == 0:
            proc = panda.plugins['osi'].get_current_process(cpu)
            if proc == ffi.NULL:
                return

            proc_name = ffi.string(proc.name).decode("utf-8")
            pc = panda.current_pc(cpu)
            in_dll = panda.plugins['osi'].in_shared_object(cpu, proc)
            print(f"{proc_name}@{pc:016x}, in SO? {in_dll}")
예제 #10
0
def populate_ghidra(cpu, pc):
    tid = currentProgram.startTransaction("BRIDGE: Change Memory Sections")
    memory = currentProgram.getMemory()
    delete_all_memory_segments(memory, monitor)
    names = set()
    for mapping in panda.get_mappings(cpu):
        if mapping.file != ffi.NULL:
            name = ffi.string(mapping.file).decode()
        else:
            name = "[unknown]"
        while name in names:
            from random import randint
            name += ":" + hex(randint(0, 100000000))
        names.add(name)
        memory.createInitializedBlock(name, toAddr(mapping.base), mapping.size,
                                      0, monitor, False)
        memory_read = read_memory(cpu, mapping.base, mapping.size)
        if memory_read:
            memory.setBytes(toAddr(mapping.base),
                            read_memory(cpu, mapping.base, mapping.size))
    analyzeAll(currentProgram)
    #import ghidra.app.decompiler as decomp
    decomp = b.remote_import("ghidra.app.decompiler")
    # ## get the decompiler interface
    iface = decomp.DecompInterface()

    # ## decompile the function
    iface.openProgram(currentProgram)
    fn = getFunctionContaining(toAddr(pc))
    d = iface.decompileFunction(fn, 5, monitor)

    ## get the C code as string
    if not d.decompileCompleted():
        print(d.getErrorMessage())
    else:
        code = d.getDecompiledFunction()
        ccode = code.getC()
        print(ccode)

    setCurrentLocation(toAddr(pc))
    currentProgram.endTransaction(tid, True)
예제 #11
0
        def proc_write_capture_on_sys_write_enter(cpu, pc, fd, buf, cnt):

            try_read = False

            # Capture console output
            if self._console_capture:

                # Fun trick: lazy eval of OSI
                # Based on the idea that a non-POSIX FD will only be used after boot is finished an OSI is functional
                # Note: doesn't capture boot logs (would require hooking kernel's printk, not write syscall)
                if (fd == 1) or (fd == 2) or (fd == 3):
                    try_read = True
                else:
                    curr_proc = panda.plugins['osi'].get_current_process(cpu)
                    file_name_ptr = panda.plugins[
                        'osi_linux'].osi_linux_fd_to_filename(
                            cpu, curr_proc, fd)
                    file_path = ffi.string(file_name_ptr).decode()
                    if ("tty" in file_path):
                        try_read = True

                if try_read:

                    try:
                        data = panda.virtual_memory_read(cpu, buf, cnt)
                    except ValueError:
                        raise RuntimeError(
                            f"Failed to read buffer: addr 0x{buf:016x}")

                    if fd == 2:
                        self._console_printed_err = True

                    log_file = self._console_log_dir.joinpath("console.out")
                    with open(log_file, "ab") as f:
                        f.write(data)

                    self._files_written.add(str(log_file))

            # Use OSI to capture logs for a named process
            if self._proc_name:

                curr_proc = panda.plugins['osi'].get_current_process(cpu)
                curr_proc_name = ffi.string(curr_proc.name).decode()

                if self._proc_name == curr_proc_name:

                    if not try_read:  # If we didn't already read this data in once for console capture
                        try:
                            data = panda.virtual_memory_read(cpu, buf, cnt)
                        except ValueError:
                            raise RuntimeError(
                                f"Failed to read buffer: proc \'{curr_proc_name}\', addr 0x{buf:016x}"
                            )

                    file_name_ptr = panda.plugins[
                        'osi_linux'].osi_linux_fd_to_filename(
                            cpu, curr_proc, fd)
                    file_path = ffi.string(file_name_ptr).decode()

                    # For informational purposes only, collection not reliant on this exact mapping
                    if fd == 1:  # POSIX stdout
                        file_path += ".stdout"
                    elif fd == 2:  # POSIX stderr
                        file_path += ".stderr"
                        self._proc_printed_err = True

                    log_file = self._proc_log_dir.joinpath(
                        file_path.replace("//", "_").replace("/", "_"))
                    with open(log_file, "ab") as f:
                        f.write(data)

                    self._files_written.add(str(log_file))
예제 #12
0
def proc_write_capture_on_sys_write_enter(cpu, pc, fd, buf, cnt):
    curr_proc = panda.plugins['osi'].get_current_process(cpu)
    file_name_ptr = panda.plugins['osi_linux'].osi_linux_fd_to_filename(cpu, curr_proc, fd)
    if ffi.string(file_name_ptr).decode() == "/dev/ttyS0":
        print(panda.virtual_memory_read(cpu, buf, cnt).decode(), end="")
예제 #13
0
def rec(cpu, procname, asid, pid):
    print(ffi.string(procname).decode())
    if ffi.string(procname).decode() == process_name:
        print(ffi.string(procname).decode(), " Started!")
        if not rep:
            panda.run_monitor_cmd("begin_record rec")
예제 #14
0
def bbe(cpu, tb):
    proc = panda.plugins['osi'].get_current_process(cpu)
    name = ffi.string(proc.name)
    if name not in printed:
        printed.add(name)
        print(name)