From 4010bdbfa71bed6780d76aa7a431aa917febcf9d Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Mon, 27 Sep 2021 20:20:23 -0400 Subject: [PATCH 01/79] first real linjector commit --- panda/plugins/linjector/Cargo.toml | 24 ++ panda/plugins/linjector/Makefile | 18 ++ panda/plugins/linjector/rustfmt.toml | 1 + .../linjector/src/injectables/Makefile | 31 +++ .../src/injectables/include/hypercall.h | 66 ++++++ .../injectables/include/hypercall_constants.h | 15 ++ .../src/injectables/include/syscall_x86.h | 103 ++++++++ .../linjector/src/injectables/injector.c | 54 +++++ .../linjector/src/injectables/tiny_mmap.c | 11 + panda/plugins/linjector/src/lib.rs | 222 ++++++++++++++++++ 10 files changed, 545 insertions(+) create mode 100644 panda/plugins/linjector/Cargo.toml create mode 100644 panda/plugins/linjector/Makefile create mode 100644 panda/plugins/linjector/rustfmt.toml create mode 100644 panda/plugins/linjector/src/injectables/Makefile create mode 100644 panda/plugins/linjector/src/injectables/include/hypercall.h create mode 100644 panda/plugins/linjector/src/injectables/include/hypercall_constants.h create mode 100644 panda/plugins/linjector/src/injectables/include/syscall_x86.h create mode 100644 panda/plugins/linjector/src/injectables/injector.c create mode 100644 panda/plugins/linjector/src/injectables/tiny_mmap.c create mode 100644 panda/plugins/linjector/src/lib.rs diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml new file mode 100644 index 00000000000..6aacfe61b5e --- /dev/null +++ b/panda/plugins/linjector/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "linjector" +version = "0.1.0" +authors = ["Luke Craig ", "Jordan McLeod "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +panda-re = { version = "0.13.0", default-features = false } +once_cell = "1.8.0" +object = "0.26.2" + +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +aarch64 = ["panda-re/aarch64"] diff --git a/panda/plugins/linjector/Makefile b/panda/plugins/linjector/Makefile new file mode 100644 index 00000000000..2234476df57 --- /dev/null +++ b/panda/plugins/linjector/Makefile @@ -0,0 +1,18 @@ +# Don't forget to add your plugin to config.panda! + +# Build rust plugins with make! + +# The main rule for your plugin. List all object-file dependencies. + +PANDA_PATH = $(realpath $(shell pwd)/..) +PLUGIN_DIR = $(realpath $(join $(PANDA_PATH), /../panda/plugins/$(PLUGIN_NAME)/)) +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so : $(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + @echo " CARGO $(PLUGIN_DIR)" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --no-default-features --features=$(TARGET_NAME) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @cp -p $(PLUGIN_ARTIFACTS_DIR)/release/lib$(PLUGIN_NAME).so $@ diff --git a/panda/plugins/linjector/rustfmt.toml b/panda/plugins/linjector/rustfmt.toml new file mode 100644 index 00000000000..5c8d9318b3b --- /dev/null +++ b/panda/plugins/linjector/rustfmt.toml @@ -0,0 +1 @@ +max_width = 80 \ No newline at end of file diff --git a/panda/plugins/linjector/src/injectables/Makefile b/panda/plugins/linjector/src/injectables/Makefile new file mode 100644 index 00000000000..854de7ca585 --- /dev/null +++ b/panda/plugins/linjector/src/injectables/Makefile @@ -0,0 +1,31 @@ +.DEFAULT_GOAL := all +LIST=hello_world read_file read_all_files injector tiny_mmap + +all: $(LIST) + +.PHONY: all + +CC=gcc -m32 +EXTRA_GCC_ARGS= -fomit-frame-pointer -nodefaultlibs -nostdlib -fpic + + +hello_world: hello_world.c + $(CC) $(EXTRA_GCC_ARGS) $< -o $@ + +read_file: read_file.c + $(CC) $(EXTRA_GCC_ARGS) $< -o $@ + +read_all_files: read_all_files.c + $(CC) $(EXTRA_GCC_ARGS) $< -o $@ + +injector: injector.c + $(CC) -O3 $(EXTRA_GCC_ARGS) $< -o $@ + +tiny_mmap: tiny_mmap.c + $(CC) $(EXTRA_GCC_ARGS) $< -o $@ + +basic_hello_world: basic_hello_world.c + $(CC) -static $< -o $@ + +clean: + rm -rf $(LIST) \ No newline at end of file diff --git a/panda/plugins/linjector/src/injectables/include/hypercall.h b/panda/plugins/linjector/src/injectables/include/hypercall.h new file mode 100644 index 00000000000..c1235ede477 --- /dev/null +++ b/panda/plugins/linjector/src/injectables/include/hypercall.h @@ -0,0 +1,66 @@ +// stolen from recctrl.h; modified to make more generic +#include "hypercall_constants.h" + + +#if defined(__x86_64__) || defined(__i386__) +static inline __attribute__((always_inline)) int hc_rec(hc_cmd action, char *s, int len) { + int eax = HC_MAGIC; + int ret = HC_ERROR; + + asm __volatile__( + "mov %1, %%eax \t\n\ + mov %2, %%ebx \t\n\ + mov %3, %%ecx \t\n\ + mov %4, %%edx \t\n\ + cpuid \t\n\ + mov %%eax, %0 \t\n\ + " + : "=g"(ret) /* output operand */ + : "g" (eax), "g" (action), "g" (s), "g" (len)/* input operands */ + : "eax", "ebx", "ecx", "edx" /* clobbered registers */ + ); + + return ret; +} +static inline __attribute__((always_inline)) int hc(hc_cmd action, char *s) { + int eax = HC_MAGIC; + int ret = HC_ERROR; + + asm __volatile__( + "mov %1, %%eax \t\n\ + mov %2, %%ebx \t\n\ + mov %3, %%ecx \t\n\ + cpuid \t\n\ + mov %%eax, %0 \t\n\ + " + : "=g"(ret) /* output operand */ + : "g" (eax), "g" (action), "g" (s) /* input operands */ + : "eax", "ebx", "ecx", "edx" /* clobbered registers */ + ); + + return ret; +} +#elif defined(__arm__) +static inline __attribute__((always_inline)) int hc(hc_cmd action, char *s) { + unsigned long r0 = HC_MAGIC; + int ret = HC_ERROR; + + asm __volatile__( + "push {r0-r4} \t\n\ + ldr r0, %1 \t\n\ + ldr r1, %2 \t\n\ + ldr r2, %3 \t\n\ + ldr p7, 0, r0, c0, c0, 0 \t\n\ + sdr r0, %0 \t\n\ + pop {r0-r4} \t\n\ + " + : "=g"(ret) /* output operand */ + : "g" (r0), "g" (action), "g" (s) /* input operands */ + : "r0", "r1", "r2", "r3" /* clobbered registers */ + ); + + return ret; +} +#else +#error Unsupported platform. +#endif diff --git a/panda/plugins/linjector/src/injectables/include/hypercall_constants.h b/panda/plugins/linjector/src/injectables/include/hypercall_constants.h new file mode 100644 index 00000000000..d2b234195f8 --- /dev/null +++ b/panda/plugins/linjector/src/injectables/include/hypercall_constants.h @@ -0,0 +1,15 @@ +/** @brief Magic code to use in cpuid hypercall. */ +#define HC_MAGIC 0x10adc0d3 + +typedef enum { + HC_NOOP = 0, + HC_START, /* start new action */ + HC_STOP, /* stop action */ + HC_READ, /* read buffer from hypervisor */ + HC_WRITE, /* write buffer TO hypervisor*/ + HC_ERROR, /* report error to hypervisor*/ + HC_CONDITIONAL_OP, /* ask the hypervisor if op should be completed*/ + HC_NEXT_STATE_MACHINE, /* ask the hypervisor manager to move to the next + state machine*/ +} hc_cmd; + diff --git a/panda/plugins/linjector/src/injectables/include/syscall_x86.h b/panda/plugins/linjector/src/injectables/include/syscall_x86.h new file mode 100644 index 00000000000..cf20621a6d7 --- /dev/null +++ b/panda/plugins/linjector/src/injectables/include/syscall_x86.h @@ -0,0 +1,103 @@ +#ifndef BASE_C_EXAMPLE +#include "/usr/include/i386-linux-gnu/asm/unistd_32.h" +#include "/usr/include/asm-generic/fcntl.h" +#define _SYS_MMAN_H // it's a lie. but it's a good intention +#define __USE_MISC +#include "/usr/include/bits/mman-linux.h" +#endif +#define NULL 0L + +#define SYSINL static inline __attribute__((always_inline)) + +/* +* All the syscall stuff is from musl /arch/i386/syscall_arch.h +*/ + +#define SYSCALL_INSNS "int $128" + +#define SYSCALL_INSNS_12 "xchg %%ebx,%%edx ; " SYSCALL_INSNS " ; xchg %%ebx,%%edx" +#define SYSCALL_INSNS_34 "xchg %%ebx,%%edi ; " SYSCALL_INSNS " ; xchg %%ebx,%%edi" + + +SYSINL long syscall_0(long n) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n) : "memory"); + return __ret; +} + +SYSINL long syscall_1(long n, long a1) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS_12 : "=a"(__ret) : "a"(n), "d"(a1) : "memory"); + return __ret; +} + +SYSINL long syscall_2(long n, long a1, long a2) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS_12 : "=a"(__ret) : "a"(n), "d"(a1), "c"(a2) : "memory"); + return __ret; +} + +SYSINL long syscall_3(long n, long a1, long a2, long a3) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3) : "memory"); +#else + __asm__ __volatile__ (SYSCALL_INSNS_34 : "=a"(__ret) : "a"(n), "D"(a1), "c"(a2), "d"(a3) : "memory"); +#endif + return __ret; +} + +SYSINL long syscall_4(long n, long a1, long a2, long a3, long a4) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4) : "memory"); +#else + __asm__ __volatile__ (SYSCALL_INSNS_34 : "=a"(__ret) : "a"(n), "D"(a1), "c"(a2), "d"(a3), "S"(a4) : "memory"); +#endif + return __ret; +} + +SYSINL long syscall_5(long n, long a1, long a2, long a3, long a4, long a5) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS + : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#else + __asm__ __volatile__ ("pushl %2 ; push %%ebx ; mov 4(%%esp),%%ebx ; " SYSCALL_INSNS " ; pop %%ebx ; add $4,%%esp" + : "=a"(__ret) : "a"(n), "g"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#endif + return __ret; +} + +SYSINL long syscall_6(long n, long a1, long a2, long a3, long a4, long a5, long a6) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ ("pushl %7 ; push %%ebp ; mov 4(%%esp),%%ebp ; " SYSCALL_INSNS " ; pop %%ebp ; add $4,%%esp" + : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5), "g"(a6) : "memory"); +#else + unsigned long a1a6[2] = { a1, a6 }; + __asm__ __volatile__ ("pushl %1 ; push %%ebx ; push %%ebp ; mov 8(%%esp),%%ebx ; mov 4(%%ebx),%%ebp ; mov (%%ebx),%%ebx ; " SYSCALL_INSNS " ; pop %%ebp ; pop %%ebx ; add $4,%%esp" + : "=a"(__ret) : "g"(&a1a6), "a"(n), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#endif + return __ret; +} + + + + +static inline void* memset(void *buf, int num, int l){ + char* writer = (char*) buf; + void* end = buf + l; + while ((void*)writer < end){ + *writer = num; + writer++; + } + return buf; +} \ No newline at end of file diff --git a/panda/plugins/linjector/src/injectables/injector.c b/panda/plugins/linjector/src/injectables/injector.c new file mode 100644 index 00000000000..4dfdd114ab6 --- /dev/null +++ b/panda/plugins/linjector/src/injectables/injector.c @@ -0,0 +1,54 @@ +#include "include/syscall_x86.h" +#include "include/hypercall.h" +#define MFD_CLOEXEC 0x0001U + +int _start(void){ + int pid = syscall_0(__NR_fork); + if (pid == 0){ + // child process + int val = 0; + while(!val){ + hc(HC_STOP, (char*)&val); + syscall_0(__NR_sched_yield); + } + char none = '\0'; + int fd = syscall_2(__NR_memfd_create, (int)&none, MFD_CLOEXEC); + char buf[512]; + int rlen; + while ((rlen = hc_rec(HC_WRITE, (char*)&buf,sizeof(buf)/sizeof(buf[0])))>0){ + syscall_3(__NR_write, fd, (int)buf, rlen); + } + hc(HC_NEXT_STATE_MACHINE, (char*)0); + unsigned char execbuf[] = {47, 112, 114, 111, 99, 47, 115, 101, 108, 102, 47, 102, 100, 47, 48, 0}; + execbuf[14] += fd; + char* argv[] = {(char*)0}; + syscall_3(__NR_execve, (int)execbuf, (int)argv, (int)argv); + }else{ + // parent process + int pathname = hc(HC_READ,(char*)pid); + int argv = hc(HC_READ, (char*) pid); + int envp = hc(HC_READ, (char*) pid); + syscall_3(__NR_execve, pathname, argv, envp); + } +} + + //int pc = hc(HC_READ, (char*)pid); + //int eax = hc(HC_READ, (char*)pid); + //int ecx = hc(HC_READ, (char*)pid); + //int edx = hc(HC_READ, (char*)pid); + //int ebx = hc(HC_READ, (char*)pid); + //int esp = hc(HC_READ, (char*)pid); + //int ebp = hc(HC_READ, (char*)pid); + //int esi = hc(HC_READ, (char*)pid); + //int edi = hc(HC_READ, (char*)pid); + //asm volatile("mov %%eax, %0" : : "r"(eax)); + //asm volatile("mov %%ecx, %0" : : "r"(ecx)); + //asm volatile("mov %%edx, %0" : : "r"(edx)); + //asm volatile("mov %%ebx, %0" : : "r"(ebx)); + //asm volatile("mov %%esi, %0" : : "r"(esi)); + //asm volatile("mov %%edi, %0" : : "r"(edi)); + //asm volatile("mov %%esp, %0" : : "r"(esp)); + //asm volatile("mov %%ebp, %0" : : "r"(ebp)); + ////asm volatile ("jmp *%0" : : "r" (pc)); + //asm volatile ("jmp -2"); + //while(1); \ No newline at end of file diff --git a/panda/plugins/linjector/src/injectables/tiny_mmap.c b/panda/plugins/linjector/src/injectables/tiny_mmap.c new file mode 100644 index 00000000000..7ea79d1250e --- /dev/null +++ b/panda/plugins/linjector/src/injectables/tiny_mmap.c @@ -0,0 +1,11 @@ +#include "include/syscall_x86.h" +#include "include/hypercall.h" + +// how much memory we give the injector +#define PAGE_SIZE 0x1000 + +int _start(void){ + void* region = syscall_6(__NR_mmap2, NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_ANON,-1,0); + hc(HC_START,(char*)region); + (*(void(*)()) region)(); +} \ No newline at end of file diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs new file mode 100644 index 00000000000..50ddd489c49 --- /dev/null +++ b/panda/plugins/linjector/src/lib.rs @@ -0,0 +1,222 @@ +use object::{Object, ObjectSection}; +use once_cell::sync::OnceCell; +use panda::mem::{virtual_memory_read, virtual_memory_write}; +use panda::plugins::hooks::Hook; +use panda::plugins::proc_start_linux::{AuxvValues, PROC_START_LINUX}; +use panda::prelude::*; +use panda::regs::{get_pc, get_reg, set_reg, Reg}; +use std::convert::TryFrom; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::cmp::min; + +static POINTERS: OnceCell<[target_ulong; 3]> = OnceCell::new(); +static POINTERS_READ: AtomicUsize = AtomicUsize::new(0); +static SAVED_BUF: OnceCell> = OnceCell::new(); +static ELF_TO_INJECT: OnceCell> = OnceCell::new(); +static ELF_READ_POS: AtomicUsize = AtomicUsize::new(0); + +const MAGIC: usize = 0x10adc0d3; +const X86_REG_ORDER: [Reg; 4] = [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX]; +const ELF_PATH: &str = "/home/luke/workspace/igloo/pie_idea/rusty_shell/target/i686-unknown-linux-musl/release/rusty_shell"; + +#[derive(Copy, Clone)] +pub enum HcCmd { + Noop = 0, + Start, /* start new action */ + Stop, /* stop action */ + Read, /* read buffer from hypervisor */ + Write, /* write buffer TO hypervisor*/ + Error, /* report error to hypervisor*/ + ConditionalOp, /* ask the hypervisor if op should be completed*/ + NextStateMachine, /* ask the hypervisor manager to move to the next + state machine*/ +} + +impl TryFrom for HcCmd { + type Error = (); + + fn try_from(value: usize) -> Result { + match value { + 0 => Ok(HcCmd::Noop), + 1 => Ok(HcCmd::Start), + 2 => Ok(HcCmd::Stop), + 3 => Ok(HcCmd::Read), + 4 => Ok(HcCmd::Write), + 5 => Ok(HcCmd::Error), + 6 => Ok(HcCmd::ConditionalOp), + 7 => Ok(HcCmd::NextStateMachine), + _ => Err(()), + } + } +} + +fn parse_file_data(file_bytes: &[u8]) -> (&[u8], usize, usize) { + let obj_file = object::File::parse(file_bytes).expect("Couldn't parse ELF"); + let text_section = obj_file + .section_by_name(".text") + .expect("Couldn't locate .text section"); + let text_data = text_section.data().unwrap(); + let offset = text_section.address() - obj_file.entry(); + let section_size = text_section.size(); + (text_data, offset as usize, section_size as usize) +} + +#[panda::hook] +fn inject_hook( + cpu: &mut CPUState, + _tb: &mut TranslationBlock, + _exit_code: u8, + hook: &mut Hook, +) { + let inject_bytes = include_bytes!("./injectables/injector"); + let (text_data, _offset, _section_size) = parse_file_data(&inject_bytes[..]); + let pc = panda::regs::get_pc(cpu); + virtual_memory_write(cpu, pc, text_data); + hook.enabled = false; +} + +fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { + let reg_to_read = X86_REG_ORDER[num]; + get_reg(cpu, reg_to_read) as usize +} + +fn hyp_start(_cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { + inject_hook::hook().after_block_exec().at_addr(arg1 as u64); + None +} + +fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { + ELF_TO_INJECT.get_or_init(|| { + std::fs::read(ELF_PATH).unwrap() + + }); + let buf_to_write = arg1; + let size_requested = arg2; + + let read_pos = ELF_READ_POS.load(Ordering::SeqCst); + let buf_size = ELF_TO_INJECT.get().expect("").len(); + if read_pos < buf_size { + let lower = read_pos; + let upper = min(buf_size, read_pos+size_requested); + let data_to_write = &ELF_TO_INJECT.get().expect("")[lower..upper]; + virtual_memory_write(cpu, buf_to_write as u64, data_to_write); + ELF_READ_POS.fetch_add(upper - lower, Ordering::SeqCst); + Some(upper - lower) + }else { + None + } +} + +fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { + println!("Got to read with {:#x}", arg1); + assert!(arg1 != 0, "arg1 is a fork return 0 is the child"); + let ptr_pos = POINTERS_READ.load(Ordering::SeqCst); + let pointers = POINTERS.get().unwrap(); + let pc = get_pc(cpu); + + if ptr_pos <= pointers.len(){ + if ptr_pos == pointers.len(){ + virtual_memory_write(cpu, pc, SAVED_BUF.get().unwrap()); + None + } else{ + POINTERS_READ.fetch_add(1, Ordering::SeqCst); + Some(pointers[ptr_pos] as usize) + } + }else{ + None + } +} + +fn hyp_stop(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { + if POINTERS_READ.load(Ordering::SeqCst) == POINTERS.get().unwrap().len(){ + virtual_memory_write(cpu, arg1 as u64, "\x01\x02\x03\x04".as_bytes()); + } + None +} + +#[panda::guest_hypercall] +fn hypercall_handler(cpu: &mut CPUState) -> bool { + let magicval = get_hyp_reg(cpu, 0); + if magicval == MAGIC { + let action = get_hyp_reg(cpu, 1); + let first_arg = get_hyp_reg(cpu, 2); + let second_arg = get_hyp_reg(cpu, 3); + + let retval = match HcCmd::try_from(action) { + Ok(HcCmd::Start) => hyp_start(cpu, first_arg, second_arg), + Ok(HcCmd::Write) => hyp_write(cpu, first_arg, second_arg), + Ok(HcCmd::Read) => hyp_read(cpu, first_arg, second_arg), + Ok(HcCmd::Stop) => hyp_stop(cpu, first_arg, second_arg), + _ => None, + }; + + match retval { + Some(p) => set_reg(cpu, Reg::RAX, p as u64), + None => (), + } + } + true +} + +#[panda::hook] +fn entry_hook( + cpu: &mut CPUState, + _tb: &mut TranslationBlock, + _exit_code: u8, + hook: &mut Hook, +) { + let inject_bytes = include_bytes!("./injectables/tiny_mmap"); + let (text_data, offset, section_size) = parse_file_data(&inject_bytes[..]); + assert_eq!( + offset, 0, + "get better shellcode. why is there another function?" + ); + let pc = get_pc(cpu); + SAVED_BUF + .set( + virtual_memory_read(cpu, pc, section_size as usize) + .expect("failed to read buf. you might need a smaller injector or another stage"), + ) + .unwrap(); + virtual_memory_write(cpu, pc, text_data); + println!("Replacing bytes at PC with tiny_mmap"); + + hook.enabled = false; +} + +extern "C" fn handle_proc_start( + _cpu: &mut CPUState, + _tb: &mut TranslationBlock, + auxv: &AuxvValues, +) { + if true { + // auxv.euid == 0 for root only + println!("accepting new proc with euid {}", auxv.euid); + // get pointers to values for re-starting process + let execfn_ptr = auxv.execfn_ptr; + let argv_ptr_ptr = auxv.argv_ptr_ptr; + let env_ptr_ptr = auxv.env_ptr_ptr; + + // in your callback + POINTERS + .set([execfn_ptr, argv_ptr_ptr, env_ptr_ptr]) + .unwrap(); + + // set a + entry_hook::hook().after_block_exec().at_addr(auxv.entry); + + PROC_START_LINUX.remove_callback_on_rec_auxv(handle_proc_start); + } +} + +#[panda::init] +fn init(_: &mut PluginHandle) -> bool { + println!("Initialized!"); + PROC_START_LINUX.add_callback_on_rec_auxv(handle_proc_start); + true +} + +#[panda::uninit] +fn exit(_: &mut PluginHandle) { + println!("Exiting"); +} From 165f6729a936965872e86d54db01397b061f8189 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Mon, 27 Sep 2021 21:10:13 -0400 Subject: [PATCH 02/79] formatting changes --- panda/plugins/linjector/src/lib.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 50ddd489c49..d7188c01b8b 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -5,9 +5,9 @@ use panda::plugins::hooks::Hook; use panda::plugins::proc_start_linux::{AuxvValues, PROC_START_LINUX}; use panda::prelude::*; use panda::regs::{get_pc, get_reg, set_reg, Reg}; +use std::cmp::min; use std::convert::TryFrom; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::cmp::min; static POINTERS: OnceCell<[target_ulong; 3]> = OnceCell::new(); static POINTERS_READ: AtomicUsize = AtomicUsize::new(0); @@ -69,7 +69,8 @@ fn inject_hook( hook: &mut Hook, ) { let inject_bytes = include_bytes!("./injectables/injector"); - let (text_data, _offset, _section_size) = parse_file_data(&inject_bytes[..]); + let (text_data, _offset, _section_size) = + parse_file_data(&inject_bytes[..]); let pc = panda::regs::get_pc(cpu); virtual_memory_write(cpu, pc, text_data); hook.enabled = false; @@ -86,10 +87,7 @@ fn hyp_start(_cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { } fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { - ELF_TO_INJECT.get_or_init(|| { - std::fs::read(ELF_PATH).unwrap() - - }); + ELF_TO_INJECT.get_or_init(|| std::fs::read(ELF_PATH).unwrap()); let buf_to_write = arg1; let size_requested = arg2; @@ -97,12 +95,12 @@ fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { let buf_size = ELF_TO_INJECT.get().expect("").len(); if read_pos < buf_size { let lower = read_pos; - let upper = min(buf_size, read_pos+size_requested); + let upper = min(buf_size, read_pos + size_requested); let data_to_write = &ELF_TO_INJECT.get().expect("")[lower..upper]; virtual_memory_write(cpu, buf_to_write as u64, data_to_write); ELF_READ_POS.fetch_add(upper - lower, Ordering::SeqCst); Some(upper - lower) - }else { + } else { None } } @@ -114,21 +112,21 @@ fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { let pointers = POINTERS.get().unwrap(); let pc = get_pc(cpu); - if ptr_pos <= pointers.len(){ - if ptr_pos == pointers.len(){ + if ptr_pos <= pointers.len() { + if ptr_pos == pointers.len() { virtual_memory_write(cpu, pc, SAVED_BUF.get().unwrap()); None - } else{ + } else { POINTERS_READ.fetch_add(1, Ordering::SeqCst); Some(pointers[ptr_pos] as usize) } - }else{ + } else { None } } fn hyp_stop(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { - if POINTERS_READ.load(Ordering::SeqCst) == POINTERS.get().unwrap().len(){ + if POINTERS_READ.load(Ordering::SeqCst) == POINTERS.get().unwrap().len() { virtual_memory_write(cpu, arg1 as u64, "\x01\x02\x03\x04".as_bytes()); } None From 679d4353b665097e6f40a39ecfe7f36f9eacaeaf Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 29 Sep 2021 01:51:42 -0400 Subject: [PATCH 03/79] working fully now --- panda/plugins/linjector/src/lib.rs | 64 ++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index d7188c01b8b..2209f885168 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -12,12 +12,24 @@ use std::sync::atomic::{AtomicUsize, Ordering}; static POINTERS: OnceCell<[target_ulong; 3]> = OnceCell::new(); static POINTERS_READ: AtomicUsize = AtomicUsize::new(0); static SAVED_BUF: OnceCell> = OnceCell::new(); +static SAVED_PC: OnceCell = OnceCell::new(); static ELF_TO_INJECT: OnceCell> = OnceCell::new(); static ELF_READ_POS: AtomicUsize = AtomicUsize::new(0); const MAGIC: usize = 0x10adc0d3; -const X86_REG_ORDER: [Reg; 4] = [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX]; -const ELF_PATH: &str = "/home/luke/workspace/igloo/pie_idea/rusty_shell/target/i686-unknown-linux-musl/release/rusty_shell"; +const X86_REG_ORDER: [Reg; 4] = [Reg::EAX, Reg::EBX, Reg::ECX, Reg::EDX]; + +#[derive(PandaArgs)] +#[name = "linjector"] // plugin name +struct Args { + #[arg(required)] + proc: String +} + +lazy_static::lazy_static! { + static ref ARGS: Args = Args::from_panda_args(); +} + #[derive(Copy, Clone)] pub enum HcCmd { @@ -61,6 +73,11 @@ fn parse_file_data(file_bytes: &[u8]) -> (&[u8], usize, usize) { (text_data, offset as usize, section_size as usize) } +fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { + let reg_to_read = X86_REG_ORDER[num]; + get_reg(cpu, reg_to_read) as usize +} + #[panda::hook] fn inject_hook( cpu: &mut CPUState, @@ -72,22 +89,19 @@ fn inject_hook( let (text_data, _offset, _section_size) = parse_file_data(&inject_bytes[..]); let pc = panda::regs::get_pc(cpu); + println!("about to inject injector at {:#x}", pc); virtual_memory_write(cpu, pc, text_data); hook.enabled = false; } -fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { - let reg_to_read = X86_REG_ORDER[num]; - get_reg(cpu, reg_to_read) as usize -} - fn hyp_start(_cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { - inject_hook::hook().after_block_exec().at_addr(arg1 as u64); + println!("Got to hyp_start"); + inject_hook::hook().after_block_exec().at_addr(arg1 as target_ulong); None } fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { - ELF_TO_INJECT.get_or_init(|| std::fs::read(ELF_PATH).unwrap()); + ELF_TO_INJECT.get_or_init(|| std::fs::read(ARGS.guest_binary).unwrap()); let buf_to_write = arg1; let size_requested = arg2; @@ -97,7 +111,7 @@ fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { let lower = read_pos; let upper = min(buf_size, read_pos + size_requested); let data_to_write = &ELF_TO_INJECT.get().expect("")[lower..upper]; - virtual_memory_write(cpu, buf_to_write as u64, data_to_write); + virtual_memory_write(cpu, buf_to_write as target_ulong, data_to_write); ELF_READ_POS.fetch_add(upper - lower, Ordering::SeqCst); Some(upper - lower) } else { @@ -105,21 +119,22 @@ fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { } } + fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { println!("Got to read with {:#x}", arg1); assert!(arg1 != 0, "arg1 is a fork return 0 is the child"); let ptr_pos = POINTERS_READ.load(Ordering::SeqCst); let pointers = POINTERS.get().unwrap(); - let pc = get_pc(cpu); - - if ptr_pos <= pointers.len() { - if ptr_pos == pointers.len() { - virtual_memory_write(cpu, pc, SAVED_BUF.get().unwrap()); - None - } else { - POINTERS_READ.fetch_add(1, Ordering::SeqCst); - Some(pointers[ptr_pos] as usize) + println!("ptr_pos {}, ptrs.len() {}", ptr_pos, pointers.len()); + + if ptr_pos < pointers.len() { + POINTERS_READ.fetch_add(1, Ordering::SeqCst); + println!("Returning {:#x}", pointers[ptr_pos]); + // on the last ptr_pos replace the new code + if ptr_pos == pointers.len() -1 { + virtual_memory_write(cpu, *SAVED_PC.get().unwrap(), SAVED_BUF.get().unwrap()); } + Some(pointers[ptr_pos] as usize) } else { None } @@ -127,7 +142,8 @@ fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { fn hyp_stop(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { if POINTERS_READ.load(Ordering::SeqCst) == POINTERS.get().unwrap().len() { - virtual_memory_write(cpu, arg1 as u64, "\x01\x02\x03\x04".as_bytes()); + virtual_memory_write(cpu, arg1 as target_ulong, "\x01\x02\x03\x04".as_bytes()); + virtual_memory_write(cpu, *SAVED_PC.get().unwrap(), SAVED_BUF.get().unwrap()); } None } @@ -149,7 +165,7 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { }; match retval { - Some(p) => set_reg(cpu, Reg::RAX, p as u64), + Some(p) => set_reg(cpu, Reg::EAX, p as target_ulong), None => (), } } @@ -163,6 +179,7 @@ fn entry_hook( _exit_code: u8, hook: &mut Hook, ) { + println!("AT ENTRY_HOOK"); let inject_bytes = include_bytes!("./injectables/tiny_mmap"); let (text_data, offset, section_size) = parse_file_data(&inject_bytes[..]); assert_eq!( @@ -170,12 +187,14 @@ fn entry_hook( "get better shellcode. why is there another function?" ); let pc = get_pc(cpu); + SAVED_PC.set(pc).unwrap(); SAVED_BUF .set( virtual_memory_read(cpu, pc, section_size as usize) .expect("failed to read buf. you might need a smaller injector or another stage"), ) .unwrap(); + println!("Writing {:#x} bytes at {:#x}",section_size, pc); virtual_memory_write(cpu, pc, text_data); println!("Replacing bytes at PC with tiny_mmap"); @@ -207,9 +226,10 @@ extern "C" fn handle_proc_start( } } + #[panda::init] fn init(_: &mut PluginHandle) -> bool { - println!("Initialized!"); + lazy_static::initialize(&ARGS); PROC_START_LINUX.add_callback_on_rec_auxv(handle_proc_start); true } From fea15129e819591c0e87dbbafcd3d84c8ee23f49 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 29 Sep 2021 12:07:51 -0400 Subject: [PATCH 04/79] Fix linjector compilation issues --- panda/plugins/linjector/.gitignore | 3 + panda/plugins/linjector/Cargo.lock | 493 ++++++++++++++++++ panda/plugins/linjector/Cargo.toml | 1 + .../linjector/src/injectables/Makefile | 4 +- panda/plugins/linjector/src/lib.rs | 36 +- 5 files changed, 524 insertions(+), 13 deletions(-) create mode 100644 panda/plugins/linjector/.gitignore create mode 100644 panda/plugins/linjector/Cargo.lock diff --git a/panda/plugins/linjector/.gitignore b/panda/plugins/linjector/.gitignore new file mode 100644 index 00000000000..bdb80413b49 --- /dev/null +++ b/panda/plugins/linjector/.gitignore @@ -0,0 +1,3 @@ +/target +src/injectables/injector +src/injectables/tiny_mmap diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock new file mode 100644 index 00000000000..300aeec2feb --- /dev/null +++ b/panda/plugins/linjector/Cargo.lock @@ -0,0 +1,493 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ctor" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "inventory" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "linjector" +version = "0.1.0" +dependencies = [ + "lazy_static", + "object", + "once_cell", + "panda-re", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "object" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" +dependencies = [ + "flate2", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + +[[package]] +name = "panda-re" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f70db200bc5fd6609d6a6eadb571964507dcb308dd98fbc8b5bd5586fa2fa270" +dependencies = [ + "dirs", + "glib-sys", + "inventory", + "lazy_static", + "libloading", + "panda-re-macros", + "panda-re-sys", + "paste", + "strum 0.20.0", + "strum_macros 0.20.1", + "thiserror", +] + +[[package]] +name = "panda-re-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daee3587300135fd563445fe7511eff6e67474007aeeae2b58734eab3e71082b" +dependencies = [ + "darling", + "doc-comment", + "quote", + "syn", +] + +[[package]] +name = "panda-re-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0721969582932a84196625fd23b02e514dd6d1291f7fa074929f416fb56929a" + +[[package]] +name = "paste" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" + +[[package]] +name = "pkg-config" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" + +[[package]] +name = "proc-macro2" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "serde" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "strum" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" + +[[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" + +[[package]] +name = "strum_macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" +dependencies = [ + "heck", + "pkg-config", + "strum 0.18.0", + "strum_macros 0.18.0", + "thiserror", + "toml", + "version-compare", +] + +[[package]] +name = "thiserror" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index 6aacfe61b5e..a8eb0ec2884 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["cdylib"] panda-re = { version = "0.13.0", default-features = false } once_cell = "1.8.0" object = "0.26.2" +lazy_static = "1.4.0" [features] default = ["x86_64"] diff --git a/panda/plugins/linjector/src/injectables/Makefile b/panda/plugins/linjector/src/injectables/Makefile index 854de7ca585..1616672f058 100644 --- a/panda/plugins/linjector/src/injectables/Makefile +++ b/panda/plugins/linjector/src/injectables/Makefile @@ -1,5 +1,5 @@ .DEFAULT_GOAL := all -LIST=hello_world read_file read_all_files injector tiny_mmap +LIST=injector tiny_mmap all: $(LIST) @@ -28,4 +28,4 @@ basic_hello_world: basic_hello_world.c $(CC) -static $< -o $@ clean: - rm -rf $(LIST) \ No newline at end of file + rm -rf $(LIST) diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 2209f885168..08f8f1a8c9d 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -23,14 +23,16 @@ const X86_REG_ORDER: [Reg; 4] = [Reg::EAX, Reg::EBX, Reg::ECX, Reg::EDX]; #[name = "linjector"] // plugin name struct Args { #[arg(required)] - proc: String + proc: String, + + #[arg(default = "guest_daemon")] + guest_binary: String, } lazy_static::lazy_static! { static ref ARGS: Args = Args::from_panda_args(); } - #[derive(Copy, Clone)] pub enum HcCmd { Noop = 0, @@ -96,12 +98,14 @@ fn inject_hook( fn hyp_start(_cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { println!("Got to hyp_start"); - inject_hook::hook().after_block_exec().at_addr(arg1 as target_ulong); + inject_hook::hook() + .after_block_exec() + .at_addr(arg1 as target_ulong); None } fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { - ELF_TO_INJECT.get_or_init(|| std::fs::read(ARGS.guest_binary).unwrap()); + ELF_TO_INJECT.get_or_init(|| std::fs::read(&ARGS.guest_binary).unwrap()); let buf_to_write = arg1; let size_requested = arg2; @@ -119,7 +123,6 @@ fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { } } - fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { println!("Got to read with {:#x}", arg1); assert!(arg1 != 0, "arg1 is a fork return 0 is the child"); @@ -131,8 +134,12 @@ fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { POINTERS_READ.fetch_add(1, Ordering::SeqCst); println!("Returning {:#x}", pointers[ptr_pos]); // on the last ptr_pos replace the new code - if ptr_pos == pointers.len() -1 { - virtual_memory_write(cpu, *SAVED_PC.get().unwrap(), SAVED_BUF.get().unwrap()); + if ptr_pos == pointers.len() - 1 { + virtual_memory_write( + cpu, + *SAVED_PC.get().unwrap(), + SAVED_BUF.get().unwrap(), + ); } Some(pointers[ptr_pos] as usize) } else { @@ -142,8 +149,16 @@ fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { fn hyp_stop(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { if POINTERS_READ.load(Ordering::SeqCst) == POINTERS.get().unwrap().len() { - virtual_memory_write(cpu, arg1 as target_ulong, "\x01\x02\x03\x04".as_bytes()); - virtual_memory_write(cpu, *SAVED_PC.get().unwrap(), SAVED_BUF.get().unwrap()); + virtual_memory_write( + cpu, + arg1 as target_ulong, + "\x01\x02\x03\x04".as_bytes(), + ); + virtual_memory_write( + cpu, + *SAVED_PC.get().unwrap(), + SAVED_BUF.get().unwrap(), + ); } None } @@ -194,7 +209,7 @@ fn entry_hook( .expect("failed to read buf. you might need a smaller injector or another stage"), ) .unwrap(); - println!("Writing {:#x} bytes at {:#x}",section_size, pc); + println!("Writing {:#x} bytes at {:#x}", section_size, pc); virtual_memory_write(cpu, pc, text_data); println!("Replacing bytes at PC with tiny_mmap"); @@ -226,7 +241,6 @@ extern "C" fn handle_proc_start( } } - #[panda::init] fn init(_: &mut PluginHandle) -> bool { lazy_static::initialize(&ARGS); From 86e8569f2c90da52672bc79515d33e1965d38a05 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 29 Sep 2021 12:44:26 -0400 Subject: [PATCH 05/79] Cleanup linjector some --- panda/plugins/linjector/src/lib.rs | 62 +++++++++++++++++------------ panda/plugins/linjector/src/regs.rs | 16 ++++++++ 2 files changed, 52 insertions(+), 26 deletions(-) create mode 100644 panda/plugins/linjector/src/regs.rs diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 08f8f1a8c9d..d9f57e50e04 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -1,13 +1,21 @@ +use panda::{ + mem::{virtual_memory_read, virtual_memory_write}, + plugins::{ + hooks::Hook, + proc_start_linux::{AuxvValues, PROC_START_LINUX}, + }, + prelude::*, + regs::{get_pc, get_reg, set_reg}, +}; + +use std::{ + cmp::min, + convert::TryFrom, + sync::atomic::{AtomicUsize, Ordering}, +}; + use object::{Object, ObjectSection}; use once_cell::sync::OnceCell; -use panda::mem::{virtual_memory_read, virtual_memory_write}; -use panda::plugins::hooks::Hook; -use panda::plugins::proc_start_linux::{AuxvValues, PROC_START_LINUX}; -use panda::prelude::*; -use panda::regs::{get_pc, get_reg, set_reg, Reg}; -use std::cmp::min; -use std::convert::TryFrom; -use std::sync::atomic::{AtomicUsize, Ordering}; static POINTERS: OnceCell<[target_ulong; 3]> = OnceCell::new(); static POINTERS_READ: AtomicUsize = AtomicUsize::new(0); @@ -17,7 +25,9 @@ static ELF_TO_INJECT: OnceCell> = OnceCell::new(); static ELF_READ_POS: AtomicUsize = AtomicUsize::new(0); const MAGIC: usize = 0x10adc0d3; -const X86_REG_ORDER: [Reg; 4] = [Reg::EAX, Reg::EBX, Reg::ECX, Reg::EDX]; + +mod regs; +use regs::{REG_ORDER, RET_REG}; #[derive(PandaArgs)] #[name = "linjector"] // plugin name @@ -27,6 +37,8 @@ struct Args { #[arg(default = "guest_daemon")] guest_binary: String, + + require_root: bool, } lazy_static::lazy_static! { @@ -76,7 +88,7 @@ fn parse_file_data(file_bytes: &[u8]) -> (&[u8], usize, usize) { } fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { - let reg_to_read = X86_REG_ORDER[num]; + let reg_to_read = REG_ORDER[num]; get_reg(cpu, reg_to_read) as usize } @@ -149,11 +161,7 @@ fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { fn hyp_stop(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { if POINTERS_READ.load(Ordering::SeqCst) == POINTERS.get().unwrap().len() { - virtual_memory_write( - cpu, - arg1 as target_ulong, - "\x01\x02\x03\x04".as_bytes(), - ); + virtual_memory_write(cpu, arg1 as target_ulong, b"\x01\x02\x03\x04"); virtual_memory_write( cpu, *SAVED_PC.get().unwrap(), @@ -179,9 +187,8 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { _ => None, }; - match retval { - Some(p) => set_reg(cpu, Reg::EAX, p as target_ulong), - None => (), + if let Some(retval) = retval { + set_reg(cpu, RET_REG, retval as target_ulong); } } true @@ -216,25 +223,29 @@ fn entry_hook( hook.enabled = false; } -extern "C" fn handle_proc_start( +#[panda::on_rec_auxv] +fn handle_proc_start( _cpu: &mut CPUState, _tb: &mut TranslationBlock, auxv: &AuxvValues, ) { - if true { - // auxv.euid == 0 for root only + if !ARGS.require_root || auxv.euid == 0 { println!("accepting new proc with euid {}", auxv.euid); // get pointers to values for re-starting process - let execfn_ptr = auxv.execfn_ptr; - let argv_ptr_ptr = auxv.argv_ptr_ptr; - let env_ptr_ptr = auxv.env_ptr_ptr; + + let &AuxvValues { + execfn_ptr, + argv_ptr_ptr, + env_ptr_ptr, + .. + } = auxv; // in your callback POINTERS .set([execfn_ptr, argv_ptr_ptr, env_ptr_ptr]) .unwrap(); - // set a + // set a hook at the entrypoint entry_hook::hook().after_block_exec().at_addr(auxv.entry); PROC_START_LINUX.remove_callback_on_rec_auxv(handle_proc_start); @@ -244,7 +255,6 @@ extern "C" fn handle_proc_start( #[panda::init] fn init(_: &mut PluginHandle) -> bool { lazy_static::initialize(&ARGS); - PROC_START_LINUX.add_callback_on_rec_auxv(handle_proc_start); true } diff --git a/panda/plugins/linjector/src/regs.rs b/panda/plugins/linjector/src/regs.rs new file mode 100644 index 00000000000..c3bfe36d056 --- /dev/null +++ b/panda/plugins/linjector/src/regs.rs @@ -0,0 +1,16 @@ +use panda::regs::Reg; + +// =================== Register Order =================== +#[cfg(feature = "i386")] +pub const REG_ORDER: [Reg; 4] = [Reg::EAX, Reg::EBX, Reg::ECX, Reg::EDX]; + +// XXX: is this right? +#[cfg(feature = "x86_64")] +pub const REG_ORDER: [Reg; 4] = [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX]; + +// =================== Return Value =================== +#[cfg(feature = "i386")] +pub const RET_REG: Reg = Reg::EAX; + +#[cfg(feature = "x86_64")] +pub const RET_REG: Reg = Reg::RAX; From 7626b22fcfeb0fe448f870bbce148d85db8ea56c Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 29 Sep 2021 13:21:47 -0400 Subject: [PATCH 06/79] remove some prints --- panda/plugins/linjector/src/lib.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index d9f57e50e04..3cca30083b6 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -55,7 +55,7 @@ pub enum HcCmd { Error, /* report error to hypervisor*/ ConditionalOp, /* ask the hypervisor if op should be completed*/ NextStateMachine, /* ask the hypervisor manager to move to the next - state machine*/ + state machine*/ } impl TryFrom for HcCmd { @@ -109,7 +109,6 @@ fn inject_hook( } fn hyp_start(_cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { - println!("Got to hyp_start"); inject_hook::hook() .after_block_exec() .at_addr(arg1 as target_ulong); @@ -122,11 +121,11 @@ fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { let size_requested = arg2; let read_pos = ELF_READ_POS.load(Ordering::SeqCst); - let buf_size = ELF_TO_INJECT.get().expect("").len(); + let buf_size = ELF_TO_INJECT.get().unwrap().len(); if read_pos < buf_size { let lower = read_pos; let upper = min(buf_size, read_pos + size_requested); - let data_to_write = &ELF_TO_INJECT.get().expect("")[lower..upper]; + let data_to_write = &ELF_TO_INJECT.get().unwrap()[lower..upper]; virtual_memory_write(cpu, buf_to_write as target_ulong, data_to_write); ELF_READ_POS.fetch_add(upper - lower, Ordering::SeqCst); Some(upper - lower) @@ -136,7 +135,6 @@ fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { } fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { - println!("Got to read with {:#x}", arg1); assert!(arg1 != 0, "arg1 is a fork return 0 is the child"); let ptr_pos = POINTERS_READ.load(Ordering::SeqCst); let pointers = POINTERS.get().unwrap(); @@ -201,7 +199,6 @@ fn entry_hook( _exit_code: u8, hook: &mut Hook, ) { - println!("AT ENTRY_HOOK"); let inject_bytes = include_bytes!("./injectables/tiny_mmap"); let (text_data, offset, section_size) = parse_file_data(&inject_bytes[..]); assert_eq!( @@ -259,6 +256,4 @@ fn init(_: &mut PluginHandle) -> bool { } #[panda::uninit] -fn exit(_: &mut PluginHandle) { - println!("Exiting"); -} +fn exit(_: &mut PluginHandle) {} From 689ca7457d5290e818350da547af14b3401d0895 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 29 Sep 2021 13:40:11 -0400 Subject: [PATCH 07/79] initial gpm --- panda/plugins/guest_plugin_manager/Cargo.lock | 425 ++++++++++++++++++ panda/plugins/guest_plugin_manager/Cargo.toml | 22 + panda/plugins/guest_plugin_manager/Makefile | 18 + panda/plugins/guest_plugin_manager/README.md | 95 ++++ panda/plugins/guest_plugin_manager/src/lib.rs | 16 + 5 files changed, 576 insertions(+) create mode 100644 panda/plugins/guest_plugin_manager/Cargo.lock create mode 100644 panda/plugins/guest_plugin_manager/Cargo.toml create mode 100644 panda/plugins/guest_plugin_manager/Makefile create mode 100644 panda/plugins/guest_plugin_manager/README.md create mode 100644 panda/plugins/guest_plugin_manager/src/lib.rs diff --git a/panda/plugins/guest_plugin_manager/Cargo.lock b/panda/plugins/guest_plugin_manager/Cargo.lock new file mode 100644 index 00000000000..06a5d341779 --- /dev/null +++ b/panda/plugins/guest_plugin_manager/Cargo.lock @@ -0,0 +1,425 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ctor" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "inventory" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "panda-re" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8040bb4e407d4c2c5a564f5b0974387e2aa7566851b1bf3e26819cfc3ff7e4bc" +dependencies = [ + "dirs", + "glib-sys", + "inventory", + "lazy_static", + "libloading", + "panda-re-macros", + "panda-re-sys", + "paste", + "strum 0.20.0", + "strum_macros 0.20.1", + "thiserror", +] + +[[package]] +name = "panda-re-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c27b19c47785554542bb20b2a8185c15bb9c30694efea83eaccf1725bcf13e80" +dependencies = [ + "darling", + "doc-comment", + "quote", + "syn", +] + +[[package]] +name = "panda-re-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a37f3c9092a0586216fbeda31e9130558ae40e27120ad7616cecb8b6cf2d020" + +[[package]] +name = "paste" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "proc-macro2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "rust_skeleton" +version = "0.1.0" +dependencies = [ + "panda-re", +] + +[[package]] +name = "serde" +version = "1.0.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "strum" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" + +[[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" + +[[package]] +name = "strum_macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" +dependencies = [ + "heck", + "pkg-config", + "strum 0.18.0", + "strum_macros 0.18.0", + "thiserror", + "toml", + "version-compare", +] + +[[package]] +name = "thiserror" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/plugins/guest_plugin_manager/Cargo.toml b/panda/plugins/guest_plugin_manager/Cargo.toml new file mode 100644 index 00000000000..3574fe10a8f --- /dev/null +++ b/panda/plugins/guest_plugin_manager/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "rust_skeleton" +version = "0.1.0" +authors = ["Luke Craig ", "Jordan McLeod "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +panda-re = { version = "0.9.1", default-features = false } + +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +aarch64 = ["panda-re/aarch64"] diff --git a/panda/plugins/guest_plugin_manager/Makefile b/panda/plugins/guest_plugin_manager/Makefile new file mode 100644 index 00000000000..2234476df57 --- /dev/null +++ b/panda/plugins/guest_plugin_manager/Makefile @@ -0,0 +1,18 @@ +# Don't forget to add your plugin to config.panda! + +# Build rust plugins with make! + +# The main rule for your plugin. List all object-file dependencies. + +PANDA_PATH = $(realpath $(shell pwd)/..) +PLUGIN_DIR = $(realpath $(join $(PANDA_PATH), /../panda/plugins/$(PLUGIN_NAME)/)) +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so : $(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + @echo " CARGO $(PLUGIN_DIR)" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --no-default-features --features=$(TARGET_NAME) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @cp -p $(PLUGIN_ARTIFACTS_DIR)/release/lib$(PLUGIN_NAME).so $@ diff --git a/panda/plugins/guest_plugin_manager/README.md b/panda/plugins/guest_plugin_manager/README.md new file mode 100644 index 00000000000..81a52bc976b --- /dev/null +++ b/panda/plugins/guest_plugin_manager/README.md @@ -0,0 +1,95 @@ +# Rust Skeleton + +This is a basic example of how to build a PANDA plugin with Rust. + +## Building + +To check if the plugin will build: + +``` +cargo check +``` + +To actually build the plugin: + +``` +cargo build --release +``` + +(remove `--release` if you want to build in debug mode) + +The resulting plugin will be located in `target/release/librust_skeleton.so`. + +## Structure + +``` +├── Cargo.toml +├── Makefile +├── README.md +└── src + └── lib.rs +``` + +* Cargo.toml - The core plugin info. This informs `cargo` how to actually go about building the plugin. It includes the name, dependencies, and features of plugins. +* Makefile - Instructions for how the PANDA build system will build the plugin. +* lib.rs - The main source file of your plugin. Additional source files can be referenced from here. + +## Cargo.toml + +The dependencies section: + +```toml +[dependencies] +panda-re = { version = "0.5", default-features = false } +``` + +To add a new dependency, add a new line in the form `name = "version"`. + +For example to add [`libc`](https://docs.rs/libc), simply add the following line: + +```toml +libc = "0.2" +``` + +## Targetting Multiple Architectures + +In PANDA, a plugin is recompiled once per target architecture (that is to say, the architecture of the guest). To enable this behavior in Rust plugins, we use ["features"](https://doc.rust-lang.org/cargo/reference/features.html) in order to specify which architecture we are building for. + +This is controlled by this section of Cargo.toml: + +```toml +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +``` + +by default `x86_64` is the only feature enabled (which is why we don't need to specify any features to build), this is primarily so that IDE support (rust-analyzer for VSCode/vim/etc, IntelliJ/CLion integration) works out of the box, as IDEs typically do type checking with the default feature set. + +To build for, say, `arm` you can use the following command: + +``` +cargo build --release --no-default-features --features=arm +``` + +And if you wish to prevent certain code from compiling on certain platforms you can use the following: + +```rust +#[cfg(not(feature = "arm"))] +fn breaks_arm() { + // ... +} +``` + +## Other Resources + +* [panda-rs documentation](https://docs.rs/panda-re) +* [panda-rs announcement blog post](https://panda.re/blog/panda-rs) +* [panda-sys documentation](https://docs.rs/panda-re-sys) +* [The Rust Programming Language](https://doc.rust-lang.org/book/) +* [Some example Rust plugins](https://github.com/panda-re/panda-rs-plugins/) diff --git a/panda/plugins/guest_plugin_manager/src/lib.rs b/panda/plugins/guest_plugin_manager/src/lib.rs new file mode 100644 index 00000000000..91a376fc22b --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/lib.rs @@ -0,0 +1,16 @@ +use panda::prelude::*; + +#[panda::init] +fn init(_: &mut PluginHandle) -> bool { + println!("Initialized!"); + true +} + +#[panda::uninit] +fn exit(_: &mut PluginHandle) { + println!("Exiting"); +} + +#[panda::before_block_exec] +fn bbe(_cpu: &mut CPUState, _tb: &mut TranslationBlock){ +} From 07ada0aba9364d2915fc8687424351086fd25bc6 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 30 Sep 2021 01:07:14 -0400 Subject: [PATCH 08/79] early commits for guest_daemon --- panda/plugins/guest_plugin_manager/Cargo.toml | 6 +- .../plugins/guest_plugin_manager/rustfmt.toml | 1 + .../src/guest_plugin_manager.rs | 76 +++++++++++++++++++ .../guest_plugin_manager/src/hyp_regs.rs | 29 +++++++ .../guest_plugin_manager/src/interface/api.rs | 39 ++++++++++ .../src/interface/guest_daemon_manager.rs | 45 +++++++++++ .../guest_plugin_manager/src/interface/hci.rs | 58 ++++++++++++++ .../guest_plugin_manager/src/interface/mod.rs | 4 + .../src/interface/plugin.rs | 75 ++++++++++++++++++ panda/plugins/guest_plugin_manager/src/lib.rs | 16 ---- 10 files changed, 332 insertions(+), 17 deletions(-) create mode 100644 panda/plugins/guest_plugin_manager/rustfmt.toml create mode 100644 panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs create mode 100644 panda/plugins/guest_plugin_manager/src/hyp_regs.rs create mode 100644 panda/plugins/guest_plugin_manager/src/interface/api.rs create mode 100644 panda/plugins/guest_plugin_manager/src/interface/guest_daemon_manager.rs create mode 100644 panda/plugins/guest_plugin_manager/src/interface/hci.rs create mode 100644 panda/plugins/guest_plugin_manager/src/interface/mod.rs create mode 100644 panda/plugins/guest_plugin_manager/src/interface/plugin.rs delete mode 100644 panda/plugins/guest_plugin_manager/src/lib.rs diff --git a/panda/plugins/guest_plugin_manager/Cargo.toml b/panda/plugins/guest_plugin_manager/Cargo.toml index 3574fe10a8f..4d295fd38c1 100644 --- a/panda/plugins/guest_plugin_manager/Cargo.toml +++ b/panda/plugins/guest_plugin_manager/Cargo.toml @@ -6,9 +6,13 @@ edition = "2018" [lib] crate-type = ["cdylib"] +path = "./src/guest_plugin_manager.rs" [dependencies] -panda-re = { version = "0.9.1", default-features = false } +panda-re = { version = "0.13.0", default-features = false } +crossbeam-queue = "0.3.2" +parking_lot = "0.11.2" +lazy_static = "1.4.0" [features] default = ["x86_64"] diff --git a/panda/plugins/guest_plugin_manager/rustfmt.toml b/panda/plugins/guest_plugin_manager/rustfmt.toml new file mode 100644 index 00000000000..5c8d9318b3b --- /dev/null +++ b/panda/plugins/guest_plugin_manager/rustfmt.toml @@ -0,0 +1 @@ +max_width = 80 \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs new file mode 100644 index 00000000000..ec50ba91b2b --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -0,0 +1,76 @@ +use panda::prelude::*; + +use std::convert::TryFrom; + +mod hyp_regs; +use hyp_regs::{get_hyp_reg, set_hyp_reg}; + +mod interface; +use interface::hci::{hyp_error, hyp_read, hyp_start, hyp_stop, hyp_write}; + +const MAGIC: usize = 0x1337c0d3; + +#[derive(Copy, Clone)] +pub enum HcCmd { + Start = 1, /* start new action */ + Stop, /* stop action */ + Read, /* read buffer from hypervisor */ + Write, /* write buffer TO hypervisor*/ + Error, /* report error to hypervisor*/ +} + +impl TryFrom for HcCmd { + type Error = (); + + fn try_from(value: usize) -> Result { + match value { + 1 => Ok(HcCmd::Start), + 2 => Ok(HcCmd::Stop), + 3 => Ok(HcCmd::Read), + 4 => Ok(HcCmd::Write), + 5 => Ok(HcCmd::Error), + _ => Err(()), + } + } +} + +#[panda::guest_hypercall] +fn hypercall_handler(cpu: &mut CPUState) -> bool { + let magicval = get_hyp_reg(cpu, 0); + if magicval == MAGIC { + let action = get_hyp_reg(cpu, 1); + let channel_id = get_hyp_reg(cpu, 2) as u32; + let first_arg = get_hyp_reg(cpu, 3); + let second_arg = get_hyp_reg(cpu, 4); + + let retval = match HcCmd::try_from(action) { + Ok(HcCmd::Start) => { + hyp_start(cpu, channel_id, first_arg, second_arg) + } + Ok(HcCmd::Write) => { + hyp_write(cpu, channel_id, first_arg, second_arg) + } + Ok(HcCmd::Read) => hyp_read(cpu, channel_id, first_arg, second_arg), + Ok(HcCmd::Stop) => hyp_stop(cpu, channel_id, first_arg, second_arg), + Ok(HcCmd::Error) => { + hyp_error(cpu, channel_id, first_arg, second_arg) + } + _ => None, + }; + + if let Some(retval) = retval { + set_hyp_reg(cpu, 0, retval); + } + } + true +} + +#[panda::init] +fn init(_: &mut PluginHandle) -> bool { + true +} + +#[panda::uninit] +fn exit(_: &mut PluginHandle) { + println!("Exiting"); +} diff --git a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs new file mode 100644 index 00000000000..efb42e248fb --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs @@ -0,0 +1,29 @@ +use panda::{ + prelude::*, + regs::{get_reg, set_reg, Reg}, +}; + +// =================== Register Order =================== +#[cfg(feature = "i386")] +pub const REG_ORDER: [Reg; 4] = [Reg::EAX, Reg::EBX, Reg::ECX, Reg::EDX]; + +// XXX: is this right? +#[cfg(feature = "x86_64")] +pub const REG_ORDER: [Reg; 4] = [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX]; + +// =================== Return Value =================== +#[cfg(feature = "i386")] +pub const RET_REG: Reg = Reg::EAX; + +#[cfg(feature = "x86_64")] +pub const RET_REG: Reg = Reg::RAX; + +pub fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { + let reg_to_read = REG_ORDER[num]; + get_reg(cpu, reg_to_read) as usize +} + +pub fn set_hyp_reg(cpu: &mut CPUState, num: usize, value: usize) { + let reg_to_write = REG_ORDER[num]; + set_reg(cpu, reg_to_write, value as target_ulong) +} diff --git a/panda/plugins/guest_plugin_manager/src/interface/api.rs b/panda/plugins/guest_plugin_manager/src/interface/api.rs new file mode 100644 index 00000000000..2cd7c892a40 --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/interface/api.rs @@ -0,0 +1,39 @@ +use std::ffi::CStr; +use std::os::raw::c_char; +use std::slice::from_raw_parts; + +use super::plugin::{ + add_plugin, publish_message_to_guest, ChannelId, PluginCB, +}; + +#[repr(C)] +pub struct GuestPlugin { + pub name: *const c_char, + pub elf_path: *const c_char, + pub msg_receive_cb: PluginCB, +} + +// returns channel ID +#[no_mangle] +pub extern "C" fn add_guest_plugin(plugin: GuestPlugin) -> ChannelId { + let _elf_path = unsafe { + CStr::from_ptr(plugin.elf_path) + .to_string_lossy() + .into_owned() + }; + let name = unsafe { + CStr::from_ptr(plugin.name) + .to_string_lossy() + .into_owned() + }; + add_plugin(&name, plugin.msg_receive_cb) +} + +#[no_mangle] +pub unsafe extern "C" fn channel_write( + channel: ChannelId, + out: *mut u8, + out_len: usize, +) { + publish_message_to_guest(channel, from_raw_parts(out, out_len).to_vec()) +} diff --git a/panda/plugins/guest_plugin_manager/src/interface/guest_daemon_manager.rs b/panda/plugins/guest_plugin_manager/src/interface/guest_daemon_manager.rs new file mode 100644 index 00000000000..043de9df9d5 --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/interface/guest_daemon_manager.rs @@ -0,0 +1,45 @@ +use super::plugin::{add_plugin}; +use std::mem::size_of; +use std::convert::TryFrom; + +type OperationID = u32; + +enum ManagerOp { + GetChannelFromName = 0, + GetNewChannel = 1, + DebugOutput = 2, +} + +impl TryFrom for ManagerOp { + type Error = (); + + fn try_from(value: usize) -> Result { + match value { + 0 => Ok(ManagerOp::GetChannelFromName), + 1 => Ok(ManagerOp::GetNewChannel), + 2 => Ok(ManagerOp::DebugOutput), + _ => Err(()), + } + } +} + +fn get_channel_from_name(buffer: Vec){ + let plugin_name = String::from_utf8_lossy(&buffer).into_owned(); + if let Some(channel_id) = super::plugin::get_channel_from_name(&plugin_name){ + // publish_message_to_guest(); + } +} + +fn read_callback(mut buf: Vec){ + const OPSIZE: usize = size_of::(); + let mut operation: [u8;OPSIZE] = [0;4]; + operation.copy_from_slice(&buf[..OPSIZE]); + let OpNum = OperationID::from_le_bytes(operation); + buf.drain(0..OPSIZE); + match ManagerOp::try_from(OpNum as usize) { + Ok(ManagerOp::GetChannelFromName) => get_channel_from_name(buf), + Ok(ManagerOp::GetNewChannel) => {}, + Ok(ManagerOp::DebugOutput) => {}, + _ => {} + } +} \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/hci.rs b/panda/plugins/guest_plugin_manager/src/interface/hci.rs new file mode 100644 index 00000000000..200badf6d3e --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/interface/hci.rs @@ -0,0 +1,58 @@ +use super::plugin::ChannelId; +use super::plugin::{poll_plugin_message, publish_message_from_guest}; +use panda::mem::{virtual_memory_read, virtual_memory_write}; +use panda::prelude::*; + +pub fn hyp_start( + cpu: &mut CPUState, + channel_id: ChannelId, + arg1: usize, + _arg2: usize, +) -> Option { + None +} +pub fn hyp_stop( + cpu: &mut CPUState, + channel_id: ChannelId, + arg1: usize, + _arg2: usize, +) -> Option { + None +} +pub fn hyp_read( + cpu: &mut CPUState, + channel_id: ChannelId, + addr: usize, + max_size: usize, +) -> Option { + if let Some(msg) = poll_plugin_message(channel_id) { + virtual_memory_write(cpu, addr as target_ulong, &msg); + Some(msg.len()) + } else { + None + } +} +pub fn hyp_write( + cpu: &mut CPUState, + channel_id: ChannelId, + buf_ptr: usize, + buf_size: usize, +) -> Option { + if let Ok(buf_out) = + virtual_memory_read(cpu, buf_ptr as target_ulong, buf_size) + { + publish_message_from_guest(channel_id, buf_out); + Some(0) + } else { + println!("Failed to read virtual memory in hyp_write"); + None + } +} +pub fn hyp_error( + cpu: &mut CPUState, + channel_id: ChannelId, + arg1: usize, + _arg2: usize, +) -> Option { + None +} diff --git a/panda/plugins/guest_plugin_manager/src/interface/mod.rs b/panda/plugins/guest_plugin_manager/src/interface/mod.rs new file mode 100644 index 00000000000..9b030dbdc4c --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/interface/mod.rs @@ -0,0 +1,4 @@ +pub mod api; +pub mod guest_daemon_manager; +pub mod hci; +pub mod plugin; diff --git a/panda/plugins/guest_plugin_manager/src/interface/plugin.rs b/panda/plugins/guest_plugin_manager/src/interface/plugin.rs new file mode 100644 index 00000000000..16686e5a45c --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/interface/plugin.rs @@ -0,0 +1,75 @@ +use crossbeam_queue::SegQueue; +use panda::prelude::*; +use parking_lot::RwLock; +use std::collections::HashMap; +use lazy_static::lazy_static; +use std::sync::atomic::{AtomicU32, Ordering}; + +pub type ChannelId = u32; +pub type PluginCB = extern "C" fn(Vec); + +static NEXT_PLUGIN_NUMBER: AtomicU32 = AtomicU32::new(0); + +lazy_static!{ +static ref PLUGINS: RwLock> = + RwLock::new(HashMap::new()); +} + +struct Plugin { + name: String, + channel_ids: Vec, + msg_receive_cb: PluginCB, + MessageQueue: SegQueue>, +} + +pub fn add_plugin(p_name: &str, cb: PluginCB) -> ChannelId { + let mut plugins = PLUGINS.write(); + let channel_id = NEXT_PLUGIN_NUMBER.load(Ordering::SeqCst); + if plugins.insert(channel_id, Plugin{ + name: p_name.to_owned(), + channel_ids: Vec::new(), + msg_receive_cb: cb, + MessageQueue: SegQueue::new() + }).is_none() { + panic!("We've somehow added a duplicate ID"); + } + NEXT_PLUGIN_NUMBER.fetch_add(1, Ordering::SeqCst); + channel_id +} + +pub fn poll_plugin_message(channel_id: ChannelId) -> Option> { + let pm = PLUGINS.read(); + if let Some(plugin) = pm.get(&channel_id){ + if let Some(msg) = plugin.MessageQueue.pop() { + Some(msg) + } else { + None + } + } else { + panic!("poll_plugin_message for plugin with incorrect ID"); + } +} + +pub fn publish_message_from_guest(channel_id: ChannelId, msg: Vec) { + let pm = PLUGINS.read(); + if let Some(plugin) = pm.get(&channel_id){ + (plugin.msg_receive_cb)(msg) + } +} + +pub fn publish_message_to_guest(channel_id: ChannelId, msg: Vec) { + let pm = PLUGINS.read(); + if let Some(plugin) = pm.get(&channel_id){ + plugin.MessageQueue.push(msg) + } +} + +pub fn get_channel_from_name(p_name: &str) -> Option{ + let pm = PLUGINS.read(); + for (_,value) in &*pm{ + if value.name == p_name { + return Some(value.channel_ids[0]); + } + } + None +} \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/lib.rs b/panda/plugins/guest_plugin_manager/src/lib.rs deleted file mode 100644 index 91a376fc22b..00000000000 --- a/panda/plugins/guest_plugin_manager/src/lib.rs +++ /dev/null @@ -1,16 +0,0 @@ -use panda::prelude::*; - -#[panda::init] -fn init(_: &mut PluginHandle) -> bool { - println!("Initialized!"); - true -} - -#[panda::uninit] -fn exit(_: &mut PluginHandle) { - println!("Exiting"); -} - -#[panda::before_block_exec] -fn bbe(_cpu: &mut CPUState, _tb: &mut TranslationBlock){ -} From 94c360f43157bea6d4b56469331f1a3e54fd0478 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 30 Sep 2021 01:11:02 -0400 Subject: [PATCH 09/79] fix publish message type --- panda/plugins/guest_plugin_manager/src/interface/plugin.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/panda/plugins/guest_plugin_manager/src/interface/plugin.rs b/panda/plugins/guest_plugin_manager/src/interface/plugin.rs index 16686e5a45c..ee90300d560 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/plugin.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/plugin.rs @@ -6,7 +6,7 @@ use lazy_static::lazy_static; use std::sync::atomic::{AtomicU32, Ordering}; pub type ChannelId = u32; -pub type PluginCB = extern "C" fn(Vec); +pub type PluginCB = extern "C" fn(*const u8, usize); static NEXT_PLUGIN_NUMBER: AtomicU32 = AtomicU32::new(0); @@ -53,7 +53,8 @@ pub fn poll_plugin_message(channel_id: ChannelId) -> Option> { pub fn publish_message_from_guest(channel_id: ChannelId, msg: Vec) { let pm = PLUGINS.read(); if let Some(plugin) = pm.get(&channel_id){ - (plugin.msg_receive_cb)(msg) + let buf_ptr = msg.as_ptr(); + (plugin.msg_receive_cb)(buf_ptr, msg.len()) } } From 99838bab9da537848e3cb1cf3650140f1ee11dc5 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 30 Sep 2021 01:14:32 -0400 Subject: [PATCH 10/79] add get_channel_from_nam to api --- .../guest_plugin_manager/src/interface/api.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/panda/plugins/guest_plugin_manager/src/interface/api.rs b/panda/plugins/guest_plugin_manager/src/interface/api.rs index 2cd7c892a40..36c30938837 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/api.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/api.rs @@ -3,7 +3,7 @@ use std::os::raw::c_char; use std::slice::from_raw_parts; use super::plugin::{ - add_plugin, publish_message_to_guest, ChannelId, PluginCB, + add_plugin, publish_message_to_guest, ChannelId, PluginCB }; #[repr(C)] @@ -37,3 +37,13 @@ pub unsafe extern "C" fn channel_write( ) { publish_message_to_guest(channel, from_raw_parts(out, out_len).to_vec()) } + +#[no_mangle] +pub extern "C" fn get_channel_from_name(channel_name: *const c_char) -> ChannelId { + let name = unsafe { + CStr::from_ptr(channel_name) + .to_string_lossy() + .into_owned() + }; + super::plugin::get_channel_from_name(&name).unwrap() +} \ No newline at end of file From 3cb13f5c5d307383480895c0fff8c93ff3800b60 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Fri, 1 Oct 2021 00:56:49 -0400 Subject: [PATCH 11/79] added guest_plugin_manager initial implementation --- panda/plugins/guest_plugin_manager/Cargo.toml | 1 + .../src/guest_plugin_manager.rs | 36 ++++----- .../guest_plugin_manager/src/hyp_regs.rs | 5 +- .../guest_plugin_manager/src/interface/api.rs | 25 +++--- .../src/interface/channels.rs | 62 +++++++++++++++ .../src/interface/daemon_manager.rs | 51 +++++++++++++ .../guest_plugin_manager/src/interface/hci.rs | 37 +++++---- .../guest_plugin_manager/src/interface/mod.rs | 5 +- .../src/interface/plugin.rs | 76 ------------------- ...st_daemon_manager.rs => plugin_manager.rs} | 25 +++--- 10 files changed, 189 insertions(+), 134 deletions(-) create mode 100644 panda/plugins/guest_plugin_manager/src/interface/channels.rs create mode 100644 panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs delete mode 100644 panda/plugins/guest_plugin_manager/src/interface/plugin.rs rename panda/plugins/guest_plugin_manager/src/interface/{guest_daemon_manager.rs => plugin_manager.rs} (55%) diff --git a/panda/plugins/guest_plugin_manager/Cargo.toml b/panda/plugins/guest_plugin_manager/Cargo.toml index 4d295fd38c1..320582e4407 100644 --- a/panda/plugins/guest_plugin_manager/Cargo.toml +++ b/panda/plugins/guest_plugin_manager/Cargo.toml @@ -13,6 +13,7 @@ panda-re = { version = "0.13.0", default-features = false } crossbeam-queue = "0.3.2" parking_lot = "0.11.2" lazy_static = "1.4.0" +once_cell = "1.8.0" [features] default = ["x86_64"] diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index ec50ba91b2b..63383e85ae6 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -3,10 +3,10 @@ use panda::prelude::*; use std::convert::TryFrom; mod hyp_regs; -use hyp_regs::{get_hyp_reg, set_hyp_reg}; +use hyp_regs::{get_hyp_reg, set_hyp_ret_reg}; mod interface; -use interface::hci::{hyp_error, hyp_read, hyp_start, hyp_stop, hyp_write}; +use interface::hci::{hyp_error, hyp_read, hyp_start, hyp_stop, hyp_write,hyp_get_manager}; const MAGIC: usize = 0x1337c0d3; @@ -17,6 +17,7 @@ pub enum HcCmd { Read, /* read buffer from hypervisor */ Write, /* write buffer TO hypervisor*/ Error, /* report error to hypervisor*/ + GetManager, /* returns unique chanenl ID to manager from plugin */ } impl TryFrom for HcCmd { @@ -29,6 +30,7 @@ impl TryFrom for HcCmd { 3 => Ok(HcCmd::Read), 4 => Ok(HcCmd::Write), 5 => Ok(HcCmd::Error), + 6 => Ok(HcCmd::GetManager), _ => Err(()), } } @@ -39,34 +41,32 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { let magicval = get_hyp_reg(cpu, 0); if magicval == MAGIC { let action = get_hyp_reg(cpu, 1); - let channel_id = get_hyp_reg(cpu, 2) as u32; - let first_arg = get_hyp_reg(cpu, 3); - let second_arg = get_hyp_reg(cpu, 4); + let chan_id = get_hyp_reg(cpu, 2) as u32; + let arg1 = get_hyp_reg(cpu, 3); + let arg2 = get_hyp_reg(cpu, 4); let retval = match HcCmd::try_from(action) { - Ok(HcCmd::Start) => { - hyp_start(cpu, channel_id, first_arg, second_arg) - } - Ok(HcCmd::Write) => { - hyp_write(cpu, channel_id, first_arg, second_arg) - } - Ok(HcCmd::Read) => hyp_read(cpu, channel_id, first_arg, second_arg), - Ok(HcCmd::Stop) => hyp_stop(cpu, channel_id, first_arg, second_arg), - Ok(HcCmd::Error) => { - hyp_error(cpu, channel_id, first_arg, second_arg) - } + Ok(HcCmd::Start) => hyp_start(cpu, chan_id, arg1, arg2), + Ok(HcCmd::Write) => hyp_write(cpu, chan_id, arg1, arg2), + Ok(HcCmd::Read) => hyp_read(cpu, chan_id, arg1, arg2), + Ok(HcCmd::Stop) => hyp_stop(cpu, chan_id, arg1, arg2), + Ok(HcCmd::Error) => hyp_error(cpu, chan_id, arg1, arg2), + Ok(HcCmd::GetManager) => hyp_get_manager(cpu, chan_id, arg1, arg2), _ => None, }; if let Some(retval) = retval { - set_hyp_reg(cpu, 0, retval); + set_hyp_ret_reg(cpu, retval); } + true + }else{ + false } - true } #[panda::init] fn init(_: &mut PluginHandle) -> bool { + interface::daemon_manager::init(); true } diff --git a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs index efb42e248fb..26b32a4a732 100644 --- a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs +++ b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs @@ -23,7 +23,6 @@ pub fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { get_reg(cpu, reg_to_read) as usize } -pub fn set_hyp_reg(cpu: &mut CPUState, num: usize, value: usize) { - let reg_to_write = REG_ORDER[num]; - set_reg(cpu, reg_to_write, value as target_ulong) +pub fn set_hyp_ret_reg(cpu: &mut CPUState, value: usize) { + set_reg(cpu, RET_REG,value as target_ulong) } diff --git a/panda/plugins/guest_plugin_manager/src/interface/api.rs b/panda/plugins/guest_plugin_manager/src/interface/api.rs index 36c30938837..1c6d550e090 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/api.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/api.rs @@ -1,32 +1,33 @@ use std::ffi::CStr; use std::os::raw::c_char; use std::slice::from_raw_parts; +use super::daemon_manager::load_binary; +use super::channels::add_channel; -use super::plugin::{ - add_plugin, publish_message_to_guest, ChannelId, PluginCB +use super::channels::{ + publish_message_to_guest, ChannelId, ChannelCB }; #[repr(C)] pub struct GuestPlugin { - pub name: *const c_char, - pub elf_path: *const c_char, - pub msg_receive_cb: PluginCB, + pub plugin_name: *const c_char, + pub guest_binary_path: *const c_char, + pub msg_receive_cb: ChannelCB, } // returns channel ID #[no_mangle] pub extern "C" fn add_guest_plugin(plugin: GuestPlugin) -> ChannelId { - let _elf_path = unsafe { - CStr::from_ptr(plugin.elf_path) + let binary_path = unsafe { + CStr::from_ptr(plugin.guest_binary_path) .to_string_lossy() - .into_owned() }; + load_binary(&binary_path); let name = unsafe { - CStr::from_ptr(plugin.name) + CStr::from_ptr(plugin.plugin_name) .to_string_lossy() - .into_owned() }; - add_plugin(&name, plugin.msg_receive_cb) + add_channel(Some(&name), plugin.msg_receive_cb) } #[no_mangle] @@ -45,5 +46,5 @@ pub extern "C" fn get_channel_from_name(channel_name: *const c_char) -> ChannelI .to_string_lossy() .into_owned() }; - super::plugin::get_channel_from_name(&name).unwrap() + super::channels::get_channel_from_name(&name).unwrap() } \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/channels.rs b/panda/plugins/guest_plugin_manager/src/interface/channels.rs new file mode 100644 index 00000000000..302c5f20dd8 --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/interface/channels.rs @@ -0,0 +1,62 @@ +use crossbeam_queue::SegQueue; +use parking_lot::RwLock; +use std::collections::HashMap; +use lazy_static::lazy_static; +use std::sync::atomic::{AtomicU32, Ordering}; + +pub type ChannelId = u32; +pub type ChannelCB = extern "C" fn(ChannelId, *const u8, usize); + +static NEXT_CHANNEL_NUMBER: AtomicU32 = AtomicU32::new(0); + +lazy_static!{ +static ref CHANNELS: RwLock> = + RwLock::new(HashMap::new()); +} + +struct Channel { + name: Option, + msg_receive_cb: ChannelCB, + message_queue: SegQueue>, +} + +pub fn add_channel(p_name: Option<&str>, cb: ChannelCB) -> ChannelId { + let mut plugins = CHANNELS.write(); + let channel_id = NEXT_CHANNEL_NUMBER.fetch_add(1, Ordering::SeqCst); + if plugins.insert(channel_id, Channel { + name: p_name.map(ToString::to_string), + msg_receive_cb: cb, + message_queue: SegQueue::new() + }).is_some() { + panic!("We've somehow added a duplicate ID"); + } + channel_id +} + +pub fn poll_plugin_message(channel_id: ChannelId) -> Option> { + let pm = CHANNELS.read(); + if let Some(plugin) = pm.get(&channel_id){ + plugin.message_queue.pop() + } else { + panic!("poll_plugin_message for plugin with incorrect ID"); + } +} + +pub fn publish_message_from_guest(channel_id: ChannelId, msg: Vec) { + let pm = CHANNELS.read(); + if let Some(plugin) = pm.get(&channel_id){ + let buf_ptr = msg.as_ptr(); + (plugin.msg_receive_cb)(channel_id, buf_ptr, msg.len()) + } +} + +pub fn publish_message_to_guest(channel_id: ChannelId, msg: Vec) { + let pm = CHANNELS.read(); + if let Some(plugin) = pm.get(&channel_id){ + plugin.message_queue.push(msg) + } +} + +pub fn get_channel_from_name(p_name: &str) -> Option{ + CHANNELS.read().iter().find(|(_, v)| v.name.as_deref() == Some(p_name)).map(|x| *x.0) +} \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs b/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs new file mode 100644 index 00000000000..8803ed35668 --- /dev/null +++ b/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs @@ -0,0 +1,51 @@ +use super::channels::{ChannelId, add_channel, publish_message_to_guest}; +use std::fs::read_to_string; +use std::path::Path; +use once_cell::sync::OnceCell; + +const CHANNEL_NAME: &str = "guest_daemon"; +static CHANNEL_DESC: OnceCell = OnceCell::new(); + +enum PacketKind { + LoadPlugin = 0, +} + +#[allow(dead_code)] +struct Packet { + kind: PacketKind, + payload: Vec, +} + +#[allow(dead_code)] +impl PacketKind { + fn from(kind: u32) -> Option { + match kind { + 0 => Some(Self::LoadPlugin), + _ => None + } + } +} + +extern "C" fn read_callback(_channel_id: ChannelId, _ptr: *const u8, _len: usize){} + +pub fn load_binary(binary_path: &str){ + if Path::new(binary_path).is_file() { + if let Ok(binary) = read_to_string(binary_path) { + let payload_size = binary.len(); + let mut buf = u32::to_le_bytes(PacketKind::LoadPlugin as u32).to_vec(); + buf.extend(u32::to_le_bytes(payload_size as u32).to_vec()); + let cd = CHANNEL_DESC.get().unwrap(); + publish_message_to_guest(*cd, buf); + publish_message_to_guest(*cd, binary.as_bytes().to_vec()); + + }else{ + panic!("Failed to read binary at {}", binary_path); + } + }else{ + panic!("failed to check for file {}", binary_path); + } +} + +pub fn init(){ + CHANNEL_DESC.set(add_channel(Some(CHANNEL_NAME), read_callback)).unwrap(); +} \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/hci.rs b/panda/plugins/guest_plugin_manager/src/interface/hci.rs index 200badf6d3e..60dc0c7415a 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/hci.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/hci.rs @@ -1,20 +1,22 @@ -use super::plugin::ChannelId; -use super::plugin::{poll_plugin_message, publish_message_from_guest}; +use super::channels::ChannelId; +use super::channels::{poll_plugin_message, publish_message_from_guest}; +use super::plugin_manager::new_manager_channel; +use crate::MAGIC; use panda::mem::{virtual_memory_read, virtual_memory_write}; use panda::prelude::*; pub fn hyp_start( - cpu: &mut CPUState, - channel_id: ChannelId, - arg1: usize, + _cpu: &mut CPUState, + _channel_id: ChannelId, + _arg1: usize, _arg2: usize, ) -> Option { - None + Some(!MAGIC) } pub fn hyp_stop( - cpu: &mut CPUState, - channel_id: ChannelId, - arg1: usize, + _cpu: &mut CPUState, + _channel_id: ChannelId, + _arg1: usize, _arg2: usize, ) -> Option { None @@ -23,9 +25,10 @@ pub fn hyp_read( cpu: &mut CPUState, channel_id: ChannelId, addr: usize, - max_size: usize, + _max_size: usize, ) -> Option { if let Some(msg) = poll_plugin_message(channel_id) { + // could check max len more virtual_memory_write(cpu, addr as target_ulong, &msg); Some(msg.len()) } else { @@ -49,10 +52,18 @@ pub fn hyp_write( } } pub fn hyp_error( - cpu: &mut CPUState, - channel_id: ChannelId, - arg1: usize, + _cpu: &mut CPUState, + _channel_id: ChannelId, + _arg1: usize, _arg2: usize, ) -> Option { None } + +pub fn hyp_get_manager( + _cpu: &mut CPUState, + _channel_id: ChannelId, + _arg1: usize, + _arg2: usize,) -> Option{ + Some(new_manager_channel() as usize) +} \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/mod.rs b/panda/plugins/guest_plugin_manager/src/interface/mod.rs index 9b030dbdc4c..b732c698581 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/mod.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/mod.rs @@ -1,4 +1,5 @@ pub mod api; -pub mod guest_daemon_manager; +pub mod plugin_manager; pub mod hci; -pub mod plugin; +pub mod channels; +pub mod daemon_manager; \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/plugin.rs b/panda/plugins/guest_plugin_manager/src/interface/plugin.rs deleted file mode 100644 index ee90300d560..00000000000 --- a/panda/plugins/guest_plugin_manager/src/interface/plugin.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crossbeam_queue::SegQueue; -use panda::prelude::*; -use parking_lot::RwLock; -use std::collections::HashMap; -use lazy_static::lazy_static; -use std::sync::atomic::{AtomicU32, Ordering}; - -pub type ChannelId = u32; -pub type PluginCB = extern "C" fn(*const u8, usize); - -static NEXT_PLUGIN_NUMBER: AtomicU32 = AtomicU32::new(0); - -lazy_static!{ -static ref PLUGINS: RwLock> = - RwLock::new(HashMap::new()); -} - -struct Plugin { - name: String, - channel_ids: Vec, - msg_receive_cb: PluginCB, - MessageQueue: SegQueue>, -} - -pub fn add_plugin(p_name: &str, cb: PluginCB) -> ChannelId { - let mut plugins = PLUGINS.write(); - let channel_id = NEXT_PLUGIN_NUMBER.load(Ordering::SeqCst); - if plugins.insert(channel_id, Plugin{ - name: p_name.to_owned(), - channel_ids: Vec::new(), - msg_receive_cb: cb, - MessageQueue: SegQueue::new() - }).is_none() { - panic!("We've somehow added a duplicate ID"); - } - NEXT_PLUGIN_NUMBER.fetch_add(1, Ordering::SeqCst); - channel_id -} - -pub fn poll_plugin_message(channel_id: ChannelId) -> Option> { - let pm = PLUGINS.read(); - if let Some(plugin) = pm.get(&channel_id){ - if let Some(msg) = plugin.MessageQueue.pop() { - Some(msg) - } else { - None - } - } else { - panic!("poll_plugin_message for plugin with incorrect ID"); - } -} - -pub fn publish_message_from_guest(channel_id: ChannelId, msg: Vec) { - let pm = PLUGINS.read(); - if let Some(plugin) = pm.get(&channel_id){ - let buf_ptr = msg.as_ptr(); - (plugin.msg_receive_cb)(buf_ptr, msg.len()) - } -} - -pub fn publish_message_to_guest(channel_id: ChannelId, msg: Vec) { - let pm = PLUGINS.read(); - if let Some(plugin) = pm.get(&channel_id){ - plugin.MessageQueue.push(msg) - } -} - -pub fn get_channel_from_name(p_name: &str) -> Option{ - let pm = PLUGINS.read(); - for (_,value) in &*pm{ - if value.name == p_name { - return Some(value.channel_ids[0]); - } - } - None -} \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/guest_daemon_manager.rs b/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs similarity index 55% rename from panda/plugins/guest_plugin_manager/src/interface/guest_daemon_manager.rs rename to panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs index 043de9df9d5..b1c13dccecc 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/guest_daemon_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs @@ -1,12 +1,13 @@ -use super::plugin::{add_plugin}; +use super::channels::{publish_message_to_guest,ChannelId,add_channel}; use std::mem::size_of; use std::convert::TryFrom; +use std::slice::from_raw_parts; + +type OperationID = u32; -type OperationID = u32; enum ManagerOp { GetChannelFromName = 0, - GetNewChannel = 1, DebugOutput = 2, } @@ -16,7 +17,6 @@ impl TryFrom for ManagerOp { fn try_from(value: usize) -> Result { match value { 0 => Ok(ManagerOp::GetChannelFromName), - 1 => Ok(ManagerOp::GetNewChannel), 2 => Ok(ManagerOp::DebugOutput), _ => Err(()), } @@ -25,21 +25,26 @@ impl TryFrom for ManagerOp { fn get_channel_from_name(buffer: Vec){ let plugin_name = String::from_utf8_lossy(&buffer).into_owned(); - if let Some(channel_id) = super::plugin::get_channel_from_name(&plugin_name){ - // publish_message_to_guest(); + if let Some(channel_id) = super::channels::get_channel_from_name(&plugin_name){ + let buf = u32::to_le_bytes(channel_id); + publish_message_to_guest(channel_id,buf.to_vec()); } } -fn read_callback(mut buf: Vec){ +extern "C" fn read_callback(_channel_id: ChannelId, ptr: *const u8, len: usize){ + let mut buf = unsafe{from_raw_parts(ptr, len).to_vec()}; const OPSIZE: usize = size_of::(); let mut operation: [u8;OPSIZE] = [0;4]; operation.copy_from_slice(&buf[..OPSIZE]); - let OpNum = OperationID::from_le_bytes(operation); + let op_num = OperationID::from_le_bytes(operation); buf.drain(0..OPSIZE); - match ManagerOp::try_from(OpNum as usize) { + match ManagerOp::try_from(op_num as usize) { Ok(ManagerOp::GetChannelFromName) => get_channel_from_name(buf), - Ok(ManagerOp::GetNewChannel) => {}, Ok(ManagerOp::DebugOutput) => {}, _ => {} } +} + +pub fn new_manager_channel() -> ChannelId { + add_channel(None, read_callback) } \ No newline at end of file From 061ef69246754a70cd92bc84a307e24028d66493 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 1 Oct 2021 04:56:22 -0400 Subject: [PATCH 12/79] Add hyperfuse --- panda/plugins/config.panda | 3 + panda/plugins/guest_plugin_manager/Cargo.lock | 107 ++- panda/plugins/guest_plugin_manager/Cargo.toml | 2 +- .../src/guest_plugin_manager.rs | 19 +- .../guest_plugin_manager/src/hyp_regs.rs | 8 +- .../src/interface/daemon_manager.rs | 37 +- .../guest_plugin_manager/src/interface/hci.rs | 12 +- panda/plugins/hyperfuse/Cargo.lock | 699 ++++++++++++++++++ panda/plugins/hyperfuse/Cargo.toml | 31 + panda/plugins/hyperfuse/Makefile | 18 + panda/plugins/hyperfuse/README.md | 95 +++ panda/plugins/hyperfuse/src/lib.rs | 242 ++++++ panda/plugins/hyperfuse/src/types.rs | 86 +++ panda/plugins/linjector/src/lib.rs | 9 +- 14 files changed, 1324 insertions(+), 44 deletions(-) create mode 100644 panda/plugins/hyperfuse/Cargo.lock create mode 100644 panda/plugins/hyperfuse/Cargo.toml create mode 100644 panda/plugins/hyperfuse/Makefile create mode 100644 panda/plugins/hyperfuse/README.md create mode 100644 panda/plugins/hyperfuse/src/lib.rs create mode 100644 panda/plugins/hyperfuse/src/types.rs diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index 72db6034cd5..e555e6cac5b 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -13,10 +13,13 @@ edge_coverage filereadmon forcedexec gdb +guest_plugin_manager hooks hooks2 +hyperfuse libfi lighthouse_coverage +linjector loaded loaded_libs mem_hooks diff --git a/panda/plugins/guest_plugin_manager/Cargo.lock b/panda/plugins/guest_plugin_manager/Cargo.lock index 06a5d341779..296669e8041 100644 --- a/panda/plugins/guest_plugin_manager/Cargo.lock +++ b/panda/plugins/guest_plugin_manager/Cargo.lock @@ -14,6 +14,26 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "crossbeam-queue" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +dependencies = [ + "cfg-if", + "lazy_static", +] + [[package]] name = "ctor" version = "0.1.20" @@ -123,6 +143,17 @@ dependencies = [ "system-deps", ] +[[package]] +name = "guest_plugin_manager" +version = "0.1.0" +dependencies = [ + "crossbeam-queue", + "lazy_static", + "once_cell", + "panda-re", + "parking_lot", +] + [[package]] name = "heck" version = "0.3.3" @@ -138,6 +169,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "instant" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +dependencies = [ + "cfg-if", +] + [[package]] name = "inventory" version = "0.1.10" @@ -182,11 +222,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + [[package]] name = "panda-re" -version = "0.9.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8040bb4e407d4c2c5a564f5b0974387e2aa7566851b1bf3e26819cfc3ff7e4bc" +checksum = "f70db200bc5fd6609d6a6eadb571964507dcb308dd98fbc8b5bd5586fa2fa270" dependencies = [ "dirs", "glib-sys", @@ -203,9 +258,9 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.6.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27b19c47785554542bb20b2a8185c15bb9c30694efea83eaccf1725bcf13e80" +checksum = "daee3587300135fd563445fe7511eff6e67474007aeeae2b58734eab3e71082b" dependencies = [ "darling", "doc-comment", @@ -215,9 +270,34 @@ dependencies = [ [[package]] name = "panda-re-sys" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a37f3c9092a0586216fbeda31e9130558ae40e27120ad7616cecb8b6cf2d020" +checksum = "c0721969582932a84196625fd23b02e514dd6d1291f7fa074929f416fb56929a" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] [[package]] name = "paste" @@ -269,11 +349,10 @@ dependencies = [ ] [[package]] -name = "rust_skeleton" -version = "0.1.0" -dependencies = [ - "panda-re", -] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" @@ -281,6 +360,12 @@ version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + [[package]] name = "strsim" version = "0.9.3" diff --git a/panda/plugins/guest_plugin_manager/Cargo.toml b/panda/plugins/guest_plugin_manager/Cargo.toml index 320582e4407..c57bcff4442 100644 --- a/panda/plugins/guest_plugin_manager/Cargo.toml +++ b/panda/plugins/guest_plugin_manager/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rust_skeleton" +name = "guest_plugin_manager" version = "0.1.0" authors = ["Luke Craig ", "Jordan McLeod "] edition = "2018" diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index 63383e85ae6..19235c11d91 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -6,17 +6,19 @@ mod hyp_regs; use hyp_regs::{get_hyp_reg, set_hyp_ret_reg}; mod interface; -use interface::hci::{hyp_error, hyp_read, hyp_start, hyp_stop, hyp_write,hyp_get_manager}; +use interface::hci::{ + hyp_error, hyp_get_manager, hyp_read, hyp_start, hyp_stop, hyp_write, +}; const MAGIC: usize = 0x1337c0d3; #[derive(Copy, Clone)] pub enum HcCmd { - Start = 1, /* start new action */ - Stop, /* stop action */ - Read, /* read buffer from hypervisor */ - Write, /* write buffer TO hypervisor*/ - Error, /* report error to hypervisor*/ + Start = 1, /* start new action */ + Stop, /* stop action */ + Read, /* read buffer from hypervisor */ + Write, /* write buffer TO hypervisor*/ + Error, /* report error to hypervisor*/ GetManager, /* returns unique chanenl ID to manager from plugin */ } @@ -41,6 +43,7 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { let magicval = get_hyp_reg(cpu, 0); if magicval == MAGIC { let action = get_hyp_reg(cpu, 1); + dbg!(action); let chan_id = get_hyp_reg(cpu, 2) as u32; let arg1 = get_hyp_reg(cpu, 3); let arg2 = get_hyp_reg(cpu, 4); @@ -56,10 +59,10 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { }; if let Some(retval) = retval { - set_hyp_ret_reg(cpu, retval); + set_hyp_ret_reg(cpu, retval); } true - }else{ + } else { false } } diff --git a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs index 26b32a4a732..7bc1e5aaf81 100644 --- a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs +++ b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs @@ -5,11 +5,13 @@ use panda::{ // =================== Register Order =================== #[cfg(feature = "i386")] -pub const REG_ORDER: [Reg; 4] = [Reg::EAX, Reg::EBX, Reg::ECX, Reg::EDX]; +pub const REG_ORDER: [Reg; 5] = + [Reg::EAX, Reg::EBX, Reg::ECX, Reg::EDX, Reg::EDI]; // XXX: is this right? #[cfg(feature = "x86_64")] -pub const REG_ORDER: [Reg; 4] = [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX]; +pub const REG_ORDER: [Reg; 5] = + [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX, Reg::RDI]; // =================== Return Value =================== #[cfg(feature = "i386")] @@ -24,5 +26,5 @@ pub fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { } pub fn set_hyp_ret_reg(cpu: &mut CPUState, value: usize) { - set_reg(cpu, RET_REG,value as target_ulong) + set_reg(cpu, RET_REG, value as target_ulong) } diff --git a/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs b/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs index 8803ed35668..3f6571bec47 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs @@ -1,7 +1,6 @@ -use super::channels::{ChannelId, add_channel, publish_message_to_guest}; -use std::fs::read_to_string; -use std::path::Path; +use super::channels::{add_channel, publish_message_to_guest, ChannelId}; use once_cell::sync::OnceCell; +use std::path::Path; const CHANNEL_NAME: &str = "guest_daemon"; static CHANNEL_DESC: OnceCell = OnceCell::new(); @@ -21,31 +20,39 @@ impl PacketKind { fn from(kind: u32) -> Option { match kind { 0 => Some(Self::LoadPlugin), - _ => None + _ => None, } } } -extern "C" fn read_callback(_channel_id: ChannelId, _ptr: *const u8, _len: usize){} +extern "C" fn read_callback( + _channel_id: ChannelId, + _ptr: *const u8, + _len: usize, +) { +} -pub fn load_binary(binary_path: &str){ +pub fn load_binary(binary_path: &str) { if Path::new(binary_path).is_file() { - if let Ok(binary) = read_to_string(binary_path) { + if let Ok(binary) = std::fs::read(binary_path) { let payload_size = binary.len(); - let mut buf = u32::to_le_bytes(PacketKind::LoadPlugin as u32).to_vec(); + let mut buf = + u32::to_le_bytes(PacketKind::LoadPlugin as u32).to_vec(); buf.extend(u32::to_le_bytes(payload_size as u32).to_vec()); let cd = CHANNEL_DESC.get().unwrap(); publish_message_to_guest(*cd, buf); - publish_message_to_guest(*cd, binary.as_bytes().to_vec()); - - }else{ + publish_message_to_guest(*cd, binary); + } else { panic!("Failed to read binary at {}", binary_path); } - }else{ + } else { panic!("failed to check for file {}", binary_path); } } -pub fn init(){ - CHANNEL_DESC.set(add_channel(Some(CHANNEL_NAME), read_callback)).unwrap(); -} \ No newline at end of file +pub fn init() { + CHANNEL_DESC + .set(add_channel(Some(CHANNEL_NAME), read_callback)) + .unwrap(); +} + diff --git a/panda/plugins/guest_plugin_manager/src/interface/hci.rs b/panda/plugins/guest_plugin_manager/src/interface/hci.rs index 60dc0c7415a..3c0bc411264 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/hci.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/hci.rs @@ -11,6 +11,7 @@ pub fn hyp_start( _arg1: usize, _arg2: usize, ) -> Option { + println!("start"); Some(!MAGIC) } pub fn hyp_stop( @@ -19,6 +20,7 @@ pub fn hyp_stop( _arg1: usize, _arg2: usize, ) -> Option { + println!("stop"); None } pub fn hyp_read( @@ -27,6 +29,7 @@ pub fn hyp_read( addr: usize, _max_size: usize, ) -> Option { + println!("read"); if let Some(msg) = poll_plugin_message(channel_id) { // could check max len more virtual_memory_write(cpu, addr as target_ulong, &msg); @@ -41,6 +44,7 @@ pub fn hyp_write( buf_ptr: usize, buf_size: usize, ) -> Option { + println!("write"); if let Ok(buf_out) = virtual_memory_read(cpu, buf_ptr as target_ulong, buf_size) { @@ -57,6 +61,7 @@ pub fn hyp_error( _arg1: usize, _arg2: usize, ) -> Option { + println!("error"); None } @@ -64,6 +69,9 @@ pub fn hyp_get_manager( _cpu: &mut CPUState, _channel_id: ChannelId, _arg1: usize, - _arg2: usize,) -> Option{ + _arg2: usize, +) -> Option { + println!("get_manager"); Some(new_manager_channel() as usize) -} \ No newline at end of file +} + diff --git a/panda/plugins/hyperfuse/Cargo.lock b/panda/plugins/hyperfuse/Cargo.lock new file mode 100644 index 00000000000..c66a87ba5fe --- /dev/null +++ b/panda/plugins/hyperfuse/Cargo.lock @@ -0,0 +1,699 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crossbeam-queue" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "ctor" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fuser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "166e3212e0cc562dd17eefa4d80cf443720eec051e7171fe2b94e4ba8d272786" +dependencies = [ + "libc", + "log", + "memchr", + "page_size", + "pkg-config", + "serde", + "smallvec", + "users", + "zerocopy", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyperfuse" +version = "0.1.0" +dependencies = [ + "bincode", + "crossbeam-queue", + "env_logger", + "fuser", + "lazy_static", + "libc", + "panda-re", + "parking_lot", + "serde", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "instant" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "inventory" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "page_size" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "panda-re" +version = "0.13.0" +dependencies = [ + "dirs", + "glib-sys", + "inventory", + "lazy_static", + "libloading", + "panda-re-macros", + "panda-re-sys", + "paste", + "strum 0.20.0", + "strum_macros 0.20.1", + "thiserror", +] + +[[package]] +name = "panda-re-macros" +version = "0.9.0" +dependencies = [ + "darling", + "doc-comment", + "quote", + "syn", +] + +[[package]] +name = "panda-re-sys" +version = "0.4.0" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "proc-macro2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "strum" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" + +[[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" + +[[package]] +name = "strum_macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" +dependencies = [ + "heck", + "pkg-config", + "strum 0.18.0", + "strum_macros 0.18.0", + "thiserror", + "toml", + "version-compare", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", + "log", +] + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "zerocopy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6580539ad917b7c026220c4b3f2c08d52ce54d6ce0dc491e66002e35388fab46" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" +dependencies = [ + "proc-macro2", + "syn", + "synstructure", +] diff --git a/panda/plugins/hyperfuse/Cargo.toml b/panda/plugins/hyperfuse/Cargo.toml new file mode 100644 index 00000000000..c8d3f630b6d --- /dev/null +++ b/panda/plugins/hyperfuse/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "hyperfuse" +version = "0.1.0" +authors = ["Luke Craig ", "Jordan McLeod "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +#panda-re = { version = "0.13.0", default-features = false } +panda-re = { path = "/home/jamcleod/dev/work/panda-rs/panda-rs", default-features = false } +fuser = { version = "0.8.0", features = ["serializable"] } +libc = "0.2.98" +env_logger = "0.9.0" +serde = { version = "1", features = ["derive"] } +bincode = "1.3.3" +lazy_static = "1" +parking_lot = "0.11" +crossbeam-queue = "0.3" + +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +aarch64 = ["panda-re/aarch64"] diff --git a/panda/plugins/hyperfuse/Makefile b/panda/plugins/hyperfuse/Makefile new file mode 100644 index 00000000000..2234476df57 --- /dev/null +++ b/panda/plugins/hyperfuse/Makefile @@ -0,0 +1,18 @@ +# Don't forget to add your plugin to config.panda! + +# Build rust plugins with make! + +# The main rule for your plugin. List all object-file dependencies. + +PANDA_PATH = $(realpath $(shell pwd)/..) +PLUGIN_DIR = $(realpath $(join $(PANDA_PATH), /../panda/plugins/$(PLUGIN_NAME)/)) +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so : $(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + @echo " CARGO $(PLUGIN_DIR)" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --no-default-features --features=$(TARGET_NAME) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @cp -p $(PLUGIN_ARTIFACTS_DIR)/release/lib$(PLUGIN_NAME).so $@ diff --git a/panda/plugins/hyperfuse/README.md b/panda/plugins/hyperfuse/README.md new file mode 100644 index 00000000000..81a52bc976b --- /dev/null +++ b/panda/plugins/hyperfuse/README.md @@ -0,0 +1,95 @@ +# Rust Skeleton + +This is a basic example of how to build a PANDA plugin with Rust. + +## Building + +To check if the plugin will build: + +``` +cargo check +``` + +To actually build the plugin: + +``` +cargo build --release +``` + +(remove `--release` if you want to build in debug mode) + +The resulting plugin will be located in `target/release/librust_skeleton.so`. + +## Structure + +``` +├── Cargo.toml +├── Makefile +├── README.md +└── src + └── lib.rs +``` + +* Cargo.toml - The core plugin info. This informs `cargo` how to actually go about building the plugin. It includes the name, dependencies, and features of plugins. +* Makefile - Instructions for how the PANDA build system will build the plugin. +* lib.rs - The main source file of your plugin. Additional source files can be referenced from here. + +## Cargo.toml + +The dependencies section: + +```toml +[dependencies] +panda-re = { version = "0.5", default-features = false } +``` + +To add a new dependency, add a new line in the form `name = "version"`. + +For example to add [`libc`](https://docs.rs/libc), simply add the following line: + +```toml +libc = "0.2" +``` + +## Targetting Multiple Architectures + +In PANDA, a plugin is recompiled once per target architecture (that is to say, the architecture of the guest). To enable this behavior in Rust plugins, we use ["features"](https://doc.rust-lang.org/cargo/reference/features.html) in order to specify which architecture we are building for. + +This is controlled by this section of Cargo.toml: + +```toml +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +``` + +by default `x86_64` is the only feature enabled (which is why we don't need to specify any features to build), this is primarily so that IDE support (rust-analyzer for VSCode/vim/etc, IntelliJ/CLion integration) works out of the box, as IDEs typically do type checking with the default feature set. + +To build for, say, `arm` you can use the following command: + +``` +cargo build --release --no-default-features --features=arm +``` + +And if you wish to prevent certain code from compiling on certain platforms you can use the following: + +```rust +#[cfg(not(feature = "arm"))] +fn breaks_arm() { + // ... +} +``` + +## Other Resources + +* [panda-rs documentation](https://docs.rs/panda-re) +* [panda-rs announcement blog post](https://panda.re/blog/panda-rs) +* [panda-sys documentation](https://docs.rs/panda-re-sys) +* [The Rust Programming Language](https://doc.rust-lang.org/book/) +* [Some example Rust plugins](https://github.com/panda-re/panda-rs-plugins/) diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs new file mode 100644 index 00000000000..c1b7f714076 --- /dev/null +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -0,0 +1,242 @@ +use fuser::{ + Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, ReplyOpen, + ReplyWrite, +}; +use libc::ENOENT; +use panda::prelude::*; +use serde::{Deserialize, Serialize}; +use std::borrow::Borrow; +use std::ffi::{CString, OsStr}; +use std::marker::PhantomData; +use std::path::Path; +use std::sync::mpsc; + +mod types; +use types::*; + +struct HelloFS { + reply: Receiver, + request: Sender, +} + +macro_rules! on_reply { + ( + $self:ident => $reply:ident ( + $type:ident { $($field:ident),* } + + => $reply_ty:ident { $( + $reply_field:ident + ),*} + + => $code:block + ) $(;)? + ) => { + println!("Before send"); + $self.request.send(Request::$type { $( $field ),* }).unwrap(); + println!("After send"); + match $self.reply.recv() { + Ok(Reply::$reply_ty { $( $reply_field ),* }) => $code, + Ok(Reply::Error(err)) => $reply.error(err), + Ok(reply) => panic!("Invalid reply {:?}", reply), + Err(_) => $reply.error(ENOENT), + } + }; +} + +macro_rules! send_reply { + ( + $self:ident => $reply:ident.$method:ident ( + $type:ident { $($field:ident),* } + + => $reply_ty:ident { $( + $reply_field:ident $( . $reply_field_method:ident () )? + ),*} + ) $(;)? + ) => { + println!("{}(...)", stringify!($method)); + on_reply! { + $self => $reply ( + $type { $($field),* } + + => $reply_ty { $( + $reply_field + ),*} + + => { + $( + let $reply_field = $reply_field $( .$reply_field_method () )?; + )* + $reply.$method( $($reply_field),* ); + } + ) + } + }; +} + +impl Filesystem for HelloFS { + fn lookup(&mut self, _req: &fuser::Request, parent_ino: u64, name: &OsStr, reply: ReplyEntry) { + let name = name.to_string_lossy().into_owned(); + send_reply! { + self => reply.entry( + Lookup { parent_ino, name } => Entry { ttl.borrow(), attr.borrow(), generation } + ); + } + } + + fn getattr(&mut self, _req: &fuser::Request, ino: u64, reply: ReplyAttr) { + send_reply! { + self => reply.attr( + GetAttr { ino } => Attr { ttl.borrow(), attr.borrow() } + ); + } + } + + fn read( + &mut self, + _req: &fuser::Request, + ino: u64, + _fh: u64, + offset: i64, + size: u32, + flags: i32, + _lock: Option, + reply: ReplyData, + ) { + send_reply! { + self => reply.data( + Read { ino, offset, size, flags } => Data { data.as_ref() } + ); + } + } + + fn readdir( + &mut self, + _req: &fuser::Request, + ino: u64, + _fh: u64, + offset: i64, + mut reply: ReplyDirectory, + ) { + on_reply! { + self => reply( + ReadDir { ino, offset } + => Directory { dir_entries } + => { + for DirEntry { ino, offset, kind, name } in dir_entries { + if reply.add(ino, offset, kind, name) { + break + } + } + + reply.ok(); + } + ); + } + } + + fn open(&mut self, _req: &fuser::Request<'_>, ino: u64, flags: i32, reply: ReplyOpen) { + send_reply! { + self => reply.opened( + Open { ino, flags } => Opened { file_handle, flags } + ); + } + } + + fn write( + &mut self, + _req: &fuser::Request<'_>, + ino: u64, + _fh: u64, + offset: i64, + data: &[u8], + write_flags: u32, + flags: i32, + _lock_owner: Option, + reply: ReplyWrite, + ) { + let data = data.to_owned(); + send_reply! { + self => reply.written( + Write { ino, offset, data, write_flags, flags } => Written { size } + ); + } + } +} + +struct Sender(ChannelId, PhantomData); + +impl Sender { + fn send(&self, val: T) -> Result<(), ()> { + let bytes = bincode::serialize(&val).unwrap(); + GUEST_PLUGIN_MANAGER.channel_write(self.0, bytes.as_ptr(), bytes.len()); + Ok(()) + } +} + +struct Receiver>(ChannelId, PhantomData); + +impl Receiver { + fn recv(&self) -> Result { + loop { + match MESSAGE_QUEUE.pop() { + Some(bytes) => break bincode::deserialize(&bytes).map_err(|_| ()), + None => std::thread::yield_now(), + } + } + } +} + +//fn channel>(channel: ChannelId) -> (Sender, Receiver) { +// (Sender(channel, PhantomData), Receiver(channel, PhantomData)) +//} + +fn mount(channel: ChannelId) { + let mountpoint = "/home/jamcleod/dev/work/fuse-expirement/test"; + let options = vec![ + MountOption::FSName("hello".to_string()), + MountOption::AutoUnmount, + ]; + + let (request, reply) = (Sender(channel, PhantomData), Receiver(channel, PhantomData)); + + //other_thread::start(incoming_request, response); + + fuser::mount2(HelloFS { request, reply }, mountpoint, &options).unwrap(); +} + +use crossbeam_queue::SegQueue; +use panda::plugins::guest_plugin_manager::*; //GUEST_PLUGIN_MANAGER; + +static MESSAGE_QUEUE: SegQueue> = SegQueue::new(); + +extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { + unsafe { + let bytes = std::slice::from_raw_parts(ptr, len); + MESSAGE_QUEUE.push(bytes.to_owned()); + } +} + +#[panda::init] +fn init(_: &mut PluginHandle) -> bool { + let path = "/home/jamcleod/dev/work/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/guest_daemon"; + let plugin_name = CString::new("linjector".as_bytes()).unwrap(); + let plugin_arg = CString::new(format!("guest_binary={}", path).as_bytes()).unwrap(); + unsafe { + let path = panda::sys::panda_plugin_path(plugin_name.as_ptr()); + panda::sys::panda_add_arg(plugin_name.as_ptr(), plugin_arg.as_ptr()); + panda::sys::panda_load_plugin(path, plugin_name.as_ptr()); + } + + GUEST_PLUGIN_MANAGER.ensure_init(); + let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( + "hyperfuse".into(), + Path::new("/home/jamcleod/dev/work/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/hyperfuse_guest"), + message_recv, + )); + + std::thread::spawn(move || { + mount(channel); + }); + + true +} diff --git a/panda/plugins/hyperfuse/src/types.rs b/panda/plugins/hyperfuse/src/types.rs new file mode 100644 index 00000000000..d22babc3c51 --- /dev/null +++ b/panda/plugins/hyperfuse/src/types.rs @@ -0,0 +1,86 @@ +use libc::c_int; +use std::time::Duration; + +use fuser::{FileAttr, FileType}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub enum Request { + Lookup { + parent_ino: u64, + name: String, + }, + GetAttr { + ino: u64, + }, + Read { + ino: u64, + offset: i64, + size: u32, + flags: i32, + }, + ReadDir { + ino: u64, + offset: i64, + }, + Open { + ino: u64, + flags: i32, + }, + Write { + ino: u64, + offset: i64, + data: Vec, + write_flags: u32, + flags: i32, + }, + Create { + parent: u64, + name: String, + mode: u32, + umask: u32, + flags: u32, + }, +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum Reply { + Entry { + ttl: Duration, + attr: FileAttr, + generation: u64, + }, + Attr { + ttl: Duration, + attr: FileAttr, + }, + Data { + data: Vec, + }, + Directory { + dir_entries: Vec, + }, + Opened { + file_handle: u64, + flags: u32, + }, + Written { + size: u32, + }, + Created { + ttl: Duration, + attr: FileAttr, + generation: u64, + fh: u64, + flags: u32, + }, + Error(c_int), +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DirEntry { + pub ino: u64, + pub offset: i64, + pub kind: FileType, + pub name: String, +} diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 3cca30083b6..2b09bc84b17 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -32,9 +32,6 @@ use regs::{REG_ORDER, RET_REG}; #[derive(PandaArgs)] #[name = "linjector"] // plugin name struct Args { - #[arg(required)] - proc: String, - #[arg(default = "guest_daemon")] guest_binary: String, @@ -55,7 +52,7 @@ pub enum HcCmd { Error, /* report error to hypervisor*/ ConditionalOp, /* ask the hypervisor if op should be completed*/ NextStateMachine, /* ask the hypervisor manager to move to the next - state machine*/ + state machine*/ } impl TryFrom for HcCmd { @@ -99,6 +96,7 @@ fn inject_hook( _exit_code: u8, hook: &mut Hook, ) { + println!("Inject hook"); let inject_bytes = include_bytes!("./injectables/injector"); let (text_data, _offset, _section_size) = parse_file_data(&inject_bytes[..]); @@ -174,6 +172,7 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { let magicval = get_hyp_reg(cpu, 0); if magicval == MAGIC { let action = get_hyp_reg(cpu, 1); + dbg!(action); let first_arg = get_hyp_reg(cpu, 2); let second_arg = get_hyp_reg(cpu, 3); @@ -199,6 +198,7 @@ fn entry_hook( _exit_code: u8, hook: &mut Hook, ) { + println!("Entry hook"); let inject_bytes = include_bytes!("./injectables/tiny_mmap"); let (text_data, offset, section_size) = parse_file_data(&inject_bytes[..]); assert_eq!( @@ -226,6 +226,7 @@ fn handle_proc_start( _tb: &mut TranslationBlock, auxv: &AuxvValues, ) { + println!("proc start"); if !ARGS.require_root || auxv.euid == 0 { println!("accepting new proc with euid {}", auxv.euid); // get pointers to values for re-starting process From d4df8931fb4e430b53f206bc3265713b478ebd64 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 1 Oct 2021 06:15:48 -0400 Subject: [PATCH 13/79] Write length before payload in hyperfuse --- panda/plugins/hyperfuse/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index c1b7f714076..dde59d7e9d1 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -168,7 +168,11 @@ struct Sender(ChannelId, PhantomData); impl Sender { fn send(&self, val: T) -> Result<(), ()> { let bytes = bincode::serialize(&val).unwrap(); + + let len = (bytes.len() as u32).to_le_bytes(); + GUEST_PLUGIN_MANAGER.channel_write(self.0, len.as_ptr(), 4); GUEST_PLUGIN_MANAGER.channel_write(self.0, bytes.as_ptr(), bytes.len()); + Ok(()) } } From 425da249a562ec691ce76883da00b16df74cdbae Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Fri, 1 Oct 2021 06:17:19 -0400 Subject: [PATCH 14/79] no. my hardcoded paths --- panda/plugins/hyperfuse/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index c1b7f714076..628e3938255 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -191,7 +191,7 @@ impl Receiver { //} fn mount(channel: ChannelId) { - let mountpoint = "/home/jamcleod/dev/work/fuse-expirement/test"; + let mountpoint = "/home/luke/workspace/fuse_mount"; let options = vec![ MountOption::FSName("hello".to_string()), MountOption::AutoUnmount, @@ -218,7 +218,7 @@ extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { #[panda::init] fn init(_: &mut PluginHandle) -> bool { - let path = "/home/jamcleod/dev/work/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/guest_daemon"; + let path = "/home/luke/workspace/igloo/pie_idea/guest_code/target/i686-unknown-linux-musl/release/guest_daemon"; let plugin_name = CString::new("linjector".as_bytes()).unwrap(); let plugin_arg = CString::new(format!("guest_binary={}", path).as_bytes()).unwrap(); unsafe { @@ -230,7 +230,7 @@ fn init(_: &mut PluginHandle) -> bool { GUEST_PLUGIN_MANAGER.ensure_init(); let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( "hyperfuse".into(), - Path::new("/home/jamcleod/dev/work/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/hyperfuse_guest"), + Path::new("/home/luke/workspace/igloo/pie_idea/guest_code/target/i686-unknown-linux-musl/debug/hyperfuse_guest"), message_recv, )); From f483620f1a233c14ce39cd1df618cae84ba8846d Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 13 Oct 2021 12:37:40 -0400 Subject: [PATCH 15/79] core changes --- panda/plugins/guest_plugin_manager/Makefile | 2 +- .../src/guest_plugin_manager.rs | 8 +- .../src/interface/channels.rs | 14 +++ .../src/interface/daemon_manager.rs | 20 ++-- .../guest_plugin_manager/src/interface/hci.rs | 37 +++++- .../src/interface/plugin_manager.rs | 15 ++- panda/plugins/guest_shell/Cargo.toml | 22 ++++ panda/plugins/guest_shell/Makefile | 18 +++ panda/plugins/guest_shell/README.md | 95 +++++++++++++++ .../guest_shell/rusty_shell/Cargo.toml | 4 + .../guest_shell/rusty_shell/src/hypercall.rs | 113 ++++++++++++++++++ .../guest_shell/rusty_shell/src/main.rs | 52 ++++++++ panda/plugins/guest_shell/src/lib.rs | 17 +++ panda/plugins/hyperfuse/Cargo.toml | 2 +- panda/plugins/hyperfuse/src/lib.rs | 9 +- panda/plugins/linjector/README.md | 95 +++++++++++++++ panda/plugins/linjector/src/lib.rs | 8 +- 17 files changed, 504 insertions(+), 27 deletions(-) create mode 100644 panda/plugins/guest_shell/Cargo.toml create mode 100644 panda/plugins/guest_shell/Makefile create mode 100644 panda/plugins/guest_shell/README.md create mode 100644 panda/plugins/guest_shell/rusty_shell/Cargo.toml create mode 100644 panda/plugins/guest_shell/rusty_shell/src/hypercall.rs create mode 100644 panda/plugins/guest_shell/rusty_shell/src/main.rs create mode 100644 panda/plugins/guest_shell/src/lib.rs create mode 100644 panda/plugins/linjector/README.md diff --git a/panda/plugins/guest_plugin_manager/Makefile b/panda/plugins/guest_plugin_manager/Makefile index 2234476df57..d34fc42957c 100644 --- a/panda/plugins/guest_plugin_manager/Makefile +++ b/panda/plugins/guest_plugin_manager/Makefile @@ -6,7 +6,7 @@ PANDA_PATH = $(realpath $(shell pwd)/..) PLUGIN_DIR = $(realpath $(join $(PANDA_PATH), /../panda/plugins/$(PLUGIN_NAME)/)) -RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +RUST_SOURCE = $(shell find $(PLUGIN_DIR)/src/ -name "*.rs") PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target $(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so : $(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index 19235c11d91..984e29af159 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -7,7 +7,7 @@ use hyp_regs::{get_hyp_reg, set_hyp_ret_reg}; mod interface; use interface::hci::{ - hyp_error, hyp_get_manager, hyp_read, hyp_start, hyp_stop, hyp_write, + hyp_error, hyp_get_manager, hyp_read, hyp_start, hyp_stop, hyp_write,hyp_get_channel_by_name }; const MAGIC: usize = 0x1337c0d3; @@ -20,6 +20,7 @@ pub enum HcCmd { Write, /* write buffer TO hypervisor*/ Error, /* report error to hypervisor*/ GetManager, /* returns unique chanenl ID to manager from plugin */ + GetChannelByName, /* returns existing channel mapped to unique name */ } impl TryFrom for HcCmd { @@ -33,6 +34,7 @@ impl TryFrom for HcCmd { 4 => Ok(HcCmd::Write), 5 => Ok(HcCmd::Error), 6 => Ok(HcCmd::GetManager), + 7 => Ok(HcCmd::GetChannelByName), _ => Err(()), } } @@ -43,7 +45,7 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { let magicval = get_hyp_reg(cpu, 0); if magicval == MAGIC { let action = get_hyp_reg(cpu, 1); - dbg!(action); + // dbg!(action); let chan_id = get_hyp_reg(cpu, 2) as u32; let arg1 = get_hyp_reg(cpu, 3); let arg2 = get_hyp_reg(cpu, 4); @@ -55,12 +57,14 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { Ok(HcCmd::Stop) => hyp_stop(cpu, chan_id, arg1, arg2), Ok(HcCmd::Error) => hyp_error(cpu, chan_id, arg1, arg2), Ok(HcCmd::GetManager) => hyp_get_manager(cpu, chan_id, arg1, arg2), + Ok(HcCmd::GetChannelByName) => hyp_get_channel_by_name(cpu, chan_id, arg1, arg2), _ => None, }; if let Some(retval) = retval { set_hyp_ret_reg(cpu, retval); } + println!("end of hc"); true } else { false diff --git a/panda/plugins/guest_plugin_manager/src/interface/channels.rs b/panda/plugins/guest_plugin_manager/src/interface/channels.rs index 302c5f20dd8..b4f4cb1efa0 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/channels.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/channels.rs @@ -30,10 +30,12 @@ pub fn add_channel(p_name: Option<&str>, cb: ChannelCB) -> ChannelId { }).is_some() { panic!("We've somehow added a duplicate ID"); } + println!("Added channel {} FD: {}", p_name.unwrap_or("?"), channel_id); channel_id } pub fn poll_plugin_message(channel_id: ChannelId) -> Option> { + println!("in poll_plugin_message"); let pm = CHANNELS.read(); if let Some(plugin) = pm.get(&channel_id){ plugin.message_queue.pop() @@ -46,17 +48,29 @@ pub fn publish_message_from_guest(channel_id: ChannelId, msg: Vec) { let pm = CHANNELS.read(); if let Some(plugin) = pm.get(&channel_id){ let buf_ptr = msg.as_ptr(); + println!("published message to FD {}", channel_id); (plugin.msg_receive_cb)(channel_id, buf_ptr, msg.len()) + }else{ + println!("failed publish message to FD {}", channel_id); } } pub fn publish_message_to_guest(channel_id: ChannelId, msg: Vec) { let pm = CHANNELS.read(); if let Some(plugin) = pm.get(&channel_id){ + // println!("message pushed"); plugin.message_queue.push(msg) + }else{ + println!("failed to publish message"); } } pub fn get_channel_from_name(p_name: &str) -> Option{ + // let unnamed = "unnamed".to_owned(); + println!("channel_from_name"); + for ch in CHANNELS.read().iter(){ + println!("channel name: {} FD: {}",&ch.1.name.as_ref().unwrap_or(&"unnamed".to_string()), ch.0); + } + CHANNELS.read().iter().find(|(_, v)| v.name.as_deref() == Some(p_name)).map(|x| *x.0) } \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs b/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs index 3f6571bec47..ff5b0fd9c14 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs @@ -35,13 +35,19 @@ extern "C" fn read_callback( pub fn load_binary(binary_path: &str) { if Path::new(binary_path).is_file() { if let Ok(binary) = std::fs::read(binary_path) { - let payload_size = binary.len(); - let mut buf = - u32::to_le_bytes(PacketKind::LoadPlugin as u32).to_vec(); - buf.extend(u32::to_le_bytes(payload_size as u32).to_vec()); - let cd = CHANNEL_DESC.get().unwrap(); - publish_message_to_guest(*cd, buf); - publish_message_to_guest(*cd, binary); + for chunk in binary.chunks(4096){ + // let mut buf = + // u32::to_le_bytes(PacketKind::LoadPlugin as u32).to_vec(); + // buf.extend(u32::to_le_bytes(chunk.len() as u32).to_vec()); + let cd = CHANNEL_DESC.get().unwrap(); + // publish_message_to_guest(*cd, buf); + publish_message_to_guest(*cd, chunk.to_owned()); + } + // let mut buf = + // u32::to_le_bytes(PacketKind::LoadPlugin as u32).to_vec(); + // buf.extend(u32::to_le_bytes(0 as u32).to_vec()); + // let cd = CHANNEL_DESC.get().unwrap(); + // publish_message_to_guest(*cd, buf); } else { panic!("Failed to read binary at {}", binary_path); } diff --git a/panda/plugins/guest_plugin_manager/src/interface/hci.rs b/panda/plugins/guest_plugin_manager/src/interface/hci.rs index 3c0bc411264..f4e3fc6e5c9 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/hci.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/hci.rs @@ -1,5 +1,5 @@ use super::channels::ChannelId; -use super::channels::{poll_plugin_message, publish_message_from_guest}; +use super::channels::{poll_plugin_message, publish_message_from_guest,get_channel_from_name}; use super::plugin_manager::new_manager_channel; use crate::MAGIC; use panda::mem::{virtual_memory_read, virtual_memory_write}; @@ -27,15 +27,20 @@ pub fn hyp_read( cpu: &mut CPUState, channel_id: ChannelId, addr: usize, - _max_size: usize, + max_size: usize, ) -> Option { - println!("read"); + println!("got to hyp_read with CID {}", channel_id); if let Some(msg) = poll_plugin_message(channel_id) { + if msg.len() > max_size{ + panic!(); + } // could check max len more virtual_memory_write(cpu, addr as target_ulong, &msg); + println!("end of get some message"); Some(msg.len()) } else { - None + println!("end of get nothing"); + Some(0) } } pub fn hyp_write( @@ -71,7 +76,27 @@ pub fn hyp_get_manager( _arg1: usize, _arg2: usize, ) -> Option { - println!("get_manager"); - Some(new_manager_channel() as usize) + dbg!(Some(new_manager_channel() as usize)) } +pub fn hyp_get_channel_by_name( + cpu: &mut CPUState, + _channel_id: ChannelId, + buf_ptr: usize, + buf_size: usize, +) -> Option{ + println!("channel_by_name"); + if let Ok(buf_out) = + virtual_memory_read(cpu, buf_ptr as target_ulong, buf_size) + { + if let Some(cd) = get_channel_from_name(dbg!(&String::from_utf8_lossy(&buf_out))){ + println!("found channel number {}", cd); + Some(cd as usize) + }else{ + println!("failed to find channel number"); + Some(-1_isize as usize) + } + } else { + panic!("Failed to read virtual memory in hyp_write"); + } +} \ No newline at end of file diff --git a/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs index b1c13dccecc..6595631c944 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs @@ -23,15 +23,20 @@ impl TryFrom for ManagerOp { } } -fn get_channel_from_name(buffer: Vec){ +fn get_channel_from_name(origin_channel: ChannelId, buffer: Vec){ let plugin_name = String::from_utf8_lossy(&buffer).into_owned(); if let Some(channel_id) = super::channels::get_channel_from_name(&plugin_name){ + println!("success got channel from name {} FD is {}", plugin_name, channel_id); let buf = u32::to_le_bytes(channel_id); - publish_message_to_guest(channel_id,buf.to_vec()); + + publish_message_to_guest(origin_channel,buf.to_vec()); + }else{ + println!("Failed to get channel from name"); } } -extern "C" fn read_callback(_channel_id: ChannelId, ptr: *const u8, len: usize){ +extern "C" fn read_callback(channel_id: ChannelId, ptr: *const u8, len: usize){ + println!("made it to read callback"); let mut buf = unsafe{from_raw_parts(ptr, len).to_vec()}; const OPSIZE: usize = size_of::(); let mut operation: [u8;OPSIZE] = [0;4]; @@ -39,12 +44,12 @@ extern "C" fn read_callback(_channel_id: ChannelId, ptr: *const u8, len: usize){ let op_num = OperationID::from_le_bytes(operation); buf.drain(0..OPSIZE); match ManagerOp::try_from(op_num as usize) { - Ok(ManagerOp::GetChannelFromName) => get_channel_from_name(buf), + Ok(ManagerOp::GetChannelFromName) => get_channel_from_name(channel_id, buf), Ok(ManagerOp::DebugOutput) => {}, _ => {} } } pub fn new_manager_channel() -> ChannelId { - add_channel(None, read_callback) + dbg!(add_channel(None, read_callback)) } \ No newline at end of file diff --git a/panda/plugins/guest_shell/Cargo.toml b/panda/plugins/guest_shell/Cargo.toml new file mode 100644 index 00000000000..3574fe10a8f --- /dev/null +++ b/panda/plugins/guest_shell/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "rust_skeleton" +version = "0.1.0" +authors = ["Luke Craig ", "Jordan McLeod "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +panda-re = { version = "0.9.1", default-features = false } + +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +aarch64 = ["panda-re/aarch64"] diff --git a/panda/plugins/guest_shell/Makefile b/panda/plugins/guest_shell/Makefile new file mode 100644 index 00000000000..2234476df57 --- /dev/null +++ b/panda/plugins/guest_shell/Makefile @@ -0,0 +1,18 @@ +# Don't forget to add your plugin to config.panda! + +# Build rust plugins with make! + +# The main rule for your plugin. List all object-file dependencies. + +PANDA_PATH = $(realpath $(shell pwd)/..) +PLUGIN_DIR = $(realpath $(join $(PANDA_PATH), /../panda/plugins/$(PLUGIN_NAME)/)) +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so : $(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + @echo " CARGO $(PLUGIN_DIR)" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --no-default-features --features=$(TARGET_NAME) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @cp -p $(PLUGIN_ARTIFACTS_DIR)/release/lib$(PLUGIN_NAME).so $@ diff --git a/panda/plugins/guest_shell/README.md b/panda/plugins/guest_shell/README.md new file mode 100644 index 00000000000..81a52bc976b --- /dev/null +++ b/panda/plugins/guest_shell/README.md @@ -0,0 +1,95 @@ +# Rust Skeleton + +This is a basic example of how to build a PANDA plugin with Rust. + +## Building + +To check if the plugin will build: + +``` +cargo check +``` + +To actually build the plugin: + +``` +cargo build --release +``` + +(remove `--release` if you want to build in debug mode) + +The resulting plugin will be located in `target/release/librust_skeleton.so`. + +## Structure + +``` +├── Cargo.toml +├── Makefile +├── README.md +└── src + └── lib.rs +``` + +* Cargo.toml - The core plugin info. This informs `cargo` how to actually go about building the plugin. It includes the name, dependencies, and features of plugins. +* Makefile - Instructions for how the PANDA build system will build the plugin. +* lib.rs - The main source file of your plugin. Additional source files can be referenced from here. + +## Cargo.toml + +The dependencies section: + +```toml +[dependencies] +panda-re = { version = "0.5", default-features = false } +``` + +To add a new dependency, add a new line in the form `name = "version"`. + +For example to add [`libc`](https://docs.rs/libc), simply add the following line: + +```toml +libc = "0.2" +``` + +## Targetting Multiple Architectures + +In PANDA, a plugin is recompiled once per target architecture (that is to say, the architecture of the guest). To enable this behavior in Rust plugins, we use ["features"](https://doc.rust-lang.org/cargo/reference/features.html) in order to specify which architecture we are building for. + +This is controlled by this section of Cargo.toml: + +```toml +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +``` + +by default `x86_64` is the only feature enabled (which is why we don't need to specify any features to build), this is primarily so that IDE support (rust-analyzer for VSCode/vim/etc, IntelliJ/CLion integration) works out of the box, as IDEs typically do type checking with the default feature set. + +To build for, say, `arm` you can use the following command: + +``` +cargo build --release --no-default-features --features=arm +``` + +And if you wish to prevent certain code from compiling on certain platforms you can use the following: + +```rust +#[cfg(not(feature = "arm"))] +fn breaks_arm() { + // ... +} +``` + +## Other Resources + +* [panda-rs documentation](https://docs.rs/panda-re) +* [panda-rs announcement blog post](https://panda.re/blog/panda-rs) +* [panda-sys documentation](https://docs.rs/panda-re-sys) +* [The Rust Programming Language](https://doc.rust-lang.org/book/) +* [Some example Rust plugins](https://github.com/panda-re/panda-rs-plugins/) diff --git a/panda/plugins/guest_shell/rusty_shell/Cargo.toml b/panda/plugins/guest_shell/rusty_shell/Cargo.toml new file mode 100644 index 00000000000..230c5c70459 --- /dev/null +++ b/panda/plugins/guest_shell/rusty_shell/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "rusty_shell" +version = "0.1.0" +edition = "2018" diff --git a/panda/plugins/guest_shell/rusty_shell/src/hypercall.rs b/panda/plugins/guest_shell/rusty_shell/src/hypercall.rs new file mode 100644 index 00000000000..abf8e6ad513 --- /dev/null +++ b/panda/plugins/guest_shell/rusty_shell/src/hypercall.rs @@ -0,0 +1,113 @@ +use std::{io::Write, marker::PhantomData}; + +const HC_MAGIC: usize = 0x666; + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub enum HcCmd { + Noop = 0, + Start, /* start new action */ + Stop, /* stop action */ + Read, /* read buffer from hypervisor */ + Write, /* write buffer TO hypervisor*/ + Error, /* report error to hypervisor*/ + ConditionalOp, /* ask the hypervisor if op should be completed*/ + NextStateMachine, /* ask the hypervisor manager to move to the next + state machine*/ +} + +pub struct HyperCall<'a> { + cmd : HcCmd, + args: Vec, + lifetime: PhantomData<&'a ()>, +} + +impl HyperCall<'static> { + pub fn new(cmd: HcCmd) -> Self { + Self { + cmd, + args: vec![0; 2], + lifetime: PhantomData, + } + } +} + +#[allow(dead_code)] +impl<'a> HyperCall<'a> { + pub fn arg(&mut self, arg: usize) -> &mut Self { + self.args.push(arg); + self + } + + pub fn from_string(command: HcCmd, s: &'a str) -> HyperCall<'a> { + Self { + cmd: command, + args: vec![ + s.as_ptr() as usize, + s.len(), + ], + lifetime: PhantomData, + } + } + + pub fn from_buf(command: HcCmd, buf: &'a [u8]) -> HyperCall<'a> { + Self { + cmd: command, + args: vec![ + buf.as_ptr() as usize, + buf.len(), + ], + lifetime: PhantomData, + } + } + + pub fn from_mut_buf(command: HcCmd, buf: &'a mut [u8]) -> HyperCall<'a> { + Self { + cmd: command, + args: vec![ + buf.as_ptr() as usize, + buf.len(), + ], + lifetime: PhantomData, + } + } + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn call(&mut self) -> usize { + let ret_val; + + while self.args.len() < 2 { + self.args.push(0); + } + + unsafe { + asm!( + "mov eax, {hc_magic}", + "mov ebx, {command:e}", + "cpuid", + hc_magic = const HC_MAGIC, + command = in(reg) self.cmd as u32, + in("ecx") self.args[0], + in("edx") self.args[1], + out("eax") ret_val, + ); + } + + ret_val + } +} + +struct HyperWriter; + +impl Write for HyperWriter { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + HyperCall::from_buf(HcCmd::Write, buf).call(); + + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} diff --git a/panda/plugins/guest_shell/rusty_shell/src/main.rs b/panda/plugins/guest_shell/rusty_shell/src/main.rs new file mode 100644 index 00000000000..7d1308954f8 --- /dev/null +++ b/panda/plugins/guest_shell/rusty_shell/src/main.rs @@ -0,0 +1,52 @@ +#![feature(asm)] + +mod hypercall; +use std::process::Command; + +use hypercall::{HyperCall, HcCmd}; + +/// Read a line of input from the hypervisor +fn read_line() -> String { + let mut buf = vec![0u8; 1024]; + + let len = loop { + let ret = HyperCall::from_mut_buf(HcCmd::Read, &mut buf).call() as isize; + + if ret > 0 { + break ret + } else { + std::thread::yield_now(); + } + }; + + buf.truncate(len as usize); + + String::from_utf8(buf).unwrap() +} + +/// Write a buffer or string across the hypervisor +fn write(output: impl AsRef<[u8]>) { + HyperCall::from_buf(HcCmd::Write, output.as_ref()).call(); +} + +fn main() { + HyperCall::new(HcCmd::Start).call(); + + loop { + let input = read_line(); + + let args: Vec<&str> = input.trim().split_whitespace().collect(); + + if let [program, args @ ..] = &args[..] { + match Command::new(program).args(args).output() { + Ok(output) => { + write(&output.stdout); + write("[CMD_FINISHED]"); + } + Err(_) => break, + } + } + } + + HyperCall::new(HcCmd::Stop).call(); +} diff --git a/panda/plugins/guest_shell/src/lib.rs b/panda/plugins/guest_shell/src/lib.rs new file mode 100644 index 00000000000..608c7175374 --- /dev/null +++ b/panda/plugins/guest_shell/src/lib.rs @@ -0,0 +1,17 @@ +use panda::prelude::*; +use panda::plugin_import; + + + + + +#[panda::init] +fn init(_: &mut PluginHandle) -> bool { + println!("Initialized!"); + true +} + +#[panda::uninit] +fn exit(_: &mut PluginHandle) { + println!("Exiting"); +} \ No newline at end of file diff --git a/panda/plugins/hyperfuse/Cargo.toml b/panda/plugins/hyperfuse/Cargo.toml index c8d3f630b6d..56fa94d1d6c 100644 --- a/panda/plugins/hyperfuse/Cargo.toml +++ b/panda/plugins/hyperfuse/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] #panda-re = { version = "0.13.0", default-features = false } -panda-re = { path = "/home/jamcleod/dev/work/panda-rs/panda-rs", default-features = false } +panda-re = { git = "https://github.com/panda-re/panda-rs", default-features = false } fuser = { version = "0.8.0", features = ["serializable"] } libc = "0.2.98" env_logger = "0.9.0" diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index ad37c153b27..2fdbd02380d 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -195,7 +195,7 @@ impl Receiver { //} fn mount(channel: ChannelId) { - let mountpoint = "/home/luke/workspace/fuse_mount"; + let mountpoint = "/home/luke/workspace/fuse_mount/"; let options = vec![ MountOption::FSName("hello".to_string()), MountOption::AutoUnmount, @@ -215,6 +215,7 @@ static MESSAGE_QUEUE: SegQueue> = SegQueue::new(); extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { unsafe { + println!("message_recv in hyperfuse"); let bytes = std::slice::from_raw_parts(ptr, len); MESSAGE_QUEUE.push(bytes.to_owned()); } @@ -230,17 +231,21 @@ fn init(_: &mut PluginHandle) -> bool { panda::sys::panda_add_arg(plugin_name.as_ptr(), plugin_arg.as_ptr()); panda::sys::panda_load_plugin(path, plugin_name.as_ptr()); } + println!("after load_plugin in hyperfuse"); GUEST_PLUGIN_MANAGER.ensure_init(); let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( "hyperfuse".into(), - Path::new("/home/luke/workspace/igloo/pie_idea/guest_code/target/i686-unknown-linux-musl/debug/hyperfuse_guest"), + Path::new("/home/luke/workspace/igloo/pie_idea/guest_code/target/i686-unknown-linux-musl/release/hyperfuse_guest"), message_recv, )); + println!("hyperfuse established channel with fd {}", channel); std::thread::spawn(move || { + println!("new hyperfuse thread"); mount(channel); }); + println!("returning after new thread hyperfuse"); true } diff --git a/panda/plugins/linjector/README.md b/panda/plugins/linjector/README.md new file mode 100644 index 00000000000..81a52bc976b --- /dev/null +++ b/panda/plugins/linjector/README.md @@ -0,0 +1,95 @@ +# Rust Skeleton + +This is a basic example of how to build a PANDA plugin with Rust. + +## Building + +To check if the plugin will build: + +``` +cargo check +``` + +To actually build the plugin: + +``` +cargo build --release +``` + +(remove `--release` if you want to build in debug mode) + +The resulting plugin will be located in `target/release/librust_skeleton.so`. + +## Structure + +``` +├── Cargo.toml +├── Makefile +├── README.md +└── src + └── lib.rs +``` + +* Cargo.toml - The core plugin info. This informs `cargo` how to actually go about building the plugin. It includes the name, dependencies, and features of plugins. +* Makefile - Instructions for how the PANDA build system will build the plugin. +* lib.rs - The main source file of your plugin. Additional source files can be referenced from here. + +## Cargo.toml + +The dependencies section: + +```toml +[dependencies] +panda-re = { version = "0.5", default-features = false } +``` + +To add a new dependency, add a new line in the form `name = "version"`. + +For example to add [`libc`](https://docs.rs/libc), simply add the following line: + +```toml +libc = "0.2" +``` + +## Targetting Multiple Architectures + +In PANDA, a plugin is recompiled once per target architecture (that is to say, the architecture of the guest). To enable this behavior in Rust plugins, we use ["features"](https://doc.rust-lang.org/cargo/reference/features.html) in order to specify which architecture we are building for. + +This is controlled by this section of Cargo.toml: + +```toml +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +``` + +by default `x86_64` is the only feature enabled (which is why we don't need to specify any features to build), this is primarily so that IDE support (rust-analyzer for VSCode/vim/etc, IntelliJ/CLion integration) works out of the box, as IDEs typically do type checking with the default feature set. + +To build for, say, `arm` you can use the following command: + +``` +cargo build --release --no-default-features --features=arm +``` + +And if you wish to prevent certain code from compiling on certain platforms you can use the following: + +```rust +#[cfg(not(feature = "arm"))] +fn breaks_arm() { + // ... +} +``` + +## Other Resources + +* [panda-rs documentation](https://docs.rs/panda-re) +* [panda-rs announcement blog post](https://panda.re/blog/panda-rs) +* [panda-sys documentation](https://docs.rs/panda-re-sys) +* [The Rust Programming Language](https://doc.rust-lang.org/book/) +* [Some example Rust plugins](https://github.com/panda-re/panda-rs-plugins/) diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 2b09bc84b17..45b283e12ff 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -34,7 +34,7 @@ use regs::{REG_ORDER, RET_REG}; struct Args { #[arg(default = "guest_daemon")] guest_binary: String, - + #[arg(default = true)] require_root: bool, } @@ -128,7 +128,8 @@ fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { ELF_READ_POS.fetch_add(upper - lower, Ordering::SeqCst); Some(upper - lower) } else { - None + println!("finished processing binary"); + Some(0) } } @@ -172,7 +173,6 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { let magicval = get_hyp_reg(cpu, 0); if magicval == MAGIC { let action = get_hyp_reg(cpu, 1); - dbg!(action); let first_arg = get_hyp_reg(cpu, 2); let second_arg = get_hyp_reg(cpu, 3); @@ -252,7 +252,9 @@ fn handle_proc_start( #[panda::init] fn init(_: &mut PluginHandle) -> bool { + println!("linjector hit"); lazy_static::initialize(&ARGS); + println!("got args {} {}", ARGS.guest_binary, ARGS.require_root); true } From f63c471c43b39b0fa1072191b81d876a2865b827 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 17 Nov 2021 12:06:25 -0500 Subject: [PATCH 16/79] first attempt at pure syscall injection --- panda/plugins/linjector/src/lib.rs | 341 +++++++++++------------------ 1 file changed, 133 insertions(+), 208 deletions(-) diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 45b283e12ff..5cc87d10ecb 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -1,34 +1,22 @@ +use panda::current_asid; +use panda::sys::get_cpu; use panda::{ - mem::{virtual_memory_read, virtual_memory_write}, - plugins::{ - hooks::Hook, - proc_start_linux::{AuxvValues, PROC_START_LINUX}, - }, + mem::virtual_memory_write, + plugins::syscalls2::SYSCALLS, prelude::*, - regs::{get_pc, get_reg, set_reg}, + syscall_injection::{run_injector, syscall}, }; use std::{ cmp::min, - convert::TryFrom, sync::atomic::{AtomicUsize, Ordering}, }; -use object::{Object, ObjectSection}; use once_cell::sync::OnceCell; -static POINTERS: OnceCell<[target_ulong; 3]> = OnceCell::new(); -static POINTERS_READ: AtomicUsize = AtomicUsize::new(0); -static SAVED_BUF: OnceCell> = OnceCell::new(); -static SAVED_PC: OnceCell = OnceCell::new(); static ELF_TO_INJECT: OnceCell> = OnceCell::new(); static ELF_READ_POS: AtomicUsize = AtomicUsize::new(0); -const MAGIC: usize = 0x10adc0d3; - -mod regs; -use regs::{REG_ORDER, RET_REG}; - #[derive(PandaArgs)] #[name = "linjector"] // plugin name struct Args { @@ -42,218 +30,155 @@ lazy_static::lazy_static! { static ref ARGS: Args = Args::from_panda_args(); } -#[derive(Copy, Clone)] -pub enum HcCmd { - Noop = 0, - Start, /* start new action */ - Stop, /* stop action */ - Read, /* read buffer from hypervisor */ - Write, /* write buffer TO hypervisor*/ - Error, /* report error to hypervisor*/ - ConditionalOp, /* ask the hypervisor if op should be completed*/ - NextStateMachine, /* ask the hypervisor manager to move to the next - state machine*/ -} - -impl TryFrom for HcCmd { - type Error = (); - - fn try_from(value: usize) -> Result { - match value { - 0 => Ok(HcCmd::Noop), - 1 => Ok(HcCmd::Start), - 2 => Ok(HcCmd::Stop), - 3 => Ok(HcCmd::Read), - 4 => Ok(HcCmd::Write), - 5 => Ok(HcCmd::Error), - 6 => Ok(HcCmd::ConditionalOp), - 7 => Ok(HcCmd::NextStateMachine), - _ => Err(()), - } - } -} - -fn parse_file_data(file_bytes: &[u8]) -> (&[u8], usize, usize) { - let obj_file = object::File::parse(file_bytes).expect("Couldn't parse ELF"); - let text_section = obj_file - .section_by_name(".text") - .expect("Couldn't locate .text section"); - let text_data = text_section.data().unwrap(); - let offset = text_section.address() - obj_file.entry(); - let section_size = text_section.size(); - (text_data, offset as usize, section_size as usize) -} - -fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { - let reg_to_read = REG_ORDER[num]; - get_reg(cpu, reg_to_read) as usize -} - -#[panda::hook] -fn inject_hook( - cpu: &mut CPUState, - _tb: &mut TranslationBlock, - _exit_code: u8, - hook: &mut Hook, -) { - println!("Inject hook"); - let inject_bytes = include_bytes!("./injectables/injector"); - let (text_data, _offset, _section_size) = - parse_file_data(&inject_bytes[..]); - let pc = panda::regs::get_pc(cpu); - println!("about to inject injector at {:#x}", pc); - virtual_memory_write(cpu, pc, text_data); - hook.enabled = false; -} - -fn hyp_start(_cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { - inject_hook::hook() - .after_block_exec() - .at_addr(arg1 as target_ulong); - None +const MMAP2: target_ulong = 192; +const NULL: target_ulong = 0; +const NEG_1: target_ulong = target_ulong::MAX; +const PAGE_SIZE: target_ulong = 0x1000; +const PROT_READ: target_ulong = 0x1; /* Page can be read. */ +const PROT_WRITE: target_ulong = 0x2; /* Page can be written. */ +const PROT_EXEC: target_ulong = 0x4; /* Page can be executed. */ +const MAP_SHARED: target_ulong = 0x1; +const MAP_ANON: target_ulong = 0x20; + +async fn do_mmap() -> target_ulong { + syscall( + MMAP2, + ( + NULL, + PAGE_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED | MAP_ANON, + NEG_1, + NULL, + ), + ) + .await } -fn hyp_write(cpu: &mut CPUState, arg1: usize, arg2: usize) -> Option { - ELF_TO_INJECT.get_or_init(|| std::fs::read(&ARGS.guest_binary).unwrap()); - let buf_to_write = arg1; - let size_requested = arg2; +const MEMFD_CREATE: target_ulong = 356; +const MFD_CLOEXEC: target_ulong = 1; - let read_pos = ELF_READ_POS.load(Ordering::SeqCst); - let buf_size = ELF_TO_INJECT.get().unwrap().len(); - if read_pos < buf_size { - let lower = read_pos; - let upper = min(buf_size, read_pos + size_requested); - let data_to_write = &ELF_TO_INJECT.get().unwrap()[lower..upper]; - virtual_memory_write(cpu, buf_to_write as target_ulong, data_to_write); - ELF_READ_POS.fetch_add(upper - lower, Ordering::SeqCst); - Some(upper - lower) - } else { - println!("finished processing binary"); - Some(0) - } +async fn do_memfd_create(mmap_addr: target_ulong) -> target_ulong { + // we use the mmap_addr for the name because we've zeroed it + // so it will be a '\0' litera,l name + syscall(MEMFD_CREATE, (mmap_addr, MFD_CLOEXEC)).await } -fn hyp_read(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { - assert!(arg1 != 0, "arg1 is a fork return 0 is the child"); - let ptr_pos = POINTERS_READ.load(Ordering::SeqCst); - let pointers = POINTERS.get().unwrap(); - println!("ptr_pos {}, ptrs.len() {}", ptr_pos, pointers.len()); - - if ptr_pos < pointers.len() { - POINTERS_READ.fetch_add(1, Ordering::SeqCst); - println!("Returning {:#x}", pointers[ptr_pos]); - // on the last ptr_pos replace the new code - if ptr_pos == pointers.len() - 1 { - virtual_memory_write( - cpu, - *SAVED_PC.get().unwrap(), - SAVED_BUF.get().unwrap(), - ); - } - Some(pointers[ptr_pos] as usize) - } else { - None - } -} +const WRITE: target_ulong = 4; -fn hyp_stop(cpu: &mut CPUState, arg1: usize, _arg2: usize) -> Option { - if POINTERS_READ.load(Ordering::SeqCst) == POINTERS.get().unwrap().len() { - virtual_memory_write(cpu, arg1 as target_ulong, b"\x01\x02\x03\x04"); - virtual_memory_write( - cpu, - *SAVED_PC.get().unwrap(), - SAVED_BUF.get().unwrap(), - ); - } - None +async fn do_write( + mem_fd: target_ulong, + mmap_addr: target_ulong, + len: target_ulong, +) -> target_ulong { + syscall(WRITE, (mem_fd, mmap_addr, len)).await } -#[panda::guest_hypercall] -fn hypercall_handler(cpu: &mut CPUState) -> bool { - let magicval = get_hyp_reg(cpu, 0); - if magicval == MAGIC { - let action = get_hyp_reg(cpu, 1); - let first_arg = get_hyp_reg(cpu, 2); - let second_arg = get_hyp_reg(cpu, 3); +const FORK: target_ulong = 2; - let retval = match HcCmd::try_from(action) { - Ok(HcCmd::Start) => hyp_start(cpu, first_arg, second_arg), - Ok(HcCmd::Write) => hyp_write(cpu, first_arg, second_arg), - Ok(HcCmd::Read) => hyp_read(cpu, first_arg, second_arg), - Ok(HcCmd::Stop) => hyp_stop(cpu, first_arg, second_arg), - _ => None, - }; - - if let Some(retval) = retval { - set_reg(cpu, RET_REG, retval as target_ulong); - } - } - true +async fn do_fork() -> target_ulong { + syscall(FORK, ()).await } -#[panda::hook] -fn entry_hook( - cpu: &mut CPUState, - _tb: &mut TranslationBlock, - _exit_code: u8, - hook: &mut Hook, -) { - println!("Entry hook"); - let inject_bytes = include_bytes!("./injectables/tiny_mmap"); - let (text_data, offset, section_size) = parse_file_data(&inject_bytes[..]); - assert_eq!( - offset, 0, - "get better shellcode. why is there another function?" - ); - let pc = get_pc(cpu); - SAVED_PC.set(pc).unwrap(); - SAVED_BUF - .set( - virtual_memory_read(cpu, pc, section_size as usize) - .expect("failed to read buf. you might need a smaller injector or another stage"), - ) - .unwrap(); - println!("Writing {:#x} bytes at {:#x}", section_size, pc); - virtual_memory_write(cpu, pc, text_data); - println!("Replacing bytes at PC with tiny_mmap"); +const EXECVE: target_ulong = 11; - hook.enabled = false; +async fn do_execve( + path: target_ulong, + argv: target_ulong, + envp: target_ulong, +) -> target_ulong { + syscall(EXECVE, (path, argv, envp)).await } -#[panda::on_rec_auxv] -fn handle_proc_start( +#[panda::on_all_sys_enter] +fn on_sys_enter( _cpu: &mut CPUState, - _tb: &mut TranslationBlock, - auxv: &AuxvValues, + pc: SyscallPc, + _syscall_num: target_ulong, ) { - println!("proc start"); - if !ARGS.require_root || auxv.euid == 0 { - println!("accepting new proc with euid {}", auxv.euid); - // get pointers to values for re-starting process - - let &AuxvValues { - execfn_ptr, - argv_ptr_ptr, - env_ptr_ptr, - .. - } = auxv; - - // in your callback - POINTERS - .set([execfn_ptr, argv_ptr_ptr, env_ptr_ptr]) - .unwrap(); - - // set a hook at the entrypoint - entry_hook::hook().after_block_exec().at_addr(auxv.entry); - - PROC_START_LINUX.remove_callback_on_rec_auxv(handle_proc_start); - } + let file_data = ELF_TO_INJECT.get().unwrap(); + run_injector(pc, async move { + if ARGS.require_root { + let is_root = syscall(24, ()).await == 0 as target_ulong; + if !is_root { + SYSCALLS.add_callback_on_all_sys_enter(on_sys_enter); + return; + } + } + let cpu = unsafe { &mut *get_cpu() }; + println!("In injector"); + println!("current asid: {:x}", current_asid(cpu)); + // only problematic in multi-cpu systems + // mmap a region + let mmap_addr = do_mmap().await; + println!("Got mmap addr {:#x}", mmap_addr); + println!("current asid: {:x}", current_asid(cpu)); + // zero it out + virtual_memory_write(cpu, mmap_addr, &[0u8; PAGE_SIZE as usize]); + let mem_fd = do_memfd_create(mmap_addr).await; + println!("Got fd {:#x}", mem_fd); + println!("current asid: {:x}", current_asid(cpu)); + loop { + match ELF_READ_POS.fetch_add(PAGE_SIZE as usize, Ordering::SeqCst) { + x if x < file_data.len() => { + let size = + min(PAGE_SIZE as isize, (file_data.len() - x) as isize); + println!( + "Writing {} bytes [{}-{}] total: {}...", + PAGE_SIZE, + x, + x + PAGE_SIZE as usize, + file_data.len() + ); + println!("current asid: {:x}", current_asid(cpu)); + virtual_memory_write( + cpu, + mmap_addr, + &file_data[x..x + size as usize], + ); + do_write(mem_fd, mmap_addr, PAGE_SIZE).await; + } + _ => break, + } + } + println!("forking..."); + + let is_parent = do_fork().await == 0 as target_ulong; + println!("is_parent is {}", is_parent); + + let execbuf = [ + 47u8, + 112, + 114, + 111, + 99, + 47, + 115, + 101, + 108, + 102, + 47, + 102, + 100, + 47, + 48 + mem_fd as u8, + 0, + ]; + virtual_memory_write(cpu, mmap_addr, &execbuf); + println!("execve()"); + let end_mmap_buf = + mmap_addr as target_ulong + (execbuf.len() - 1) as target_ulong; + do_execve(mmap_addr, end_mmap_buf, end_mmap_buf).await; + println!("finished"); + }); + SYSCALLS.remove_callback_on_all_sys_enter(on_sys_enter); } #[panda::init] fn init(_: &mut PluginHandle) -> bool { - println!("linjector hit"); + println!("linjector asdf hit"); lazy_static::initialize(&ARGS); + ELF_TO_INJECT.get_or_init(|| std::fs::read(&ARGS.guest_binary).unwrap()); println!("got args {} {}", ARGS.guest_binary, ARGS.require_root); true } From 3ab1e0a73d85f95c7a3884567cf3b30fd81617e7 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 17 Nov 2021 16:20:55 -0500 Subject: [PATCH 17/79] some stuff --- panda/plugins/linjector/src/lib.rs | 67 ++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 5cc87d10ecb..7e8da6d82ae 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -1,6 +1,7 @@ -use panda::current_asid; use panda::sys::get_cpu; +use panda::{current_asid, current_pc}; use panda::{ + mem::virtual_memory_read, mem::virtual_memory_write, plugins::syscalls2::SYSCALLS, prelude::*, @@ -30,7 +31,19 @@ lazy_static::lazy_static! { static ref ARGS: Args = Args::from_panda_args(); } -const MMAP2: target_ulong = 192; +// i386 +// const MMAP2: target_ulong = 192; +// const WRITE: target_ulong = 4; +// const FORK: target_ulong = 2; +// const EXECVE: target_ulong = 11; +// const MEMFD_CREATE: target_ulong = 356; +// x86_64 +const MMAP: target_ulong = 9; +const WRITE: target_ulong = 1; +const FORK: target_ulong = 57; +const EXECVE: target_ulong = 59; +const MEMFD_CREATE: target_ulong = 319; + const NULL: target_ulong = 0; const NEG_1: target_ulong = target_ulong::MAX; const PAGE_SIZE: target_ulong = 0x1000; @@ -42,7 +55,7 @@ const MAP_ANON: target_ulong = 0x20; async fn do_mmap() -> target_ulong { syscall( - MMAP2, + MMAP, ( NULL, PAGE_SIZE, @@ -55,7 +68,6 @@ async fn do_mmap() -> target_ulong { .await } -const MEMFD_CREATE: target_ulong = 356; const MFD_CLOEXEC: target_ulong = 1; async fn do_memfd_create(mmap_addr: target_ulong) -> target_ulong { @@ -64,8 +76,6 @@ async fn do_memfd_create(mmap_addr: target_ulong) -> target_ulong { syscall(MEMFD_CREATE, (mmap_addr, MFD_CLOEXEC)).await } -const WRITE: target_ulong = 4; - async fn do_write( mem_fd: target_ulong, mmap_addr: target_ulong, @@ -74,14 +84,10 @@ async fn do_write( syscall(WRITE, (mem_fd, mmap_addr, len)).await } -const FORK: target_ulong = 2; - async fn do_fork() -> target_ulong { syscall(FORK, ()).await } -const EXECVE: target_ulong = 11; - async fn do_execve( path: target_ulong, argv: target_ulong, @@ -90,31 +96,50 @@ async fn do_execve( syscall(EXECVE, (path, argv, envp)).await } +const GETPID: target_ulong = 24; + +fn read_2_bytes_at_pc(_cpu: &mut CPUState, pc: target_ulong) { + let a = virtual_memory_read(_cpu, pc, 2).unwrap(); + println!("opcode@PC 0: {:x} 1: {:x}", a[0], a[1]); +} + #[panda::on_all_sys_enter] -fn on_sys_enter( - _cpu: &mut CPUState, - pc: SyscallPc, - _syscall_num: target_ulong, -) { +fn on_sys_enter(_cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { + println!("Got syscall {}", syscall_num); + println!( + "SYSCALLS PC is {:x} CURRENT_PC is {:x}", + pc.pc(), + current_pc(_cpu) + ); + let asid = current_asid(_cpu); + let cpc = current_pc(_cpu); + read_2_bytes_at_pc(_cpu, pc.pc()); + read_2_bytes_at_pc(_cpu, cpc); + let file_data = ELF_TO_INJECT.get().unwrap(); run_injector(pc, async move { + let cpu = unsafe { &mut *get_cpu() }; + println!("current asid: {:x}", current_asid(cpu)); if ARGS.require_root { - let is_root = syscall(24, ()).await == 0 as target_ulong; + let is_root = syscall(GETPID, ()).await == 0 as target_ulong; if !is_root { SYSCALLS.add_callback_on_all_sys_enter(on_sys_enter); return; + } else { + println!("Got root!"); } } - let cpu = unsafe { &mut *get_cpu() }; + println!("In injector"); println!("current asid: {:x}", current_asid(cpu)); // only problematic in multi-cpu systems // mmap a region let mmap_addr = do_mmap().await; println!("Got mmap addr {:#x}", mmap_addr); + println!("{}", mmap_addr as i64); println!("current asid: {:x}", current_asid(cpu)); // zero it out - virtual_memory_write(cpu, mmap_addr, &[0u8; PAGE_SIZE as usize]); + // virtual_memory_write(cpu, mmap_addr, &[0u8; PAGE_SIZE as usize]); let mem_fd = do_memfd_create(mmap_addr).await; println!("Got fd {:#x}", mem_fd); println!("current asid: {:x}", current_asid(cpu)); @@ -171,6 +196,12 @@ fn on_sys_enter( do_execve(mmap_addr, end_mmap_buf, end_mmap_buf).await; println!("finished"); }); + panda::hook::before_block_exec(move |cpu, _, hook| { + if asid == current_asid(cpu) { + println!("Hit PC for SYSCALL {:x}", pc.pc()); + } + }) + .at_addr(pc.pc()); SYSCALLS.remove_callback_on_all_sys_enter(on_sys_enter); } From c7e1e6d0dcc1ba8a4fb194462bf89959355ba5c9 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 18 Nov 2021 15:33:02 -0500 Subject: [PATCH 18/79] forward progress --- panda/plugins/linjector/src/lib.rs | 181 ++++++++++++++++++++--------- 1 file changed, 127 insertions(+), 54 deletions(-) diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 7e8da6d82ae..9749c0737c1 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -1,10 +1,12 @@ -use panda::sys::get_cpu; -use panda::{current_asid, current_pc}; +use panda::sys::{get_cpu, qemu_loglevel, CPUX86State}; +use panda::{current_asid, current_pc, current_sp, PppCallback}; use panda::{ mem::virtual_memory_read, mem::virtual_memory_write, + plugins::osi::OSI, plugins::syscalls2::SYSCALLS, prelude::*, + regs::Reg::*, syscall_injection::{run_injector, syscall}, }; @@ -45,21 +47,27 @@ const EXECVE: target_ulong = 59; const MEMFD_CREATE: target_ulong = 319; const NULL: target_ulong = 0; -const NEG_1: target_ulong = target_ulong::MAX; -const PAGE_SIZE: target_ulong = 0x1000; -const PROT_READ: target_ulong = 0x1; /* Page can be read. */ -const PROT_WRITE: target_ulong = 0x2; /* Page can be written. */ -const PROT_EXEC: target_ulong = 0x4; /* Page can be executed. */ -const MAP_SHARED: target_ulong = 0x1; +const NEG_1: target_ulong = u32::MAX as target_ulong; +const PAGE_SIZE: target_ulong = 1024; +// const PROT_READ: target_ulong = 0x1; /* Page can be read. */ +// const PROT_WRITE: target_ulong = 0x2; /* Page can be written. */ +// const PROT_EXEC: target_ulong = 0x4; /* Page can be executed. */ +//const MAP_SHARED: target_ulong = 0x1; +//const MAP_ANON: target_ulong = 0x20; +//const MAP_PRIVATE: target_ulong = 0x2; +// andrew's script values +const PROT_READ: target_ulong = 4; +const PROT_WRITE: target_ulong = 2; const MAP_ANON: target_ulong = 0x20; +const MAP_SHARED: target_ulong = 0x2; async fn do_mmap() -> target_ulong { syscall( MMAP, ( - NULL, + 0u64, PAGE_SIZE, - PROT_READ | PROT_WRITE | PROT_EXEC, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, NEG_1, NULL, @@ -72,7 +80,7 @@ const MFD_CLOEXEC: target_ulong = 1; async fn do_memfd_create(mmap_addr: target_ulong) -> target_ulong { // we use the mmap_addr for the name because we've zeroed it - // so it will be a '\0' litera,l name + // so it will be a '\0' literal name syscall(MEMFD_CREATE, (mmap_addr, MFD_CLOEXEC)).await } @@ -103,35 +111,60 @@ fn read_2_bytes_at_pc(_cpu: &mut CPUState, pc: target_ulong) { println!("opcode@PC 0: {:x} 1: {:x}", a[0], a[1]); } +const DUP: target_ulong = 32; +const DUP2: target_ulong = 63; +const MLOCK: target_ulong = 150; + #[panda::on_all_sys_enter] fn on_sys_enter(_cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { + if OSI.get_current_process(_cpu).get_name() != "cat" { + return; + } println!("Got syscall {}", syscall_num); println!( "SYSCALLS PC is {:x} CURRENT_PC is {:x}", pc.pc(), current_pc(_cpu) ); + read_2_bytes_at_pc(_cpu, pc.pc()); let asid = current_asid(_cpu); let cpc = current_pc(_cpu); read_2_bytes_at_pc(_cpu, pc.pc()); read_2_bytes_at_pc(_cpu, cpc); let file_data = ELF_TO_INJECT.get().unwrap(); + + let sys_enter = PppCallback::new(); + let sys_return = PppCallback::new(); + run_injector(pc, async move { + // unsafe { + // qemu_loglevel |= 1 << 1; + // } let cpu = unsafe { &mut *get_cpu() }; - println!("current asid: {:x}", current_asid(cpu)); - if ARGS.require_root { - let is_root = syscall(GETPID, ()).await == 0 as target_ulong; - if !is_root { - SYSCALLS.add_callback_on_all_sys_enter(on_sys_enter); - return; - } else { - println!("Got root!"); - } - } + // println!("current asid: {:x}", current_asid(cpu)); + // if ARGS.require_root { + // let is_root = syscall(GETPID, ()).await == 0 as target_ulong; + // if !is_root { + + // SYSCALLS.add_callback_on_all_sys_enter(on_sys_enter); + // return; + // } else { + // println!("Got root!"); + + // } + // } println!("In injector"); println!("current asid: {:x}", current_asid(cpu)); + + // let dupfd = syscall(DUP, (0u64,)).await; + // let dupfd = syscall(DUP2, (0u64, 10u64)).await; + // println!("got new FD {}", dupfd); + // let round_address = 0x7fffffffe000u64; + // let not_round = 0x00007fffffffeaa8u64; + // let mlock_ret = syscall(MLOCK, (round_address, u64::MAX)).await; + // println!("mlock_ret: {}", mlock_ret as i64); // only problematic in multi-cpu systems // mmap a region let mmap_addr = do_mmap().await; @@ -140,8 +173,11 @@ fn on_sys_enter(_cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { println!("current asid: {:x}", current_asid(cpu)); // zero it out // virtual_memory_write(cpu, mmap_addr, &[0u8; PAGE_SIZE as usize]); + // let mmap_addr = panda::current_sp(cpu) + 0x1000; + // virtual_memory_write(cpu, mmap_addr, &[0u8; 20]); let mem_fd = do_memfd_create(mmap_addr).await; println!("Got fd {:#x}", mem_fd); + println!("{}", mmap_addr as i64); println!("current asid: {:x}", current_asid(cpu)); loop { match ELF_READ_POS.fetch_add(PAGE_SIZE as usize, Ordering::SeqCst) { @@ -167,41 +203,78 @@ fn on_sys_enter(_cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { } } println!("forking..."); + panda::hook::start_block_exec(move |cpu, _, hook| { + println!("RAX: {:x}", panda::regs::get_reg(cpu, RAX)); + }) + .at_addr(pc.pc() + 2); + + // let pid = syscall(GETPID, ()).await; + // println!("PID is {}", pid); + + let fork_ret = do_fork().await; + println!("fork ret {:x}", fork_ret); + + // let is_parent = fork_ret != 0 as target_ulong; + // println!("is_parent is {}", is_parent); - let is_parent = do_fork().await == 0 as target_ulong; - println!("is_parent is {}", is_parent); - - let execbuf = [ - 47u8, - 112, - 114, - 111, - 99, - 47, - 115, - 101, - 108, - 102, - 47, - 102, - 100, - 47, - 48 + mem_fd as u8, - 0, - ]; - virtual_memory_write(cpu, mmap_addr, &execbuf); - println!("execve()"); - let end_mmap_buf = - mmap_addr as target_ulong + (execbuf.len() - 1) as target_ulong; - do_execve(mmap_addr, end_mmap_buf, end_mmap_buf).await; - println!("finished"); + // // /proc/self/fd/# + + // let execbuf = [ + // 47u8, + // 112, + // 114, + // 111, + // 99, + // 47, + // 115, + // 101, + // 108, + // 102, + // 47, + // 102, + // 100, + // 47, + // 48 + mem_fd as u8, + // 0, + // ]; + // virtual_memory_write(cpu, mmap_addr, &execbuf); + // println!("execve()"); + // let end_mmap_buf = + // mmap_addr as target_ulong + (execbuf.len() - 1) as target_ulong; + // do_execve(mmap_addr, end_mmap_buf, end_mmap_buf).await; + // println!("finished"); + // // // unsafe { + // // qemu_loglevel = 0; + // } }); - panda::hook::before_block_exec(move |cpu, _, hook| { - if asid == current_asid(cpu) { - println!("Hit PC for SYSCALL {:x}", pc.pc()); - } - }) - .at_addr(pc.pc()); + + // let r = unsafe { _cpu.env_ptr as *mut CPUX86State }; + // let HF_CS64_SHIFT: u64 = 15; + // let HF_CS64_MASK = 1 << HF_CS64_SHIFT; + + // let syscall_addr = unsafe { + // // if HF_CS64_MASK & (*r).eflags != 0 { + // // println!("lstar"); + // (*r).lstar + // // } else { + // // println!("cstar"); + // // (*r).cstar + // // } + // }; + + // panda::hook::before_block_exec(move |cpu, _, hook| { + // if asid == current_asid(cpu) { + // println!("Hit PC for LSTAR {:x}", pc.pc()); + // println!("RAX: {:x}", panda::regs::get_reg(cpu, RAX)); + // println!("RDI: {:x}", panda::regs::get_reg(cpu, RDI)); + // println!("RSI: {:x}", panda::regs::get_reg(cpu, RSI)); + // println!("RDX: {:x}", panda::regs::get_reg(cpu, RDX)); + // println!("RCX: {:x}", panda::regs::get_reg(cpu, RCX)); + // println!("R8: {:x}", panda::regs::get_reg(cpu, R8)); + // println!("R9: {:x}", panda::regs::get_reg(cpu, R9)); + // } + // }) + // .at_addr(syscall_addr); SYSCALLS.remove_callback_on_all_sys_enter(on_sys_enter); } From 7a17cfa539be62754522900d6e64b2e63fa9a078 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 8 Dec 2021 22:37:37 -0500 Subject: [PATCH 19/79] Linjector updates: * Fix linjector forking * Cleanup linjector and add python example * Rework linjector to use panda-rs for injection * Remove outdated test code from linjector * Add logging to linjector (behind 'LINJECTOR_LOG') * Add 'proc_name' option to linjector * Fix Rust linjector to not run off of a malformed forked/CoW buffer --- panda/plugins/hyperfuse/Cargo.lock | 16 +- panda/plugins/hyperfuse/src/lib.rs | 16 +- panda/plugins/linjector/Cargo.lock | 215 +++++++++- panda/plugins/linjector/Cargo.toml | 4 +- panda/plugins/linjector/src/args.rs | 42 ++ panda/plugins/linjector/src/lib.rs | 400 +++++++----------- panda/plugins/linjector/src/syscalls.rs | 78 ++++ .../syscall_switch_enter_linux_x64.cpp | 2 +- panda/python/examples/hyperfuse.py | 19 + panda/python/examples/linject.py | 31 ++ 10 files changed, 556 insertions(+), 267 deletions(-) create mode 100644 panda/plugins/linjector/src/args.rs create mode 100644 panda/plugins/linjector/src/syscalls.rs create mode 100644 panda/python/examples/hyperfuse.py create mode 100644 panda/python/examples/linject.py diff --git a/panda/plugins/hyperfuse/Cargo.lock b/panda/plugins/hyperfuse/Cargo.lock index c66a87ba5fe..476d1123a7c 100644 --- a/panda/plugins/hyperfuse/Cargo.lock +++ b/panda/plugins/hyperfuse/Cargo.lock @@ -330,6 +330,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + [[package]] name = "page_size" version = "0.4.2" @@ -342,13 +348,15 @@ dependencies = [ [[package]] name = "panda-re" -version = "0.13.0" +version = "0.22.0" +source = "git+https://github.com/panda-re/panda-rs#cfa0d34cc7ca372be7daab76e09c603eab415059" dependencies = [ "dirs", "glib-sys", "inventory", "lazy_static", "libloading", + "once_cell", "panda-re-macros", "panda-re-sys", "paste", @@ -359,7 +367,8 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.9.0" +version = "0.14.0" +source = "git+https://github.com/panda-re/panda-rs#cfa0d34cc7ca372be7daab76e09c603eab415059" dependencies = [ "darling", "doc-comment", @@ -369,7 +378,8 @@ dependencies = [ [[package]] name = "panda-re-sys" -version = "0.4.0" +version = "0.7.0" +source = "git+https://github.com/panda-re/panda-rs#cfa0d34cc7ca372be7daab76e09c603eab415059" [[package]] name = "parking_lot" diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index 2fdbd02380d..ee87a7a27fd 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -122,7 +122,9 @@ impl Filesystem for HelloFS { ReadDir { ino, offset } => Directory { dir_entries } => { + println!("Got to dir entry"); for DirEntry { ino, offset, kind, name } in dir_entries { + println!("{:?}", name); if reply.add(ino, offset, kind, name) { break } @@ -132,6 +134,7 @@ impl Filesystem for HelloFS { } ); } + println!("Finished reply"); } fn open(&mut self, _req: &fuser::Request<'_>, ino: u64, flags: i32, reply: ReplyOpen) { @@ -184,7 +187,11 @@ impl Receiver { loop { match MESSAGE_QUEUE.pop() { Some(bytes) => break bincode::deserialize(&bytes).map_err(|_| ()), - None => std::thread::yield_now(), + None => { + println!("Nothing recieved, sleeping..."); + //std::thread::yield_now(); + std::thread::sleep(std::time::Duration::from_millis(500)); + } } } } @@ -195,7 +202,7 @@ impl Receiver { //} fn mount(channel: ChannelId) { - let mountpoint = "/home/luke/workspace/fuse_mount/"; + let mountpoint = "/home/jmcleod/dev/panda/build/fuse_mount"; let options = vec![ MountOption::FSName("hello".to_string()), MountOption::AutoUnmount, @@ -206,6 +213,7 @@ fn mount(channel: ChannelId) { //other_thread::start(incoming_request, response); fuser::mount2(HelloFS { request, reply }, mountpoint, &options).unwrap(); + println!("Unmounted"); } use crossbeam_queue::SegQueue; @@ -223,7 +231,7 @@ extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { #[panda::init] fn init(_: &mut PluginHandle) -> bool { - let path = "/home/luke/workspace/igloo/pie_idea/guest_code/target/i686-unknown-linux-musl/release/guest_daemon"; + let path = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_daemon"; let plugin_name = CString::new("linjector".as_bytes()).unwrap(); let plugin_arg = CString::new(format!("guest_binary={}", path).as_bytes()).unwrap(); unsafe { @@ -236,7 +244,7 @@ fn init(_: &mut PluginHandle) -> bool { GUEST_PLUGIN_MANAGER.ensure_init(); let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( "hyperfuse".into(), - Path::new("/home/luke/workspace/igloo/pie_idea/guest_code/target/i686-unknown-linux-musl/release/hyperfuse_guest"), + Path::new("/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/hyperfuse_guest"), message_recv, )); println!("hyperfuse established channel with fd {}", channel); diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index 300aeec2feb..22a02387570 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -8,6 +8,37 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "async-trait" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -80,6 +111,16 @@ dependencies = [ "syn", ] +[[package]] +name = "dashmap" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +dependencies = [ + "cfg-if", + "num_cpus", +] + [[package]] name = "dirs" version = "3.0.2" @@ -106,6 +147,19 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "flate2" version = "1.0.22" @@ -165,12 +219,39 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "inventory" version = "0.1.10" @@ -220,9 +301,29 @@ name = "linjector" version = "0.1.0" dependencies = [ "lazy_static", + "log", "object", "once_cell", "panda-re", + "pretty_env_logger", +] + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", ] [[package]] @@ -241,6 +342,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "object" version = "0.26.2" @@ -259,17 +370,21 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.13.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f70db200bc5fd6609d6a6eadb571964507dcb308dd98fbc8b5bd5586fa2fa270" +checksum = "b31fe3ef9172ce66a9957e7e0f703be08b7f5c8fba234e6adde2ab3a08792d38" dependencies = [ + "async-trait", + "dashmap", "dirs", "glib-sys", "inventory", "lazy_static", "libloading", + "once_cell", "panda-re-macros", "panda-re-sys", + "parking_lot", "paste", "strum 0.20.0", "strum_macros 0.20.1", @@ -278,9 +393,9 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.9.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daee3587300135fd563445fe7511eff6e67474007aeeae2b58734eab3e71082b" +checksum = "f81c6e3b78cf36e32f50b53a41d2d71b55b5ffee17978aac0c0b61e160f60d9f" dependencies = [ "darling", "doc-comment", @@ -290,9 +405,34 @@ dependencies = [ [[package]] name = "panda-re-sys" -version = "0.4.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0721969582932a84196625fd23b02e514dd6d1291f7fa074929f416fb56929a" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] [[package]] name = "paste" @@ -306,6 +446,16 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" +[[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger", + "log", +] + [[package]] name = "proc-macro2" version = "1.0.29" @@ -315,6 +465,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.9" @@ -343,12 +499,41 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + [[package]] name = "strsim" version = "0.9.3" @@ -417,6 +602,15 @@ dependencies = [ "version-compare", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.29" @@ -486,6 +680,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index a8eb0ec2884..976ae9718bd 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,10 +8,12 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.13.0", default-features = false } +panda-re = { version = "0.23", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" +log = "0.4" +pretty_env_logger = "0.4" [features] default = ["x86_64"] diff --git a/panda/plugins/linjector/src/args.rs b/panda/plugins/linjector/src/args.rs new file mode 100644 index 00000000000..be857afe713 --- /dev/null +++ b/panda/plugins/linjector/src/args.rs @@ -0,0 +1,42 @@ +use once_cell::sync::OnceCell; +use panda::prelude::*; + +static ELF_TO_INJECT: OnceCell> = OnceCell::new(); + +#[derive(PandaArgs)] +#[name = "linjector"] // plugin name +pub struct Args { + #[arg(default = "guest_daemon")] + pub guest_binary: String, + + #[arg(default = "[any]")] + pub proc_name: String, + + #[arg(default = true)] + pub require_root: bool, +} + +lazy_static::lazy_static! { + pub static ref ARGS: Args = Args::from_panda_args(); +} + +pub fn ensure_init() { + lazy_static::initialize(&ARGS); +} + +pub fn load_elf() { + log::info!("Loading binary: {:?}", ARGS.guest_binary); + ELF_TO_INJECT.get_or_init(|| std::fs::read(&ARGS.guest_binary).unwrap()); +} + +pub fn elf_to_inject() -> &'static [u8] { + &ELF_TO_INJECT.get().expect("No elf file loaded")[..] +} + +pub fn require_root() -> bool { + ARGS.require_root +} + +pub fn proc_name() -> &'static str { + ARGS.proc_name.as_str() +} diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 9749c0737c1..d01134fceb8 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -1,289 +1,185 @@ -use panda::sys::{get_cpu, qemu_loglevel, CPUX86State}; -use panda::{current_asid, current_pc, current_sp, PppCallback}; use panda::{ - mem::virtual_memory_read, + current_asid, + enums::MemRWStatus, mem::virtual_memory_write, plugins::osi::OSI, plugins::syscalls2::SYSCALLS, prelude::*, - regs::Reg::*, - syscall_injection::{run_injector, syscall}, + sys::get_cpu, + syscall_injection::{fork, run_injector}, }; -use std::{ - cmp::min, - sync::atomic::{AtomicUsize, Ordering}, +mod args; +mod syscalls; + +use syscalls::{ + chdir, do_execve, do_memfd_create, do_mmap, do_write, getpid, setsid, + PAGE_SIZE, }; -use once_cell::sync::OnceCell; +/// mmap a buffer and ensure it's paged in, then return the address to it +async fn get_guest_buffer() -> target_ptr_t { + // mmap in a new page + let mmap_addr = do_mmap().await; + log::debug!("mmap addr {:#x}", mmap_addr); -static ELF_TO_INJECT: OnceCell> = OnceCell::new(); -static ELF_READ_POS: AtomicUsize = AtomicUsize::new(0); + if (mmap_addr as target_long).is_negative() { + log::error!("linjector mmap error: {}", mmap_addr as target_long); + } -#[derive(PandaArgs)] -#[name = "linjector"] // plugin name -struct Args { - #[arg(default = "guest_daemon")] - guest_binary: String, - #[arg(default = true)] - require_root: bool, -} + // Ensure the page is mapped in + let chdir_return = chdir(mmap_addr).await; + log::debug!("Chdir return: {:#x}", chdir_return); -lazy_static::lazy_static! { - static ref ARGS: Args = Args::from_panda_args(); + mmap_addr as target_ptr_t } -// i386 -// const MMAP2: target_ulong = 192; -// const WRITE: target_ulong = 4; -// const FORK: target_ulong = 2; -// const EXECVE: target_ulong = 11; -// const MEMFD_CREATE: target_ulong = 356; -// x86_64 -const MMAP: target_ulong = 9; -const WRITE: target_ulong = 1; -const FORK: target_ulong = 57; -const EXECVE: target_ulong = 59; -const MEMFD_CREATE: target_ulong = 319; - -const NULL: target_ulong = 0; -const NEG_1: target_ulong = u32::MAX as target_ulong; -const PAGE_SIZE: target_ulong = 1024; -// const PROT_READ: target_ulong = 0x1; /* Page can be read. */ -// const PROT_WRITE: target_ulong = 0x2; /* Page can be written. */ -// const PROT_EXEC: target_ulong = 0x4; /* Page can be executed. */ -//const MAP_SHARED: target_ulong = 0x1; -//const MAP_ANON: target_ulong = 0x20; -//const MAP_PRIVATE: target_ulong = 0x2; -// andrew's script values -const PROT_READ: target_ulong = 4; -const PROT_WRITE: target_ulong = 2; -const MAP_ANON: target_ulong = 0x20; -const MAP_SHARED: target_ulong = 0x2; - -async fn do_mmap() -> target_ulong { - syscall( - MMAP, - ( - 0u64, - PAGE_SIZE, - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANON, - NEG_1, - NULL, - ), - ) - .await +fn current_process_name(cpu: &mut CPUState) -> String { + let proc = OSI.get_current_process(cpu); + proc.get_name().into_owned() } -const MFD_CLOEXEC: target_ulong = 1; +#[panda::on_all_sys_enter] +fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { + // Only check process name when a target process name is provided + if args::proc_name() != "[any]" { + let proc_name = current_process_name(cpu); + + // Only inject into this process if the process matches the provided name + if proc_name == args::proc_name() { + log::trace!("Injecting into process {:?}", proc_name); + } else { + log::trace!("Not injecting into process {:?}", proc_name); + return; + } + } -async fn do_memfd_create(mmap_addr: target_ulong) -> target_ulong { - // we use the mmap_addr for the name because we've zeroed it - // so it will be a '\0' literal name - syscall(MEMFD_CREATE, (mmap_addr, MFD_CLOEXEC)).await -} + log::trace!("Attempting injection into syscall {}", syscall_num); + let file_data = args::elf_to_inject(); -async fn do_write( - mem_fd: target_ulong, - mmap_addr: target_ulong, - len: target_ulong, -) -> target_ulong { - syscall(WRITE, (mem_fd, mmap_addr, len)).await -} + // Inject our syscall chain into the current system call. This injector + // copies our ELF to a memory file descriptor then forks and runs it as + // a daemon process. + run_injector(pc, async move { + let cpu = unsafe { &mut *get_cpu() }; + if args::require_root() { + if getpid().await == 0 { + log::debug!("Got root!"); + } else { + // Set the injector back up for next syscall + log::trace!("Not root, retrying next syscall..."); + SYSCALLS.add_callback_on_all_sys_enter(on_sys_enter); + return; + } + } -async fn do_fork() -> target_ulong { - syscall(FORK, ()).await -} + log::debug!("In injector"); + log::debug!("current asid: {:x}", current_asid(cpu)); -async fn do_execve( - path: target_ulong, - argv: target_ulong, - envp: target_ulong, -) -> target_ulong { - syscall(EXECVE, (path, argv, envp)).await -} + // mmap a region so we have a buffer in the guest to use + let guest_buf = get_guest_buffer().await; -const GETPID: target_ulong = 24; + // Create a memory file descriptor for loading our binary into + let mem_fd = do_memfd_create(guest_buf).await; + log::debug!("Got memory fd {:#x}", mem_fd); -fn read_2_bytes_at_pc(_cpu: &mut CPUState, pc: target_ulong) { - let a = virtual_memory_read(_cpu, pc, 2).unwrap(); - println!("opcode@PC 0: {:x} 1: {:x}", a[0], a[1]); -} + if (mem_fd as target_long).is_negative() { + log::error!("linjector mem_fd error: {}", mem_fd as target_long); + } -const DUP: target_ulong = 32; -const DUP2: target_ulong = 63; -const MLOCK: target_ulong = 150; + // Write our file to our memory fd + let mut elf_write_pos = 0; + while elf_write_pos < file_data.len() { + // Calculate max size to attempt to copy to our guest buffer + let attempt_write_size = + usize::min(PAGE_SIZE as usize, file_data.len() - elf_write_pos); + + // Calculate the end of the range we're attempting to copy + let end_write = elf_write_pos + attempt_write_size; + + log::debug!( + "Writing {} bytes [{}-{}]... (file len: {})", + PAGE_SIZE, + elf_write_pos, + end_write, + file_data.len(), + ); + + // Copy to guest buffer + virtual_memory_write( + cpu, + guest_buf, + &file_data[elf_write_pos..end_write], + ); + + // Write guest buffer to memory file descriptor + let written = do_write(mem_fd, guest_buf, PAGE_SIZE).await; + + if written < 0 { + log::error!("Write returned error {}", written); + } else { + elf_write_pos += written as usize; + } + } -#[panda::on_all_sys_enter] -fn on_sys_enter(_cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { - if OSI.get_current_process(_cpu).get_name() != "cat" { - return; - } - println!("Got syscall {}", syscall_num); - println!( - "SYSCALLS PC is {:x} CURRENT_PC is {:x}", - pc.pc(), - current_pc(_cpu) - ); - read_2_bytes_at_pc(_cpu, pc.pc()); - let asid = current_asid(_cpu); - let cpc = current_pc(_cpu); - read_2_bytes_at_pc(_cpu, pc.pc()); - read_2_bytes_at_pc(_cpu, cpc); - - let file_data = ELF_TO_INJECT.get().unwrap(); - - let sys_enter = PppCallback::new(); - let sys_return = PppCallback::new(); + log::debug!("Finished writing to memfd"); + log::debug!("Forking..."); - run_injector(pc, async move { - // unsafe { - // qemu_loglevel |= 1 << 1; - // } - let cpu = unsafe { &mut *get_cpu() }; - // println!("current asid: {:x}", current_asid(cpu)); - // if ARGS.require_root { - // let is_root = syscall(GETPID, ()).await == 0 as target_ulong; - // if !is_root { - - // SYSCALLS.add_callback_on_all_sys_enter(on_sys_enter); - // return; - // } else { - // println!("Got root!"); - - // } - // } - - println!("In injector"); - println!("current asid: {:x}", current_asid(cpu)); - - // let dupfd = syscall(DUP, (0u64,)).await; - // let dupfd = syscall(DUP2, (0u64, 10u64)).await; - // println!("got new FD {}", dupfd); - // let round_address = 0x7fffffffe000u64; - // let not_round = 0x00007fffffffeaa8u64; - // let mlock_ret = syscall(MLOCK, (round_address, u64::MAX)).await; - // println!("mlock_ret: {}", mlock_ret as i64); - // only problematic in multi-cpu systems - // mmap a region - let mmap_addr = do_mmap().await; - println!("Got mmap addr {:#x}", mmap_addr); - println!("{}", mmap_addr as i64); - println!("current asid: {:x}", current_asid(cpu)); - // zero it out - // virtual_memory_write(cpu, mmap_addr, &[0u8; PAGE_SIZE as usize]); - // let mmap_addr = panda::current_sp(cpu) + 0x1000; - // virtual_memory_write(cpu, mmap_addr, &[0u8; 20]); - let mem_fd = do_memfd_create(mmap_addr).await; - println!("Got fd {:#x}", mem_fd); - println!("{}", mmap_addr as i64); - println!("current asid: {:x}", current_asid(cpu)); - loop { - match ELF_READ_POS.fetch_add(PAGE_SIZE as usize, Ordering::SeqCst) { - x if x < file_data.len() => { - let size = - min(PAGE_SIZE as isize, (file_data.len() - x) as isize); - println!( - "Writing {} bytes [{}-{}] total: {}...", - PAGE_SIZE, - x, - x + PAGE_SIZE as usize, - file_data.len() - ); - println!("current asid: {:x}", current_asid(cpu)); - virtual_memory_write( - cpu, - mmap_addr, - &file_data[x..x + size as usize], - ); - do_write(mem_fd, mmap_addr, PAGE_SIZE).await; - } - _ => break, + // Fork and have the child process spawn the injected elf + fork(async move { + log::debug!("Child process began"); + + // Daemonize child process + let session_id = setsid().await; + log::debug!("Session id: {:#x}", session_id); + + // Get a new buffer for writing the path to our memfd + let guest_path_buf = get_guest_buffer().await; + + // Path should be "/proc/self/fd/#" where # is the memory file descriptor we + // loaded our executable into, + let path = format!("/proc/self/fd/{}", mem_fd); + log::debug!("fd path: {:?}", path); + + // Convert to bytes and add null terminator + let mut path = path.into_bytes(); + path.push(0); + + // Copy the path to the guest buffer we mmap'd + log::debug!("Writing path to guest..."); + let write_result = virtual_memory_write(cpu, guest_path_buf, &path); + + if !matches!(write_result, MemRWStatus::MemTxOk) { + log::error!("Write to guest status: {:?}", write_result); } - } - println!("forking..."); - panda::hook::start_block_exec(move |cpu, _, hook| { - println!("RAX: {:x}", panda::regs::get_reg(cpu, RAX)); + + // Execute the host binary + log::debug!("Performing execve"); + do_execve(guest_path_buf, 0, 0).await; }) - .at_addr(pc.pc() + 2); - - // let pid = syscall(GETPID, ()).await; - // println!("PID is {}", pid); - - let fork_ret = do_fork().await; - println!("fork ret {:x}", fork_ret); - - // let is_parent = fork_ret != 0 as target_ulong; - // println!("is_parent is {}", is_parent); - - // // /proc/self/fd/# - - // let execbuf = [ - // 47u8, - // 112, - // 114, - // 111, - // 99, - // 47, - // 115, - // 101, - // 108, - // 102, - // 47, - // 102, - // 100, - // 47, - // 48 + mem_fd as u8, - // 0, - // ]; - // virtual_memory_write(cpu, mmap_addr, &execbuf); - // println!("execve()"); - // let end_mmap_buf = - // mmap_addr as target_ulong + (execbuf.len() - 1) as target_ulong; - // do_execve(mmap_addr, end_mmap_buf, end_mmap_buf).await; - // println!("finished"); - // // // unsafe { - // // qemu_loglevel = 0; - // } + .await; + + // Allow the original process to resume executing }); - // let r = unsafe { _cpu.env_ptr as *mut CPUX86State }; - // let HF_CS64_SHIFT: u64 = 15; - // let HF_CS64_MASK = 1 << HF_CS64_SHIFT; - - // let syscall_addr = unsafe { - // // if HF_CS64_MASK & (*r).eflags != 0 { - // // println!("lstar"); - // (*r).lstar - // // } else { - // // println!("cstar"); - // // (*r).cstar - // // } - // }; - - // panda::hook::before_block_exec(move |cpu, _, hook| { - // if asid == current_asid(cpu) { - // println!("Hit PC for LSTAR {:x}", pc.pc()); - // println!("RAX: {:x}", panda::regs::get_reg(cpu, RAX)); - // println!("RDI: {:x}", panda::regs::get_reg(cpu, RDI)); - // println!("RSI: {:x}", panda::regs::get_reg(cpu, RSI)); - // println!("RDX: {:x}", panda::regs::get_reg(cpu, RDX)); - // println!("RCX: {:x}", panda::regs::get_reg(cpu, RCX)); - // println!("R8: {:x}", panda::regs::get_reg(cpu, R8)); - // println!("R9: {:x}", panda::regs::get_reg(cpu, R9)); - // } - // }) - // .at_addr(syscall_addr); + // Once we inject to a process stop looking for syscalls to inject into SYSCALLS.remove_callback_on_all_sys_enter(on_sys_enter); } #[panda::init] fn init(_: &mut PluginHandle) -> bool { - println!("linjector asdf hit"); - lazy_static::initialize(&ARGS); - ELF_TO_INJECT.get_or_init(|| std::fs::read(&ARGS.guest_binary).unwrap()); - println!("got args {} {}", ARGS.guest_binary, ARGS.require_root); + args::ensure_init(); + + pretty_env_logger::init_custom_env("LINJECTOR_LOG"); + args::load_elf(); + + log::info!("linjector loaded"); + if args::require_root() { + log::info!("linjector requiring root"); + } else { + log::info!("linjector not requiring root"); + } + true } diff --git a/panda/plugins/linjector/src/syscalls.rs b/panda/plugins/linjector/src/syscalls.rs new file mode 100644 index 00000000000..82a53b3d0a1 --- /dev/null +++ b/panda/plugins/linjector/src/syscalls.rs @@ -0,0 +1,78 @@ +use panda::prelude::*; +use panda::syscall_injection::{syscall, syscall_no_return}; + +// i386 +// const MMAP2: target_ulong = 192; +// const WRITE: target_ulong = 4; +// const FORK: target_ulong = 2; +// const EXECVE: target_ulong = 11; +// const MEMFD_CREATE: target_ulong = 356; + +// x86_64 +const GETPID: target_ulong = 39; +const MMAP: target_ulong = 9; +const WRITE: target_ulong = 1; +const EXECVE: target_ulong = 59; +const MEMFD_CREATE: target_ulong = 319; +const CHDIR: target_ulong = 80; +const SETSID: target_ulong = 112; + +const NULL: target_ulong = 0; +const NEG_1: target_ulong = u32::MAX as target_ulong; +pub const PAGE_SIZE: target_ulong = 1024; + +const PROT_READ: target_ulong = 4; +const PROT_WRITE: target_ulong = 2; +const MAP_ANON: target_ulong = 0x20; +const MAP_SHARED: target_ulong = 0x2; + +pub async fn do_mmap() -> target_ulong { + syscall( + MMAP, + ( + 0u64, + PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANON, + NEG_1, + NULL, + ), + ) + .await +} + +const MFD_CLOEXEC: target_ulong = 1; + +pub async fn do_memfd_create(mmap_addr: target_ulong) -> target_ulong { + // we use the mmap_addr for the name because we've zeroed it + // so it will be a '\0' literal name + syscall(MEMFD_CREATE, (mmap_addr, MFD_CLOEXEC)).await +} + +pub async fn do_write( + mem_fd: target_ulong, + mmap_addr: target_ulong, + len: target_ulong, +) -> target_long { + syscall(WRITE, (mem_fd, mmap_addr, len)).await as target_long +} + +pub async fn do_execve( + path: target_ulong, + argv: target_ulong, + envp: target_ulong, +) -> target_ulong { + syscall_no_return(EXECVE, (path, argv, envp)).await +} + +pub async fn getpid() -> target_ulong { + syscall(GETPID, ()).await +} + +pub async fn chdir(addr: target_ulong) -> target_ulong { + syscall(CHDIR, (addr,)).await +} + +pub async fn setsid() -> target_ulong { + syscall(SETSID, ()).await +} diff --git a/panda/plugins/syscalls2/generated/syscall_switch_enter_linux_x64.cpp b/panda/plugins/syscalls2/generated/syscall_switch_enter_linux_x64.cpp index 2b5f0488195..e72f900c9c1 100644 --- a/panda/plugins/syscalls2/generated/syscall_switch_enter_linux_x64.cpp +++ b/panda/plugins/syscalls2/generated/syscall_switch_enter_linux_x64.cpp @@ -4589,4 +4589,4 @@ void syscall_enter_switch_linux_x64(CPUState *cpu, target_ptr_t pc, int static_c #endif } -/* vim: set tabstop=4 softtabstop=4 noexpandtab ft=cpp: */ \ No newline at end of file +/* vim: set tabstop=4 softtabstop=4 noexpandtab ft=cpp: */ diff --git a/panda/python/examples/hyperfuse.py b/panda/python/examples/hyperfuse.py new file mode 100644 index 00000000000..5b560b805bb --- /dev/null +++ b/panda/python/examples/hyperfuse.py @@ -0,0 +1,19 @@ +from pandare import Panda +from termcolor import colored +import os + +panda = Panda(generic="x86_64") +panda.load_plugin("hyperfuse", {}) + +@panda.queue_blocking +def run_cmd(): + panda.revert_sync("root") + + # if it's worth running it's worth running twice + # (don't ask, and definitely don't remove either line) + panda.run_serial_cmd("cat") + panda.run_serial_cmd("cat") + + panda.end_analysis() + +panda.run() diff --git a/panda/python/examples/linject.py b/panda/python/examples/linject.py new file mode 100644 index 00000000000..50987c3b367 --- /dev/null +++ b/panda/python/examples/linject.py @@ -0,0 +1,31 @@ +from pandare import Panda +from termcolor import colored +import os + +# Please don't do it this way normally +code = """#include +#include + +int main() { + printf("Hello World!\\n"); + sleep(3); + + return 0; +} +""" +os.system(f'printf {repr(code)} | gcc -x c - -o hello_world_x86_64') + +panda = Panda(generic="x86_64") +panda.load_plugin("linjector", { + "require_root": False, + "guest_binary": "hello_world_x86_64", + "proc_name": "cat" +}) + +@panda.queue_blocking +def run_cmd(): + panda.revert_sync("root") + print(colored(panda.run_serial_cmd("cat /proc/cpuinfo"), "white", attrs=['bold'])) + panda.end_analysis() + +panda.run() From 7939fd646f9c306ccac46f15f06e793f96b29967 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Tue, 30 Nov 2021 15:46:51 -0500 Subject: [PATCH 20/79] Hyperfuse updates: - Add logging to hyperfuse, remove excess logging from guest_plugin_manager - Add pre-fetching for hyperfuse dir listing --- .../src/guest_plugin_manager.rs | 1 - .../src/interface/channels.rs | 56 ++++++++++++------- .../guest_plugin_manager/src/interface/hci.rs | 20 ++++--- .../src/interface/plugin_manager.rs | 38 +++++++------ panda/plugins/hyperfuse/Cargo.lock | 41 ++++++++++---- panda/plugins/hyperfuse/Cargo.toml | 4 +- panda/plugins/hyperfuse/src/lib.rs | 37 ++++++++++-- panda/plugins/hyperfuse/src/types.rs | 8 +++ panda/python/examples/hyperfuse.py | 5 +- 9 files changed, 141 insertions(+), 69 deletions(-) diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index 984e29af159..62fb58d028a 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -64,7 +64,6 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { if let Some(retval) = retval { set_hyp_ret_reg(cpu, retval); } - println!("end of hc"); true } else { false diff --git a/panda/plugins/guest_plugin_manager/src/interface/channels.rs b/panda/plugins/guest_plugin_manager/src/interface/channels.rs index b4f4cb1efa0..47201cf0f2e 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/channels.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/channels.rs @@ -1,7 +1,7 @@ use crossbeam_queue::SegQueue; +use lazy_static::lazy_static; use parking_lot::RwLock; use std::collections::HashMap; -use lazy_static::lazy_static; use std::sync::atomic::{AtomicU32, Ordering}; pub type ChannelId = u32; @@ -9,9 +9,9 @@ pub type ChannelCB = extern "C" fn(ChannelId, *const u8, usize); static NEXT_CHANNEL_NUMBER: AtomicU32 = AtomicU32::new(0); -lazy_static!{ -static ref CHANNELS: RwLock> = - RwLock::new(HashMap::new()); +lazy_static! { + static ref CHANNELS: RwLock> = + RwLock::new(HashMap::new()); } struct Channel { @@ -22,12 +22,18 @@ struct Channel { pub fn add_channel(p_name: Option<&str>, cb: ChannelCB) -> ChannelId { let mut plugins = CHANNELS.write(); - let channel_id = NEXT_CHANNEL_NUMBER.fetch_add(1, Ordering::SeqCst); - if plugins.insert(channel_id, Channel { - name: p_name.map(ToString::to_string), - msg_receive_cb: cb, - message_queue: SegQueue::new() - }).is_some() { + let channel_id = NEXT_CHANNEL_NUMBER.fetch_add(1, Ordering::SeqCst); + if plugins + .insert( + channel_id, + Channel { + name: p_name.map(ToString::to_string), + msg_receive_cb: cb, + message_queue: SegQueue::new(), + }, + ) + .is_some() + { panic!("We've somehow added a duplicate ID"); } println!("Added channel {} FD: {}", p_name.unwrap_or("?"), channel_id); @@ -35,9 +41,8 @@ pub fn add_channel(p_name: Option<&str>, cb: ChannelCB) -> ChannelId { } pub fn poll_plugin_message(channel_id: ChannelId) -> Option> { - println!("in poll_plugin_message"); let pm = CHANNELS.read(); - if let Some(plugin) = pm.get(&channel_id){ + if let Some(plugin) = pm.get(&channel_id) { plugin.message_queue.pop() } else { panic!("poll_plugin_message for plugin with incorrect ID"); @@ -46,31 +51,40 @@ pub fn poll_plugin_message(channel_id: ChannelId) -> Option> { pub fn publish_message_from_guest(channel_id: ChannelId, msg: Vec) { let pm = CHANNELS.read(); - if let Some(plugin) = pm.get(&channel_id){ + if let Some(plugin) = pm.get(&channel_id) { let buf_ptr = msg.as_ptr(); println!("published message to FD {}", channel_id); (plugin.msg_receive_cb)(channel_id, buf_ptr, msg.len()) - }else{ + } else { println!("failed publish message to FD {}", channel_id); } } pub fn publish_message_to_guest(channel_id: ChannelId, msg: Vec) { let pm = CHANNELS.read(); - if let Some(plugin) = pm.get(&channel_id){ + if let Some(plugin) = pm.get(&channel_id) { // println!("message pushed"); plugin.message_queue.push(msg) - }else{ + } else { println!("failed to publish message"); } } -pub fn get_channel_from_name(p_name: &str) -> Option{ +pub fn get_channel_from_name(p_name: &str) -> Option { // let unnamed = "unnamed".to_owned(); println!("channel_from_name"); - for ch in CHANNELS.read().iter(){ - println!("channel name: {} FD: {}",&ch.1.name.as_ref().unwrap_or(&"unnamed".to_string()), ch.0); + for ch in CHANNELS.read().iter() { + println!( + "channel name: {} FD: {}", + &ch.1.name.as_ref().unwrap_or(&"unnamed".to_string()), + ch.0 + ); } - CHANNELS.read().iter().find(|(_, v)| v.name.as_deref() == Some(p_name)).map(|x| *x.0) -} \ No newline at end of file + CHANNELS + .read() + .iter() + .find(|(_, v)| v.name.as_deref() == Some(p_name)) + .map(|x| *x.0) +} + diff --git a/panda/plugins/guest_plugin_manager/src/interface/hci.rs b/panda/plugins/guest_plugin_manager/src/interface/hci.rs index f4e3fc6e5c9..4c83dd7aa47 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/hci.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/hci.rs @@ -1,5 +1,7 @@ use super::channels::ChannelId; -use super::channels::{poll_plugin_message, publish_message_from_guest,get_channel_from_name}; +use super::channels::{ + get_channel_from_name, poll_plugin_message, publish_message_from_guest, +}; use super::plugin_manager::new_manager_channel; use crate::MAGIC; use panda::mem::{virtual_memory_read, virtual_memory_write}; @@ -29,17 +31,14 @@ pub fn hyp_read( addr: usize, max_size: usize, ) -> Option { - println!("got to hyp_read with CID {}", channel_id); if let Some(msg) = poll_plugin_message(channel_id) { - if msg.len() > max_size{ + if msg.len() > max_size { panic!(); } // could check max len more virtual_memory_write(cpu, addr as target_ulong, &msg); - println!("end of get some message"); Some(msg.len()) } else { - println!("end of get nothing"); Some(0) } } @@ -84,19 +83,22 @@ pub fn hyp_get_channel_by_name( _channel_id: ChannelId, buf_ptr: usize, buf_size: usize, -) -> Option{ +) -> Option { println!("channel_by_name"); if let Ok(buf_out) = virtual_memory_read(cpu, buf_ptr as target_ulong, buf_size) { - if let Some(cd) = get_channel_from_name(dbg!(&String::from_utf8_lossy(&buf_out))){ + if let Some(cd) = + get_channel_from_name(dbg!(&String::from_utf8_lossy(&buf_out))) + { println!("found channel number {}", cd); Some(cd as usize) - }else{ + } else { println!("failed to find channel number"); Some(-1_isize as usize) } } else { panic!("Failed to read virtual memory in hyp_write"); } -} \ No newline at end of file +} + diff --git a/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs index 6595631c944..228e67db58a 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/plugin_manager.rs @@ -1,10 +1,9 @@ -use super::channels::{publish_message_to_guest,ChannelId,add_channel}; -use std::mem::size_of; +use super::channels::{add_channel, publish_message_to_guest, ChannelId}; use std::convert::TryFrom; +use std::mem::size_of; use std::slice::from_raw_parts; -type OperationID = u32; - +type OperationID = u32; enum ManagerOp { GetChannelFromName = 0, @@ -23,33 +22,40 @@ impl TryFrom for ManagerOp { } } -fn get_channel_from_name(origin_channel: ChannelId, buffer: Vec){ +fn get_channel_from_name(origin_channel: ChannelId, buffer: Vec) { let plugin_name = String::from_utf8_lossy(&buffer).into_owned(); - if let Some(channel_id) = super::channels::get_channel_from_name(&plugin_name){ - println!("success got channel from name {} FD is {}", plugin_name, channel_id); + if let Some(channel_id) = + super::channels::get_channel_from_name(&plugin_name) + { + println!( + "success got channel from name {} FD is {}", + plugin_name, channel_id + ); let buf = u32::to_le_bytes(channel_id); - publish_message_to_guest(origin_channel,buf.to_vec()); - }else{ + publish_message_to_guest(origin_channel, buf.to_vec()); + } else { println!("Failed to get channel from name"); } } -extern "C" fn read_callback(channel_id: ChannelId, ptr: *const u8, len: usize){ - println!("made it to read callback"); - let mut buf = unsafe{from_raw_parts(ptr, len).to_vec()}; +extern "C" fn read_callback(channel_id: ChannelId, ptr: *const u8, len: usize) { + let mut buf = unsafe { from_raw_parts(ptr, len).to_vec() }; const OPSIZE: usize = size_of::(); - let mut operation: [u8;OPSIZE] = [0;4]; + let mut operation: [u8; OPSIZE] = [0; 4]; operation.copy_from_slice(&buf[..OPSIZE]); let op_num = OperationID::from_le_bytes(operation); buf.drain(0..OPSIZE); match ManagerOp::try_from(op_num as usize) { - Ok(ManagerOp::GetChannelFromName) => get_channel_from_name(channel_id, buf), - Ok(ManagerOp::DebugOutput) => {}, + Ok(ManagerOp::GetChannelFromName) => { + get_channel_from_name(channel_id, buf) + } + Ok(ManagerOp::DebugOutput) => {} _ => {} } } pub fn new_manager_channel() -> ChannelId { dbg!(add_channel(None, read_callback)) -} \ No newline at end of file +} + diff --git a/panda/plugins/hyperfuse/Cargo.lock b/panda/plugins/hyperfuse/Cargo.lock index 476d1123a7c..b9ba19f9f15 100644 --- a/panda/plugins/hyperfuse/Cargo.lock +++ b/panda/plugins/hyperfuse/Cargo.lock @@ -142,9 +142,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "env_logger" -version = "0.9.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ "atty", "humantime", @@ -161,9 +161,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fuser" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166e3212e0cc562dd17eefa4d80cf443720eec051e7171fe2b94e4ba8d272786" +checksum = "096c834eabc44f7151b8f17d28eb0501e30ea9139b4a2d64f33ad9ef4bdae8d3" dependencies = [ "libc", "log", @@ -228,9 +228,12 @@ dependencies = [ [[package]] name = "humantime" -version = "2.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] [[package]] name = "hyperfuse" @@ -238,12 +241,12 @@ version = "0.1.0" dependencies = [ "bincode", "crossbeam-queue", - "env_logger", "fuser", "lazy_static", "libc", "panda-re", "parking_lot", + "pretty_env_logger", "serde", ] @@ -418,6 +421,16 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +[[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger", + "log", +] + [[package]] name = "proc-macro2" version = "1.0.27" @@ -427,6 +440,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.9" @@ -689,9 +708,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "zerocopy" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6580539ad917b7c026220c4b3f2c08d52ce54d6ce0dc491e66002e35388fab46" +checksum = "5e59ec1d2457bd6c0dd89b50e7d9d6b0b647809bf3f0a59ac85557046950b7b2" dependencies = [ "byteorder", "zerocopy-derive", @@ -699,9 +718,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" +checksum = "a0fbc82b82efe24da867ee52e015e58178684bd9dd64c34e66bdf21da2582a9f" dependencies = [ "proc-macro2", "syn", diff --git a/panda/plugins/hyperfuse/Cargo.toml b/panda/plugins/hyperfuse/Cargo.toml index 56fa94d1d6c..0dda4ef09d4 100644 --- a/panda/plugins/hyperfuse/Cargo.toml +++ b/panda/plugins/hyperfuse/Cargo.toml @@ -10,9 +10,9 @@ crate-type = ["cdylib"] [dependencies] #panda-re = { version = "0.13.0", default-features = false } panda-re = { git = "https://github.com/panda-re/panda-rs", default-features = false } -fuser = { version = "0.8.0", features = ["serializable"] } +fuser = { version = "0.9", features = ["serializable"] } libc = "0.2.98" -env_logger = "0.9.0" +pretty_env_logger = "0.4.0" serde = { version = "1", features = ["derive"] } bincode = "1.3.3" lazy_static = "1" diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index ee87a7a27fd..d780a20dffb 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -6,17 +6,19 @@ use libc::ENOENT; use panda::prelude::*; use serde::{Deserialize, Serialize}; use std::borrow::Borrow; -use std::ffi::{CString, OsStr}; +use std::collections::HashMap; +use std::ffi::{CString, OsStr, OsString}; use std::marker::PhantomData; use std::path::Path; -use std::sync::mpsc; mod types; use types::*; -struct HelloFS { +struct HyperFilesystem { reply: Receiver, request: Sender, + + lookup_cache: HashMap<(u64, OsString), LookupCacheEntry>, } macro_rules! on_reply { @@ -73,8 +75,18 @@ macro_rules! send_reply { }; } -impl Filesystem for HelloFS { +impl Filesystem for HyperFilesystem { fn lookup(&mut self, _req: &fuser::Request, parent_ino: u64, name: &OsStr, reply: ReplyEntry) { + if let Some(LookupCacheEntry { + ttl, + attr, + generation, + }) = self.lookup_cache.remove(&(parent_ino, name.to_os_string())) + { + reply.entry(&ttl, &attr, generation); + return; + } + let name = name.to_string_lossy().into_owned(); send_reply! { self => reply.entry( @@ -117,14 +129,16 @@ impl Filesystem for HelloFS { offset: i64, mut reply: ReplyDirectory, ) { + let parent_ino = ino; on_reply! { self => reply( ReadDir { ino, offset } => Directory { dir_entries } => { println!("Got to dir entry"); - for DirEntry { ino, offset, kind, name } in dir_entries { + for DirEntry { ino, offset, kind, name, lookup_cache } in dir_entries { println!("{:?}", name); + self.lookup_cache.insert((parent_ino, name.clone().into()), lookup_cache); if reply.add(ino, offset, kind, name) { break } @@ -212,7 +226,16 @@ fn mount(channel: ChannelId) { //other_thread::start(incoming_request, response); - fuser::mount2(HelloFS { request, reply }, mountpoint, &options).unwrap(); + fuser::mount2( + HyperFilesystem { + request, + reply, + lookup_cache: Default::default(), + }, + mountpoint, + &options, + ) + .unwrap(); println!("Unmounted"); } @@ -231,6 +254,8 @@ extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { #[panda::init] fn init(_: &mut PluginHandle) -> bool { + pretty_env_logger::init_custom_env("HYPERFUSE_LOG"); + let path = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_daemon"; let plugin_name = CString::new("linjector".as_bytes()).unwrap(); let plugin_arg = CString::new(format!("guest_binary={}", path).as_bytes()).unwrap(); diff --git a/panda/plugins/hyperfuse/src/types.rs b/panda/plugins/hyperfuse/src/types.rs index d22babc3c51..c897025c8b3 100644 --- a/panda/plugins/hyperfuse/src/types.rs +++ b/panda/plugins/hyperfuse/src/types.rs @@ -83,4 +83,12 @@ pub struct DirEntry { pub offset: i64, pub kind: FileType, pub name: String, + pub lookup_cache: LookupCacheEntry, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct LookupCacheEntry { + pub ttl: Duration, + pub attr: FileAttr, + pub generation: u64, } diff --git a/panda/python/examples/hyperfuse.py b/panda/python/examples/hyperfuse.py index 5b560b805bb..d840aa4cbbe 100644 --- a/panda/python/examples/hyperfuse.py +++ b/panda/python/examples/hyperfuse.py @@ -1,5 +1,4 @@ from pandare import Panda -from termcolor import colored import os panda = Panda(generic="x86_64") @@ -11,8 +10,8 @@ def run_cmd(): # if it's worth running it's worth running twice # (don't ask, and definitely don't remove either line) - panda.run_serial_cmd("cat") - panda.run_serial_cmd("cat") + panda.run_serial_cmd("cat", no_timeout=True) + panda.run_serial_cmd("cat", no_timeout=True) panda.end_analysis() From a2fdcd4c8dfba4c9660cfb33eba18c6f71ff6f5e Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 3 Dec 2021 11:39:28 -0500 Subject: [PATCH 21/79] Begin porting linjector to arm/i386 --- panda/plugins/config.panda | 2 +- .../guest_plugin_manager/src/hyp_regs.rs | 22 +++-- panda/plugins/hyperfuse/src/lib.rs | 23 +++++- panda/plugins/linjector/Cargo.lock | 6 -- panda/plugins/linjector/Cargo.toml | 3 +- panda/plugins/linjector/src/lib.rs | 81 +++++++++++++------ panda/plugins/linjector/src/syscalls.rs | 43 +++++++--- panda/plugins/linjector/src/syscalls/arm.rs | 17 ++++ panda/plugins/linjector/src/syscalls/i386.rs | 17 ++++ .../plugins/linjector/src/syscalls/x86_64.rs | 17 ++++ .../syscall_switch_enter_linux_arm.cpp | 13 ++- 11 files changed, 186 insertions(+), 58 deletions(-) create mode 100644 panda/plugins/linjector/src/syscalls/arm.rs create mode 100644 panda/plugins/linjector/src/syscalls/i386.rs create mode 100644 panda/plugins/linjector/src/syscalls/x86_64.rs diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index e555e6cac5b..efde357b995 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -29,7 +29,7 @@ mmio_trace net network osi -osi_linux +#osi_linux osi_test pri pri_dwarf diff --git a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs index 7bc1e5aaf81..5be443a5267 100644 --- a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs +++ b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs @@ -1,24 +1,30 @@ use panda::{ prelude::*, - regs::{get_reg, set_reg, Reg}, + regs::{ + get_reg, set_reg, + Reg::{self, *}, + }, }; // =================== Register Order =================== #[cfg(feature = "i386")] -pub const REG_ORDER: [Reg; 5] = - [Reg::EAX, Reg::EBX, Reg::ECX, Reg::EDX, Reg::EDI]; +pub const REG_ORDER: [Reg; 5] = [EAX, EBX, ECX, EDX, EDI]; -// XXX: is this right? #[cfg(feature = "x86_64")] -pub const REG_ORDER: [Reg; 5] = - [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX, Reg::RDI]; +pub const REG_ORDER: [Reg; 5] = [RAX, RBX, RCX, RDX, RDI]; + +#[cfg(feature = "arm")] +pub const REG_ORDER: [Reg; 5] = [R0, R1, R2, R3, R4]; // =================== Return Value =================== #[cfg(feature = "i386")] -pub const RET_REG: Reg = Reg::EAX; +pub const RET_REG: Reg = EAX; #[cfg(feature = "x86_64")] -pub const RET_REG: Reg = Reg::RAX; +pub const RET_REG: Reg = RAX; + +#[cfg(feature = "arm")] +pub const RET_REG: Reg = R0; pub fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { let reg_to_read = REG_ORDER[num]; diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index d780a20dffb..45211536a0f 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -252,13 +252,30 @@ extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { } } +#[cfg(feature = "x86_64")] +const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_daemon"; + +#[cfg(feature = "arm")] +const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/arm-unknown-linux-musleabi/release/guest_daemon"; + +#[cfg(feature = "i386")] +const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/guest_daemon"; + +#[cfg(feature = "x86_64")] +const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/hyperfuse_guest"; + +#[cfg(feature = "arm")] +const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/arm-unknown-linux-musleabi/release/hyperfuse_guest"; + +#[cfg(feature = "i386")] +const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/hyperfuse_guest"; + #[panda::init] fn init(_: &mut PluginHandle) -> bool { pretty_env_logger::init_custom_env("HYPERFUSE_LOG"); - let path = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_daemon"; let plugin_name = CString::new("linjector".as_bytes()).unwrap(); - let plugin_arg = CString::new(format!("guest_binary={}", path).as_bytes()).unwrap(); + let plugin_arg = CString::new(format!("guest_binary={}", PATH).as_bytes()).unwrap(); unsafe { let path = panda::sys::panda_plugin_path(plugin_name.as_ptr()); panda::sys::panda_add_arg(plugin_name.as_ptr(), plugin_arg.as_ptr()); @@ -269,7 +286,7 @@ fn init(_: &mut PluginHandle) -> bool { GUEST_PLUGIN_MANAGER.ensure_init(); let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( "hyperfuse".into(), - Path::new("/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/hyperfuse_guest"), + Path::new(GUEST_PLUGIN_PATH), message_recv, )); println!("hyperfuse established channel with fd {}", channel); diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index 22a02387570..9c7e4633a4f 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -371,8 +371,6 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b31fe3ef9172ce66a9957e7e0f703be08b7f5c8fba234e6adde2ab3a08792d38" dependencies = [ "async-trait", "dashmap", @@ -394,8 +392,6 @@ dependencies = [ [[package]] name = "panda-re-macros" version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81c6e3b78cf36e32f50b53a41d2d71b55b5ffee17978aac0c0b61e160f60d9f" dependencies = [ "darling", "doc-comment", @@ -406,8 +402,6 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index 976ae9718bd..06aa8da56d7 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,7 +8,8 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.23", default-features = false, features = ["syscall-injection"] } +#panda-re = { version = "0.23", default-features = false, features = ["syscall-injection"] } +panda-re = { path = "../../../../panda-rs/panda-rs", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index d01134fceb8..5b58f9822bb 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -13,8 +13,8 @@ mod args; mod syscalls; use syscalls::{ - chdir, do_execve, do_memfd_create, do_mmap, do_write, getpid, setsid, - PAGE_SIZE, + chdir, close, do_execve, do_memfd_create, do_mmap, do_write, getpid, open, + setsid, O_CLOEXEC, O_CREAT, O_RDWR, O_TRUNC, PAGE_SIZE, }; /// mmap a buffer and ensure it's paged in, then return the address to it @@ -23,7 +23,7 @@ async fn get_guest_buffer() -> target_ptr_t { let mmap_addr = do_mmap().await; log::debug!("mmap addr {:#x}", mmap_addr); - if (mmap_addr as target_long).is_negative() { + if (mmap_addr as target_long).is_negative() && mmap_addr > 0xffff_0000 { log::error!("linjector mmap error: {}", mmap_addr as target_long); } @@ -39,6 +39,29 @@ fn current_process_name(cpu: &mut CPUState) -> String { proc.get_name().into_owned() } +/// Convert to bytes and add null terminator +fn cstr_bytes(string: impl Into) -> Vec { + let mut string = string.into().into_bytes(); + string.push(0); + string +} + +/// Format a string and copy it to the guest +macro_rules! guest_string { + ($cpu:ident, $($tt:tt)*) => {{ + let bytes = cstr_bytes(format!($($tt)*)); + let guest_buf = get_guest_buffer().await; + + let write_result = virtual_memory_write($cpu, guest_buf, &bytes); + + if !matches!(write_result, MemRWStatus::MemTxOk) { + log::error!("Write to guest status: {:?}", write_result); + } + + guest_buf + }}; +} + #[panda::on_all_sys_enter] fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { // Only check process name when a target process name is provided @@ -83,9 +106,25 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { let mem_fd = do_memfd_create(guest_buf).await; log::debug!("Got memory fd {:#x}", mem_fd); - if (mem_fd as target_long).is_negative() { + let (fd, is_mem_fd) = if (mem_fd as target_long).is_negative() { log::error!("linjector mem_fd error: {}", mem_fd as target_long); - } + + log::debug!("linjector trying to write to /tmp instead..."); + + let path = guest_string!(cpu, "/tmp/payload"); + let fd = + open(path, O_CREAT | O_CLOEXEC | O_RDWR | O_TRUNC, 0o777).await; + + log::debug!("open of /tmp/payload returned {}", fd); + + if (fd as target_long).is_negative() { + log::error!("open of /tmp/payload returned error {}", fd); + } + + (fd, false) + } else { + (mem_fd, true) + }; // Write our file to our memory fd let mut elf_write_pos = 0; @@ -113,10 +152,11 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { ); // Write guest buffer to memory file descriptor - let written = do_write(mem_fd, guest_buf, PAGE_SIZE).await; + let written = do_write(fd, guest_buf, PAGE_SIZE).await; if written < 0 { log::error!("Write returned error {}", written); + panic!(); } else { elf_write_pos += written as usize; } @@ -125,6 +165,13 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { log::debug!("Finished writing to memfd"); log::debug!("Forking..."); + if !is_mem_fd { + let close_ret = close(fd).await; + if close_ret != 0 { + log::error!("Close of fd failed: {}", close_ret); + } + } + // Fork and have the child process spawn the injected elf fork(async move { log::debug!("Child process began"); @@ -133,25 +180,13 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { let session_id = setsid().await; log::debug!("Session id: {:#x}", session_id); - // Get a new buffer for writing the path to our memfd - let guest_path_buf = get_guest_buffer().await; - // Path should be "/proc/self/fd/#" where # is the memory file descriptor we // loaded our executable into, - let path = format!("/proc/self/fd/{}", mem_fd); - log::debug!("fd path: {:?}", path); - - // Convert to bytes and add null terminator - let mut path = path.into_bytes(); - path.push(0); - - // Copy the path to the guest buffer we mmap'd - log::debug!("Writing path to guest..."); - let write_result = virtual_memory_write(cpu, guest_path_buf, &path); - - if !matches!(write_result, MemRWStatus::MemTxOk) { - log::error!("Write to guest status: {:?}", write_result); - } + let guest_path_buf = if is_mem_fd { + guest_string!(cpu, "/proc/self/fd/{}", fd) + } else { + guest_string!(cpu, "/tmp/payload") + }; // Execute the host binary log::debug!("Performing execve"); diff --git a/panda/plugins/linjector/src/syscalls.rs b/panda/plugins/linjector/src/syscalls.rs index 82a53b3d0a1..6b821bc0728 100644 --- a/panda/plugins/linjector/src/syscalls.rs +++ b/panda/plugins/linjector/src/syscalls.rs @@ -8,24 +8,24 @@ use panda::syscall_injection::{syscall, syscall_no_return}; // const EXECVE: target_ulong = 11; // const MEMFD_CREATE: target_ulong = 356; -// x86_64 -const GETPID: target_ulong = 39; -const MMAP: target_ulong = 9; -const WRITE: target_ulong = 1; -const EXECVE: target_ulong = 59; -const MEMFD_CREATE: target_ulong = 319; -const CHDIR: target_ulong = 80; -const SETSID: target_ulong = 112; +#[cfg(feature = "x86_64")] +#[path = "syscalls/x86_64.rs"] +mod sys_nums; + +#[cfg(feature = "i386")] +#[path = "syscalls/i386.rs"] +mod sys_nums; + +#[cfg(feature = "arm")] +#[path = "syscalls/arm.rs"] +mod sys_nums; + +use sys_nums::*; const NULL: target_ulong = 0; const NEG_1: target_ulong = u32::MAX as target_ulong; pub const PAGE_SIZE: target_ulong = 1024; -const PROT_READ: target_ulong = 4; -const PROT_WRITE: target_ulong = 2; -const MAP_ANON: target_ulong = 0x20; -const MAP_SHARED: target_ulong = 0x2; - pub async fn do_mmap() -> target_ulong { syscall( MMAP, @@ -41,6 +41,11 @@ pub async fn do_mmap() -> target_ulong { .await } +pub const O_CREAT: i32 = 0o100; +pub const O_RDWR: i32 = 0o002; +pub const O_CLOEXEC: i32 = 0o2000000; +pub const O_TRUNC: i32 = 0o1000; + const MFD_CLOEXEC: target_ulong = 1; pub async fn do_memfd_create(mmap_addr: target_ulong) -> target_ulong { @@ -76,3 +81,15 @@ pub async fn chdir(addr: target_ulong) -> target_ulong { pub async fn setsid() -> target_ulong { syscall(SETSID, ()).await } + +pub async fn close(fd: target_ulong) -> target_ulong { + syscall(CLOSE, (fd,)).await +} + +pub async fn open( + path_ptr: target_ulong, + flags: i32, + mode: target_ulong, +) -> target_ulong { + syscall(OPEN, (path_ptr, flags as target_long as target_ulong, mode)).await +} diff --git a/panda/plugins/linjector/src/syscalls/arm.rs b/panda/plugins/linjector/src/syscalls/arm.rs new file mode 100644 index 00000000000..a03a0e16dd8 --- /dev/null +++ b/panda/plugins/linjector/src/syscalls/arm.rs @@ -0,0 +1,17 @@ +use panda::prelude::*; + +pub(crate) const GETPID: target_ulong = 20; +pub(crate) const MMAP: target_ulong = 192; // mmap2, must not use page offset != 0 +pub(crate) const WRITE: target_ulong = 4; +pub(crate) const EXECVE: target_ulong = 11; +pub(crate) const MEMFD_CREATE: target_ulong = 385; +pub(crate) const CHDIR: target_ulong = 12; +pub(crate) const SETSID: target_ulong = 66; +pub(crate) const OPEN: target_ulong = 5; +pub(crate) const CLOSE: target_ulong = 6; + +pub(crate) const PROT_READ: target_ulong = 1; +pub(crate) const PROT_WRITE: target_ulong = 2; + +pub(crate) const MAP_SHARED: target_ulong = 0x1; +pub(crate) const MAP_ANON: target_ulong = 0x20; diff --git a/panda/plugins/linjector/src/syscalls/i386.rs b/panda/plugins/linjector/src/syscalls/i386.rs new file mode 100644 index 00000000000..8b229cc469c --- /dev/null +++ b/panda/plugins/linjector/src/syscalls/i386.rs @@ -0,0 +1,17 @@ +use panda::prelude::*; + +pub(crate) const GETPID: target_ulong = 20; +pub(crate) const MMAP: target_ulong = 90; +pub(crate) const WRITE: target_ulong = 4; +pub(crate) const EXECVE: target_ulong = 11; +pub(crate) const MEMFD_CREATE: target_ulong = 356; +pub(crate) const CHDIR: target_ulong = 12; +pub(crate) const SETSID: target_ulong = 66; +pub(crate) const OPEN: target_ulong = 5; +pub(crate) const CLOSE: target_ulong = 6; + +pub(crate) const PROT_READ: target_ulong = 1; +pub(crate) const PROT_WRITE: target_ulong = 2; + +pub(crate) const MAP_SHARED: target_ulong = 0x1; +pub(crate) const MAP_ANON: target_ulong = 0x20; diff --git a/panda/plugins/linjector/src/syscalls/x86_64.rs b/panda/plugins/linjector/src/syscalls/x86_64.rs new file mode 100644 index 00000000000..d24db3c7786 --- /dev/null +++ b/panda/plugins/linjector/src/syscalls/x86_64.rs @@ -0,0 +1,17 @@ +use panda::prelude::*; + +pub(crate) const GETPID: target_ulong = 39; +pub(crate) const MMAP: target_ulong = 9; +pub(crate) const WRITE: target_ulong = 1; +pub(crate) const EXECVE: target_ulong = 59; +pub(crate) const MEMFD_CREATE: target_ulong = 319; +pub(crate) const CHDIR: target_ulong = 80; +pub(crate) const SETSID: target_ulong = 112; +pub(crate) const OPEN: target_ulong = 2; +pub(crate) const CLOSE: target_ulong = 3; + +pub(crate) const PROT_READ: target_ulong = 1; +pub(crate) const PROT_WRITE: target_ulong = 2; + +pub(crate) const MAP_SHARED: target_ulong = 0x1; +pub(crate) const MAP_ANON: target_ulong = 0x20; diff --git a/panda/plugins/syscalls2/generated/syscall_switch_enter_linux_arm.cpp b/panda/plugins/syscalls2/generated/syscall_switch_enter_linux_arm.cpp index d6eb91912a1..9e5bbbb72ee 100644 --- a/panda/plugins/syscalls2/generated/syscall_switch_enter_linux_arm.cpp +++ b/panda/plugins/syscalls2/generated/syscall_switch_enter_linux_arm.cpp @@ -33,6 +33,7 @@ void syscall_enter_switch_linux_arm(CPUState *cpu, target_ptr_t pc, int static_c } ctx.asid = panda_current_asid(cpu); ctx.retaddr = calc_retaddr(cpu, pc); + ctx.double_return = false; bool panda_noreturn; // true if PANDA should not track the return of this system call const syscall_info_t *call = (syscall_meta == NULL || ctx.no > syscall_meta->max_generic) ? NULL : &syscall_info[ctx.no]; @@ -56,6 +57,8 @@ void syscall_enter_switch_linux_arm(CPUState *cpu, target_ptr_t pc, int static_c // 2 long sys_fork ['void'] case 2: { panda_noreturn = false; + ctx.double_return = true; + printf("enabling double return for fork\n"); PPP_RUN_CB(on_sys_fork_enter, cpu, pc); }; break; // 3 long sys_read ['unsigned int fd', 'char __user *buf', 'size_t count'] @@ -5012,16 +5015,20 @@ void syscall_enter_switch_linux_arm(CPUState *cpu, target_ptr_t pc, int static_c if (!panda_noreturn) { struct hook h; h.addr = ctx.retaddr; - h.asid = ctx.asid; + if (ctx.double_return) { + h.asid = 0; + } else { + h.asid = ctx.asid; + } h.cb.start_block_exec = hook_syscall_return; h.type = PANDA_CB_START_BLOCK_EXEC; h.enabled = true; h.km = MODE_ANY; //you'd expect this to be user only hooks_add_hook(&h); - running_syscalls[std::make_pair(ctx.retaddr, ctx.asid)] = ctx; + running_syscalls[std::make_pair(ctx.retaddr, h.asid)] = ctx; } #endif } -/* vim: set tabstop=4 softtabstop=4 noexpandtab ft=cpp: */ \ No newline at end of file +/* vim: set tabstop=4 softtabstop=4 noexpandtab ft=cpp: */ From ae29be2a2a065fd5509deacf73b36cb30225ff1b Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 3 Dec 2021 11:49:20 -0500 Subject: [PATCH 22/79] Fix hardcoded linjector dependency --- panda/plugins/linjector/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index 06aa8da56d7..976ae9718bd 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,8 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -#panda-re = { version = "0.23", default-features = false, features = ["syscall-injection"] } -panda-re = { path = "../../../../panda-rs/panda-rs", default-features = false, features = ["syscall-injection"] } +panda-re = { version = "0.23", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" From 398d0e2332a3f3f67a9bdee4a702de6dacdbadeb Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 8 Dec 2021 13:30:39 -0500 Subject: [PATCH 23/79] Guest shell updates: - Add latest guest shell additions - Add guest_shell script --- panda/plugins/config.panda | 1 + .../src/interface/channels.rs | 1 - .../guest_plugin_manager/src/interface/hci.rs | 2 - panda/plugins/guest_shell/Cargo.lock | 434 ++++++++++++++++++ panda/plugins/guest_shell/Cargo.toml | 6 +- panda/plugins/guest_shell/guest_shell_pty.sh | 1 + panda/plugins/guest_shell/src/lib.rs | 84 +++- panda/plugins/linjector/Cargo.lock | 8 +- panda/plugins/linjector/Cargo.toml | 2 +- panda/python/examples/guest_shell.py | 19 + 10 files changed, 548 insertions(+), 10 deletions(-) create mode 100644 panda/plugins/guest_shell/Cargo.lock create mode 100755 panda/plugins/guest_shell/guest_shell_pty.sh create mode 100644 panda/python/examples/guest_shell.py diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index efde357b995..c326e03fb89 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -14,6 +14,7 @@ filereadmon forcedexec gdb guest_plugin_manager +guest_shell hooks hooks2 hyperfuse diff --git a/panda/plugins/guest_plugin_manager/src/interface/channels.rs b/panda/plugins/guest_plugin_manager/src/interface/channels.rs index 47201cf0f2e..f1b9b9bafa7 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/channels.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/channels.rs @@ -53,7 +53,6 @@ pub fn publish_message_from_guest(channel_id: ChannelId, msg: Vec) { let pm = CHANNELS.read(); if let Some(plugin) = pm.get(&channel_id) { let buf_ptr = msg.as_ptr(); - println!("published message to FD {}", channel_id); (plugin.msg_receive_cb)(channel_id, buf_ptr, msg.len()) } else { println!("failed publish message to FD {}", channel_id); diff --git a/panda/plugins/guest_plugin_manager/src/interface/hci.rs b/panda/plugins/guest_plugin_manager/src/interface/hci.rs index 4c83dd7aa47..9d184a4fad6 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/hci.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/hci.rs @@ -48,7 +48,6 @@ pub fn hyp_write( buf_ptr: usize, buf_size: usize, ) -> Option { - println!("write"); if let Ok(buf_out) = virtual_memory_read(cpu, buf_ptr as target_ulong, buf_size) { @@ -101,4 +100,3 @@ pub fn hyp_get_channel_by_name( panic!("Failed to read virtual memory in hyp_write"); } } - diff --git a/panda/plugins/guest_shell/Cargo.lock b/panda/plugins/guest_shell/Cargo.lock new file mode 100644 index 00000000000..602a7de4eee --- /dev/null +++ b/panda/plugins/guest_shell/Cargo.lock @@ -0,0 +1,434 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ctor" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "guest_shell" +version = "0.1.0" +dependencies = [ + "lazy_static", + "once_cell", + "panda-re", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "inventory" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb5160c60ba1e809707918ee329adb99d222888155835c6feedba19f6c3fd4" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e41b53715c6f0c4be49510bb82dee2c1e51c8586d885abe65396e82ed518548" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + +[[package]] +name = "panda-re" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08711e736078d68061143eec0b876cb7faac788fc91147dc2584fc4a73e2f519" +dependencies = [ + "dirs", + "glib-sys", + "inventory", + "lazy_static", + "libloading", + "once_cell", + "panda-re-macros", + "panda-re-sys", + "paste", + "strum 0.20.0", + "strum_macros 0.20.1", + "thiserror", +] + +[[package]] +name = "panda-re-macros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81c6e3b78cf36e32f50b53a41d2d71b55b5ffee17978aac0c0b61e160f60d9f" +dependencies = [ + "darling", + "doc-comment", + "quote", + "syn", +] + +[[package]] +name = "panda-re-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" + +[[package]] +name = "paste" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" + +[[package]] +name = "pkg-config" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1a3ea4f0dd7f1f3e512cf97bf100819aa547f36a6eccac8dbaae839eb92363e" + +[[package]] +name = "proc-macro2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "serde" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "strum" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" + +[[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" + +[[package]] +name = "strum_macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" +dependencies = [ + "heck", + "pkg-config", + "strum 0.18.0", + "strum_macros 0.18.0", + "thiserror", + "toml", + "version-compare", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/plugins/guest_shell/Cargo.toml b/panda/plugins/guest_shell/Cargo.toml index 3574fe10a8f..3cef391144f 100644 --- a/panda/plugins/guest_shell/Cargo.toml +++ b/panda/plugins/guest_shell/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rust_skeleton" +name = "guest_shell" version = "0.1.0" authors = ["Luke Craig ", "Jordan McLeod "] edition = "2018" @@ -8,7 +8,9 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.9.1", default-features = false } +panda-re = { version = "0.23", default-features = false } +once_cell = "1" +lazy_static = "1" [features] default = ["x86_64"] diff --git a/panda/plugins/guest_shell/guest_shell_pty.sh b/panda/plugins/guest_shell/guest_shell_pty.sh new file mode 100755 index 00000000000..8532b6fbda2 --- /dev/null +++ b/panda/plugins/guest_shell/guest_shell_pty.sh @@ -0,0 +1 @@ +socat UNIX-CONNECT:/tmp/guest_shell.sock PTY,link=/tmp/guest_shell_pty & screen /tmp/guest_shell_pty diff --git a/panda/plugins/guest_shell/src/lib.rs b/panda/plugins/guest_shell/src/lib.rs index 608c7175374..1d49978a5ad 100644 --- a/panda/plugins/guest_shell/src/lib.rs +++ b/panda/plugins/guest_shell/src/lib.rs @@ -1,17 +1,95 @@ +use once_cell::sync::OnceCell; +use panda::plugins::guest_plugin_manager::*; use panda::prelude::*; -use panda::plugin_import; +use std::ffi::CString; +use std::io::Write; +use std::os::unix::net::{UnixListener, UnixStream}; +use std::path::Path; +use std::sync::Mutex; +#[cfg(feature = "x86_64")] +const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_daemon"; +#[cfg(feature = "arm")] +const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/arm-unknown-linux-musleabi/release/guest_daemon"; +#[cfg(feature = "i386")] +const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/guest_daemon"; + +#[cfg(feature = "x86_64")] +const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_shell"; + +static STDOUT: OnceCell> = OnceCell::new(); + +extern "C" fn message_recv(_: u32, data: *const u8, size: usize) { + let data = unsafe { std::slice::from_raw_parts(data, size) }; + + let mut stdout = STDOUT.get().unwrap().lock().unwrap(); + + let _ = stdout.write_all(data); +} + +#[derive(PandaArgs)] +#[name = "guest_shell"] +struct Args { + #[arg(default = "/tmp/guest_shell.sock")] + socket_path: String, +} + +lazy_static::lazy_static! { + static ref ARGS: Args = Args::from_panda_args(); +} + +struct Channel(ChannelId); + +impl Write for Channel { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + GUEST_PLUGIN_MANAGER.channel_write(self.0, buf.as_ptr(), buf.len()); + + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} #[panda::init] fn init(_: &mut PluginHandle) -> bool { - println!("Initialized!"); + let plugin_name = CString::new("linjector".as_bytes()).unwrap(); + let plugin_arg = CString::new(format!("guest_binary={}", PATH).as_bytes()).unwrap(); + unsafe { + let path = panda::sys::panda_plugin_path(plugin_name.as_ptr()); + panda::sys::panda_add_arg(plugin_name.as_ptr(), plugin_arg.as_ptr()); + panda::sys::panda_load_plugin(path, plugin_name.as_ptr()); + } + println!("after load_plugin in guest_shell"); + + GUEST_PLUGIN_MANAGER.ensure_init(); + let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( + "guest_shell".into(), + Path::new(GUEST_PLUGIN_PATH), + message_recv, + )); + println!("hyperfuse established channel with fd {}", channel); + + let socket = UnixListener::bind(&ARGS.socket_path).unwrap(); + let socket = socket.accept().unwrap().0; + + let socket_out = socket.try_clone().unwrap(); + STDOUT.set(Mutex::new(socket_out)).unwrap(); + + std::thread::spawn(move || { + std::io::copy(&mut { socket }, &mut Channel(channel)).unwrap(); + println!("Closed"); + }); + true } #[panda::uninit] fn exit(_: &mut PluginHandle) { println!("Exiting"); -} \ No newline at end of file +} + diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index 9c7e4633a4f..59c933e3067 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -370,7 +370,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.23.1" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d16235401d62d2809c2fe781bb7dc8ec87bc279986fcf3c64f939bc921eb13d" dependencies = [ "async-trait", "dashmap", @@ -392,6 +394,8 @@ dependencies = [ [[package]] name = "panda-re-macros" version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81c6e3b78cf36e32f50b53a41d2d71b55b5ffee17978aac0c0b61e160f60d9f" dependencies = [ "darling", "doc-comment", @@ -402,6 +406,8 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index 976ae9718bd..da39be272d5 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.23", default-features = false, features = ["syscall-injection"] } +panda-re = { version = "0.23.3", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" diff --git a/panda/python/examples/guest_shell.py b/panda/python/examples/guest_shell.py new file mode 100644 index 00000000000..35854867f5b --- /dev/null +++ b/panda/python/examples/guest_shell.py @@ -0,0 +1,19 @@ +# See panda/plugins/guest_shell/guest_shell_pty.sh for actually interacting with the shell +from pandare import Panda +import os + +panda = Panda(generic="x86_64") +panda.load_plugin("guest_shell", {}) + +@panda.queue_blocking +def run_cmd(): + panda.revert_sync("root") + + # if it's worth running it's worth running twice + # (don't ask, and definitely don't remove either line) + panda.run_serial_cmd("cat", no_timeout=True) + panda.run_serial_cmd("cat", no_timeout=True) + + panda.end_analysis() + +panda.run() From a1df2deafe3a1b32b78b7d0b17c1d624ec56216c Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 8 Dec 2021 23:21:50 -0500 Subject: [PATCH 24/79] remove osi_linux removal --- panda/plugins/config.panda | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index c326e03fb89..8043edb96a0 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -30,7 +30,7 @@ mmio_trace net network osi -#osi_linux +osi_linux osi_test pri pri_dwarf From f40d99a537c827968b7cceeed416eeed9538b528 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 9 Dec 2021 17:25:04 -0500 Subject: [PATCH 25/79] Add initial guest agent plugin build system --- panda/Makefile.panda.target | 24 +- panda/guest_plugins/config.panda | 1 + panda/guest_plugins/panda.mak | 3 + panda/guest_plugins/rust_example/Cargo.lock | 438 +++++++++++++++++++ panda/guest_plugins/rust_example/Cargo.toml | 8 + panda/guest_plugins/rust_example/Makefile | 16 + panda/guest_plugins/rust_example/src/main.rs | 16 + panda/plugins/config.panda | 2 +- 8 files changed, 506 insertions(+), 2 deletions(-) create mode 100644 panda/guest_plugins/config.panda create mode 100644 panda/guest_plugins/panda.mak create mode 100644 panda/guest_plugins/rust_example/Cargo.lock create mode 100644 panda/guest_plugins/rust_example/Cargo.toml create mode 100644 panda/guest_plugins/rust_example/Makefile create mode 100644 panda/guest_plugins/rust_example/src/main.rs diff --git a/panda/Makefile.panda.target b/panda/Makefile.panda.target index 34a71ce5a8e..f675236b8fc 100644 --- a/panda/Makefile.panda.target +++ b/panda/Makefile.panda.target @@ -56,7 +56,7 @@ extra-plugin-%: plog.pb-c.h plog.pb.h $(PANDA_API_EXT) PLUGIN_SRC_ROOT="$(EXTRA_PLUGINS_PATH)/panda/plugins" \ V="$(V)" PLUGIN_NAME="$*" all,) -all: $(PLUGIN_SUBDIR_RULES) $(EXTRA_PLUGIN_SUBDIR_RULES) +all: $(PLUGIN_SUBDIR_RULES) $(EXTRA_PLUGIN_SUBDIR_RULES) build_guest_plugins PROTO_FILES=$(wildcard $(addsuffix /*.proto,$(ALL_PLUGIN_SUBDIRS))) @@ -147,6 +147,28 @@ clean-panda: rm -f panda/panda_*.so;\ fi +######################################################### +# Guest Plugins + +# determine list of guest plugins +# remove spaces from lines. skip lines starting with a #. concatenate the rest into +# a space-delimited list +PANDA_GUEST_PLUGINS=$(shell tr -d "[:blank:]" < $(SRC_PATH)/panda/guest_plugins/config.panda | grep -v "^\#" | xargs) +GUEST_PLUGIN_SUBDIR_RULES=$(patsubst %,guest-plugin-%, $(PANDA_GUEST_PLUGINS)) +GUEST_PLUGIN_SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) BUILD_DIR=$(BUILD_DIR) + +build_guest_plugins: $(GUEST_PLUGIN_SUBDIR_RULES) + @echo "GUEST_PLUGINS: ${PANDA_GUEST_PLUGINS}" + +guest-plugin-%: + $(call quiet-command,mkdir -p ../panda/guest_plugins/$*,) + $(call quiet-command,mkdir -p panda/guest_plugins/$*,) + $(call quiet-command,$(MAKE) $(GUEST_PLUGIN_SUBDIR_MAKEFLAGS) \ + -f "$(SRC_PATH)/panda/guest_plugins/panda.mak" \ + -f "$(SRC_PATH)/panda/guest_plugins/$*/Makefile" \ + PLUGIN_SRC_ROOT="$(SRC_PATH)/panda/guest_plugins" \ + V="$(V)" PLUGIN_NAME="$*" all,) + ifdef CONFIG_LLVM ######################################################### # LLVM library diff --git a/panda/guest_plugins/config.panda b/panda/guest_plugins/config.panda new file mode 100644 index 00000000000..837b01d97cf --- /dev/null +++ b/panda/guest_plugins/config.panda @@ -0,0 +1 @@ +rust_example diff --git a/panda/guest_plugins/panda.mak b/panda/guest_plugins/panda.mak new file mode 100644 index 00000000000..5e2462e009f --- /dev/null +++ b/panda/guest_plugins/panda.mak @@ -0,0 +1,3 @@ +include config-target.mak + +PLUGIN_TARGET_DIR=panda/plugins diff --git a/panda/guest_plugins/rust_example/Cargo.lock b/panda/guest_plugins/rust_example/Cargo.lock new file mode 100644 index 00000000000..38d8a687f33 --- /dev/null +++ b/panda/guest_plugins/rust_example/Cargo.lock @@ -0,0 +1,438 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cbindgen" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38728c31b994e4b849cf59feefb4a8bf26acd299ee0b92c9fb35bd14ad4b8dfa" +dependencies = [ + "clap", + "heck", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", + "tempfile", + "toml", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "channels" +version = "0.1.0" +dependencies = [ + "cbindgen", + "lazy_static", + "parking_lot", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + +[[package]] +name = "proc-macro2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rust_example" +version = "0.1.0" +dependencies = [ + "channels", +] + +[[package]] +name = "ryu" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/guest_plugins/rust_example/Cargo.toml b/panda/guest_plugins/rust_example/Cargo.toml new file mode 100644 index 00000000000..71dcd73b661 --- /dev/null +++ b/panda/guest_plugins/rust_example/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust_example" +version = "0.1.0" +edition = "2021" + +[dependencies] +# TODO: move to its own repo to version separately +channels = { path = "../../../../igloo-internal/pie_idea/guest_code/channels" } diff --git a/panda/guest_plugins/rust_example/Makefile b/panda/guest_plugins/rust_example/Makefile new file mode 100644 index 00000000000..d3bec0d3e5b --- /dev/null +++ b/panda/guest_plugins/rust_example/Makefile @@ -0,0 +1,16 @@ +PLUGIN_DIR = $(realpath $(join $(SRC_PATH), /panda/guest_plugins/$(PLUGIN_NAME)/)) +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +PLUGIN_DEPS=$(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + +BUILD_TARGET=$(addprefix build-,$(TARGET_NAME)) + +all: $(BUILD_TARGET) + +build-x86_64: $(PLUGIN_DEPS) + @echo " CARGO $(PLUGIN_NAME)" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --target=x86_64-unknown-linux-musl \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) diff --git a/panda/guest_plugins/rust_example/src/main.rs b/panda/guest_plugins/rust_example/src/main.rs new file mode 100644 index 00000000000..3306171766a --- /dev/null +++ b/panda/guest_plugins/rust_example/src/main.rs @@ -0,0 +1,16 @@ +use channels::Channel; +use std::io::Write; + +fn main() { + // This print won't be visible outside of the serial log + println!("Hello, world!"); + + // Get the main channel for our plugin by name + let mut channel = Channel::main("rust_example").unwrap(); + + // Write some text to the channel using the standard std::io::Write interface + channel.write_all(b"Hello rust_example channel").unwrap(); + + // Or use formatting utilties to do so + writeln!(&mut channel, "today's lucky number is: {}", 3).unwrap(); +} diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index 8043edb96a0..e841d906aeb 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -51,6 +51,6 @@ trace track_intexc unigrams win2000x86intro -win7x86intro +#win7x86intro wintrospection winxpx86intro From d2217ed2062bdb5a14cb8f87741eace55ff10ca7 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 10 Dec 2021 13:29:20 -0500 Subject: [PATCH 26/79] Improve guest plugin build system --- panda/guest_plugins/panda.mak | 37 ++++++++++++++++++++++- panda/guest_plugins/rust_example/Makefile | 22 ++++++++------ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/panda/guest_plugins/panda.mak b/panda/guest_plugins/panda.mak index 5e2462e009f..85bd0138251 100644 --- a/panda/guest_plugins/panda.mak +++ b/panda/guest_plugins/panda.mak @@ -1,3 +1,38 @@ include config-target.mak -PLUGIN_TARGET_DIR=panda/plugins +ifndef SRC_PATH +$(error SRC_PATH is not set) +endif +ifndef PLUGIN_NAME +$(error PLUGIN_NAME is not set) +endif + +PLUGIN_DIR = $(realpath $(join $(SRC_PATH), /panda/guest_plugins/$(PLUGIN_NAME)/)) +PLUGIN_TARGET_DIR=panda/guest_plugins +PLUGIN_BIN_DIR=$(PLUGIN_TARGET_DIR)/bin +PLUGIN_OUT_PATH=$(PLUGIN_BIN_DIR)/$(PLUGIN_NAME) + +BUILD_TARGET=$(addprefix build-,$(TARGET_NAME)) + +all: $(BUILD_TARGET) + +build-x86_64: TARGET_TRIPLE=x86_64-unknown-linux-musl +build-x86_64: $(PLUGIN_OUT_PATH) + +build-i386: TARGET_TRIPLE=i686-unknown-linux-musl +build-i386: $(PLUGIN_OUT_PATH) + +build-arm: TARGET_TRIPLE=arm-unknown-linux-musleabi +build-arm: $(PLUGIN_OUT_PATH) + +build-aarch64: TARGET_TRIPLE=aarch64-unknown-linux-musl +build-aarch64: $(PLUGIN_OUT_PATH) + +build-mips: TARGET_TRIPLE=mips-unknown-linux-musl +build-mips: $(PLUGIN_OUT_PATH) + +build-mipsel: TARGET_TRIPLE=mipsel-unknown-linux-musl +build-mipsel: $(PLUGIN_OUT_PATH) + +build-mips64: TARGET_TRIPLE=mips64-unknown-linux-muslabi64 +build-mips64: $(PLUGIN_OUT_PATH) diff --git a/panda/guest_plugins/rust_example/Makefile b/panda/guest_plugins/rust_example/Makefile index d3bec0d3e5b..1458392b517 100644 --- a/panda/guest_plugins/rust_example/Makefile +++ b/panda/guest_plugins/rust_example/Makefile @@ -1,16 +1,20 @@ -PLUGIN_DIR = $(realpath $(join $(SRC_PATH), /panda/guest_plugins/$(PLUGIN_NAME)/)) -RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +# Remember to: +# * Add your plugin name to config.panda +# * Keep your plugin name the same as the folder name and Cargo.toml package name + +# Output build artifacts to the build directory PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target +# recompile if any of the src/*.rs files changed, or Cargo.toml +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) PLUGIN_DEPS=$(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml -BUILD_TARGET=$(addprefix build-,$(TARGET_NAME)) - -all: $(BUILD_TARGET) - -build-x86_64: $(PLUGIN_DEPS) - @echo " CARGO $(PLUGIN_NAME)" +$(PLUGIN_OUT_PATH): BUILD_RESULT="$(PLUGIN_ARTIFACTS_DIR)/$(TARGET_TRIPLE)/release/$(PLUGIN_NAME)" +$(PLUGIN_OUT_PATH): $(PLUGIN_DEPS) + @echo " CARGO $(PLUGIN_NAME) (${TARGET_TRIPLE})" @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ - --target=x86_64-unknown-linux-musl \ + --target=$(TARGET_TRIPLE) \ --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @mkdir -p $(PLUGIN_BIN_DIR) + @cp -p $(BUILD_RESULT) $@ From e4efe266d7310cbdcf3a60a3b16d0f309c50f5c6 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 10 Dec 2021 16:47:51 -0500 Subject: [PATCH 27/79] Add guest plugin name-to-path lookup --- panda/include/panda/plugin.h | 1 + panda/plugins/hyperfuse/src/lib.rs | 25 +++++++++++++++++++++++++ panda/src/callbacks.c | 23 +++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/panda/include/panda/plugin.h b/panda/include/panda/plugin.h index 83b186805ea..a4ff2e06cdd 100644 --- a/panda/include/panda/plugin.h +++ b/panda/include/panda/plugin.h @@ -154,6 +154,7 @@ char** str_split(char *a_str, const char a_delim); extern gchar *panda_argv[MAX_PANDA_PLUGIN_ARGS]; extern int panda_argc; +char *panda_guest_plugin_path(const char *name); char *panda_plugin_path(const char *name); void panda_require_from_library(const char *plugin_name, char **plugin_args, uint32_t num_args); void panda_require(const char *plugin_name); diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index 45211536a0f..04550fd8481 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -270,10 +270,35 @@ const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest #[cfg(feature = "i386")] const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/hyperfuse_guest"; +use std::{ffi::CStr, os::raw::c_char, path::PathBuf}; +fn guest_plugin_path(name: &str) -> Option { + extern "C" { + fn panda_guest_plugin_path(name: *const c_char) -> *mut c_char; + } + + let name = dbg!(CString::new(name).ok())?; + let path_result = unsafe { panda_guest_plugin_path(name.as_ptr()) }; + + if dbg!(path_result).is_null() { + None + } else { + let path = unsafe { CStr::from_ptr(path_result) }; + let path = dbg!(path.to_str().ok().map(PathBuf::from)); + + unsafe { + panda::sys::free(path_result as _); + } + + path + } +} + #[panda::init] fn init(_: &mut PluginHandle) -> bool { pretty_env_logger::init_custom_env("HYPERFUSE_LOG"); + //let guest_plugin_path = guest_plugin_path("hyperfuse"); + let plugin_name = CString::new("linjector".as_bytes()).unwrap(); let plugin_arg = CString::new(format!("guest_binary={}", PATH).as_bytes()).unwrap(); unsafe { diff --git a/panda/src/callbacks.c b/panda/src/callbacks.c index e7198a10d6f..a331b9fb9b0 100644 --- a/panda/src/callbacks.c +++ b/panda/src/callbacks.c @@ -250,6 +250,29 @@ bool _panda_load_plugin(const char *filename, const char *plugin_name, bool libr extern const char *qemu_file; +char *panda_guest_plugin_path(const char *plugin_name) { + gchar* plugin_path; + // Note qemu_file is set in the first call to main_aux + // so if this is called (likely via load_plugin) qemu_file must be set directly + assert(qemu_file != NULL); + + // try relative to PANDA binary as it would be in the build or install directory + char *dir = g_path_get_dirname(qemu_file); + plugin_path = g_strdup_printf("%s/panda/guest_plugins/bin/%s", dir, + plugin_name); + + g_free(dir); + if (TRUE == g_file_test(plugin_path, G_FILE_TEST_EXISTS)) { + char* path = strdup(plugin_path); + g_free(plugin_path); + return path; + } + g_free(plugin_path); + + // Return null if plugin resolution failed. + return NULL; +} + // Resolve a plugin to a path. If the plugin doesn't exist in any of the search // paths, then NULL is returned. The search order for plugins is as follows: // From 3a744c95d5e663adf63edac42953d424af17002c Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 10 Dec 2021 16:53:39 -0500 Subject: [PATCH 28/79] Remove debug prints from hyperfuse --- panda/plugins/hyperfuse/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index 04550fd8481..58aa846830e 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -276,14 +276,14 @@ fn guest_plugin_path(name: &str) -> Option { fn panda_guest_plugin_path(name: *const c_char) -> *mut c_char; } - let name = dbg!(CString::new(name).ok())?; + let name = CString::new(name).ok()?; let path_result = unsafe { panda_guest_plugin_path(name.as_ptr()) }; - if dbg!(path_result).is_null() { + if path_result.is_null() { None } else { let path = unsafe { CStr::from_ptr(path_result) }; - let path = dbg!(path.to_str().ok().map(PathBuf::from)); + let path = path.to_str().ok().map(PathBuf::from); unsafe { panda::sys::free(path_result as _); From 8e983e4a87f58f1828df45ade7c39db42f13099c Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 13 Dec 2021 11:49:59 -0500 Subject: [PATCH 29/79] Add out-of-tree guest plugin building --- panda/Makefile.panda.target | 21 +++++++++++++++++++-- panda/guest_plugins/panda.mak | 6 +++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/panda/Makefile.panda.target b/panda/Makefile.panda.target index f675236b8fc..834746e2e9a 100644 --- a/panda/Makefile.panda.target +++ b/panda/Makefile.panda.target @@ -157,8 +157,16 @@ PANDA_GUEST_PLUGINS=$(shell tr -d "[:blank:]" < $(SRC_PATH)/panda/guest_plugins/ GUEST_PLUGIN_SUBDIR_RULES=$(patsubst %,guest-plugin-%, $(PANDA_GUEST_PLUGINS)) GUEST_PLUGIN_SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) BUILD_DIR=$(BUILD_DIR) -build_guest_plugins: $(GUEST_PLUGIN_SUBDIR_RULES) - @echo "GUEST_PLUGINS: ${PANDA_GUEST_PLUGINS}" +ALL_GUEST_PLUGIN_RULES=$(GUEST_PLUGIN_SUBDIR_RULES) + +ifdef EXTRA_GUEST_PLUGINS_PATH + EXTRA_GUEST_PLUGINS=$(shell tr -d "[:blank:]" < $(EXTRA_GUEST_PLUGINS_PATH)/config.panda | grep -v "^\#" | xargs) + EXTRA_GUEST_PLUGIN_SUBDIR_RULES=$(patsubst %,extra-guest-plugin-%, $(EXTRA_GUEST_PLUGINS)) + ALL_GUEST_PLUGIN_RULES+=$(EXTRA_GUEST_PLUGIN_SUBDIR_RULES) +endif + +build_guest_plugins: $(ALL_GUEST_PLUGIN_RULES) + @echo "GUEST_PLUGINS: ${PANDA_GUEST_PLUGINS} ${EXTRA_GUEST_PLUGINS}" guest-plugin-%: $(call quiet-command,mkdir -p ../panda/guest_plugins/$*,) @@ -169,6 +177,15 @@ guest-plugin-%: PLUGIN_SRC_ROOT="$(SRC_PATH)/panda/guest_plugins" \ V="$(V)" PLUGIN_NAME="$*" all,) +extra-guest-plugin-%: + $(call quiet-command,mkdir -p ../panda/guest_plugins/$*,) + $(call quiet-command,mkdir -p panda/guest_plugins/$*,) + $(call quiet-command,$(MAKE) $(GUEST_PLUGIN_SUBDIR_MAKEFLAGS) \ + -f "$(SRC_PATH)/panda/guest_plugins/panda.mak" \ + -f "$(EXTRA_GUEST_PLUGINS_PATH)/$*/Makefile" \ + PLUGIN_SRC_ROOT="$(EXTRA_GUEST_PLUGINS_PATH)" \ + V="$(V)" PLUGIN_NAME="$*" all,) + ifdef CONFIG_LLVM ######################################################### # LLVM library diff --git a/panda/guest_plugins/panda.mak b/panda/guest_plugins/panda.mak index 85bd0138251..01ccf71987b 100644 --- a/panda/guest_plugins/panda.mak +++ b/panda/guest_plugins/panda.mak @@ -1,13 +1,13 @@ include config-target.mak -ifndef SRC_PATH -$(error SRC_PATH is not set) +ifndef PLUGIN_SRC_ROOT +$(error PLUGIN_SRC_ROOT is not set) endif ifndef PLUGIN_NAME $(error PLUGIN_NAME is not set) endif -PLUGIN_DIR = $(realpath $(join $(SRC_PATH), /panda/guest_plugins/$(PLUGIN_NAME)/)) +PLUGIN_DIR = $(realpath $(join $(PLUGIN_SRC_ROOT), /$(PLUGIN_NAME)/)) PLUGIN_TARGET_DIR=panda/guest_plugins PLUGIN_BIN_DIR=$(PLUGIN_TARGET_DIR)/bin PLUGIN_OUT_PATH=$(PLUGIN_BIN_DIR)/$(PLUGIN_NAME) From c778dfdd05061122790d87464cbd62eca8ff7d86 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 13 Dec 2021 12:36:57 -0500 Subject: [PATCH 30/79] Remove hardcoded paths from guest_shell and hyperfuse --- panda/plugins/guest_shell/src/lib.rs | 48 +++++++++++++++++++--------- panda/plugins/hyperfuse/src/lib.rs | 30 ++++++----------- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/panda/plugins/guest_shell/src/lib.rs b/panda/plugins/guest_shell/src/lib.rs index 1d49978a5ad..884bd58dedc 100644 --- a/panda/plugins/guest_shell/src/lib.rs +++ b/panda/plugins/guest_shell/src/lib.rs @@ -8,18 +8,6 @@ use std::os::unix::net::{UnixListener, UnixStream}; use std::path::Path; use std::sync::Mutex; -#[cfg(feature = "x86_64")] -const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_daemon"; - -#[cfg(feature = "arm")] -const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/arm-unknown-linux-musleabi/release/guest_daemon"; - -#[cfg(feature = "i386")] -const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/guest_daemon"; - -#[cfg(feature = "x86_64")] -const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_shell"; - static STDOUT: OnceCell> = OnceCell::new(); extern "C" fn message_recv(_: u32, data: *const u8, size: usize) { @@ -55,10 +43,41 @@ impl Write for Channel { } } +// TODO: move to panda-rs +use std::{ffi::CStr, os::raw::c_char, path::PathBuf}; +fn guest_plugin_path(name: &str) -> Option { + extern "C" { + fn panda_guest_plugin_path(name: *const c_char) -> *mut c_char; + } + + let name = CString::new(name).ok()?; + let path_result = unsafe { panda_guest_plugin_path(name.as_ptr()) }; + + if path_result.is_null() { + None + } else { + let path = unsafe { CStr::from_ptr(path_result) }; + let path = path.to_str().ok().map(PathBuf::from); + + unsafe { + panda::sys::free(path_result as _); + } + + path + } +} + #[panda::init] fn init(_: &mut PluginHandle) -> bool { + let guest_daemon_path = guest_plugin_path("guest_daemon") + .expect("Failed to retrieve guest_daemon guest plugin path"); + + let guest_plugin_path = guest_plugin_path("guest_shell") + .expect("Failed to retrieve guest_shell guest plugin path for loading"); + let plugin_name = CString::new("linjector".as_bytes()).unwrap(); - let plugin_arg = CString::new(format!("guest_binary={}", PATH).as_bytes()).unwrap(); + let plugin_arg = + CString::new(format!("guest_binary={}", guest_daemon_path.display()).as_bytes()).unwrap(); unsafe { let path = panda::sys::panda_plugin_path(plugin_name.as_ptr()); panda::sys::panda_add_arg(plugin_name.as_ptr(), plugin_arg.as_ptr()); @@ -69,7 +88,7 @@ fn init(_: &mut PluginHandle) -> bool { GUEST_PLUGIN_MANAGER.ensure_init(); let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( "guest_shell".into(), - Path::new(GUEST_PLUGIN_PATH), + &guest_plugin_path, message_recv, )); println!("hyperfuse established channel with fd {}", channel); @@ -92,4 +111,3 @@ fn init(_: &mut PluginHandle) -> bool { fn exit(_: &mut PluginHandle) { println!("Exiting"); } - diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index 58aa846830e..a31c9e18847 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -252,24 +252,7 @@ extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { } } -#[cfg(feature = "x86_64")] -const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/guest_daemon"; - -#[cfg(feature = "arm")] -const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/arm-unknown-linux-musleabi/release/guest_daemon"; - -#[cfg(feature = "i386")] -const PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/guest_daemon"; - -#[cfg(feature = "x86_64")] -const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/x86_64-unknown-linux-musl/release/hyperfuse_guest"; - -#[cfg(feature = "arm")] -const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/arm-unknown-linux-musleabi/release/hyperfuse_guest"; - -#[cfg(feature = "i386")] -const GUEST_PLUGIN_PATH: &str = "/home/jmcleod/dev/igloo-internal/pie_idea/guest_code/target/i686-unknown-linux-musl/release/hyperfuse_guest"; - +// TODO: move to panda-rs use std::{ffi::CStr, os::raw::c_char, path::PathBuf}; fn guest_plugin_path(name: &str) -> Option { extern "C" { @@ -297,10 +280,15 @@ fn guest_plugin_path(name: &str) -> Option { fn init(_: &mut PluginHandle) -> bool { pretty_env_logger::init_custom_env("HYPERFUSE_LOG"); - //let guest_plugin_path = guest_plugin_path("hyperfuse"); + let guest_daemon_path = guest_plugin_path("guest_daemon") + .expect("Failed to retrieve guest_daemon guest plugin path"); + + let guest_plugin_path = guest_plugin_path("hyperfuse_guest") + .expect("Failed to retrieve hyperfuse_guest guest plugin"); let plugin_name = CString::new("linjector".as_bytes()).unwrap(); - let plugin_arg = CString::new(format!("guest_binary={}", PATH).as_bytes()).unwrap(); + let plugin_arg = + CString::new(format!("guest_binary={}", guest_daemon_path.display()).as_bytes()).unwrap(); unsafe { let path = panda::sys::panda_plugin_path(plugin_name.as_ptr()); panda::sys::panda_add_arg(plugin_name.as_ptr(), plugin_arg.as_ptr()); @@ -311,7 +299,7 @@ fn init(_: &mut PluginHandle) -> bool { GUEST_PLUGIN_MANAGER.ensure_init(); let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( "hyperfuse".into(), - Path::new(GUEST_PLUGIN_PATH), + &guest_plugin_path, message_recv, )); println!("hyperfuse established channel with fd {}", channel); From 321ad89e9ca7eec226a31f31e06997178e3dedfc Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 13 Dec 2021 16:13:22 -0500 Subject: [PATCH 31/79] Have guest_plugin_manager load linjector; Guest plugin cleanup --- panda/plugins/guest_plugin_manager/Cargo.lock | 13 ++-- panda/plugins/guest_plugin_manager/Cargo.toml | 2 +- .../src/guest_plugin_manager.rs | 39 ++++++++--- .../guest_plugin_manager/src/interface/api.rs | 45 ++++++------ panda/plugins/guest_shell/Cargo.lock | 8 +-- panda/plugins/guest_shell/Cargo.toml | 2 +- panda/plugins/guest_shell/src/lib.rs | 68 +------------------ panda/plugins/hyperfuse/Cargo.lock | 13 ++-- panda/plugins/hyperfuse/Cargo.toml | 3 +- panda/plugins/hyperfuse/src/lib.rs | 47 +------------ panda/python/examples/guest_shell.py | 5 +- 11 files changed, 89 insertions(+), 156 deletions(-) diff --git a/panda/plugins/guest_plugin_manager/Cargo.lock b/panda/plugins/guest_plugin_manager/Cargo.lock index 296669e8041..738462e6c85 100644 --- a/panda/plugins/guest_plugin_manager/Cargo.lock +++ b/panda/plugins/guest_plugin_manager/Cargo.lock @@ -239,15 +239,16 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.13.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f70db200bc5fd6609d6a6eadb571964507dcb308dd98fbc8b5bd5586fa2fa270" +checksum = "bfd819f91df8381e0b6255a47f749a1dd52589c34a0b007bbee41f27630ff7ee" dependencies = [ "dirs", "glib-sys", "inventory", "lazy_static", "libloading", + "once_cell", "panda-re-macros", "panda-re-sys", "paste", @@ -258,9 +259,9 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.9.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daee3587300135fd563445fe7511eff6e67474007aeeae2b58734eab3e71082b" +checksum = "9d807aa10d149e5ddde4e9cd386df1791efda6d6716077349da9f78cb6d32460" dependencies = [ "darling", "doc-comment", @@ -270,9 +271,9 @@ dependencies = [ [[package]] name = "panda-re-sys" -version = "0.4.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0721969582932a84196625fd23b02e514dd6d1291f7fa074929f416fb56929a" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/guest_plugin_manager/Cargo.toml b/panda/plugins/guest_plugin_manager/Cargo.toml index c57bcff4442..8b4d1f6be96 100644 --- a/panda/plugins/guest_plugin_manager/Cargo.toml +++ b/panda/plugins/guest_plugin_manager/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] path = "./src/guest_plugin_manager.rs" [dependencies] -panda-re = { version = "0.13.0", default-features = false } +panda-re = { version = "0.25", default-features = false } crossbeam-queue = "0.3.2" parking_lot = "0.11.2" lazy_static = "1.4.0" diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index 62fb58d028a..5f8fc6148dc 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -1,3 +1,4 @@ +use panda::plugins::guest_plugin_manager::guest_plugin_path; use panda::prelude::*; use std::convert::TryFrom; @@ -7,19 +8,20 @@ use hyp_regs::{get_hyp_reg, set_hyp_ret_reg}; mod interface; use interface::hci::{ - hyp_error, hyp_get_manager, hyp_read, hyp_start, hyp_stop, hyp_write,hyp_get_channel_by_name + hyp_error, hyp_get_channel_by_name, hyp_get_manager, hyp_read, hyp_start, + hyp_stop, hyp_write, }; const MAGIC: usize = 0x1337c0d3; #[derive(Copy, Clone)] pub enum HcCmd { - Start = 1, /* start new action */ - Stop, /* stop action */ - Read, /* read buffer from hypervisor */ - Write, /* write buffer TO hypervisor*/ - Error, /* report error to hypervisor*/ - GetManager, /* returns unique chanenl ID to manager from plugin */ + Start = 1, /* start new action */ + Stop, /* stop action */ + Read, /* read buffer from hypervisor */ + Write, /* write buffer TO hypervisor*/ + Error, /* report error to hypervisor*/ + GetManager, /* returns unique chanenl ID to manager from plugin */ GetChannelByName, /* returns existing channel mapped to unique name */ } @@ -57,7 +59,9 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { Ok(HcCmd::Stop) => hyp_stop(cpu, chan_id, arg1, arg2), Ok(HcCmd::Error) => hyp_error(cpu, chan_id, arg1, arg2), Ok(HcCmd::GetManager) => hyp_get_manager(cpu, chan_id, arg1, arg2), - Ok(HcCmd::GetChannelByName) => hyp_get_channel_by_name(cpu, chan_id, arg1, arg2), + Ok(HcCmd::GetChannelByName) => { + hyp_get_channel_by_name(cpu, chan_id, arg1, arg2) + } _ => None, }; @@ -70,9 +74,28 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { } } +#[derive(PandaArgs)] +#[name = "linjector"] +struct Linjector { + guest_binary: String, +} + #[panda::init] fn init(_: &mut PluginHandle) -> bool { interface::daemon_manager::init(); + + let guest_binary = guest_plugin_path("guest_daemon") + .expect("Failed to retrieve guest_daemon guest plugin path") + .to_string_lossy() + .into_owned(); + + assert!( + panda::os::family().is_linux(), + "Guest plugin manager currently only supports Linux" + ); + + panda::require_plugin(&Linjector { guest_binary }); + true } diff --git a/panda/plugins/guest_plugin_manager/src/interface/api.rs b/panda/plugins/guest_plugin_manager/src/interface/api.rs index 1c6d550e090..5012299a655 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/api.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/api.rs @@ -1,12 +1,10 @@ +use super::channels::add_channel; +use super::daemon_manager::load_binary; use std::ffi::CStr; use std::os::raw::c_char; use std::slice::from_raw_parts; -use super::daemon_manager::load_binary; -use super::channels::add_channel; -use super::channels::{ - publish_message_to_guest, ChannelId, ChannelCB -}; +use super::channels::{publish_message_to_guest, ChannelCB, ChannelId}; #[repr(C)] pub struct GuestPlugin { @@ -18,15 +16,24 @@ pub struct GuestPlugin { // returns channel ID #[no_mangle] pub extern "C" fn add_guest_plugin(plugin: GuestPlugin) -> ChannelId { - let binary_path = unsafe { - CStr::from_ptr(plugin.guest_binary_path) - .to_string_lossy() + let name = unsafe { CStr::from_ptr(plugin.plugin_name).to_string_lossy() }; + let binary_path = if plugin.guest_binary_path.is_null() { + match crate::guest_plugin_path(&name) { + Some(path) => path.to_string_lossy().into_owned(), + None => panic!( + "No guest plugin path was provided but plugin {0:?} \ + could not be found, ensure {0:?} has been built.", + name + ), + } + } else { + unsafe { + CStr::from_ptr(plugin.guest_binary_path) + .to_string_lossy() + .into_owned() + } }; load_binary(&binary_path); - let name = unsafe { - CStr::from_ptr(plugin.plugin_name) - .to_string_lossy() - }; add_channel(Some(&name), plugin.msg_receive_cb) } @@ -40,11 +47,11 @@ pub unsafe extern "C" fn channel_write( } #[no_mangle] -pub extern "C" fn get_channel_from_name(channel_name: *const c_char) -> ChannelId { - let name = unsafe { - CStr::from_ptr(channel_name) - .to_string_lossy() - .into_owned() - }; +pub extern "C" fn get_channel_from_name( + channel_name: *const c_char, +) -> ChannelId { + let name = + unsafe { CStr::from_ptr(channel_name).to_string_lossy().into_owned() }; super::channels::get_channel_from_name(&name).unwrap() -} \ No newline at end of file +} + diff --git a/panda/plugins/guest_shell/Cargo.lock b/panda/plugins/guest_shell/Cargo.lock index 602a7de4eee..483490dda38 100644 --- a/panda/plugins/guest_shell/Cargo.lock +++ b/panda/plugins/guest_shell/Cargo.lock @@ -199,9 +199,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.23.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08711e736078d68061143eec0b876cb7faac788fc91147dc2584fc4a73e2f519" +checksum = "bfd819f91df8381e0b6255a47f749a1dd52589c34a0b007bbee41f27630ff7ee" dependencies = [ "dirs", "glib-sys", @@ -219,9 +219,9 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81c6e3b78cf36e32f50b53a41d2d71b55b5ffee17978aac0c0b61e160f60d9f" +checksum = "9d807aa10d149e5ddde4e9cd386df1791efda6d6716077349da9f78cb6d32460" dependencies = [ "darling", "doc-comment", diff --git a/panda/plugins/guest_shell/Cargo.toml b/panda/plugins/guest_shell/Cargo.toml index 3cef391144f..51469118b9f 100644 --- a/panda/plugins/guest_shell/Cargo.toml +++ b/panda/plugins/guest_shell/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.23", default-features = false } +panda-re = { version = "0.25", default-features = false } once_cell = "1" lazy_static = "1" diff --git a/panda/plugins/guest_shell/src/lib.rs b/panda/plugins/guest_shell/src/lib.rs index 884bd58dedc..a3dd2238ef9 100644 --- a/panda/plugins/guest_shell/src/lib.rs +++ b/panda/plugins/guest_shell/src/lib.rs @@ -2,10 +2,8 @@ use once_cell::sync::OnceCell; use panda::plugins::guest_plugin_manager::*; use panda::prelude::*; -use std::ffi::CString; use std::io::Write; use std::os::unix::net::{UnixListener, UnixStream}; -use std::path::Path; use std::sync::Mutex; static STDOUT: OnceCell> = OnceCell::new(); @@ -29,78 +27,18 @@ lazy_static::lazy_static! { static ref ARGS: Args = Args::from_panda_args(); } -struct Channel(ChannelId); - -impl Write for Channel { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - GUEST_PLUGIN_MANAGER.channel_write(self.0, buf.as_ptr(), buf.len()); - - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} - -// TODO: move to panda-rs -use std::{ffi::CStr, os::raw::c_char, path::PathBuf}; -fn guest_plugin_path(name: &str) -> Option { - extern "C" { - fn panda_guest_plugin_path(name: *const c_char) -> *mut c_char; - } - - let name = CString::new(name).ok()?; - let path_result = unsafe { panda_guest_plugin_path(name.as_ptr()) }; - - if path_result.is_null() { - None - } else { - let path = unsafe { CStr::from_ptr(path_result) }; - let path = path.to_str().ok().map(PathBuf::from); - - unsafe { - panda::sys::free(path_result as _); - } - - path - } -} - #[panda::init] fn init(_: &mut PluginHandle) -> bool { - let guest_daemon_path = guest_plugin_path("guest_daemon") - .expect("Failed to retrieve guest_daemon guest plugin path"); - - let guest_plugin_path = guest_plugin_path("guest_shell") - .expect("Failed to retrieve guest_shell guest plugin path for loading"); - - let plugin_name = CString::new("linjector".as_bytes()).unwrap(); - let plugin_arg = - CString::new(format!("guest_binary={}", guest_daemon_path.display()).as_bytes()).unwrap(); - unsafe { - let path = panda::sys::panda_plugin_path(plugin_name.as_ptr()); - panda::sys::panda_add_arg(plugin_name.as_ptr(), plugin_arg.as_ptr()); - panda::sys::panda_load_plugin(path, plugin_name.as_ptr()); - } - println!("after load_plugin in guest_shell"); - - GUEST_PLUGIN_MANAGER.ensure_init(); - let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( - "guest_shell".into(), - &guest_plugin_path, - message_recv, - )); - println!("hyperfuse established channel with fd {}", channel); + let mut channel = load_guest_plugin("guest_shell", message_recv); let socket = UnixListener::bind(&ARGS.socket_path).unwrap(); - let socket = socket.accept().unwrap().0; + let mut socket = socket.accept().unwrap().0; let socket_out = socket.try_clone().unwrap(); STDOUT.set(Mutex::new(socket_out)).unwrap(); std::thread::spawn(move || { - std::io::copy(&mut { socket }, &mut Channel(channel)).unwrap(); + std::io::copy(&mut socket, &mut channel).unwrap(); println!("Closed"); }); diff --git a/panda/plugins/hyperfuse/Cargo.lock b/panda/plugins/hyperfuse/Cargo.lock index b9ba19f9f15..68044083319 100644 --- a/panda/plugins/hyperfuse/Cargo.lock +++ b/panda/plugins/hyperfuse/Cargo.lock @@ -351,8 +351,9 @@ dependencies = [ [[package]] name = "panda-re" -version = "0.22.0" -source = "git+https://github.com/panda-re/panda-rs#cfa0d34cc7ca372be7daab76e09c603eab415059" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd819f91df8381e0b6255a47f749a1dd52589c34a0b007bbee41f27630ff7ee" dependencies = [ "dirs", "glib-sys", @@ -370,8 +371,9 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.14.0" -source = "git+https://github.com/panda-re/panda-rs#cfa0d34cc7ca372be7daab76e09c603eab415059" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d807aa10d149e5ddde4e9cd386df1791efda6d6716077349da9f78cb6d32460" dependencies = [ "darling", "doc-comment", @@ -382,7 +384,8 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" -source = "git+https://github.com/panda-re/panda-rs#cfa0d34cc7ca372be7daab76e09c603eab415059" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/hyperfuse/Cargo.toml b/panda/plugins/hyperfuse/Cargo.toml index 0dda4ef09d4..0c6c13161d0 100644 --- a/panda/plugins/hyperfuse/Cargo.toml +++ b/panda/plugins/hyperfuse/Cargo.toml @@ -8,8 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -#panda-re = { version = "0.13.0", default-features = false } -panda-re = { git = "https://github.com/panda-re/panda-rs", default-features = false } +panda-re = { version = "0.25", default-features = false } fuser = { version = "0.9", features = ["serializable"] } libc = "0.2.98" pretty_env_logger = "0.4.0" diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index a31c9e18847..bc249c394ac 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -252,57 +252,16 @@ extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { } } -// TODO: move to panda-rs -use std::{ffi::CStr, os::raw::c_char, path::PathBuf}; -fn guest_plugin_path(name: &str) -> Option { - extern "C" { - fn panda_guest_plugin_path(name: *const c_char) -> *mut c_char; - } - - let name = CString::new(name).ok()?; - let path_result = unsafe { panda_guest_plugin_path(name.as_ptr()) }; - - if path_result.is_null() { - None - } else { - let path = unsafe { CStr::from_ptr(path_result) }; - let path = path.to_str().ok().map(PathBuf::from); - - unsafe { - panda::sys::free(path_result as _); - } - - path - } -} - #[panda::init] fn init(_: &mut PluginHandle) -> bool { pretty_env_logger::init_custom_env("HYPERFUSE_LOG"); - let guest_daemon_path = guest_plugin_path("guest_daemon") - .expect("Failed to retrieve guest_daemon guest plugin path"); - - let guest_plugin_path = guest_plugin_path("hyperfuse_guest") - .expect("Failed to retrieve hyperfuse_guest guest plugin"); - - let plugin_name = CString::new("linjector".as_bytes()).unwrap(); - let plugin_arg = - CString::new(format!("guest_binary={}", guest_daemon_path.display()).as_bytes()).unwrap(); - unsafe { - let path = panda::sys::panda_plugin_path(plugin_name.as_ptr()); - panda::sys::panda_add_arg(plugin_name.as_ptr(), plugin_arg.as_ptr()); - panda::sys::panda_load_plugin(path, plugin_name.as_ptr()); - } println!("after load_plugin in hyperfuse"); GUEST_PLUGIN_MANAGER.ensure_init(); - let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new( - "hyperfuse".into(), - &guest_plugin_path, - message_recv, - )); - println!("hyperfuse established channel with fd {}", channel); + let hyperfuse_guest = GuestPlugin::new("hyperfuse_guest".into(), message_recv); + let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(hyperfuse_guest); + println!("hyperfuse established channel with id {}", channel); std::thread::spawn(move || { println!("new hyperfuse thread"); diff --git a/panda/python/examples/guest_shell.py b/panda/python/examples/guest_shell.py index 35854867f5b..430ad373af5 100644 --- a/panda/python/examples/guest_shell.py +++ b/panda/python/examples/guest_shell.py @@ -2,8 +2,11 @@ from pandare import Panda import os +if os.path.exists("/tmp/guest_shell.sock"): + os.remove("/tmp/guest_shell.sock") + panda = Panda(generic="x86_64") -panda.load_plugin("guest_shell", {}) +panda.load_plugin("guest_shell") @panda.queue_blocking def run_cmd(): From 1ded2b1546e5616caba606e2d01fb854150c6e79 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 13 Dec 2021 16:28:43 -0500 Subject: [PATCH 32/79] Cleanup guest_shell PANDA plugin --- panda/plugins/guest_shell/src/lib.rs | 29 ++++++++++++---------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/panda/plugins/guest_shell/src/lib.rs b/panda/plugins/guest_shell/src/lib.rs index a3dd2238ef9..27d8360b28d 100644 --- a/panda/plugins/guest_shell/src/lib.rs +++ b/panda/plugins/guest_shell/src/lib.rs @@ -1,18 +1,19 @@ use once_cell::sync::OnceCell; -use panda::plugins::guest_plugin_manager::*; -use panda::prelude::*; +use panda::{plugins::guest_plugin_manager::*, prelude::*}; -use std::io::Write; -use std::os::unix::net::{UnixListener, UnixStream}; -use std::sync::Mutex; +use std::{ + io::{self, Write}, + os::unix::net::{UnixListener, UnixStream}, + sync::Mutex, + thread, +}; static STDOUT: OnceCell> = OnceCell::new(); +// Copy all messages from the guest to the unix socket extern "C" fn message_recv(_: u32, data: *const u8, size: usize) { let data = unsafe { std::slice::from_raw_parts(data, size) }; - let mut stdout = STDOUT.get().unwrap().lock().unwrap(); - let _ = stdout.write_all(data); } @@ -34,18 +35,12 @@ fn init(_: &mut PluginHandle) -> bool { let socket = UnixListener::bind(&ARGS.socket_path).unwrap(); let mut socket = socket.accept().unwrap().0; - let socket_out = socket.try_clone().unwrap(); - STDOUT.set(Mutex::new(socket_out)).unwrap(); + STDOUT.set(Mutex::new(socket.try_clone().unwrap())).unwrap(); - std::thread::spawn(move || { - std::io::copy(&mut socket, &mut channel).unwrap(); - println!("Closed"); + thread::spawn(move || { + // Copy stdin from unix socket to guest + io::copy(&mut socket, &mut channel).unwrap(); }); true } - -#[panda::uninit] -fn exit(_: &mut PluginHandle) { - println!("Exiting"); -} From 532d79d28dff01aa0f62986fbc9e0a61c8a9aa2d Mon Sep 17 00:00:00 2001 From: jamcleod Date: Tue, 14 Dec 2021 13:43:05 -0500 Subject: [PATCH 33/79] Move guest_shell over to message_recv macro --- panda/plugins/guest_shell/Cargo.lock | 9 +++++---- panda/plugins/guest_shell/Cargo.toml | 2 +- panda/plugins/guest_shell/src/lib.rs | 12 ++++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/panda/plugins/guest_shell/Cargo.lock b/panda/plugins/guest_shell/Cargo.lock index 483490dda38..e5f413cd5c8 100644 --- a/panda/plugins/guest_shell/Cargo.lock +++ b/panda/plugins/guest_shell/Cargo.lock @@ -199,9 +199,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd819f91df8381e0b6255a47f749a1dd52589c34a0b007bbee41f27630ff7ee" +checksum = "2dfc5b9d238b9f1d4785346b7d611dcc4236f615334e0719afbf3033f8c26e0e" dependencies = [ "dirs", "glib-sys", @@ -219,12 +219,13 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d807aa10d149e5ddde4e9cd386df1791efda6d6716077349da9f78cb6d32460" +checksum = "5be1d7a86fc7fc5c32ca9d7b430e5f12f76b664f381c4213c7071d14e88fc588" dependencies = [ "darling", "doc-comment", + "proc-macro2", "quote", "syn", ] diff --git a/panda/plugins/guest_shell/Cargo.toml b/panda/plugins/guest_shell/Cargo.toml index 51469118b9f..7e391175a3f 100644 --- a/panda/plugins/guest_shell/Cargo.toml +++ b/panda/plugins/guest_shell/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.25", default-features = false } +panda-re = { version = "0.26", default-features = false } once_cell = "1" lazy_static = "1" diff --git a/panda/plugins/guest_shell/src/lib.rs b/panda/plugins/guest_shell/src/lib.rs index 27d8360b28d..43de4e6549c 100644 --- a/panda/plugins/guest_shell/src/lib.rs +++ b/panda/plugins/guest_shell/src/lib.rs @@ -11,10 +11,14 @@ use std::{ static STDOUT: OnceCell> = OnceCell::new(); // Copy all messages from the guest to the unix socket -extern "C" fn message_recv(_: u32, data: *const u8, size: usize) { - let data = unsafe { std::slice::from_raw_parts(data, size) }; - let mut stdout = STDOUT.get().unwrap().lock().unwrap(); - let _ = stdout.write_all(data); +#[channel_recv] +fn message_recv(_: u32, data: &[u8]) { + let _ = STDOUT + .get() + .expect("stdout unix socket not set") + .lock() + .unwrap() + .write_all(data); } #[derive(PandaArgs)] From d6647ab6d8c64d3e161e00dd445cb9850e6f14d9 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Tue, 14 Dec 2021 15:38:18 -0500 Subject: [PATCH 34/79] Another guest_shell cleanup pass --- panda/plugins/guest_shell/Cargo.lock | 58 +++++++++++++++++++++++++++- panda/plugins/guest_shell/Cargo.toml | 3 +- panda/plugins/guest_shell/src/lib.rs | 36 +++++++---------- 3 files changed, 70 insertions(+), 27 deletions(-) diff --git a/panda/plugins/guest_shell/Cargo.lock b/panda/plugins/guest_shell/Cargo.lock index e5f413cd5c8..2127edfa02b 100644 --- a/panda/plugins/guest_shell/Cargo.lock +++ b/panda/plugins/guest_shell/Cargo.lock @@ -127,9 +127,8 @@ dependencies = [ name = "guest_shell" version = "0.1.0" dependencies = [ - "lazy_static", - "once_cell", "panda-re", + "parking_lot", ] [[package]] @@ -147,6 +146,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "inventory" version = "0.1.11" @@ -191,6 +199,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + [[package]] name = "once_cell" version = "1.8.0" @@ -236,6 +253,31 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + [[package]] name = "paste" version = "1.0.6" @@ -285,12 +327,24 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + [[package]] name = "strsim" version = "0.9.3" diff --git a/panda/plugins/guest_shell/Cargo.toml b/panda/plugins/guest_shell/Cargo.toml index 7e391175a3f..2cb6bb759b0 100644 --- a/panda/plugins/guest_shell/Cargo.toml +++ b/panda/plugins/guest_shell/Cargo.toml @@ -9,8 +9,7 @@ crate-type = ["cdylib"] [dependencies] panda-re = { version = "0.26", default-features = false } -once_cell = "1" -lazy_static = "1" +parking_lot = "0.11" [features] default = ["x86_64"] diff --git a/panda/plugins/guest_shell/src/lib.rs b/panda/plugins/guest_shell/src/lib.rs index 43de4e6549c..3182e2d912f 100644 --- a/panda/plugins/guest_shell/src/lib.rs +++ b/panda/plugins/guest_shell/src/lib.rs @@ -1,24 +1,16 @@ -use once_cell::sync::OnceCell; use panda::{plugins::guest_plugin_manager::*, prelude::*}; - +use parking_lot::{const_mutex, Mutex}; use std::{ io::{self, Write}, os::unix::net::{UnixListener, UnixStream}, - sync::Mutex, - thread, }; -static STDOUT: OnceCell> = OnceCell::new(); +static STDOUT: Mutex> = const_mutex(None); // Copy all messages from the guest to the unix socket #[channel_recv] fn message_recv(_: u32, data: &[u8]) { - let _ = STDOUT - .get() - .expect("stdout unix socket not set") - .lock() - .unwrap() - .write_all(data); + STDOUT.lock().as_mut().unwrap().write_all(data).ok(); } #[derive(PandaArgs)] @@ -28,23 +20,21 @@ struct Args { socket_path: String, } -lazy_static::lazy_static! { - static ref ARGS: Args = Args::from_panda_args(); +fn get_split_socket(path: &str) -> io::Result<(UnixStream, UnixStream)> { + let (socket, _) = UnixListener::bind(path)?.accept()?; + Ok((socket.try_clone()?, socket)) } #[panda::init] -fn init(_: &mut PluginHandle) -> bool { - let mut channel = load_guest_plugin("guest_shell", message_recv); - - let socket = UnixListener::bind(&ARGS.socket_path).unwrap(); - let mut socket = socket.accept().unwrap().0; +fn init(_: &mut PluginHandle) { + let args = Args::from_panda_args(); + let mut guest_channel = load_guest_plugin("guest_shell", message_recv); - STDOUT.set(Mutex::new(socket.try_clone().unwrap())).unwrap(); + let (stdout, mut stdin) = get_split_socket(&args.socket_path).unwrap(); + STDOUT.lock().replace(stdout); - thread::spawn(move || { + std::thread::spawn(move || { // Copy stdin from unix socket to guest - io::copy(&mut socket, &mut channel).unwrap(); + io::copy(&mut stdin, &mut guest_channel).unwrap(); }); - - true } From de0089a3a19328927717411a31484f4eee813988 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 15 Dec 2021 11:03:40 -0500 Subject: [PATCH 35/79] Move Rust example to crates.io panda-channels --- panda/guest_plugins/rust_example/Cargo.lock | 320 +------------------ panda/guest_plugins/rust_example/Cargo.toml | 3 +- panda/guest_plugins/rust_example/src/main.rs | 2 +- 3 files changed, 8 insertions(+), 317 deletions(-) diff --git a/panda/guest_plugins/rust_example/Cargo.lock b/panda/guest_plugins/rust_example/Cargo.lock index 38d8a687f33..820d766a6a2 100644 --- a/panda/guest_plugins/rust_example/Cargo.lock +++ b/panda/guest_plugins/rust_example/Cargo.lock @@ -2,132 +2,18 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "cbindgen" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38728c31b994e4b849cf59feefb4a8bf26acd299ee0b92c9fb35bd14ad4b8dfa" -dependencies = [ - "clap", - "heck", - "indexmap", - "log", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn", - "tempfile", - "toml", -] - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "channels" -version = "0.1.0" -dependencies = [ - "cbindgen", - "lazy_static", - "parking_lot", -] - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", -] - [[package]] name = "instant" version = "0.1.12" @@ -137,12 +23,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "lazy_static" version = "1.4.0" @@ -165,12 +45,13 @@ dependencies = [ ] [[package]] -name = "log" -version = "0.4.14" +name = "panda-channels" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "c3f15dafa90983e93ae0579858b2eb73443f6d51cca28d5bdf4e3a28ce7621df" dependencies = [ - "cfg-if", + "lazy_static", + "parking_lot", ] [[package]] @@ -198,70 +79,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "ppv-lite86" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" - -[[package]] -name = "proc-macro2" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" version = "0.2.10" @@ -271,150 +88,25 @@ dependencies = [ "bitflags", ] -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rust_example" version = "0.1.0" dependencies = [ - "channels", + "panda-channels", ] -[[package]] -name = "ryu" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568" - [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "serde" -version = "1.0.131" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.131" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" -dependencies = [ - "itoa", - "ryu", - "serde", -] - [[package]] name = "smallvec" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "syn" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "tempfile" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" -dependencies = [ - "cfg-if", - "libc", - "rand", - "redox_syscall", - "remove_dir_all", - "winapi", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "unicode-segmentation" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - [[package]] name = "winapi" version = "0.3.9" diff --git a/panda/guest_plugins/rust_example/Cargo.toml b/panda/guest_plugins/rust_example/Cargo.toml index 71dcd73b661..5d5508b3c08 100644 --- a/panda/guest_plugins/rust_example/Cargo.toml +++ b/panda/guest_plugins/rust_example/Cargo.toml @@ -4,5 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -# TODO: move to its own repo to version separately -channels = { path = "../../../../igloo-internal/pie_idea/guest_code/channels" } +panda-channels = "0.1" diff --git a/panda/guest_plugins/rust_example/src/main.rs b/panda/guest_plugins/rust_example/src/main.rs index 3306171766a..6bc186b2ed2 100644 --- a/panda/guest_plugins/rust_example/src/main.rs +++ b/panda/guest_plugins/rust_example/src/main.rs @@ -1,4 +1,4 @@ -use channels::Channel; +use panda_channels::Channel; use std::io::Write; fn main() { From 44fc6a212572e24eaba94727b3d07cf9db89e3bc Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 15 Dec 2021 11:44:31 -0500 Subject: [PATCH 36/79] Add guest_plugin_example to demonstrate host<->guest communication --- panda/guest_plugins/rust_example/src/main.rs | 9 +- panda/plugins/config.panda | 1 + panda/plugins/guest_plugin_example/Cargo.lock | 489 ++++++++++++++++++ panda/plugins/guest_plugin_example/Cargo.toml | 23 + panda/plugins/guest_plugin_example/Makefile | 18 + panda/plugins/guest_plugin_example/README.md | 6 + panda/plugins/guest_plugin_example/src/lib.rs | 18 + panda/plugins/guest_plugin_example/try_it.py | 13 + 8 files changed, 576 insertions(+), 1 deletion(-) create mode 100644 panda/plugins/guest_plugin_example/Cargo.lock create mode 100644 panda/plugins/guest_plugin_example/Cargo.toml create mode 100644 panda/plugins/guest_plugin_example/Makefile create mode 100644 panda/plugins/guest_plugin_example/README.md create mode 100644 panda/plugins/guest_plugin_example/src/lib.rs create mode 100644 panda/plugins/guest_plugin_example/try_it.py diff --git a/panda/guest_plugins/rust_example/src/main.rs b/panda/guest_plugins/rust_example/src/main.rs index 6bc186b2ed2..e77424c9ff7 100644 --- a/panda/guest_plugins/rust_example/src/main.rs +++ b/panda/guest_plugins/rust_example/src/main.rs @@ -1,5 +1,5 @@ use panda_channels::Channel; -use std::io::Write; +use std::io::{Read, Write}; fn main() { // This print won't be visible outside of the serial log @@ -13,4 +13,11 @@ fn main() { // Or use formatting utilties to do so writeln!(&mut channel, "today's lucky number is: {}", 3).unwrap(); + + // The channel can also be read from + let mut buf = [0; 4]; + channel.read_exact(&mut buf).unwrap(); + + let num = u32::from_le_bytes(buf); + writeln!(&mut channel, "the number you sent the guest was: {}", num).unwrap(); } diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index e841d906aeb..2de2e9f757a 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -13,6 +13,7 @@ edge_coverage filereadmon forcedexec gdb +guest_plugin_example guest_plugin_manager guest_shell hooks diff --git a/panda/plugins/guest_plugin_example/Cargo.lock b/panda/plugins/guest_plugin_example/Cargo.lock new file mode 100644 index 00000000000..6631ad52b15 --- /dev/null +++ b/panda/plugins/guest_plugin_example/Cargo.lock @@ -0,0 +1,489 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ctor" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "guest_plugin_example" +version = "0.1.0" +dependencies = [ + "panda-re", + "parking_lot", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "inventory" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb5160c60ba1e809707918ee329adb99d222888155835c6feedba19f6c3fd4" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e41b53715c6f0c4be49510bb82dee2c1e51c8586d885abe65396e82ed518548" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "panda-re" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfc5b9d238b9f1d4785346b7d611dcc4236f615334e0719afbf3033f8c26e0e" +dependencies = [ + "dirs", + "glib-sys", + "inventory", + "lazy_static", + "libloading", + "once_cell", + "panda-re-macros", + "panda-re-sys", + "paste", + "strum 0.20.0", + "strum_macros 0.20.1", + "thiserror", +] + +[[package]] +name = "panda-re-macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be1d7a86fc7fc5c32ca9d7b430e5f12f76b664f381c4213c7071d14e88fc588" +dependencies = [ + "darling", + "doc-comment", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "panda-re-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "proc-macro2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "strum" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" + +[[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" + +[[package]] +name = "strum_macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" +dependencies = [ + "heck", + "pkg-config", + "strum 0.18.0", + "strum_macros 0.18.0", + "thiserror", + "toml", + "version-compare", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/plugins/guest_plugin_example/Cargo.toml b/panda/plugins/guest_plugin_example/Cargo.toml new file mode 100644 index 00000000000..ca478581961 --- /dev/null +++ b/panda/plugins/guest_plugin_example/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "guest_plugin_example" +version = "0.1.0" +authors = ["Jordan McLeod "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +panda-re = { version = "0.26", default-features = false } +parking_lot = "0.11" + +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +aarch64 = ["panda-re/aarch64"] diff --git a/panda/plugins/guest_plugin_example/Makefile b/panda/plugins/guest_plugin_example/Makefile new file mode 100644 index 00000000000..2234476df57 --- /dev/null +++ b/panda/plugins/guest_plugin_example/Makefile @@ -0,0 +1,18 @@ +# Don't forget to add your plugin to config.panda! + +# Build rust plugins with make! + +# The main rule for your plugin. List all object-file dependencies. + +PANDA_PATH = $(realpath $(shell pwd)/..) +PLUGIN_DIR = $(realpath $(join $(PANDA_PATH), /../panda/plugins/$(PLUGIN_NAME)/)) +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so : $(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + @echo " CARGO $(PLUGIN_DIR)" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --no-default-features --features=$(TARGET_NAME) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @cp -p $(PLUGIN_ARTIFACTS_DIR)/release/lib$(PLUGIN_NAME).so $@ diff --git a/panda/plugins/guest_plugin_example/README.md b/panda/plugins/guest_plugin_example/README.md new file mode 100644 index 00000000000..cbd6557ee87 --- /dev/null +++ b/panda/plugins/guest_plugin_example/README.md @@ -0,0 +1,6 @@ +# Guest Plugin Example + +This is a basic example of how to build a PANDA plugin for communicating with a guest +plugin using Rust. + +See [`guest_plugins/rust_example`](/panda/guest_plugins/rust_example) for the corresponding guest plugin. diff --git a/panda/plugins/guest_plugin_example/src/lib.rs b/panda/plugins/guest_plugin_example/src/lib.rs new file mode 100644 index 00000000000..5ea9fd93a08 --- /dev/null +++ b/panda/plugins/guest_plugin_example/src/lib.rs @@ -0,0 +1,18 @@ +use panda::{plugins::guest_plugin_manager::*, prelude::*}; +use std::io::Write; + +// Print out all the messages sent from the guest +#[channel_recv] +fn message_recv(_: u32, data: &str) { + println!("[rust_example] {}", data); +} + +#[panda::init] +fn init(_: &mut PluginHandle) { + let mut channel = load_guest_plugin("rust_example", message_recv); + + // the `rust_example` plugin expects to be sent a u32 which it will log + // so let's sent it one. + let num: u32 = 1234; + channel.write_all(&num.to_le_bytes()).unwrap(); +} diff --git a/panda/plugins/guest_plugin_example/try_it.py b/panda/plugins/guest_plugin_example/try_it.py new file mode 100644 index 00000000000..8df6c35a626 --- /dev/null +++ b/panda/plugins/guest_plugin_example/try_it.py @@ -0,0 +1,13 @@ +from pandare import Panda + +panda = Panda(generic="x86_64") +panda.load_plugin("guest_plugin_example") + +@panda.queue_blocking +def run_cmd(): + panda.revert_sync("root") + panda.run_serial_cmd("cat", no_timeout=True) + panda.run_serial_cmd("cat", no_timeout=True) + panda.end_analysis() + +panda.run() From 0121b7ca9071f4e24aa5a9b95b0ba774a4ce16e7 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 17 Dec 2021 14:38:35 -0500 Subject: [PATCH 37/79] Add symlink support to hyperfuse --- panda/plugins/guest_shell/src/lib.rs | 4 +- panda/plugins/hyperfuse/Cargo.lock | 26 ++++- panda/plugins/hyperfuse/Cargo.toml | 4 +- panda/plugins/hyperfuse/src/lib.rs | 159 ++++++++++++++++----------- panda/plugins/hyperfuse/src/types.rs | 16 ++- 5 files changed, 138 insertions(+), 71 deletions(-) diff --git a/panda/plugins/guest_shell/src/lib.rs b/panda/plugins/guest_shell/src/lib.rs index 3182e2d912f..d0ecfde8f15 100644 --- a/panda/plugins/guest_shell/src/lib.rs +++ b/panda/plugins/guest_shell/src/lib.rs @@ -26,7 +26,7 @@ fn get_split_socket(path: &str) -> io::Result<(UnixStream, UnixStream)> { } #[panda::init] -fn init(_: &mut PluginHandle) { +fn init(_: &mut PluginHandle) -> bool { let args = Args::from_panda_args(); let mut guest_channel = load_guest_plugin("guest_shell", message_recv); @@ -37,4 +37,6 @@ fn init(_: &mut PluginHandle) { // Copy stdin from unix socket to guest io::copy(&mut stdin, &mut guest_channel).unwrap(); }); + + true } diff --git a/panda/plugins/hyperfuse/Cargo.lock b/panda/plugins/hyperfuse/Cargo.lock index 68044083319..23a39475c0b 100644 --- a/panda/plugins/hyperfuse/Cargo.lock +++ b/panda/plugins/hyperfuse/Cargo.lock @@ -43,6 +43,16 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cached" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2bc2fd249a24a9cdd4276f3a3e0461713271ab63b0e9e656e200e8e21c8c927" +dependencies = [ + "hashbrown", + "once_cell", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -208,6 +218,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + [[package]] name = "heck" version = "0.3.3" @@ -240,6 +256,7 @@ name = "hyperfuse" version = "0.1.0" dependencies = [ "bincode", + "cached", "crossbeam-queue", "fuser", "lazy_static", @@ -351,9 +368,9 @@ dependencies = [ [[package]] name = "panda-re" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd819f91df8381e0b6255a47f749a1dd52589c34a0b007bbee41f27630ff7ee" +checksum = "2dfc5b9d238b9f1d4785346b7d611dcc4236f615334e0719afbf3033f8c26e0e" dependencies = [ "dirs", "glib-sys", @@ -371,12 +388,13 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d807aa10d149e5ddde4e9cd386df1791efda6d6716077349da9f78cb6d32460" +checksum = "5be1d7a86fc7fc5c32ca9d7b430e5f12f76b664f381c4213c7071d14e88fc588" dependencies = [ "darling", "doc-comment", + "proc-macro2", "quote", "syn", ] diff --git a/panda/plugins/hyperfuse/Cargo.toml b/panda/plugins/hyperfuse/Cargo.toml index 0c6c13161d0..58bf22cc165 100644 --- a/panda/plugins/hyperfuse/Cargo.toml +++ b/panda/plugins/hyperfuse/Cargo.toml @@ -8,8 +8,9 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.25", default-features = false } +panda-re = { version = "0.26", default-features = false } fuser = { version = "0.9", features = ["serializable"] } +#fuser = { git = "https://github.com/cberner/fuser", features = ["serializable"] } libc = "0.2.98" pretty_env_logger = "0.4.0" serde = { version = "1", features = ["derive"] } @@ -17,6 +18,7 @@ bincode = "1.3.3" lazy_static = "1" parking_lot = "0.11" crossbeam-queue = "0.3" +cached = { version = "0.26", default-features = false } [features] default = ["x86_64"] diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index bc249c394ac..3407fe6df65 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -1,15 +1,15 @@ +use cached::{stores::TimedCache, Cached}; use fuser::{ Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, ReplyOpen, ReplyWrite, }; use libc::ENOENT; use panda::prelude::*; -use serde::{Deserialize, Serialize}; +use serde::de::DeserializeOwned; +use serde::Serialize; use std::borrow::Borrow; -use std::collections::HashMap; -use std::ffi::{CString, OsStr, OsString}; +use std::ffi::{OsStr, OsString}; use std::marker::PhantomData; -use std::path::Path; mod types; use types::*; @@ -18,7 +18,8 @@ struct HyperFilesystem { reply: Receiver, request: Sender, - lookup_cache: HashMap<(u64, OsString), LookupCacheEntry>, + link_target_cache: TimedCache>, + lookup_cache: TimedCache<(u64, OsString), LookupCacheEntry>, } macro_rules! on_reply { @@ -26,18 +27,27 @@ macro_rules! on_reply { $self:ident => $reply:ident ( $type:ident { $($field:ident),* } - => $reply_ty:ident { $( + => $reply_ty:ident $({ $( $reply_field:ident - ),*} + ),*})? + + // tuple type + $(( $( + $reply_field_tuple:ident + ),*))? => $code:block ) $(;)? ) => { - println!("Before send"); $self.request.send(Request::$type { $( $field ),* }).unwrap(); - println!("After send"); + match $self.reply.recv() { - Ok(Reply::$reply_ty { $( $reply_field ),* }) => $code, + Ok(Reply::$reply_ty + // struct variant + $({ $( $reply_field ),* })? + // tuple variant + $(( $( $reply_field_tuple ),* ))? + ) => $code, Ok(Reply::Error(err)) => $reply.error(err), Ok(reply) => panic!("Invalid reply {:?}", reply), Err(_) => $reply.error(ENOENT), @@ -50,9 +60,15 @@ macro_rules! send_reply { $self:ident => $reply:ident.$method:ident ( $type:ident { $($field:ident),* } - => $reply_ty:ident { $( + => $reply_ty:ident + // struct type + $({$( $reply_field:ident $( . $reply_field_method:ident () )? - ),*} + ),*})? + // tuple type + $(($( + $reply_field_tup:ident $( . $reply_field_method_tup:ident () )? + ),*))? ) $(;)? ) => { println!("{}(...)", stringify!($method)); @@ -60,15 +76,30 @@ macro_rules! send_reply { $self => $reply ( $type { $($field),* } - => $reply_ty { $( + => $reply_ty + // struct type + $({ $( $reply_field - ),*} + ),*})? + // tuple type + $(( $( + $reply_field_tup + ),*))? => { + // struct type + $( + $( + let $reply_field = $reply_field $( .$reply_field_method () )?; + )* + $reply.$method( $($reply_field),* ); + )? $( - let $reply_field = $reply_field $( .$reply_field_method () )?; - )* - $reply.$method( $($reply_field),* ); + $( + let $reply_field_tup = $reply_field_tup $( .$reply_field_method_tup () )?; + )* + $reply.$method( $($reply_field_tup),* ); + )? } ) } @@ -81,9 +112,11 @@ impl Filesystem for HyperFilesystem { ttl, attr, generation, - }) = self.lookup_cache.remove(&(parent_ino, name.to_os_string())) + }) = self + .lookup_cache + .cache_get(&(parent_ino, name.to_os_string())) { - reply.entry(&ttl, &attr, generation); + reply.entry(ttl, attr, *generation); return; } @@ -116,7 +149,20 @@ impl Filesystem for HyperFilesystem { ) { send_reply! { self => reply.data( - Read { ino, offset, size, flags } => Data { data.as_ref() } + Read { ino, offset, size, flags } => Data(data.as_ref()) + ); + } + } + + fn readlink(&mut self, _req: &fuser::Request<'_>, ino: u64, reply: ReplyData) { + if let Some(data) = self.link_target_cache.cache_get(&ino) { + reply.data(&data); + return; + } + + send_reply! { + self => reply.data( + ReadLink { ino } => Data(data.as_ref()) ); } } @@ -135,10 +181,12 @@ impl Filesystem for HyperFilesystem { ReadDir { ino, offset } => Directory { dir_entries } => { - println!("Got to dir entry"); - for DirEntry { ino, offset, kind, name, lookup_cache } in dir_entries { - println!("{:?}", name); - self.lookup_cache.insert((parent_ino, name.clone().into()), lookup_cache); + for DirEntry { ino, offset, kind, name, link_target, lookup_cache } in dir_entries { + if let Some(LinkTarget { path, parent_ino, target_name, target_lookup }) = link_target { + self.link_target_cache.cache_set(ino, path); + self.lookup_cache.cache_set((parent_ino, target_name.into()), target_lookup); + } + self.lookup_cache.cache_set((parent_ino, name.clone().into()), lookup_cache); if reply.add(ino, offset, kind, name) { break } @@ -180,30 +228,23 @@ impl Filesystem for HyperFilesystem { } } -struct Sender(ChannelId, PhantomData); +struct Sender(Channel, PhantomData); impl Sender { - fn send(&self, val: T) -> Result<(), ()> { - let bytes = bincode::serialize(&val).unwrap(); - - let len = (bytes.len() as u32).to_le_bytes(); - GUEST_PLUGIN_MANAGER.channel_write(self.0, len.as_ptr(), 4); - GUEST_PLUGIN_MANAGER.channel_write(self.0, bytes.as_ptr(), bytes.len()); - - Ok(()) + fn send(&mut self, val: T) -> Result<(), ()> { + bincode::serialize_into(&mut self.0, &val).map_err(|_| ()) } } -struct Receiver>(ChannelId, PhantomData); +struct Receiver(PhantomData); -impl Receiver { +impl Receiver { fn recv(&self) -> Result { loop { match MESSAGE_QUEUE.pop() { Some(bytes) => break bincode::deserialize(&bytes).map_err(|_| ()), None => { println!("Nothing recieved, sleeping..."); - //std::thread::yield_now(); std::thread::sleep(std::time::Duration::from_millis(500)); } } @@ -211,26 +252,32 @@ impl Receiver { } } -//fn channel>(channel: ChannelId) -> (Sender, Receiver) { -// (Sender(channel, PhantomData), Receiver(channel, PhantomData)) -//} +fn split_channel(channel: Channel) -> (Sender, Receiver) +where + InType: DeserializeOwned, + OutType: Serialize, +{ + (Sender(channel, PhantomData), Receiver(PhantomData)) +} + +fn mount(channel: Channel) { + // TODO: make this programatically configurable + let mountpoint = std::env::var("HYPERFUSE_MOUNT") + .expect("HYPERFUSE_MOUNT is not set but is required by 'hyperfuse' plugin"); -fn mount(channel: ChannelId) { - let mountpoint = "/home/jmcleod/dev/panda/build/fuse_mount"; let options = vec![ MountOption::FSName("hello".to_string()), MountOption::AutoUnmount, ]; - let (request, reply) = (Sender(channel, PhantomData), Receiver(channel, PhantomData)); - - //other_thread::start(incoming_request, response); + let (request, reply) = split_channel(channel); fuser::mount2( HyperFilesystem { request, reply, - lookup_cache: Default::default(), + link_target_cache: TimedCache::with_lifespan(1), + lookup_cache: TimedCache::with_lifespan(1), }, mountpoint, &options, @@ -244,30 +291,18 @@ use panda::plugins::guest_plugin_manager::*; //GUEST_PLUGIN_MANAGER; static MESSAGE_QUEUE: SegQueue> = SegQueue::new(); -extern "C" fn message_recv(_channel: u32, ptr: *const u8, len: usize) { - unsafe { - println!("message_recv in hyperfuse"); - let bytes = std::slice::from_raw_parts(ptr, len); - MESSAGE_QUEUE.push(bytes.to_owned()); - } +#[channel_recv] +fn message_recv(_: u32, bytes: Vec) { + MESSAGE_QUEUE.push(bytes.to_owned()); } #[panda::init] fn init(_: &mut PluginHandle) -> bool { pretty_env_logger::init_custom_env("HYPERFUSE_LOG"); - println!("after load_plugin in hyperfuse"); - - GUEST_PLUGIN_MANAGER.ensure_init(); - let hyperfuse_guest = GuestPlugin::new("hyperfuse_guest".into(), message_recv); - let channel = GUEST_PLUGIN_MANAGER.add_guest_plugin(hyperfuse_guest); - println!("hyperfuse established channel with id {}", channel); + let channel = load_guest_plugin("hyperfuse_guest", message_recv); - std::thread::spawn(move || { - println!("new hyperfuse thread"); - mount(channel); - }); - println!("returning after new thread hyperfuse"); + std::thread::spawn(move || mount(channel)); true } diff --git a/panda/plugins/hyperfuse/src/types.rs b/panda/plugins/hyperfuse/src/types.rs index c897025c8b3..262d5eb9540 100644 --- a/panda/plugins/hyperfuse/src/types.rs +++ b/panda/plugins/hyperfuse/src/types.rs @@ -19,6 +19,9 @@ pub enum Request { size: u32, flags: i32, }, + ReadLink { + ino: u64, + }, ReadDir { ino: u64, offset: i64, @@ -54,9 +57,7 @@ pub enum Reply { ttl: Duration, attr: FileAttr, }, - Data { - data: Vec, - }, + Data(Vec), Directory { dir_entries: Vec, }, @@ -77,12 +78,21 @@ pub enum Reply { Error(c_int), } +#[derive(Serialize, Deserialize, Debug)] +pub struct LinkTarget { + pub path: Vec, + pub parent_ino: u64, + pub target_name: String, + pub target_lookup: LookupCacheEntry, +} + #[derive(Serialize, Deserialize, Debug)] pub struct DirEntry { pub ino: u64, pub offset: i64, pub kind: FileType, pub name: String, + pub link_target: Option, pub lookup_cache: LookupCacheEntry, } From 03223b93177f9fe20c682d9a2e02b2a2a4355ad4 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Tue, 21 Dec 2021 13:35:20 -0500 Subject: [PATCH 38/79] Allow reading partial messages via hyperchannels --- .../src/interface/channels.rs | 16 +++++++++++++++- .../guest_plugin_manager/src/interface/hci.rs | 7 ++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/panda/plugins/guest_plugin_manager/src/interface/channels.rs b/panda/plugins/guest_plugin_manager/src/interface/channels.rs index f1b9b9bafa7..8182a6ad902 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/channels.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/channels.rs @@ -49,6 +49,21 @@ pub fn poll_plugin_message(channel_id: ChannelId) -> Option> { } } +pub fn requeue_plugin_message(channel_id: ChannelId, message: Vec) { + let pm = CHANNELS.read(); + let plugin = pm.get(&channel_id).unwrap(); + let len = plugin.message_queue.len(); + + plugin.message_queue.push(message); + + // len won't be greater than single digit, this is fine + for _ in 0..len { + plugin + .message_queue + .push(plugin.message_queue.pop().unwrap()); + } +} + pub fn publish_message_from_guest(channel_id: ChannelId, msg: Vec) { let pm = CHANNELS.read(); if let Some(plugin) = pm.get(&channel_id) { @@ -86,4 +101,3 @@ pub fn get_channel_from_name(p_name: &str) -> Option { .find(|(_, v)| v.name.as_deref() == Some(p_name)) .map(|x| *x.0) } - diff --git a/panda/plugins/guest_plugin_manager/src/interface/hci.rs b/panda/plugins/guest_plugin_manager/src/interface/hci.rs index 9d184a4fad6..b7734afe915 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/hci.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/hci.rs @@ -1,6 +1,6 @@ -use super::channels::ChannelId; use super::channels::{ get_channel_from_name, poll_plugin_message, publish_message_from_guest, + requeue_plugin_message, ChannelId, }; use super::plugin_manager::new_manager_channel; use crate::MAGIC; @@ -31,9 +31,10 @@ pub fn hyp_read( addr: usize, max_size: usize, ) -> Option { - if let Some(msg) = poll_plugin_message(channel_id) { + if let Some(mut msg) = poll_plugin_message(channel_id) { if msg.len() > max_size { - panic!(); + requeue_plugin_message(channel_id, msg[max_size..].to_owned()); + msg.truncate(max_size); } // could check max len more virtual_memory_write(cpu, addr as target_ulong, &msg); From c26bb60af4c4882bb8db410c5c24244a47073825 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 3 Jan 2022 15:53:16 -0500 Subject: [PATCH 39/79] Update hyperfuse TODO for clarity --- panda/plugins/hyperfuse/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/plugins/hyperfuse/src/lib.rs b/panda/plugins/hyperfuse/src/lib.rs index 3407fe6df65..468658441eb 100644 --- a/panda/plugins/hyperfuse/src/lib.rs +++ b/panda/plugins/hyperfuse/src/lib.rs @@ -261,7 +261,7 @@ where } fn mount(channel: Channel) { - // TODO: make this programatically configurable + // TODO: make this programatically configurable via a plugin-to-plugin API let mountpoint = std::env::var("HYPERFUSE_MOUNT") .expect("HYPERFUSE_MOUNT is not set but is required by 'hyperfuse' plugin"); From dbbf33b3fd847e9b5983e0da548f71e0e9adb90c Mon Sep 17 00:00:00 2001 From: jamcleod Date: Tue, 11 Jan 2022 14:46:33 -0500 Subject: [PATCH 40/79] Add guest plugin guide/docs --- panda/docs/guest_plugins.md | 306 ++++++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 panda/docs/guest_plugins.md diff --git a/panda/docs/guest_plugins.md b/panda/docs/guest_plugins.md new file mode 100644 index 00000000000..696e684073f --- /dev/null +++ b/panda/docs/guest_plugins.md @@ -0,0 +1,306 @@ +# PANDA Guest Plugins + +### Overview + +PANDA guest plugins are a feature of PANDA that allows you to run non-cooperative guest agents. This means without any control of the guest, you can run programs that can communicate with code running on the host system. This gives the ability to gain a semantic understanding of the guest through stable interfaces, with the drawback of not being usable in replays. + +Some quick links to resources regarding guest plugins: + +* [`rust_example`](/panda/guest_plugins/rust_example) - An example guest plugin written in Rust +* [`guest_plugin_example`](/panda/plugins/guest_plugin_example) - The PANDA (host) plugin that loads and interacts with the guest plugin example +* [`guest_plugin_manager` Rust Documentation](https://docs.rs/panda-re/latest/panda/plugins/guest_plugin_manager/index.html) +* [`guest_plugin_manager`](/panda/plugins/guest_plugin_manager) - Source for the guest plugin manager (the PANDA host plugin which handles loading/unloading guest plugins) + +### Structure of Typical Usage + +PANDA guest plugins are a bit more involved than normal PANDA plugins, due to needing to facilitate communication across the hypervisor: + +* Host-side plugin + * A standard PANDA plugin (a shared object built from `panda/plugins`). + * Responsible for loading the code into the guest using the `guest_plugin_manager` plugin + * Handles communication with the guest plugin + * Sending - queuing up messages for the guest + * Recieving - Provides a callback for messages sent by the guest +* Guest-side plugin + * A standard statically-linked executable cross-compiled for the guest (built from `panda/guest_plugins`) + * Additional guest plugins will be built from `$EXTRA_GUEST_PLUGINS_PATH` + * Requires a `$EXTRA_GUEST_PLUGINS_PATH/config.panda` file containing newline-separated plugin names. Each plugin is built from `$EXTRA_GUEST_PLUGINS_PATH/$plugin_name/`. + * Communicates to the host using hypervisor calls via the [`panda-channels`](https://github.com/panda-re/panda-channels) library. + +### Getting Started + +For starters let's try developing an out-of-tree guest plugin. This process won't be any different than in-tree, so if down the road you wish to upstream your plugin it'll only require a bit of copy/pasting. + +#### Creating a New Plugin + +First up, create a folder to use as your "out-of-tree" plugins folder and set `EXTRA_GUEST_PLUGINS_PATH` accordingly: + +```bash +mkdir guest_plugins +export EXTRA_GUEST_PLUGINS_PATH=`realpath guest_plugins` +``` + +Now let's create a guest plugin using the example plugin as a template: + +1. Copy `panda/guest_plugins/guest_plugins/rust_example` to `$EXTRA_GUEST_PLUGINS_PATH/your_plugin_name` +2. Edit the `Cargo.toml` to change the name to match your folder name: + +```toml +[package] +name = "your_plugin_name" +``` + +3. Create a `config.panda` file in your out-of-tree `guest_plugins` folder. The only thing this needs to contain is your plugin's name: + +``` +your_plugin_name +``` + +Later, if you make more plugins you can add each one on a new line: + +``` +your_plugin_name +your_other_plugin +``` + +#### Adding Some Guest Logic + +For our example, we'll make a guest plugin which informs the host of how many files/directories are in `/etc`. + +First up some imports we'll need: + +```rust +use panda_channels::Channel; +use std::io::Write; +use std::fs; + +fn main() { +} +``` + +We'll need `Channel` and `Write` for communicating with the host, and we'll need `fs` for actually interacting with the filesystem. + +Then in our `main` function we'll read `/etc` using [`read_dir`](https://doc.rust-lang.org/std/fs/fn.read_dir.html) and use [`Iterator::count`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.count): + +```rust +let file_count = fs::read_dir("/etc").unwrap().count(); +``` + +Now let's create a channel to send this information to the host: + +```rust +let mut channel = Channel::main("your_plugin_name").unwrap(); +``` + +We pass the name of our plugin to `Channel::main` to get the main channel for our plugin. This channel is automatically allocated by the `guest_plugin_manager` when we load our plugin and for most usecases it's all we'll need. + +We've marked it as mutable so we can write to it. `Channel` implements Rust's [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html) trait, so all we need to do is serialize our file count to bytes and use [`write_all`](https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all) to send the bytes to the host: + +```rust +channel.write_all(&(file_count as u32).to_le_bytes()).unwrap(); +``` + +We convert `file_count` from `usize` (arch-width integer) to a 32-bit integer to serialize to a fixed number of bytes (that way our host code doesn't need to care about whether our guest is 32 or 64 bit) and then use `to_le_bytes` to convert to little endian bytes for us to write. + +Putting that all together we get our complete guest plugin: + +```rust +use panda_channels::Channel; +use std::io::Write; +use std::fs; + +fn main() { + let file_count = fs::read_dir("/etc").unwrap().count(); + let mut channel = Channel::main("your_plugin_name").unwrap(); + channel.write_all(&(file_count as u32).to_le_bytes()).unwrap(); +} +``` + +If we want to check if it built properly, we can run: + +``` +cargo check +``` + +This will print out any errors that need to be resolved, if there's no issues we'll get: + +``` + Finished dev [unoptimized + debuginfo] target(s) in 0.11s +``` + +This doesn't actually build or link our executable, so it saves a lot of time over doing a full PANDA build any time we want to check for compiler errors. Some other options are [`clippy`](https://github.com/rust-lang/rust-clippy) (A full Rust linter to help write idiomatic Rust) and [`bacon`](https://github.com/Canop/bacon) (Watches your project for changes and keeps a live-updating set of errors/warnings). Also helpful while developing is [`rust-analyzer`](https://rust-analyzer.github.io/), a Language Server implementation for VS Code, Emacs, Vim, etc. + +#### Writing a Host Plugin + +In order for our guest plugin to do anything, we'll need a host PANDA plugin in order to facilitate loading/message passing. + +First up, let's create a new Rust plugin. Similarly to with our guest plugin, we can use an example plugin as a template and just find/replace the names. + +I'd recommend using `panda/plugins/guest_plugin_example` as a base. Change the name in `Cargo.toml` to match the folder name, add the folder name to `panda/plugins/config.panda`, and you should be good to go. + +If you use another plugin as your base, make sure you have a somewhat recent version of `panda-re`, as you'll need at least `0.26` for this: + +```toml +[dependencies] +panda-re = { version = "0.26", default-features = false } +``` + +| Tip | +|:----| +| Install [`cargo-edit`](https://github.com/killercup/cargo-edit) and you can add the latest version of a dependency with `cargo add dep-name` | + +Now onto actually writing the host plugin. First off we'll want to pull the guest plugin management utilities we'll need into scope: + +```rust +use panda::plugins::guest_plugin_manager::{load_guest_plugin, channel_recv}; +use panda::prelude::*; +``` + +We'll need a callback function for handling incoming messages from the guest. The `panda-re` package provides an (`#[channel_recv]`) attribute for this to do most of the work for us, so for the most part we just need to define a function which takes a `u32` (an ID representing the channel we're recieving messages from) and either bytes (`&[u8]`) or a string (`&str`). In this case, since we're dealing with binary data, let's go with a byte slice: + +```rust +#[channel_recv] +fn message_recv(_: u32, data: &[u8]) { +} +``` + +And inside of that, let's just include a bit of code for converting back to an integer and printing it out to our terminal: + +```rust +// convert &[u8] to [u8; 4] +let count_bytes: [u8; 4] = data[..4].try_into().unwrap(); + +// convert [u8; 4] to u32 +let file_count = u32::from_le_bytes(count_bytes); + +// print the file count to the terminal +println!("Guest `/etc` file count: {}", file_count); +``` + +Next up, let's define our `init` function. Since all we need to do when our plugin is load the guest plugin: + +```rust +#[panda::init] +fn init(_: &mut PluginHandle) { + let mut channel = load_guest_plugin("your_guest_plugin_name", message_recv); + + // if we needed to write to the channel at all we could do so here using + // std::io::Write, just like the guest plugin. +} +``` + +Now we have everything we need for a fully-functional host plugin: + +```rust +use panda::plugins::guest_plugin_manager::{load_guest_plugin, channel_recv}; +use panda::prelude::*; + +#[channel_recv] +fn message_recv(_: u32, data: &[u8]) { + // convert &[u8] to [u8; 4] + let count_bytes: [u8; 4] = data[..4].try_into().unwrap(); + + // convert [u8; 4] to u32 + let file_count = u32::from_le_bytes(count_bytes); + + // print the file count to the terminal + println!("Guest `/etc` file count: {}", file_count); +} + +#[panda::init] +fn init(_: &mut PluginHandle) { + load_guest_plugin("your_guest_plugin_name", message_recv); +} +``` + +If your plugin uses Rust 2018 edition then you'll also need to import `std::convert::TryInto`. If you forget this, no worries though, as rustc will remind you and tell you how to fix it: + +``` +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +1 | use std::convert::TryInto; + | +``` + +#### Building + +To build, we go through the standard PANDA build process: + +1. Create a `build` folder in the root of your clone of PANDA if you haven't already +2. From within the build folder run `../build.sh`. In our case, we are only going to be testing on x86_64 while developing, so we can save ourselves some build time by only building a single architecture: `../build.sh x86_64-softmmu` + +#### Testing Our Guest Plugin + +The easiest way to test our plugin will be with a pypanda script. An example script can be found in [`panda/plugins/guest_plugin_example/try_it.py`](/panda/panda/plugins/guest_plugin_example/try_it.py). + +```python +from pandare import Panda + +panda = Panda(generic="x86_64") +panda.load_plugin("guest_plugin_example") + +@panda.queue_blocking +def run_cmd(): + panda.revert_sync("root") + panda.run_serial_cmd("cat", no_timeout=True) + panda.run_serial_cmd("cat", no_timeout=True) + + panda.end_analysis() + +panda.run() +``` + +Just replace `"guest_plugin_example"` with the name of your host PANDA plugin, then run the script. You should see roughly the following output: + +``` +$ python3 try_it.py + +[...] +Guest `/etc` file count: 170 +``` + +If you're getting this message, congrats! You've made your first PANDA guest plugin. If you're having trouble, a list of potential problems and solutions has been included below. + +### Troubleshooting + +If you issue is not listed here, ask for help in the PANDA/MIT Rehosting Slack, and we'll try to add it here. + +##### "No guest plugin path was provided but plugin could not be found" + +``` +thread '' panicked at 'No guest plugin path was provided but plugin "your_guest_plugin_name" could not be found, ensure "your_guest_plugin_name" has been built.', src/interface/api.rs:23:21 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +fatal runtime error: failed to initiate panic, error 5 +Aborted (core dumped) +``` + +Fix steps: + +1. Ensure your guest plugin is listed in guest_plugins/config.panda +2. Make sure you properly updated the guest plugin name in $host_plugin/src/lib.rs +3. Double check for typos + +#### "Fatal error: could not find path for plugin" + +``` +PANDA[core]:Fatal error: could not find path for plugin your_plugin_name +python3: {...}/panda/src/callbacks.c:166: _panda_load_plugin: Assertion `file name != NULL' failed. +Aborted (core dumped)` +``` + +Fix steps: + +1. Ensure your host plugin is listed in panda/plugins/config.panda +2. Ensure you didn't miss any build errors happening when building your host plugin + + +#### "Failed to find channel number" + +``` +failed to find channel number +``` + +Fix steps: + +1. Ensure the name you include in $guest_plugin/src/main.rs is correct when you call `Channel::main` +2. Ensure the name of the guest plugin itself is correct and contains no typos From 847384cff724cf059b95714c79368d5ad9458b84 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 12 Jan 2022 12:09:33 -0500 Subject: [PATCH 41/79] Add API documentation to guest_plugin_manager --- panda/plugins/guest_plugin_manager/README.md | 129 +++++++++--------- .../guest_plugin_manager/src/interface/api.rs | 42 ++++-- 2 files changed, 92 insertions(+), 79 deletions(-) diff --git a/panda/plugins/guest_plugin_manager/README.md b/panda/plugins/guest_plugin_manager/README.md index 81a52bc976b..2875f5ca57c 100644 --- a/panda/plugins/guest_plugin_manager/README.md +++ b/panda/plugins/guest_plugin_manager/README.md @@ -1,95 +1,92 @@ -# Rust Skeleton +# Guest Plugin Manager -This is a basic example of how to build a PANDA plugin with Rust. +The guest plugin manager is a PANDA plugin which handles loading guest agent plugins +into the guest, managing communication channels between the guest and the host. +Typical usage involves writing a host PANDA plugin which calls the plugin manager in +order to load the executable, then loading that PANDA plugin as normal (from either the +PANDA command line or from pypanda). -## Building +Currently the guest plugin manager only supports Linux guests via the `linjector` plugin +however support for other guest OS' would be possible in the presence of other backends. +The responsibility of `linjector` is, as the name would imply, inject a single binary +into the guest as a new process. The guest plugin manager uses this capability in order +to load the "Guest Daemon", an executable running the guest responsible for handling +the spawning of future guest processes and is responsible for communicating with the +guest_plugin_manager directly. -To check if the plugin will build: +## APIs and Callbacks -``` -cargo check -``` +--- -To actually build the plugin: +Name: **add_guest_plugin** -``` -cargo build --release -``` +Signature: -(remove `--release` if you want to build in debug mode) +```c +typedef ChannelId (*add_guest_plugin)(GuestPlugin); +``` -The resulting plugin will be located in `target/release/librust_skeleton.so`. +Description: Adds a guest plugin to be loaded, returns a channel ID representing the +main channel of the to-be-loaded plugin. Writes to this channel ID before plugin +load will be queued and will thus be available when the plugin begins reading. -## Structure +--- -``` -├── Cargo.toml -├── Makefile -├── README.md -└── src - └── lib.rs -``` +Name: **channel_write** -* Cargo.toml - The core plugin info. This informs `cargo` how to actually go about building the plugin. It includes the name, dependencies, and features of plugins. -* Makefile - Instructions for how the PANDA build system will build the plugin. -* lib.rs - The main source file of your plugin. Additional source files can be referenced from here. +Signature: -## Cargo.toml +```c +typedef void (*channel_write)(ChannelId, const u8*, size_t); +``` -The dependencies section: +Description: Writes bytes from a buffer to the given channel ID, queuing them up for +the next guest plugin read. The buffer is copied into a new allocation before being +added to the queue, so the act of writing has no strict lifetime requirements. -```toml -[dependencies] -panda-re = { version = "0.5", default-features = false } -``` +--- -To add a new dependency, add a new line in the form `name = "version"`. +Name: **get_channel_from_name** -For example to add [`libc`](https://docs.rs/libc), simply add the following line: +Signature: -```toml -libc = "0.2" +```c +typedef ChannelId (*get_channel_from_name)(const char*); ``` -## Targetting Multiple Architectures +Description: -In PANDA, a plugin is recompiled once per target architecture (that is to say, the architecture of the guest). To enable this behavior in Rust plugins, we use ["features"](https://doc.rust-lang.org/cargo/reference/features.html) in order to specify which architecture we are building for. +Given the name of a plugin or channel, return the associated channel, panicking +if a channel of the given name cannot be found. Channel name should be passed +as a null-terminated string. -This is controlled by this section of Cargo.toml: +The provided string has no lifetime requirements, but must be a non-null pointer +to a valid C string. -```toml -[features] -default = ["x86_64"] +--- -x86_64 = ["panda-re/x86_64"] -i386 = ["panda-re/i386"] -arm = ["panda-re/arm"] -ppc = ["panda-re/ppc"] -mips = ["panda-re/mips"] -mipsel = ["panda-re/mipsel"] -``` +## Types -by default `x86_64` is the only feature enabled (which is why we don't need to specify any features to build), this is primarily so that IDE support (rust-analyzer for VSCode/vim/etc, IntelliJ/CLion integration) works out of the box, as IDEs typically do type checking with the default feature set. +```c +// A globally unique identifier for a given channel +typedef uint32_t ChannelId; -To build for, say, `arm` you can use the following command: +// ChannelId - the unique identifier for the channel the message came from +// const unsigned char* - a pointer to the data being sent from the guest +// size_t - the length of the data buffer in bytes +typedef void (*ChannelCB)(ChannelId, const unsigned char*, size_t); -``` -cargo build --release --no-default-features --features=arm -``` +// A plugin to be passed to guest_plugin_manager to be registered +typedef struct guest_plugin { + // A unique name for the given plugin, provided as a non-null C string + const char* plugin_name; -And if you wish to prevent certain code from compiling on certain platforms you can use the following: + // An optional path to load the guest agent binary. If null, a lookup will be + // performed to find the binary from the given name. If non-null must be a valid + // C string. + const char* guest_binary_path; -```rust -#[cfg(not(feature = "arm"))] -fn breaks_arm() { - // ... -} + // A callback for when this guest plugin sends a message to the host + ChannelCB msg_recieve_cb; +} GuestPlugin; ``` - -## Other Resources - -* [panda-rs documentation](https://docs.rs/panda-re) -* [panda-rs announcement blog post](https://panda.re/blog/panda-rs) -* [panda-sys documentation](https://docs.rs/panda-re-sys) -* [The Rust Programming Language](https://doc.rust-lang.org/book/) -* [Some example Rust plugins](https://github.com/panda-re/panda-rs-plugins/) diff --git a/panda/plugins/guest_plugin_manager/src/interface/api.rs b/panda/plugins/guest_plugin_manager/src/interface/api.rs index 5012299a655..b11e8680405 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/api.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/api.rs @@ -8,18 +8,31 @@ use super::channels::{publish_message_to_guest, ChannelCB, ChannelId}; #[repr(C)] pub struct GuestPlugin { + /// A unique name for the given plugin, provided as a non-null C string pub plugin_name: *const c_char, + + /// An optional path to load the guest agent binary. If null, a lookup will be + /// performed to find the binary from the given name. If non-null must be a valid + /// C string. pub guest_binary_path: *const c_char, + + /// A callback for when this guest plugin sends a message to the host pub msg_receive_cb: ChannelCB, } -// returns channel ID +/// Adds a guest plugin to be loaded, returns a channel ID representing the +/// main channel of the to-be-loaded plugin. Writes to this channel ID before plugin +/// load will be queued and will thus be available when the plugin begins reading. #[no_mangle] pub extern "C" fn add_guest_plugin(plugin: GuestPlugin) -> ChannelId { + let path_temp; let name = unsafe { CStr::from_ptr(plugin.plugin_name).to_string_lossy() }; let binary_path = if plugin.guest_binary_path.is_null() { match crate::guest_plugin_path(&name) { - Some(path) => path.to_string_lossy().into_owned(), + Some(path) => { + path_temp = path; + path_temp.to_string_lossy() + } None => panic!( "No guest plugin path was provided but plugin {0:?} \ could not be found, ensure {0:?} has been built.", @@ -27,31 +40,34 @@ pub extern "C" fn add_guest_plugin(plugin: GuestPlugin) -> ChannelId { ), } } else { - unsafe { - CStr::from_ptr(plugin.guest_binary_path) - .to_string_lossy() - .into_owned() - } + unsafe { CStr::from_ptr(plugin.guest_binary_path).to_string_lossy() } }; load_binary(&binary_path); add_channel(Some(&name), plugin.msg_receive_cb) } +/// Writes bytes from a buffer to the given channel ID, queuing them up for the next +/// guest plugin read. The buffer is copied into a new allocation before being added +/// to the queue, so the act of writing has no strict lifetime requirements. #[no_mangle] pub unsafe extern "C" fn channel_write( channel: ChannelId, - out: *mut u8, - out_len: usize, + buf: *const u8, + buf_len: usize, ) { - publish_message_to_guest(channel, from_raw_parts(out, out_len).to_vec()) + publish_message_to_guest(channel, from_raw_parts(buf, buf_len).to_vec()) } +/// Given the name of a plugin or channel, return the associated channel, panicking +/// if a channel of the given name cannot be found. Channel name should be passed +/// as a null-terminated string. +/// +/// The provided string has no lifetime requirements, but must be a non-null pointer +/// to a valid C string. #[no_mangle] pub extern "C" fn get_channel_from_name( channel_name: *const c_char, ) -> ChannelId { - let name = - unsafe { CStr::from_ptr(channel_name).to_string_lossy().into_owned() }; + let name = unsafe { CStr::from_ptr(channel_name).to_string_lossy() }; super::channels::get_channel_from_name(&name).unwrap() } - From a4a71b247934ce053efd5a850ef234e87c70be77 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 12 Jan 2022 14:12:38 -0500 Subject: [PATCH 42/79] Add documentation to linjector --- panda/plugins/linjector/README.md | 100 +++--------------------------- 1 file changed, 8 insertions(+), 92 deletions(-) diff --git a/panda/plugins/linjector/README.md b/panda/plugins/linjector/README.md index 81a52bc976b..421b035b2e9 100644 --- a/panda/plugins/linjector/README.md +++ b/panda/plugins/linjector/README.md @@ -1,95 +1,11 @@ -# Rust Skeleton +# linjector -This is a basic example of how to build a PANDA plugin with Rust. +linjector is a PANDA plugin responsible for non-cooperatively injecting a binary into +a linux guest. This process is done via system call injection, chaining system calls +together in order to run the provided executable. It is not recommended to use this directly, but rather to use `guest_plugin_manager` in order to spawn your executable as a child of the PANDA-provided guest agent (`guest_daemon`). -## Building +### Arguments -To check if the plugin will build: - -``` -cargo check -``` - -To actually build the plugin: - -``` -cargo build --release -``` - -(remove `--release` if you want to build in debug mode) - -The resulting plugin will be located in `target/release/librust_skeleton.so`. - -## Structure - -``` -├── Cargo.toml -├── Makefile -├── README.md -└── src - └── lib.rs -``` - -* Cargo.toml - The core plugin info. This informs `cargo` how to actually go about building the plugin. It includes the name, dependencies, and features of plugins. -* Makefile - Instructions for how the PANDA build system will build the plugin. -* lib.rs - The main source file of your plugin. Additional source files can be referenced from here. - -## Cargo.toml - -The dependencies section: - -```toml -[dependencies] -panda-re = { version = "0.5", default-features = false } -``` - -To add a new dependency, add a new line in the form `name = "version"`. - -For example to add [`libc`](https://docs.rs/libc), simply add the following line: - -```toml -libc = "0.2" -``` - -## Targetting Multiple Architectures - -In PANDA, a plugin is recompiled once per target architecture (that is to say, the architecture of the guest). To enable this behavior in Rust plugins, we use ["features"](https://doc.rust-lang.org/cargo/reference/features.html) in order to specify which architecture we are building for. - -This is controlled by this section of Cargo.toml: - -```toml -[features] -default = ["x86_64"] - -x86_64 = ["panda-re/x86_64"] -i386 = ["panda-re/i386"] -arm = ["panda-re/arm"] -ppc = ["panda-re/ppc"] -mips = ["panda-re/mips"] -mipsel = ["panda-re/mipsel"] -``` - -by default `x86_64` is the only feature enabled (which is why we don't need to specify any features to build), this is primarily so that IDE support (rust-analyzer for VSCode/vim/etc, IntelliJ/CLion integration) works out of the box, as IDEs typically do type checking with the default feature set. - -To build for, say, `arm` you can use the following command: - -``` -cargo build --release --no-default-features --features=arm -``` - -And if you wish to prevent certain code from compiling on certain platforms you can use the following: - -```rust -#[cfg(not(feature = "arm"))] -fn breaks_arm() { - // ... -} -``` - -## Other Resources - -* [panda-rs documentation](https://docs.rs/panda-re) -* [panda-rs announcement blog post](https://panda.re/blog/panda-rs) -* [panda-sys documentation](https://docs.rs/panda-re-sys) -* [The Rust Programming Language](https://doc.rust-lang.org/book/) -* [Some example Rust plugins](https://github.com/panda-re/panda-rs-plugins/) +* `guest_binary` - string, the path of the executable to load into the guest +* `proc_name` - string, the process name to inject into. Defaults to `[any]`. +* `require_root` - bool, whether or not to require the process being injected into to have a UID of root From 6083a6781c4764c685c99bad4a34d7c94542c7ff Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 13 Jan 2022 15:34:21 -0500 Subject: [PATCH 43/79] Add guest agent/linjector injection PPP callbacks --- .../guest_plugin_manager_ppp.h | 11 +++++++++++ .../src/guest_plugin_manager.rs | 17 +++++++++++++++++ panda/plugins/linjector/linjector_ppp.h | 11 +++++++++++ panda/plugins/linjector/src/lib.rs | 8 +++++++- panda/python/core/create_panda_datatypes.py | 6 +++++- 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 panda/plugins/guest_plugin_manager/guest_plugin_manager_ppp.h create mode 100644 panda/plugins/linjector/linjector_ppp.h diff --git a/panda/plugins/guest_plugin_manager/guest_plugin_manager_ppp.h b/panda/plugins/guest_plugin_manager/guest_plugin_manager_ppp.h new file mode 100644 index 00000000000..7f4db0ae3e1 --- /dev/null +++ b/panda/plugins/guest_plugin_manager/guest_plugin_manager_ppp.h @@ -0,0 +1,11 @@ +#ifndef __GUEST_PLUGIN_MANAGER_PPP_H +#define __GUEST_PLUGIN_MANAGER_PPP_H +// BEGIN_PYPANDA_NEEDS_THIS -- do not delete this comment bc pypanda +// api autogen needs it. And don't put any compiler directives +// between this and END_PYPANDA_NEEDS_THIS except includes of other +// files in this directory that contain subsections like this one. + +PPP_CB_TYPEDEF(void,on_guest_agent_load,CPUState *); + +// END_PYPANDA_NEEDS_THIS -- do not delete this comment! +#endif diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index 5f8fc6148dc..a071836ab58 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -1,5 +1,6 @@ use panda::plugins::guest_plugin_manager::guest_plugin_path; use panda::prelude::*; +use panda::PppCallback; use std::convert::TryFrom; @@ -68,6 +69,7 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { if let Some(retval) = retval { set_hyp_ret_reg(cpu, retval); } + true } else { false @@ -80,6 +82,18 @@ struct Linjector { guest_binary: String, } +panda::plugin_import! { + static LINJECTOR: LinjectorApi = extern "linjector" { + callbacks { + fn before_guest_inject(cpu: &mut CPUState); + } + }; +} + +panda::export_ppp_callback! { + pub(crate) fn on_guest_agent_load(cpu: &mut CPUState); +} + #[panda::init] fn init(_: &mut PluginHandle) -> bool { interface::daemon_manager::init(); @@ -96,6 +110,9 @@ fn init(_: &mut PluginHandle) -> bool { panda::require_plugin(&Linjector { guest_binary }); + PppCallback::new() + .before_guest_inject(|cpu| on_guest_agent_load::trigger(cpu)); + true } diff --git a/panda/plugins/linjector/linjector_ppp.h b/panda/plugins/linjector/linjector_ppp.h new file mode 100644 index 00000000000..2a407a8ee0f --- /dev/null +++ b/panda/plugins/linjector/linjector_ppp.h @@ -0,0 +1,11 @@ +#ifndef __LINJECTOR_PPP_H +#define __LINJECTOR_PPP_H +// BEGIN_PYPANDA_NEEDS_THIS -- do not delete this comment bc pypanda +// api autogen needs it. And don't put any compiler directives +// between this and END_PYPANDA_NEEDS_THIS except includes of other +// files in this directory that contain subsections like this one. + +PPP_CB_TYPEDEF(void,before_guest_inject,CPUState *); + +// END_PYPANDA_NEEDS_THIS -- do not delete this comment! +#endif diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 5b58f9822bb..1f122dbb794 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -62,6 +62,10 @@ macro_rules! guest_string { }}; } +panda::export_ppp_callback! { + pub(crate) fn before_guest_inject(cpu: &mut CPUState); +} + #[panda::on_all_sys_enter] fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { // Only check process name when a target process name is provided @@ -188,7 +192,9 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { guest_string!(cpu, "/tmp/payload") }; - // Execute the host binary + before_guest_inject::trigger(cpu); + + // Execute the guest binary log::debug!("Performing execve"); do_execve(guest_path_buf, 0, 0).await; }) diff --git a/panda/python/core/create_panda_datatypes.py b/panda/python/core/create_panda_datatypes.py index 4446a08ba35..ebabc1b7217 100755 --- a/panda/python/core/create_panda_datatypes.py +++ b/panda/python/core/create_panda_datatypes.py @@ -298,6 +298,8 @@ def expand_ppp_def(line): define_clean_header(ffi, include_dir + "/proc_start_linux_ppp.h") define_clean_header(ffi, include_dir + "/forcedexec_ppp.h") define_clean_header(ffi, include_dir + "/stringsearch_ppp.h") + define_clean_header(ffi, include_dir + "/guest_plugin_manager_ppp.h") + define_clean_header(ffi, include_dir + "/linjector_ppp.h") # END PPP headers define_clean_header(ffi, include_dir + "/breakpoints.h") @@ -373,8 +375,10 @@ def main(install=False,recompile=True): # TODO: programtically copy anything that ends with _ppp.h copy_ppp_header("%s/%s" % (PLUGINS_DIR+"/forcedexec", "forcedexec_ppp.h")) copy_ppp_header("%s/%s" % (PLUGINS_DIR+"/stringsearch", "stringsearch_ppp.h")) + copy_ppp_header("%s/%s" % (PLUGINS_DIR+"/guest_plugin_manager", "guest_plugin_manager_ppp.h")) + copy_ppp_header("%s/%s" % (PLUGINS_DIR+"/linjector", "linjector_ppp.h")) create_pypanda_header("%s/%s" % (PLUGINS_DIR+"/hooks2", "hooks2.h")) - + copy_ppp_header("%s/%s" % (PLUGINS_DIR+"/proc_start_linux", "proc_start_linux_ppp.h")) create_pypanda_header("%s/%s" % (PLUGINS_DIR+"/proc_start_linux", "proc_start_linux.h")) copy_ppp_header("%s/taint2/taint2.h" % PLUGINS_DIR) From 59dbdc1a0058588d9301401fcc8dd48f52649280 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 19 Jan 2022 16:58:25 -0500 Subject: [PATCH 44/79] Get mmap working under linjector on i386 --- panda/plugins/linjector/Cargo.lock | 15 +++++++-------- panda/plugins/linjector/Cargo.toml | 3 ++- panda/plugins/linjector/src/lib.rs | 11 ++++++++++- panda/plugins/linjector/src/syscalls/i386.rs | 6 ++++-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index 59c933e3067..b8eacdd0186 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -370,9 +370,8 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.23.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d16235401d62d2809c2fe781bb7dc8ec87bc279986fcf3c64f939bc921eb13d" +version = "0.26.0" +source = "git+https://github.com/panda-re/panda-rs#aa0de9e8a59ef3c09e9b8c72ddc6121228135ec5" dependencies = [ "async-trait", "dashmap", @@ -381,6 +380,7 @@ dependencies = [ "inventory", "lazy_static", "libloading", + "log", "once_cell", "panda-re-macros", "panda-re-sys", @@ -393,12 +393,12 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81c6e3b78cf36e32f50b53a41d2d71b55b5ffee17978aac0c0b61e160f60d9f" +version = "0.16.0" +source = "git+https://github.com/panda-re/panda-rs#aa0de9e8a59ef3c09e9b8c72ddc6121228135ec5" dependencies = [ "darling", "doc-comment", + "proc-macro2", "quote", "syn", ] @@ -406,8 +406,7 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" +source = "git+https://github.com/panda-re/panda-rs#aa0de9e8a59ef3c09e9b8c72ddc6121228135ec5" [[package]] name = "parking_lot" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index da39be272d5..1913d6ee63c 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,7 +8,8 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.23.3", default-features = false, features = ["syscall-injection"] } +#panda-re = { version = "0.23.3", default-features = false, features = ["syscall-injection"] } +panda-re = { git = "https://github.com/panda-re/panda-rs", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 1f122dbb794..b16450b8d8f 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -100,7 +100,16 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { } } - log::debug!("In injector"); + //log::debug!("In injector"); + //use panda::regs; + //let sp_before = regs::get_reg(cpu, regs::reg_sp()); + //dbg!(sp_before); + //log::debug!("pid = {}", getpid().await); + //let sp_after = regs::get_reg(cpu, regs::reg_sp()); + //dbg!(sp_after); + //log::debug!("actual pid = {}", OSI.get_current_process(cpu).pid); + //log::debug!("pid = {}", getpid().await); + //log::debug!("pid = {}", getpid().await); log::debug!("current asid: {:x}", current_asid(cpu)); // mmap a region so we have a buffer in the guest to use diff --git a/panda/plugins/linjector/src/syscalls/i386.rs b/panda/plugins/linjector/src/syscalls/i386.rs index 8b229cc469c..b23b080db5b 100644 --- a/panda/plugins/linjector/src/syscalls/i386.rs +++ b/panda/plugins/linjector/src/syscalls/i386.rs @@ -1,7 +1,7 @@ use panda::prelude::*; pub(crate) const GETPID: target_ulong = 20; -pub(crate) const MMAP: target_ulong = 90; +pub(crate) const MMAP: target_ulong = 192; pub(crate) const WRITE: target_ulong = 4; pub(crate) const EXECVE: target_ulong = 11; pub(crate) const MEMFD_CREATE: target_ulong = 356; @@ -13,5 +13,7 @@ pub(crate) const CLOSE: target_ulong = 6; pub(crate) const PROT_READ: target_ulong = 1; pub(crate) const PROT_WRITE: target_ulong = 2; -pub(crate) const MAP_SHARED: target_ulong = 0x1; +//pub(crate) const MAP_SHARED: target_ulong = 0x1; +//pub(crate) const MAP_ANON: target_ulong = 0x20; +pub(crate) const MAP_SHARED: target_ulong = 0x2; pub(crate) const MAP_ANON: target_ulong = 0x20; From 8b15e28ad47e513193c9de22166c19c3a07f54b3 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 11 Feb 2022 16:14:49 -0500 Subject: [PATCH 45/79] Add guest agent frida support --- panda/plugins/config.panda | 3 +- panda/plugins/frida/Cargo.lock | 608 ++++++++++++++++++ panda/plugins/frida/Cargo.toml | 25 + panda/plugins/frida/Makefile | 18 + panda/plugins/frida/README.md | 6 + panda/plugins/frida/src/lib.rs | 33 + .../src/guest_plugin_manager.rs | 13 +- panda/plugins/linjector/Cargo.lock | 3 - panda/plugins/linjector/src/lib.rs | 48 +- panda/plugins/linjector/src/syscalls/i386.rs | 6 +- .../syscall_switch_return_linux_arm.cpp | 3 +- panda/plugins/syscalls2/syscalls2.cpp | 1 + 12 files changed, 742 insertions(+), 25 deletions(-) create mode 100644 panda/plugins/frida/Cargo.lock create mode 100644 panda/plugins/frida/Cargo.toml create mode 100644 panda/plugins/frida/Makefile create mode 100644 panda/plugins/frida/README.md create mode 100644 panda/plugins/frida/src/lib.rs diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index 2de2e9f757a..5ff943f2c2f 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -12,6 +12,7 @@ dynamic_symbols edge_coverage filereadmon forcedexec +frida gdb guest_plugin_example guest_plugin_manager @@ -31,7 +32,7 @@ mmio_trace net network osi -osi_linux +#osi_linux osi_test pri pri_dwarf diff --git a/panda/plugins/frida/Cargo.lock b/panda/plugins/frida/Cargo.lock new file mode 100644 index 00000000000..5bb3343b3ba --- /dev/null +++ b/panda/plugins/frida/Cargo.lock @@ -0,0 +1,608 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ctor" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "frida" +version = "0.1.0" +dependencies = [ + "log", + "panda-re", + "parking_lot", + "pretty_env_logger", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "inventory" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb5160c60ba1e809707918ee329adb99d222888155835c6feedba19f6c3fd4" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e41b53715c6f0c4be49510bb82dee2c1e51c8586d885abe65396e82ed518548" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "panda-re" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfc5b9d238b9f1d4785346b7d611dcc4236f615334e0719afbf3033f8c26e0e" +dependencies = [ + "dirs", + "glib-sys", + "inventory", + "lazy_static", + "libloading", + "once_cell", + "panda-re-macros", + "panda-re-sys", + "paste", + "strum 0.20.0", + "strum_macros 0.20.1", + "thiserror", +] + +[[package]] +name = "panda-re-macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be1d7a86fc7fc5c32ca9d7b430e5f12f76b664f381c4213c7071d14e88fc588" +dependencies = [ + "darling", + "doc-comment", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "panda-re-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger", + "log", +] + +[[package]] +name = "proc-macro2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "strum" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" + +[[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" + +[[package]] +name = "strum_macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" +dependencies = [ + "heck", + "pkg-config", + "strum 0.18.0", + "strum_macros 0.18.0", + "thiserror", + "toml", + "version-compare", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/plugins/frida/Cargo.toml b/panda/plugins/frida/Cargo.toml new file mode 100644 index 00000000000..3706da5502b --- /dev/null +++ b/panda/plugins/frida/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "frida" +version = "0.1.0" +authors = ["Jordan McLeod "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +panda-re = { version = "0.26", default-features = false } +parking_lot = "0.11" +log = "0.4" +pretty_env_logger = "0.4" + +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +aarch64 = ["panda-re/aarch64"] diff --git a/panda/plugins/frida/Makefile b/panda/plugins/frida/Makefile new file mode 100644 index 00000000000..2234476df57 --- /dev/null +++ b/panda/plugins/frida/Makefile @@ -0,0 +1,18 @@ +# Don't forget to add your plugin to config.panda! + +# Build rust plugins with make! + +# The main rule for your plugin. List all object-file dependencies. + +PANDA_PATH = $(realpath $(shell pwd)/..) +PLUGIN_DIR = $(realpath $(join $(PANDA_PATH), /../panda/plugins/$(PLUGIN_NAME)/)) +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so : $(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + @echo " CARGO $(PLUGIN_DIR)" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --no-default-features --features=$(TARGET_NAME) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @cp -p $(PLUGIN_ARTIFACTS_DIR)/release/lib$(PLUGIN_NAME).so $@ diff --git a/panda/plugins/frida/README.md b/panda/plugins/frida/README.md new file mode 100644 index 00000000000..cbd6557ee87 --- /dev/null +++ b/panda/plugins/frida/README.md @@ -0,0 +1,6 @@ +# Guest Plugin Example + +This is a basic example of how to build a PANDA plugin for communicating with a guest +plugin using Rust. + +See [`guest_plugins/rust_example`](/panda/guest_plugins/rust_example) for the corresponding guest plugin. diff --git a/panda/plugins/frida/src/lib.rs b/panda/plugins/frida/src/lib.rs new file mode 100644 index 00000000000..a721f07e8ec --- /dev/null +++ b/panda/plugins/frida/src/lib.rs @@ -0,0 +1,33 @@ +use panda::{plugins::guest_plugin_manager::*, prelude::*}; +use parking_lot::{const_mutex, Mutex}; +use std::io::Write; +use std::net::{TcpListener, TcpStream}; + +#[channel_recv] +fn message_recv(_: u32, data: &[u8]) { + if let Some(socket) = SOCKET.lock().as_mut() { + socket.write_all(data).unwrap(); + } +} + +static SOCKET: Mutex> = const_mutex(None); + +#[panda::init] +fn init(_: &mut PluginHandle) { + pretty_env_logger::init_custom_env("FRIDA_LOG"); + let mut channel = load_guest_plugin("frida_server", message_recv); + + std::thread::spawn(move || { + let server = TcpListener::bind("localhost:27042").unwrap(); + + for socket in server.incoming() { + let mut socket = socket.unwrap(); + log::debug!("Socket connected"); + SOCKET.lock().replace(socket.try_clone().unwrap()); + log::debug!("Forwarding socket..."); + std::io::copy(&mut socket, &mut channel).unwrap(); + log::debug!("Socket disconnected"); + SOCKET.lock().take(); + } + }); +} diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index a071836ab58..f798394c052 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -80,6 +80,7 @@ fn hypercall_handler(cpu: &mut CPUState) -> bool { #[name = "linjector"] struct Linjector { guest_binary: String, + proc_name: String, } panda::plugin_import! { @@ -108,10 +109,16 @@ fn init(_: &mut PluginHandle) -> bool { "Guest plugin manager currently only supports Linux" ); - panda::require_plugin(&Linjector { guest_binary }); + std::thread::spawn(|| { + // TODO: automatically decide which process to inject into + panda::require_plugin(&Linjector { + guest_binary, + proc_name: "cat".to_string(), + }); - PppCallback::new() - .before_guest_inject(|cpu| on_guest_agent_load::trigger(cpu)); + PppCallback::new() + .before_guest_inject(|cpu| on_guest_agent_load::trigger(cpu)); + }); true } diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index b8eacdd0186..f6009cd5569 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -371,7 +371,6 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" version = "0.26.0" -source = "git+https://github.com/panda-re/panda-rs#aa0de9e8a59ef3c09e9b8c72ddc6121228135ec5" dependencies = [ "async-trait", "dashmap", @@ -394,7 +393,6 @@ dependencies = [ [[package]] name = "panda-re-macros" version = "0.16.0" -source = "git+https://github.com/panda-re/panda-rs#aa0de9e8a59ef3c09e9b8c72ddc6121228135ec5" dependencies = [ "darling", "doc-comment", @@ -406,7 +404,6 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" -source = "git+https://github.com/panda-re/panda-rs#aa0de9e8a59ef3c09e9b8c72ddc6121228135ec5" [[package]] name = "parking_lot" diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index b16450b8d8f..e1bb35410df 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -100,23 +100,18 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { } } - //log::debug!("In injector"); - //use panda::regs; - //let sp_before = regs::get_reg(cpu, regs::reg_sp()); - //dbg!(sp_before); - //log::debug!("pid = {}", getpid().await); - //let sp_after = regs::get_reg(cpu, regs::reg_sp()); - //dbg!(sp_after); - //log::debug!("actual pid = {}", OSI.get_current_process(cpu).pid); - //log::debug!("pid = {}", getpid().await); - //log::debug!("pid = {}", getpid().await); log::debug!("current asid: {:x}", current_asid(cpu)); // mmap a region so we have a buffer in the guest to use let guest_buf = get_guest_buffer().await; // Create a memory file descriptor for loading our binary into - let mem_fd = do_memfd_create(guest_buf).await; + let mem_fd = loop { + match do_memfd_create(guest_buf).await { + 0 => log::trace!("Got memfd of 0, retrying..."), + fd => break fd, + } + }; log::debug!("Got memory fd {:#x}", mem_fd); let (fd, is_mem_fd) = if (mem_fd as target_long).is_negative() { @@ -164,6 +159,14 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { &file_data[elf_write_pos..end_write], ); + #[cfg(feature = "i386")] + { + let ebp = panda::regs::get_reg(cpu, panda::regs::Reg::EBP); + let esp = panda::regs::get_reg(cpu, panda::regs::Reg::ESP); + log::trace!("EBP: {:#08x?} | ESP: {:#08x?}", ebp, esp); + panda::mem::virt_memory_dump(cpu, esp, 0x10); + } + // Write guest buffer to memory file descriptor let written = do_write(fd, guest_buf, PAGE_SIZE).await; @@ -176,7 +179,6 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { } log::debug!("Finished writing to memfd"); - log::debug!("Forking..."); if !is_mem_fd { let close_ret = close(fd).await; @@ -185,9 +187,17 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { } } + log::debug!("Forking..."); + // Fork and have the child process spawn the injected elf - fork(async move { + let child_pid = fork(async move { log::debug!("Child process began"); + log::debug!( + "Child process pid: {:#x?}, Child's parent: {:#x?}", + OSI.get_current_process(cpu).pid, + OSI.get_current_process(cpu).ppid, + ); + log::debug!("Child asid: {:#x?}", panda::current_asid(cpu)); // Daemonize child process let session_id = setsid().await; @@ -205,10 +215,20 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { // Execute the guest binary log::debug!("Performing execve"); - do_execve(guest_path_buf, 0, 0).await; + dbg!(do_execve(guest_path_buf, 0, 0).await); + panic!(); }) .await; + log::debug!("Fork returned pid: {:#x?}", child_pid); + let cpu = unsafe { &mut *get_cpu() }; + log::debug!( + "Parent process pid: {:#x?}, Parent's parent: {:#x?}", + OSI.get_current_process(cpu).pid, + OSI.get_current_process(cpu).ppid, + ); + log::debug!("Parent asid: {:#x?}", panda::current_asid(cpu)); + // Allow the original process to resume executing }); diff --git a/panda/plugins/linjector/src/syscalls/i386.rs b/panda/plugins/linjector/src/syscalls/i386.rs index b23b080db5b..bbb840bf76e 100644 --- a/panda/plugins/linjector/src/syscalls/i386.rs +++ b/panda/plugins/linjector/src/syscalls/i386.rs @@ -13,7 +13,7 @@ pub(crate) const CLOSE: target_ulong = 6; pub(crate) const PROT_READ: target_ulong = 1; pub(crate) const PROT_WRITE: target_ulong = 2; -//pub(crate) const MAP_SHARED: target_ulong = 0x1; -//pub(crate) const MAP_ANON: target_ulong = 0x20; -pub(crate) const MAP_SHARED: target_ulong = 0x2; +pub(crate) const MAP_SHARED: target_ulong = 0x1; pub(crate) const MAP_ANON: target_ulong = 0x20; +//pub(crate) const MAP_SHARED: target_ulong = 0x2; +//pub(crate) const MAP_ANON: target_ulong = 0x20; diff --git a/panda/plugins/syscalls2/generated/syscall_switch_return_linux_arm.cpp b/panda/plugins/syscalls2/generated/syscall_switch_return_linux_arm.cpp index 3a68fa3f9ac..6ebafcc2493 100644 --- a/panda/plugins/syscalls2/generated/syscall_switch_return_linux_arm.cpp +++ b/panda/plugins/syscalls2/generated/syscall_switch_return_linux_arm.cpp @@ -42,6 +42,7 @@ void syscall_return_switch_linux_arm(CPUState *cpu, target_ptr_t pc, const sysca case 2: { if (PPP_CHECK_CB(on_sys_fork_return) || PPP_CHECK_CB(on_all_sys_return2)) { } + printf("fork return\n"); PPP_RUN_CB(on_sys_fork_return, cpu, pc) ; }; break; // 3 long sys_read ['unsigned int fd', 'char __user *buf', 'size_t count'] @@ -4032,4 +4033,4 @@ void syscall_return_switch_linux_arm(CPUState *cpu, target_ptr_t pc, const sysca #endif } -/* vim: set tabstop=4 softtabstop=4 noexpandtab ft=cpp: */ \ No newline at end of file +/* vim: set tabstop=4 softtabstop=4 noexpandtab ft=cpp: */ diff --git a/panda/plugins/syscalls2/syscalls2.cpp b/panda/plugins/syscalls2/syscalls2.cpp index 81836b87da6..152d797750c 100644 --- a/panda/plugins/syscalls2/syscalls2.cpp +++ b/panda/plugins/syscalls2/syscalls2.cpp @@ -381,6 +381,7 @@ target_ulong calc_retaddr_linux_x86(CPUState* cpu, target_ulong pc) { target_ulong ret = 0x0; target_ulong ret_ptr = ((CPUX86State *)cpu->env_ptr)->regs[R_ESP] + 0x0C; + printf("esp: %08x\n", ((CPUX86State *)cpu->env_ptr)->regs[R_ESP]); panda_virtual_memory_read(cpu, ret_ptr, (uint8_t *)&ret, sizeof(ret)); assert(ret != 0x0); return ret; From 7616c10cd7c8f8e91b282b57c2101bc5ccfb60cb Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 11 Feb 2022 17:48:11 -0500 Subject: [PATCH 46/79] Add ability to manually specify which process to inject the guest agent into --- .../src/guest_plugin_manager.rs | 21 +++++++++++++++++- panda/plugins/linjector/Cargo.lock | 10 +++++++-- panda/plugins/linjector/Cargo.toml | 3 +-- panda/plugins/linjector/src/lib.rs | 22 ++++++++++++++----- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index f798394c052..f310d0f1837 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -3,6 +3,7 @@ use panda::prelude::*; use panda::PppCallback; use std::convert::TryFrom; +use std::sync::atomic::{AtomicBool, Ordering}; mod hyp_regs; use hyp_regs::{get_hyp_reg, set_hyp_ret_reg}; @@ -83,6 +84,13 @@ struct Linjector { proc_name: String, } +#[derive(PandaArgs)] +#[name = "guest_plugin_manager"] +struct Args { + #[arg(default = "cat")] + proc_name: String, +} + panda::plugin_import! { static LINJECTOR: LinjectorApi = extern "linjector" { callbacks { @@ -95,8 +103,19 @@ panda::export_ppp_callback! { pub(crate) fn on_guest_agent_load(cpu: &mut CPUState); } +lazy_static::lazy_static! { + static ref ARGS: Args = Args::from_panda_args(); +} + +static LOADED: AtomicBool = AtomicBool::new(false); + #[panda::init] fn init(_: &mut PluginHandle) -> bool { + if LOADED.swap(true, Ordering::SeqCst) { + return true; + } + + lazy_static::initialize(&ARGS); interface::daemon_manager::init(); let guest_binary = guest_plugin_path("guest_daemon") @@ -113,7 +132,7 @@ fn init(_: &mut PluginHandle) -> bool { // TODO: automatically decide which process to inject into panda::require_plugin(&Linjector { guest_binary, - proc_name: "cat".to_string(), + proc_name: ARGS.proc_name.clone(), }); PppCallback::new() diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index f6009cd5569..fd1931a756e 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -370,7 +370,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.26.0" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68395bf0c407fd5cd77e2fc726d99f1834c0c2518ec67e0119f1b5355fa57306" dependencies = [ "async-trait", "dashmap", @@ -392,7 +394,9 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.16.0" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f911983e92df86c86f314ac54719798a091b06d64f528a0834c73da75ac6439f" dependencies = [ "darling", "doc-comment", @@ -404,6 +408,8 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index 1913d6ee63c..ec3a56cfeef 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,8 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -#panda-re = { version = "0.23.3", default-features = false, features = ["syscall-injection"] } -panda-re = { git = "https://github.com/panda-re/panda-rs", default-features = false, features = ["syscall-injection"] } +panda-re = { version = "0.27.0", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index e1bb35410df..e2d298248bc 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -9,6 +9,8 @@ use panda::{ syscall_injection::{fork, run_injector}, }; +use std::sync::atomic::{AtomicBool, Ordering}; + mod args; mod syscalls; @@ -66,8 +68,11 @@ panda::export_ppp_callback! { pub(crate) fn before_guest_inject(cpu: &mut CPUState); } -#[panda::on_all_sys_enter] -fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { +extern "C" fn on_sys_enter( + cpu: &mut CPUState, + pc: SyscallPc, + syscall_num: target_ulong, +) { // Only check process name when a target process name is provided if args::proc_name() != "[any]" { let proc_name = current_process_name(cpu); @@ -81,6 +86,9 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { } } + // Once we inject to a process stop looking for syscalls to inject into + SYSCALLS.remove_callback_on_all_sys_enter(on_sys_enter); + log::trace!("Attempting injection into syscall {}", syscall_num); let file_data = args::elf_to_inject(); @@ -231,14 +239,18 @@ fn on_sys_enter(cpu: &mut CPUState, pc: SyscallPc, syscall_num: target_ulong) { // Allow the original process to resume executing }); - - // Once we inject to a process stop looking for syscalls to inject into - SYSCALLS.remove_callback_on_all_sys_enter(on_sys_enter); } +static LOADED: AtomicBool = AtomicBool::new(false); + #[panda::init] fn init(_: &mut PluginHandle) -> bool { + if LOADED.swap(true, Ordering::SeqCst) { + return true; + } + args::ensure_init(); + SYSCALLS.add_callback_on_all_sys_enter(on_sys_enter); pretty_env_logger::init_custom_env("LINJECTOR_LOG"); args::load_elf(); From 5d43ddd56100da90af584b766bec8c0bbe1a1389 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 25 Feb 2022 11:45:07 -0500 Subject: [PATCH 47/79] Specify arm cross compiler linker --- panda/guest_plugins/panda.mak | 2 ++ 1 file changed, 2 insertions(+) diff --git a/panda/guest_plugins/panda.mak b/panda/guest_plugins/panda.mak index 01ccf71987b..f4e83dec112 100644 --- a/panda/guest_plugins/panda.mak +++ b/panda/guest_plugins/panda.mak @@ -12,6 +12,8 @@ PLUGIN_TARGET_DIR=panda/guest_plugins PLUGIN_BIN_DIR=$(PLUGIN_TARGET_DIR)/bin PLUGIN_OUT_PATH=$(PLUGIN_BIN_DIR)/$(PLUGIN_NAME) +CARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABI_LINKER="arm-linux-musleabi-cc" + BUILD_TARGET=$(addprefix build-,$(TARGET_NAME)) all: $(BUILD_TARGET) From e222e17b3a34318eb5b900d10a421b03c261da6c Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 18 Mar 2022 17:14:55 -0400 Subject: [PATCH 48/79] Add i386 support to linjector --- panda/guest_plugins/panda.mak | 2 +- panda/guest_plugins/rust_example/Cargo.lock | 4 ++-- panda/guest_plugins/rust_example/Cargo.toml | 2 +- panda/plugins/linjector/Cargo.lock | 17 +++++++++-------- panda/plugins/linjector/Cargo.toml | 2 +- panda/plugins/linjector/src/lib.rs | 8 -------- panda/plugins/syscalls2/syscalls2.cpp | 1 - 7 files changed, 14 insertions(+), 22 deletions(-) diff --git a/panda/guest_plugins/panda.mak b/panda/guest_plugins/panda.mak index f4e83dec112..a46065559a8 100644 --- a/panda/guest_plugins/panda.mak +++ b/panda/guest_plugins/panda.mak @@ -12,7 +12,7 @@ PLUGIN_TARGET_DIR=panda/guest_plugins PLUGIN_BIN_DIR=$(PLUGIN_TARGET_DIR)/bin PLUGIN_OUT_PATH=$(PLUGIN_BIN_DIR)/$(PLUGIN_NAME) -CARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABI_LINKER="arm-linux-musleabi-cc" +CARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABI_LINKER ?= "arm-linux-musleabi-cc" BUILD_TARGET=$(addprefix build-,$(TARGET_NAME)) diff --git a/panda/guest_plugins/rust_example/Cargo.lock b/panda/guest_plugins/rust_example/Cargo.lock index 820d766a6a2..568faf6b7d8 100644 --- a/panda/guest_plugins/rust_example/Cargo.lock +++ b/panda/guest_plugins/rust_example/Cargo.lock @@ -46,9 +46,9 @@ dependencies = [ [[package]] name = "panda-channels" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f15dafa90983e93ae0579858b2eb73443f6d51cca28d5bdf4e3a28ce7621df" +checksum = "a94b07d8bcc852032a8deb91be9d2bbd59421d776a9edb42fc74b40816e7d940" dependencies = [ "lazy_static", "parking_lot", diff --git a/panda/guest_plugins/rust_example/Cargo.toml b/panda/guest_plugins/rust_example/Cargo.toml index 5d5508b3c08..c4467703851 100644 --- a/panda/guest_plugins/rust_example/Cargo.toml +++ b/panda/guest_plugins/rust_example/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -panda-channels = "0.1" +panda-channels = "0.2" diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index fd1931a756e..b338f3e6a37 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -17,6 +17,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "array-init" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6945cc5422176fc5e602e590c2878d2c2acd9a4fe20a4baa7c28022521698ec6" + [[package]] name = "async-trait" version = "0.1.51" @@ -370,10 +376,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68395bf0c407fd5cd77e2fc726d99f1834c0c2518ec67e0119f1b5355fa57306" +version = "0.32.0" dependencies = [ + "array-init", "async-trait", "dashmap", "dirs", @@ -394,9 +399,7 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f911983e92df86c86f314ac54719798a091b06d64f528a0834c73da75ac6439f" +version = "0.21.0" dependencies = [ "darling", "doc-comment", @@ -408,8 +411,6 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index ec3a56cfeef..1901f28cc85 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.27.0", default-features = false, features = ["syscall-injection"] } +panda-re = { version = "0.33.0", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index e2d298248bc..a83c703bbbe 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -167,14 +167,6 @@ extern "C" fn on_sys_enter( &file_data[elf_write_pos..end_write], ); - #[cfg(feature = "i386")] - { - let ebp = panda::regs::get_reg(cpu, panda::regs::Reg::EBP); - let esp = panda::regs::get_reg(cpu, panda::regs::Reg::ESP); - log::trace!("EBP: {:#08x?} | ESP: {:#08x?}", ebp, esp); - panda::mem::virt_memory_dump(cpu, esp, 0x10); - } - // Write guest buffer to memory file descriptor let written = do_write(fd, guest_buf, PAGE_SIZE).await; diff --git a/panda/plugins/syscalls2/syscalls2.cpp b/panda/plugins/syscalls2/syscalls2.cpp index 152d797750c..81836b87da6 100644 --- a/panda/plugins/syscalls2/syscalls2.cpp +++ b/panda/plugins/syscalls2/syscalls2.cpp @@ -381,7 +381,6 @@ target_ulong calc_retaddr_linux_x86(CPUState* cpu, target_ulong pc) { target_ulong ret = 0x0; target_ulong ret_ptr = ((CPUX86State *)cpu->env_ptr)->regs[R_ESP] + 0x0C; - printf("esp: %08x\n", ((CPUX86State *)cpu->env_ptr)->regs[R_ESP]); panda_virtual_memory_read(cpu, ret_ptr, (uint8_t *)&ret, sizeof(ret)); assert(ret != 0x0); return ret; From dde1bdca3371bec701e4fc3e6818000c9c4e6acf Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 21 Mar 2022 13:10:32 -0400 Subject: [PATCH 49/79] Set arm guest plugins to build as armv5te --- panda/guest_plugins/panda.mak | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/panda/guest_plugins/panda.mak b/panda/guest_plugins/panda.mak index a46065559a8..d7df87caaab 100644 --- a/panda/guest_plugins/panda.mak +++ b/panda/guest_plugins/panda.mak @@ -12,7 +12,8 @@ PLUGIN_TARGET_DIR=panda/guest_plugins PLUGIN_BIN_DIR=$(PLUGIN_TARGET_DIR)/bin PLUGIN_OUT_PATH=$(PLUGIN_BIN_DIR)/$(PLUGIN_NAME) -CARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABI_LINKER ?= "arm-linux-musleabi-cc" +CARGO_TARGET_ARMV5TE_UNKNOWN_LINUX_MUSLEABI_LINKER ?= "arm-linux-musleabi-cc" +CARGO_TARGET_ARMV5TE_UNKNOWN_LINUX_MUSLEABI_RUSTFLAGS = "-C target-cpu=arm926ej-s" BUILD_TARGET=$(addprefix build-,$(TARGET_NAME)) @@ -24,7 +25,7 @@ build-x86_64: $(PLUGIN_OUT_PATH) build-i386: TARGET_TRIPLE=i686-unknown-linux-musl build-i386: $(PLUGIN_OUT_PATH) -build-arm: TARGET_TRIPLE=arm-unknown-linux-musleabi +build-arm: TARGET_TRIPLE=armv5te-unknown-linux-musleabi build-arm: $(PLUGIN_OUT_PATH) build-aarch64: TARGET_TRIPLE=aarch64-unknown-linux-musl From ba520ad09c7ad44e09c70f98de1615f97f7f47e5 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 5 May 2022 15:35:31 -0400 Subject: [PATCH 50/79] Add anonymous guest agent channel API --- panda/plugins/guest_plugin_manager/src/interface/api.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/panda/plugins/guest_plugin_manager/src/interface/api.rs b/panda/plugins/guest_plugin_manager/src/interface/api.rs index b11e8680405..69988ec855e 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/api.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/api.rs @@ -46,6 +46,13 @@ pub extern "C" fn add_guest_plugin(plugin: GuestPlugin) -> ChannelId { add_channel(Some(&name), plugin.msg_receive_cb) } +/// Create a new anonymous channel provided a callback for writes performed by the guest, +/// returning the channel ID. +#[no_mangle] +pub unsafe extern "C" fn allocate_channel(callback: ChannelCB) -> ChannelId { + add_channel(None, callback) +} + /// Writes bytes from a buffer to the given channel ID, queuing them up for the next /// guest plugin read. The buffer is copied into a new allocation before being added /// to the queue, so the act of writing has no strict lifetime requirements. From bead5f09302438197c9b9e27cd5f6d96ba035885 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 20 May 2022 14:00:04 -0400 Subject: [PATCH 51/79] Add TCP passthrough plugin --- panda/plugins/config.panda | 5 +- .../guest_plugin_manager/src/interface/hci.rs | 4 +- panda/plugins/linjector/Cargo.lock | 8 +- panda/plugins/print_tcp_servers/Cargo.lock | 722 ++++ panda/plugins/print_tcp_servers/Cargo.toml | 31 + panda/plugins/print_tcp_servers/Makefile | 18 + panda/plugins/print_tcp_servers/README.md | 5 + .../plugins/print_tcp_servers/src/display.rs | 70 + .../print_tcp_servers/src/forward_socket.rs | 65 + panda/plugins/print_tcp_servers/src/lib.rs | 69 + .../plugins/print_tcp_servers/src/send_ext.rs | 12 + .../print_tcp_servers/src/socket_list.rs | 51 + panda/plugins/print_tcp_servers/src/tcp.csv | 3266 +++++++++++++++++ .../tcp_shared_types/Cargo.lock | 65 + .../tcp_shared_types/Cargo.toml | 7 + .../tcp_shared_types/src/lib.rs | 29 + panda/plugins/print_tcp_servers/try_it.py | 25 + panda/plugins/snake_hook/Cargo.lock | 8 +- 18 files changed, 4452 insertions(+), 8 deletions(-) create mode 100644 panda/plugins/print_tcp_servers/Cargo.lock create mode 100644 panda/plugins/print_tcp_servers/Cargo.toml create mode 100644 panda/plugins/print_tcp_servers/Makefile create mode 100644 panda/plugins/print_tcp_servers/README.md create mode 100644 panda/plugins/print_tcp_servers/src/display.rs create mode 100644 panda/plugins/print_tcp_servers/src/forward_socket.rs create mode 100644 panda/plugins/print_tcp_servers/src/lib.rs create mode 100644 panda/plugins/print_tcp_servers/src/send_ext.rs create mode 100644 panda/plugins/print_tcp_servers/src/socket_list.rs create mode 100644 panda/plugins/print_tcp_servers/src/tcp.csv create mode 100644 panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.lock create mode 100644 panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.toml create mode 100644 panda/plugins/print_tcp_servers/tcp_shared_types/src/lib.rs create mode 100644 panda/plugins/print_tcp_servers/try_it.py diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index 5ff943f2c2f..1704f016b38 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -32,11 +32,12 @@ mmio_trace net network osi -#osi_linux +osi_linux osi_test pri pri_dwarf pri_simple +print_tcp_servers proc_start_linux proc_trace recctrl @@ -53,6 +54,6 @@ trace track_intexc unigrams win2000x86intro -#win7x86intro +win7x86intro wintrospection winxpx86intro diff --git a/panda/plugins/guest_plugin_manager/src/interface/hci.rs b/panda/plugins/guest_plugin_manager/src/interface/hci.rs index b7734afe915..bcd394cffff 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/hci.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/hci.rs @@ -52,8 +52,10 @@ pub fn hyp_write( if let Ok(buf_out) = virtual_memory_read(cpu, buf_ptr as target_ulong, buf_size) { + let bytes_read = buf_out.len(); publish_message_from_guest(channel_id, buf_out); - Some(0) + + Some(bytes_read) } else { println!("Failed to read virtual memory in hyp_write"); None diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index b338f3e6a37..27eb628998f 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -376,7 +376,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.32.0" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056bd47b4532e1e2c06492ad6b7ee1ecd253a744e8018844e68a0b654ea80b6f" dependencies = [ "array-init", "async-trait", @@ -400,6 +402,8 @@ dependencies = [ [[package]] name = "panda-re-macros" version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29772398be20723c90088ae4380d62e25cefe54c174d9082532b258985e41d04" dependencies = [ "darling", "doc-comment", @@ -411,6 +415,8 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/print_tcp_servers/Cargo.lock b/panda/plugins/print_tcp_servers/Cargo.lock new file mode 100644 index 00000000000..5614c3e3add --- /dev/null +++ b/panda/plugins/print_tcp_servers/Cargo.lock @@ -0,0 +1,722 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ansi-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcb2392079bf27198570d6af79ecbd9ec7d8f16d3ec6b60933922fdb66287127" +dependencies = [ + "heapless", + "nom", +] + +[[package]] +name = "ansi-str" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90cb0ceb8c444d026166795e474e9dfe54b443bdc07cc21bd6c5073f5e637482" +dependencies = [ + "ansi-parser", +] + +[[package]] +name = "array-init" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6945cc5422176fc5e602e590c2878d2c2acd9a4fe20a4baa7c28022521698ec6" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.5", + "stable_deref_trait", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ctor" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dashmap" +version = "5.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391b56fbd302e585b7a9494fb70e40949567b1cf9003a8e4a6041a1687c26573" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check 0.9.4", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "hash32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" + +[[package]] +name = "heapless" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74911a68a1658cfcfb61bc0ccfbd536e3b6e906f8c2f7883ee50157e3e2184f1" +dependencies = [ + "as-slice", + "generic-array 0.13.3", + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "inventory" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb5160c60ba1e809707918ee329adb99d222888155835c6feedba19f6c3fd4" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e41b53715c6f0c4be49510bb82dee2c1e51c8586d885abe65396e82ed518548" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +dependencies = [ + "memchr", + "version_check 0.1.5", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "owo-colors" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" + +[[package]] +name = "panda-re" +version = "0.33.0" +dependencies = [ + "array-init", + "dirs", + "glib-sys", + "inventory", + "lazy_static", + "libloading", + "once_cell", + "panda-re-macros", + "panda-re-sys", + "paste", + "strum 0.20.0", + "strum_macros 0.20.1", + "thiserror", +] + +[[package]] +name = "panda-re-macros" +version = "0.21.0" +dependencies = [ + "darling", + "doc-comment", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "panda-re-sys" +version = "0.7.0" + +[[package]] +name = "papergrid" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63709d10e2c2ec58f7bd91d8258d27ce80de090064b0ddf3a4bf38b907b61b8a" +dependencies = [ + "strip-ansi-escapes", + "unicode-width", +] + +[[package]] +name = "paste" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "print_tcp_servers" +version = "0.1.0" +dependencies = [ + "bincode", + "dashmap", + "once_cell", + "owo-colors", + "panda-re", + "serde", + "tabled", + "tcp_shared_types", +] + +[[package]] +name = "proc-macro2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strip-ansi-escapes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8" +dependencies = [ + "vte", +] + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "strum" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" + +[[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" + +[[package]] +name = "strum_macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" +dependencies = [ + "heck", + "pkg-config", + "strum 0.18.0", + "strum_macros 0.18.0", + "thiserror", + "toml", + "version-compare", +] + +[[package]] +name = "tabled" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15827061abcf689257b1841c8e2732b1dfcc3ef825b24ce6c606e1e9e1a7bde" +dependencies = [ + "ansi-str", + "papergrid", + "tabled_derive", +] + +[[package]] +name = "tabled_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278ea3921cee8c5a69e0542998a089f7a14fa43c9c4e4f9951295da89bd0c943" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tcp_shared_types" +version = "0.1.0" +dependencies = [ + "serde", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "utf8parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vte" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983" +dependencies = [ + "arrayvec", + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/plugins/print_tcp_servers/Cargo.toml b/panda/plugins/print_tcp_servers/Cargo.toml new file mode 100644 index 00000000000..a1f89c398ac --- /dev/null +++ b/panda/plugins/print_tcp_servers/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "print_tcp_servers" +version = "0.1.0" +authors = ["Jordan McLeod "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +#panda-re = { version = "0.26", default-features = false } +panda-re = { path = "../../../../panda-rs/panda-rs", default-features = false } +bincode = "1" +serde = { version = "1", features = ["derive"] } +tabled = { version = "0.6", features = ["color"] } +once_cell = "1" +owo-colors = "3" +dashmap = "5" + +tcp_shared_types = { path = "./tcp_shared_types" } + +[features] +default = ["x86_64"] + +x86_64 = ["panda-re/x86_64"] +i386 = ["panda-re/i386"] +arm = ["panda-re/arm"] +ppc = ["panda-re/ppc"] +mips = ["panda-re/mips"] +mipsel = ["panda-re/mipsel"] +aarch64 = ["panda-re/aarch64"] diff --git a/panda/plugins/print_tcp_servers/Makefile b/panda/plugins/print_tcp_servers/Makefile new file mode 100644 index 00000000000..2234476df57 --- /dev/null +++ b/panda/plugins/print_tcp_servers/Makefile @@ -0,0 +1,18 @@ +# Don't forget to add your plugin to config.panda! + +# Build rust plugins with make! + +# The main rule for your plugin. List all object-file dependencies. + +PANDA_PATH = $(realpath $(shell pwd)/..) +PLUGIN_DIR = $(realpath $(join $(PANDA_PATH), /../panda/plugins/$(PLUGIN_NAME)/)) +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so : $(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + @echo " CARGO $(PLUGIN_DIR)" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --no-default-features --features=$(TARGET_NAME) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @cp -p $(PLUGIN_ARTIFACTS_DIR)/release/lib$(PLUGIN_NAME).so $@ diff --git a/panda/plugins/print_tcp_servers/README.md b/panda/plugins/print_tcp_servers/README.md new file mode 100644 index 00000000000..4842c9a0a6c --- /dev/null +++ b/panda/plugins/print_tcp_servers/README.md @@ -0,0 +1,5 @@ +# Guest Agent TCP Passthrough + +A plugin for using the PANDA guest agent in order to perform passthrough of TCP servers present in the guest. + +See `try_it.py` for example on how to forward an HTTP server running on port 8000 in the guest to port 4343 on the host, as well as print out a table of the sockets listening in the guest. diff --git a/panda/plugins/print_tcp_servers/src/display.rs b/panda/plugins/print_tcp_servers/src/display.rs new file mode 100644 index 00000000000..c7ee37c0e69 --- /dev/null +++ b/panda/plugins/print_tcp_servers/src/display.rs @@ -0,0 +1,70 @@ +use std::collections::HashMap; +use std::net::Ipv4Addr; + +use once_cell::sync::Lazy; +use owo_colors::OwoColorize; +use tabled::{object::FirstRow, style::Style, Format, Modify, Table, Tabled}; + +use tcp_shared_types::SocketInfo; + +#[derive(Tabled)] +struct TableEntry { + #[tabled(rename = "Listening")] + listening: &'static str, + + #[tabled(rename = "Local IP")] + ip: Ipv4Addr, + + #[tabled(rename = "Port")] + port: u16, + + #[tabled(rename = "PID")] + pid: String, + + #[tabled(rename = "Description")] + description: &'static str, +} + +static TCP_NAMES_CSV: &str = include_str!("tcp.csv"); + +static PORT_TO_NAME: Lazy> = Lazy::new(|| { + TCP_NAMES_CSV + .trim() + .split('\n') + .filter(|line| !line.is_empty()) + .filter_map(|line| line.split_once(',')) + .filter_map(|(port, name)| port.parse().ok().map(move |port| (port, name))) + .collect() +}); + +const CHECK_MARK: &str = "\u{1f5f8}"; + +pub(crate) fn print_table(sockets: Vec) { + let tcp_server_table = sockets + .into_iter() + .map(|socket| TableEntry { + listening: if socket.server { CHECK_MARK } else { " " }, + ip: socket.ip.clone(), + port: socket.port, + pid: socket + .pid + .as_ref() + .map(ToString::to_string) + .unwrap_or_else(|| String::from("")), + description: PORT_TO_NAME.get(&socket.port).copied().unwrap_or(""), + }) + .collect::>(); + + println!( + "\n\n{}\n", + Table::new(tcp_server_table) + .with(Style::modern()) + .with(Modify::new(FirstRow).with(Format::new(|text| text.bold().to_string()))) + .with(tabled::Header("TCP Sockets")) + .with( + Modify::new(FirstRow) + .with(tabled::Alignment::center()) + .with(Format::new(|text| text.bold().to_string())) + ) + ); +} diff --git a/panda/plugins/print_tcp_servers/src/forward_socket.rs b/panda/plugins/print_tcp_servers/src/forward_socket.rs new file mode 100644 index 00000000000..b3afc9d135e --- /dev/null +++ b/panda/plugins/print_tcp_servers/src/forward_socket.rs @@ -0,0 +1,65 @@ +use dashmap::DashMap; +use once_cell::sync::Lazy; +use panda::plugins::guest_plugin_manager::*; +use std::io::Write; +use std::net::Ipv4Addr; +use std::net::{TcpListener, TcpStream}; +use std::sync::Mutex; +use std::thread; + +use tcp_shared_types::Request; + +static CONNECTIONS: Lazy>> = Lazy::new(DashMap::new); + +#[channel_recv] +fn incoming_tcp(channel_id: u32, data: &[u8]) { + eprintln!("[{channel_id}] TCP data: len={}", data.len()); + if let Some(channel) = CONNECTIONS.get(&channel_id) { + channel.lock().unwrap().write_all(data).unwrap(); + eprintln!("[{channel_id}] TCP data written"); + } +} + +pub fn forward(ip: Ipv4Addr, guest_port: u16, host_port: u16) { + thread::spawn(move || { + let listener = + TcpListener::bind(("localhost", host_port)).expect("Could not bind to host port"); + eprintln!("Listening on localhost:{}...", host_port); + + for stream in listener.incoming() { + match stream { + Ok(mut outgoing_tcp_stream) => { + println!( + "Incoming connection for port {} (guest port {})", + host_port, guest_port + ); + let mut incoming_channel = Channel::new(incoming_tcp); + + CONNECTIONS.insert( + incoming_channel.id(), + Mutex::new(outgoing_tcp_stream.try_clone().unwrap()), + ); + + let channel_id = incoming_channel.id(); + + thread::spawn(move || { + if let Err(err) = + std::io::copy(&mut outgoing_tcp_stream, &mut incoming_channel) + { + eprintln!("Connection Closed for host port {}: {:?}", host_port, err); + } + }); + + crate::send_request(Request::ForwardConnection { + ip, + port: guest_port, + channel_id, + }); + } + Err(_) => { + eprintln!("Failed to accept connection to localhost:{}", host_port); + } + } + } + }); +} diff --git a/panda/plugins/print_tcp_servers/src/lib.rs b/panda/plugins/print_tcp_servers/src/lib.rs new file mode 100644 index 00000000000..031c5c4dd33 --- /dev/null +++ b/panda/plugins/print_tcp_servers/src/lib.rs @@ -0,0 +1,69 @@ +use once_cell::sync::Lazy; +use panda::{plugins::guest_plugin_manager::*, prelude::*}; +use std::net::Ipv4Addr; +use std::sync::Mutex; + +mod display; +mod forward_socket; +mod send_ext; +mod socket_list; + +use send_ext::SendExt; +use socket_list::on_get_socket_list; + +use tcp_shared_types::Request; + +#[no_mangle] +pub extern "C" fn print_socket_info() { + on_get_socket_list(display::print_table); +} + +fn forward_socket(ip: Ipv4Addr, port: u16, host_port: u16) { + forward_socket::forward(ip, port, host_port); +} + +#[channel_recv] +fn main_channel_cb(_: u32, _: &[u8]) { + // TODO: support for guest closing the socket +} + +static MAIN_CHANNEL: Lazy> = + Lazy::new(|| Mutex::new(load_guest_plugin("tcp_servers", main_channel_cb))); + +fn send_request(req: Request) { + MAIN_CHANNEL.lock().unwrap().send(req) +} + +#[derive(PandaArgs)] +#[name = "print_tcp_servers"] +struct Args { + print_sockets: bool, + forward_port: u32, + host_port: u32, +} + +static ARGS: Lazy = Lazy::new(Args::from_panda_args); + +#[panda::init] +fn init(_: &mut PluginHandle) { + // TODO: switch to pretty_env_logger + + if ARGS.print_sockets { + print_socket_info(); + } + + let forward_port = ARGS.forward_port as u16; + let host_port = ARGS.host_port as u16; + if forward_port != 0 { + Lazy::force(&MAIN_CHANNEL); + + forward_socket( + "0.0.0.0".parse().unwrap(), + forward_port, + match host_port { + 0 => forward_port, + port => port, + }, + ); + } +} diff --git a/panda/plugins/print_tcp_servers/src/send_ext.rs b/panda/plugins/print_tcp_servers/src/send_ext.rs new file mode 100644 index 00000000000..dca58b0a02e --- /dev/null +++ b/panda/plugins/print_tcp_servers/src/send_ext.rs @@ -0,0 +1,12 @@ +use panda::plugins::guest_plugin_manager::Channel; +use serde::Serialize; + +pub(crate) trait SendExt { + fn send(&mut self, val: T); +} + +impl SendExt for Channel { + fn send(&mut self, val: T) { + self.write_packet(&bincode::serialize(&val).unwrap()); + } +} diff --git a/panda/plugins/print_tcp_servers/src/socket_list.rs b/panda/plugins/print_tcp_servers/src/socket_list.rs new file mode 100644 index 00000000000..d45778c9200 --- /dev/null +++ b/panda/plugins/print_tcp_servers/src/socket_list.rs @@ -0,0 +1,51 @@ +use crate::send_request; +use once_cell::sync::Lazy; +use panda::plugins::guest_plugin_manager::*; +use std::sync::Mutex; + +use tcp_shared_types::{Request, SocketInfo}; + +type SocketListCb = Box) + Send + 'static>; + +static SOCKET_LIST_CHANNEL: Lazy = Lazy::new(|| Channel::new(recv_socket_info)); + +static SOCKET_INFO_CALLBACK: Lazy>> = Lazy::new(|| Mutex::new(None)); + +#[channel_recv] +fn recv_socket_info(_: u32, data: &[u8]) { + if let Some(callback) = take_callback() { + callback(bincode::deserialize(data).unwrap()); + } +} + +fn take_callback() -> Option { + SOCKET_INFO_CALLBACK.lock().unwrap().take() +} + +fn set_callback(cb: SocketListCb) { + SOCKET_INFO_CALLBACK.lock().unwrap().replace(cb); +} + +pub(crate) fn on_get_socket_list(new_callback: CallbackFn) +where + CallbackFn: FnOnce(Vec) + Send + 'static, +{ + let callback = if let Some(existing_callback) = take_callback() { + // pending callback, chain them + let replacement_callback = move |sockets: Vec| { + existing_callback(sockets.clone()); + new_callback(sockets); + }; + + Box::new(replacement_callback) as SocketListCb + } else { + // no callback pending, queue a request for listing + send_request(Request::GetSocketList { + channel_id: SOCKET_LIST_CHANNEL.id(), + }); + + Box::new(new_callback) as SocketListCb + }; + + set_callback(callback); +} diff --git a/panda/plugins/print_tcp_servers/src/tcp.csv b/panda/plugins/print_tcp_servers/src/tcp.csv new file mode 100644 index 00000000000..143907685e3 --- /dev/null +++ b/panda/plugins/print_tcp_servers/src/tcp.csv @@ -0,0 +1,3266 @@ +0,Reserved +1,Port Service Multiplexer +2,Management Utility +3,Compression Process +4,Unassigned +5,Remote Job Entry +6,Unassigned +7,Echo +8,Unassigned +9,Discard +10,Unassigned +11,Active Users +12,Unassigned +13,Daytime (RFC 867) +14,Unassigned +15,Unassigned [was netstat] +16,Unassigned +17,Quote of the Day +18,Message Send Protocol +19,Character Generator +20,File Transfer [Default Data] +21,File Transfer [Control] +22,SSH Remote Login Protocol +23,Telnet +24,any private mail system +25,Simple Mail Transfer +26,Unassigned +27,NSW User System FE +28,Unassigned +29,MSG ICP +30,Unassigned +31,MSG Authentication +32,Unassigned +33,Display Support Protocol +34,Unassigned +35,any private printer server +36,Unassigned +37,Time / W32.Sober.I virus +38,Route Access Protocol +39,Resource Location Protocol +40,Unassigned +41,Graphics +42,Host Name Server +43,WhoIs +44,MPM FLAGS Protocol +45,Message Processing Module [recv] +46,MPM [default send] +47,NI FTP +48,Digital Audit Daemon +49,Login Host Protocol (TACACS) +50,Remote Mail Checking Protocol +51,IMP Logical Address Maintenance +52,XNS Time Protocol +53,Domain Name Server +54,XNS Clearinghouse +55,ISI Graphics Language +56,XNS Authentication +57,any private terminal access +58,XNS Mail +59,any private file service +60,Unassigned +61,NI MAIL +62,ACA Services +63,whois++ +64,Communications Integrator (CI) +65,TACACS-Database Service +66,Oracle SQL*NET +67,Bootstrap Protocol Server +68,Bootstrap Protocol Client +69,Trivial File Transfer +70,Gopher +71,Remote Job Service +72,Remote Job Service +73,Remote Job Service +74,Remote Job Service +75,any private dial out service +76,Distributed External Object Store +77,any private RJE service +78,vettcp +79,Finger +80,World Wide Web HTTP +81,HOSTS2 Name Server / Bagle-AZ worm / Win32.Rbot worm +82,XFER Utility +83,MIT ML Device +84,Common Trace Facility +85,MIT ML Device +86,Micro Focus Cobol +87,any private terminal link +88,Kerberos +89,SU/MIT Telnet Gateway +90,DNSIX Securit Attribute Token Map +91,MIT Dover Spooler +92,Network Printing Protocol +93,Device Control Protocol +94,Tivoli Object Dispatcher +95,SUPDUP +96,DIXIE Protocol Specification +97,Swift Remote Virtural File Protocol +98,Linuxconf / TAC News +99,Metagram Relay +100,[unauthorized use] +101,NIC Host Name Server +102,MSExchangeMTA X.400 / ISO-TSAP Class 0 +103,Genesis Point-to-Point Trans Net +104,ACR-NEMA Digital Imag. & Comm. 300 +105,Mailbox Name Nameserver +106,3COM-TSMUX +107,Remote Telnet Service +108,SNA Gateway Access Server +109,Post Office Protocol - Version 2 +110,Post Office Protocol - Version 3 +111,SUN Remote Procedure Call +112,McIDAS Data Transmission Protocol +113,Authentication Service +114,Audio News Multicast +115,Simple File Transfer Protocol +116,ANSA REX Notify +117,UUCP Path Service +118,SQL Services +119,Network News Transfer Protocol +120,CFDPTKT +121,Encore Expedited Remote Pro.Call +122,SMAKYNET +123,Network Time Protocol +124,ANSA REX Trader +125,Locus PC-Interface Net Map Ser +126,Unisys Unitary Login +127,Locus PC-Interface Conn Server +128,GSS X License Verification +129,Password Generator Protocol +130,cisco FNATIVE +131,cisco TNATIVE +132,cisco SYSMAINT +133,Statistics Service +134,INGRES-NET Service +135,DCE endpoint resolution +136,PROFILE Naming System +137,NETBIOS Name Service +138,NETBIOS Datagram Service +139,NETBIOS Session Service +140,EMFIS Data Service +141,EMFIS Control Service +142,Britton-Lee IDM +143,Internet Message Access Protocol +144,Universal Management Architecture +145,UAAC Protocol +146,ISO-IP0 +147,ISO-IP +148,Jargon +149,AED 512 Emulation Service +150,SQL-NET +151,HEMS +152,Background File Transfer Program +153,SGMP +154,NETSC +155,NETSC +156,SQL Service +157,KNET/VM Command/Message Protocol +158,PCMail Server +159,NSS-Routing +160,SGMP-TRAPS +161,SNMP +162,SNMPTRAP +163,CMIP/TCP Manager +164,CMIP/TCP Agent +165,Xerox +166,Sirius Systems +167,NAMP +168,RSVD +169,SEND +170,Network PostScript +171,Network Innovations Multiplex +172,Network Innovations CL/1 +173,Xyplex +174,MAILQ +175,VMNET +176,GENRAD-MUX +177,X Display Manager Control Protocol +178,NextStep Window Server +179,Border Gateway Protocol +180,Intergraph +181,Unify +182,Unisys Audit SITP +183,OCBinder +184,OCServer +185,Remote-KIS +186,KIS Protocol +187,Application Communication Interface +188,Plus Five's MUMPS +189,Queued File Transport +190,Gateway Access Control Protocol +191,Prospero Directory Service +192,OSU Network Monitoring System +193,Spider Remote Monitoring Protocol +194,Internet Relay Chat Protocol +195,DNSIX Network Level Module Audit +196,DNSIX Session Mgt Module Audit Redir +197,Directory Location Service +198,Directory Location Service Monitor +199,SMUX +200,IBM System Resource Controller +201,AppleTalk Routing Maintenance +202,AppleTalk Name Binding +203,AppleTalk Unused +204,AppleTalk Echo +205,AppleTalk Unused +206,AppleTalk Zone Information +207,AppleTalk Unused +208,AppleTalk Unused +209,The Quick Mail Transfer Protocol +210,ANSI Z39.50 +211,Texas Instruments 914C/G Terminal +212,ATEXSSTR +213,IPX +214,VM PWSCS +215,Insignia Solutions +216,Computer Associates Int'l License Server +217,dBASE Unix +218,Netix Message Posting Protocol +219,Unisys ARPs +220,Interactive Mail Access Protocol v3 +221,Berkeley rlogind with SPX auth +222,Berkeley rshd with SPX auth +223,Certificate Distribution Center +224,masqdialer +242,Direct +243,Survey Measurement +244,inbusiness +245,LINK +246,Display Systems Protocol +247,SUBNTBCST_TFTP +248,bhfhs +256,RAP/Checkpoint SNMP +257,Check Point / Secure Electronic Transaction +258,Check Point / Yak Winsock Personal Chat +259,Check Point Firewall-1 telnet auth / Efficient Short Remote Operations +260,Openport +261,IIOP Name Service over TLS/SSL +262,Arcisdms +263,HDAP +264,BGMP / Check Point +265,X-Bone CTL +266,SCSI on ST +267,Tobit David Service Layer +268,Tobit David Replica +280,HTTP-mgmt +281,Personal Link +282,Cable Port A/X +283,rescap +284,corerjd +286,FXP-1 +287,K-BLOCK +308,Novastor Backup +309,EntrustTime +310,bhmds +311,AppleShare IP WebAdmin +312,VSLMP +313,Magenta Logic +314,Opalis Robot +315,DPSI +316,decAuth +317,Zannet +318,PKIX TimeStamp +319,PTP Event +320,PTP General +321,PIP +322,RTSPS +333,Texar Security Port +344,Prospero Data Access Protocol +345,Perf Analysis Workbench +346,Zebra server +347,Fatmen Server +348,Cabletron Management Protocol +349,mftp +350,MATIP Type A +351,bhoetty (added 5/21/97) +352,bhoedap4 (added 5/21/97) +353,NDSAUTH +354,bh611 +355,DATEX-ASN +356,Cloanto Net 1 +357,bhevent +358,Shrinkwrap +359,Tenebris Network Trace Service +360,scoi2odialog +361,Semantix +362,SRS Send +363,RSVP Tunnel +364,Aurora CMGR +365,DTK +366,ODMR +367,MortgageWare +368,QbikGDP +369,rpc2portmap +370,codaauth2 +371,Clearcase +372,ListProcessor +373,Legent Corporation +374,Legent Corporation +375,Hassle +376,Amiga Envoy Network Inquiry Proto +377,NEC Corporation +378,NEC Corporation +379,TIA/EIA/IS-99 modem client +380,TIA/EIA/IS-99 modem server +381,hp performance data collector +382,hp performance data managed node +383,hp performance data alarm manager +384,A Remote Network Server System +385,IBM Application +386,ASA Message Router Object Def. +387,Appletalk Update-Based Routing Pro. +388,Unidata LDM +389,Lightweight Directory Access Protocol / Internet Locator Service (ILS) +390,UIS +391,SynOptics SNMP Relay Port +392,SynOptics Port Broker Port +393,Data Interpretation System +394,EMBL Nucleic Data Transfer +395,NETscout Control Protocol +396,Novell Netware over IP +397,Multi Protocol Trans. Net. +398,Kryptolan +399,ISO Transport Class 2 Non-Control over TCP +400,Workstation Solutions +401,Uninterruptible Power Supply +402,Genie Protocol +403,decap +404,nced +405,ncld +406,Interactive Mail Support Protocol +407,Timbuktu +408,Prospero Resource Manager Sys. Man. +409,Prospero Resource Manager Node Man. +410,DECLadebug Remote Debug Protocol +411,Remote MT Protocol +412,NeoModus Direct Connect (Windows file sharing program) / Trap Convention Port +413,SMSP +414,InfoSeek +415,BNet +416,Silverplatter +417,Onmux +418,Hyper-G +419,Ariel +420,SMPTE +421,Ariel +422,Ariel +423,IBM Operations Planning and Control Start +424,IBM Operations Planning and Control Track +425,ICAD +426,smartsdp +427,Server Location +428,OCS_CMU +429,OCS_AMU +430,UTMPSD +431,UTMPCD +432,IASD +433,NNSP +434,MobileIP-Agent +435,MobilIP-MN +436,DNA-CML +437,comscm +438,dsfgw +439,dasp +440,sgcp +441,decvms-sysmgt +442,cvc_hostd +443,HTTP protocol over TLS/SSL +444,Simple Network Paging Protocol +445,Microsoft-DS +446,DDM-RDB +447,DDM-RFM +448,DDM-SSL +449,AS Server Mapper +450,TServer +451,Cray Network Semaphore server +452,Cray SFS config server +453,CreativeServer +454,ContentServer +455,CreativePartnr +456,macon-tcp +457,scohelp +458,apple quick time +459,ampr-rcmd +460,skronk +461,DataRampSrv +462,DataRampSrvSec +463,alpes +464,kpasswd +465,SMTPS +466,digital-vrc +467,mylex-mapd +468,proturis +469,Radio Control Protocol +470,scx-proxy +471,Mondex +472,ljk-login +473,hybrid-pop +474,tn-tl-w1 +475,tcpnethaspsrv +476,tn-tl-fd1 +477,ss7ns +478,spsc +479,iafserver +480,iafdbase +481,Ph service +482,bgs-nsi +483,ulpnet +484,Integra Software Management Environment +485,Air Soft Power Burst +486,avian +487,saft Simple Asynchronous File Transfer +488,gss-HTTP +489,nest-protocol +490,micom-pfs +491,go-login +492,Transport Independent Convergence for FNA +493,Transport Independent Convergence for FNA +494,POV-Ray +495,intecourier +496,PIM-RP-DISC +497,dantz +498,siam +499,ISO ILL Protocol +500,ISAKMP +501,STMF +502,asa-appl-proto +503,Intrinsa +504,citadel +505,mailbox-lm +506,ohimsrv +507,crs +508,xvttp +509,snare +510,FirstClass Protocol +511,PassGo +512,Remote process execution +513,Remote Login +514,Remote Shell +515,spooler +516,videotex +517,like tenex link but across +518,talkd +519,unixtime +520,extended file name server +521,ripng +522,User Location Service / ULP +523,IBM-DB2 +524,NCP +525,timeserver +526,newdate +527,Stock IXChange +528,Customer IXChange +529,IRC-SERV +530,rpc +531,chat +532,readnews +533,for emergency broadcasts +534,MegaMedia Admin +535,iiop +536,opalis-rdv +537,Networked Media Streaming Protocol +538,gdomap +539,Apertus Technologies Load Determination +540,uucpd +541,uucp-rlogin +542,commerce +543,kerberos (v4/v5) +544,krcmd +545,appleqtcsrvr +546,DHCPv6 Client +547,DHCPv6 Server +548,AppleShare AFP over TCP +549,IDFP +550,new-who +551,cybercash +552,deviceshare +553,pirp +554,Real Time Stream Control Protocol +555,phAse Zero backdoor (Win 9x, NT) / dsf +556,rfs server +557,openvms-sysipc +558,SDNSKMP +559,TEEDTAP / Backdoor.Domwis Win32 trojan +560,rmonitord +561,monitor +562,chcmd +563,AOL IM / NNTP protocol over TLS/SSL +564,plan 9 file service +565,whoami +566,streettalk +567,banyan-rpc +568,microsoft shuttle +569,microsoft rome +570,demon +571,udemon +572,sonar +573,banyan-vip +574,FTP Software Agent System +575,VEMMI +576,ipcd +577,vnas +578,ipdd +579,decbsrv +580,SNTP HEARTBEAT +581,Bundle Discovery Protocol +582,SCC Security +583,Philips Video-Conferencing +584,Key Server +585,IMAP4+SSL +586,Password Change +587,Message Submission (Sendmail) +588,CAL +589,EyeLink +590,TNS CML +591,FileMaker Inc. - HTTP Alternate +592,Eudora Set +593,HTTP RPC Ep Map +594,TPIP +595,CAB Protocol +596,SMSD +597,PTC Name Service +598,SCO Web Server Manager 3 +599,Aeolon Core Protocol +600,Sun IPC server +606,Cray Unified Resource Manager +607,nqs +608,Sender-Initiated/Unsolicited File Transfer +609,npmp-trap +610,Apple Admin Service / npmp-local +611,npmp-gui +612,HMMP Indication +613,HMMP Operation +614,SSLshell +615,Internet Configuration Manager +616,SCO System Administration Server +617,SCO Desktop Administration Server +618,DEI-ICDA +619,Digital EVM +620,SCO WebServer Manager +621,ESCP +622,Collaborator +623,Aux Bus Shunt +624,Crypto Admin +625,DEC DLM +626,ASIA +627,PassGo Tivoli +628,QMQP +629,3Com AMP3 +630,RDA +631,IPP (Internet Printing Protocol) +632,bmpp +633,Service Status update (Sterling Software) +634,ginad +635,RLZ DBase +636,LDAP protocol over TLS/SSL +637,lanserver +638,mcns-sec +639,MSDP +640,entrust-sps +641,repcmd +642,ESRO-EMSDP V1.3 +643,SANity +644,dwr +645,PSSC +646,LDP +647,DHCP Failover +648,Registry Registrar Protocol (RRP) +649,Aminet +650,OBEX +651,IEEE MMS +652,UDLR_DTCP +653,RepCmd +654,AODV +655,TINC +656,SPMP +657,RMC +658,TenFold +659,URL Rendezvous +660,MacOS Server Admin +661,HAP +662,PFTP +663,PureNoise +664,Secure Aux Bus +665,Sun DR +666,doom Id Software +667,campaign contribution disclosures - SDR Technologies +668,MeComm +669,MeRegister +670,VACDSM-SWS +671,VACDSM-APP +672,VPPS-QUA +673,CIMPLEX +674,ACAP +675,DCTP +676,VPPS Via +677,Virtual Presence Protocol +678,GNU Gereration Foundation NCP +679,MRM +680,entrust-aaas +681,entrust-aams +682,XFR +683,CORBA IIOP +684,CORBA IIOP SSL +685,MDC Port Mapper +686,Hardware Control Protocol Wismar +687,asipregistry +688,REALM-RUSD +689,NMAP +690,VATP +691,MS Exchange Routing +692,Hyperwave-ISP +693,connendp +694,ha-cluster +695,IEEE-MMS-SSL +696,RUSHD +697,UUIDGEN +698,OLSR +704,errlog copy/server daemon +705,AgentX +706,SILC +707,W32.Nachi Worm / Borland DSJ +709,Entrust Key Management Service Handler +710,Entrust Administration Service Handler +711,Cisco TDP +729,IBM NetView DM/6000 Server/Client +730,IBM NetView DM/6000 send/tcp +731,IBM NetView DM/6000 receive/tcp +740,(old) NETscout Control Protocol (old) +741,netGW +742,Network based Rev. Cont. Sys. +744,Flexible License Manager +747,Fujitsu Device Control +748,Russell Info Sci Calendar Manager +749,kerberos administration +750,rfile +751,pump +752,Kerberos password server +753,Kerberos userreg server +754,send +758,nlogin +759,con +760,kreg, kerberos/4 registration +761,kpwd, Kerberos/4 password +762,quotad +763,cycleserv +764,omserv +765,webster +767,phone +769,vid +770,cadlock +771,rtip +772,cycleserv2 +773,submit +774,rpasswd +775,entomb +776,wpages +777,Multiling HTTP +780,wpgs +781,HP performance data collector +782,node HP performance data managed node +783,HP performance data alarm manager +786,Concert +787,QSC +799,ControlIT / Remotely Possible +800,mdbs_daemon / Remotely Possible +801,device +808,CCProxy +810,FCP +828,itm-mcell-s +829,PKIX-3 CA/RA +871,SUP server +873,rsync +886,ICL coNETion locate server +887,ICL coNETion server info +888,CD Database Protocol +900,Check Point Firewall-1 HTTP administration / OMG Initial Refs +901,Samba Web Administration Tool / Realsecure / SMPNAMERES/ NetDevil trojan +902,VMware Authentication Daemon / IDEAFARM-CHAT +903,IDEAFARM-CATCH / NetDevil trojan +911,xact-backup +912,VMware Authentication Daemon +989,FTP protocol data over TLS/SSL +990,FTP protocol control over TLS/SSL +991,Netnews Administration System +992,Telnet protocol over TLS/SSL +993,IMAP4 protocol over TLS/SSL +994,IRC protocol over TLS/SSL +995,POP3 protocol over TLS/SSL +996,vsinet +997,maitrd +998,busboy +999,puprouter +1000,cadlock +1002,Microsoft Site Server Internet Locator Service (Netmeeting/ICF) +1008,UFS-aware server +1010,surf +1011,Doly (Windows Trojan) +1015,Doly (Windows Trojan) +1023,Reserved +1024,Reserved +1025,MSTASK / network blackjack +1026,MSTASK / Remote Login Network Terminal +1030,BBN IAD +1031,InetInfo / BBN IAD +1032,BBN IAD +1042,W32.Mydoom.L virus +1047,Sun's NEO Object Request Broker +1048,Sun's NEO Object Request Broker +1049,Tobit David Postman VPMN +1050,CORBA Management Agent +1051,Optima VNET +1052,Dynamic DNS Tools +1053,Remote Assistant (RA) +1054,BRVREAD +1055,ANSYS - License Manager +1056,VFO +1057,STARTRON +1058,nim +1059,nimreg +1060,POLESTAR +1061,KIOSK +1062,Veracity +1063,KyoceraNetDev +1064,JSTEL +1065,SYSCOMLAN +1066,FPO-FNS +1067,Installation Bootstrap Proto. Serv. +1068,Installation Bootstrap Proto. Cli. +1069,COGNEX-INSIGHT +1070,GMRUpdateSERV +1071,BSQUARE-VOIP +1072,CARDAX +1073,BridgeControl +1074,FASTechnologies License Manager +1075,RDRMSHC +1076,DAB STI-C +1077,IMGames +1078,eManageCstp +1079,ASPROVATalk +1080,Socks / W32.Beagle.AB trojan +1081,PVUNIWIEN +1082,AMT-ESD-PROT +1083,Anasoft License Manager +1084,Anasoft License Manager +1085,Web Objects +1086,CPL Scrambler Logging +1087,CPL Scrambler Internal +1088,CPL Scrambler Alarm Log +1089,FF Annunciation +1090,FF Fieldbus Message Specification +1091,FF System Management +1092,OBRPD +1093,PROOFD +1094,ROOTD +1095,NICELink +1096,Common Name Resolution Protocol +1097,Sun Cluster Manager +1098,RMI Activation +1099,RMI Registry +1100,MCTP +1101,PT2-DISCOVER +1102,ADOBE SERVER 1 +1103,ADOBE SERVER 2 +1104,XRL +1105,FTRANHC +1106,ISOIPSIGPORT-1 +1107,ISOIPSIGPORT-2 +1108,ratio-adp +1109,Pop with Kerberos +1110,Cluster status info +1111,LM Social Server +1112,Intelligent Communication Protocol +1114,Mini SQL +1115,ARDUS Transfer +1116,ARDUS Control +1117,ARDUS Multicast Transfer +1123,Murray +1127,SUP debugging +1155,Network File Access +1161,Health Polling +1162,Health Trap +1169,TRIPWIRE +1178,SKK (kanji input) +1180,Millicent Client Proxy +1188,HP Web Admin +1200,SCOL +1201,Nucleus Sand +1202,caiccipc +1203,License Validation +1204,Log Request Listener +1205,Accord-MGC +1206,Anthony Data +1207,MetaSage +1208,SEAGULL AIS +1209,IPCD3 +1210,EOSS +1211,Groove DPP +1212,lupa +1213,MPC LIFENET +1214,KAZAA (Morpheus) +1215,scanSTAT 1.0 +1216,ETEBAC 5 +1217,HPSS-NDAPI +1218,AeroFlight-ADs +1219,AeroFlight-Ret +1220,QT SERVER ADMIN +1221,SweetWARE Apps +1222,SNI R&D network +1223,TGP +1224,VPNz +1225,SLINKYSEARCH +1226,STGXFWS +1227,DNS2Go +1228,FLORENCE +1229,Novell ZFS +1234,W32.Beagle.Y trojan / Infoseek Search Agent +1239,NMSD +1241,Nessus Daemon / remote message service +1243,SubSeven (Windows Trojan) +1245,Subseven backdoor remote access tool +1248,hermes +1270,Microsoft Operations Manager MOM-Encrypted +1300,H323 Host Call Secure +1310,Husky +1311,RxMon +1312,STI Envision +1313,BMC_PATROLDB +1314,Photoscript Distributed Printing System +1319,Panja-ICSP +1320,Panja-AXBNET +1321,PIP +1335,Digital Notary Protocol +1345,VPJP +1346,Alta Analytics License Manager +1347,multi media conferencing +1348,multi media conferencing +1349,Registration Network Protocol +1350,Registration Network Protocol +1351,Digital Tool Works (MIT) +1352,Lotus Notes +1353,Relief Consulting +1354,RightBrain Software +1355,Intuitive Edge +1356,CuillaMartin Company +1357,Electronic PegBoard +1358,CONNLCLI +1359,FTSRV +1360,MIMER +1361,LinX +1362,TimeFlies +1363,Network DataMover Requester +1364,Network DataMover Server +1365,Network Software Associates +1366,Novell NetWare Comm Service Platform +1367,DCS +1368,ScreenCast +1369,GlobalView to Unix Shell +1370,Unix Shell to GlobalView +1371,Fujitsu Config Protocol +1372,Fujitsu Config Protocol +1373,Chromagrafx +1374,EPI Software Systems +1375,Bytex +1376,IBM Person to Person Software +1377,Cichlid License Manager +1378,Elan License Manager +1379,Integrity Solutions +1380,Telesis Network License Manager +1381,Apple Network License Manager +1382,udt_os +1383,GW Hannaway Network License Manager +1384,Objective Solutions License Manager +1385,Atex Publishing License Manager +1386,CheckSum License Manager +1387,Computer Aided Design Software Inc LM +1388,Objective Solutions DataBase Cache +1389,Document Manager +1390,Storage Controller +1391,Storage Access Server +1392,Print Manager +1393,Network Log Server +1394,Network Log Client +1395,PC Workstation Manager software +1396,DVL Active Mail +1397,Audio Active Mail +1398,Video Active Mail +1399,Cadkey License Manager +1400,Cadkey Tablet Daemon +1401,Goldleaf License Manager +1402,Prospero Resource Manager +1403,Prospero Resource Manager +1404,Infinite Graphics License Manager +1405,IBM Remote Execution Starter +1406,NetLabs License Manager +1407,DBSA License Manager +1408,Sophia License Manager +1409,Here License Manager +1410,HiQ License Manager +1411,AudioFile +1412,InnoSys +1413,Innosys-ACL +1414,IBM MQSeries +1415,DBStar +1416,Novell LU6.2 +1417,Timbuktu Service 1 Port +1418,Timbuktu Service 2 Port +1419,Timbuktu Service 3 Port +1420,Timbuktu Service 4 Port +1421,Gandalf License Manager +1422,Autodesk License Manager +1423,Essbase Arbor Software +1424,Hybrid Encryption Protocol +1425,Zion Software License Manager +1426,Satellite-data Acquisition System 1 +1427,mloadd monitoring tool +1428,Informatik License Manager +1429,Hypercom NMS +1430,Hypercom TPDU +1431,Reverse Gossip Transport +1432,Blueberry Software License Manager +1433,Microsoft-SQL-Server +1434,Microsoft-SQL-Monitor +1435,IBM CICS +1436,Satellite-data Acquisition System 2 +1437,Tabula +1438,Eicon Security Agent/Server +1439,Eicon X25/SNA Gateway +1440,Eicon Service Location Protocol +1441,Cadis License Management +1442,Cadis License Management +1443,Integrated Engineering Software +1444,Marcam License Management +1445,Proxima License Manager +1446,Optical Research Associates License Manager +1447,Applied Parallel Research LM +1448,OpenConnect License Manager +1449,PEport +1450,Tandem Distributed Workbench Facility +1451,IBM Information Management +1452,GTE Government Systems License Man +1453,Genie License Manager +1454,interHDL License Manager +1455,ESL License Manager +1456,DCA +1457,Valisys License Manager +1458,Nichols Research Corp. +1459,Proshare Notebook Application +1460,Proshare Notebook Application +1461,IBM Wireless LAN +1462,World License Manager +1463,Nucleus +1464,MSL License Manager +1465,Pipes Platform +1466,Ocean Software License Manager +1467,CSDMBASE +1468,CSDM +1469,Active Analysis Limited License Manager +1470,Universal Analytics +1471,csdmbase +1472,csdm +1473,OpenMath +1474,Telefinder +1475,Taligent License Manager +1476,clvm-cfg +1477,ms-sna-server +1478,ms-sna-base +1479,dberegister +1480,PacerForum +1481,AIRS +1482,Miteksys License Manager +1483,AFS License Manager +1484,Confluent License Manager +1485,LANSource +1486,nms_topo_serv +1487,LocalInfoSrvr +1488,DocStor +1489,dmdocbroker +1490,insitu-conf +1491,anynetgateway +1492,stone-design-1 +1493,netmap_lm +1494,Citrix/ica +1495,cvc +1496,liberty-lm +1497,rfx-lm +1498,Sybase SQL Any +1499,Federico Heinz Consultora +1500,VLSI License Manager +1501,Satellite-data Acquisition System 3 +1502,Shiva +1503,MS Netmeeting / T.120 / Databeam +1504,EVB Software Engineering License Manager +1505,Funk Software Inc. +1506,Universal Time daemon (utcd) +1507,symplex +1508,diagmond +1509,Robcad Ltd. License Manager +1510,Midland Valley Exploration Ltd. Lic. Man. +1511,3l-l1 +1512,Microsoft's Windows Internet Name Service +1513,Fujitsu Systems Business of America Inc +1514,Fujitsu Systems Business of America Inc +1515,ifor-protocol +1516,Virtual Places Audio data +1517,Virtual Places Audio control +1518,Virtual Places Video data +1519,Virtual Places Video control +1520,atm zip office +1521,Oracle8i Listener / nCube License Manager +1522,Ricardo North America License Manager +1523,cichild +1524,dtspcd / ingres +1525,Oracle / Prospero Directory Service non-priv +1526,Prospero Data Access Prot non-priv +1527,oracle +1528,micautoreg +1529,oracle +1530,Oracle ExtProc (PLSExtProc) / rap-service +1531,rap-listen +1532,miroconnect +1533,Virtual Places Software +1534,micromuse-lm +1535,ampr-info +1536,ampr-inter +1537,isi-lm +1538,3ds-lm +1539,Intellistor License Manager +1540,rds +1541,rds2 +1542,gridgen-elmd +1543,simba-cs +1544,aspeclmd +1545,vistium-share +1546,abbaccuray +1547,laplink +1548,Axon License Manager +1549,Shiva Hose +1550,Image Storage license manager 3M Company +1551,HECMTL-DB +1552,pciarray +1553,sna-cs +1554,CACI Products Company License Manager +1555,livelan +1556,AshWin CI Tecnologies +1557,ArborText License Manager +1558,xingmpeg +1559,web2host +1560,asci-val +1561,facilityview +1562,pconnectmgr +1563,Cadabra License Manager +1564,Pay-Per-View +1565,WinDD +1566,CORELVIDEO +1567,jlicelmd +1568,tsspmap +1569,ets +1570,orbixd +1571,Oracle Remote Data Base +1572,Chipcom License Manager +1573,itscomm-ns +1574,mvel-lm +1575,oraclenames +1576,moldflow-lm +1577,hypercube-lm +1578,Jacobus License Manager +1579,ioc-sea-lm +1580,tn-tl-r1 +1581,MIL-2045-47001 +1582,MSIMS +1583,simbaexpress +1584,tn-tl-fd2 +1585,intv +1586,ibm-abtact +1587,pra_elmd +1588,triquest-lm +1589,VQP +1590,gemini-lm +1591,ncpm-pm +1592,commonspace +1593,mainsoft-lm +1594,sixtrak +1595,radio +1596,radio-sm +1597,orbplus-iiop +1598,picknfs +1599,simbaservices +1600,Bofra-A worm / issd +1601,aas +1602,inspect +1603,pickodbc +1604,icabrowser +1605,Salutation Manager (Salutation Protocol) +1606,Salutation Manager (SLM-API) +1607,stt +1608,Smart Corp. License Manager +1609,isysg-lm +1610,taurus-wh +1611,Inter Library Loan +1612,NetBill Transaction Server +1613,NetBill Key Repository +1614,NetBill Credential Server +1615,NetBill Authorization Server +1616,NetBill Product Server +1617,Nimrod Inter-Agent Communication +1618,skytelnet +1619,xs-openstorage +1620,faxportwinport +1621,softdataphone +1622,ontime +1623,jaleosnd +1624,udp-sr-port +1625,svs-omagent +1626,Shockwave +1627,T.128 Gateway +1628,LonTalk normal +1629,LonTalk urgent +1630,Oracle Net8 Cman +1631,Visit view +1632,PAMMRATC +1633,PAMMRPC +1634,Log On America Probe +1635,EDB Server 1 +1636,CableNet Control Protocol +1637,CableNet Admin Protocol +1638,Bofra-A worm / CableNet Info Protocol +1639,cert-initiator +1640,cert-responder +1641,InVision +1642,isis-am +1643,isis-ambc +1644,Satellite-data Acquisition System 4 +1645,datametrics +1646,sa-msg-port +1647,rsap +1648,concurrent-lm +1649,kermit +1650,nkd +1651,shiva_confsrvr +1652,xnmp +1653,alphatech-lm +1654,stargatealerts +1655,dec-mbadmin +1656,dec-mbadmin-h +1657,fujitsu-mmpdc +1658,sixnetudr +1659,Silicon Grail License Manager +1660,skip-mc-gikreq +1661,netview-aix-1 +1662,netview-aix-2 +1663,netview-aix-3 +1664,netview-aix-4 +1665,netview-aix-5 +1666,netview-aix-6 +1667,netview-aix-7 +1668,netview-aix-8 +1669,netview-aix-9 +1670,netview-aix-10 +1671,netview-aix-11 +1672,netview-aix-12 +1673,Intel Proshare Multicast +1674,Intel Proshare Multicast +1675,Pacific Data Products +1676,netcomm1 +1677,groupwise +1678,prolink +1679,darcorp-lm +1680,microcom-sbp +1681,sd-elmd +1682,lanyon-lantern +1683,ncpm-hip +1684,SnareSecure +1685,n2nremote +1686,cvmon +1687,nsjtp-ctrl +1688,nsjtp-data +1689,firefox +1690,ng-umds +1691,empire-empuma +1692,sstsys-lm +1693,rrirtr +1694,rrimwm +1695,rrilwm +1696,rrifmm +1697,rrisat +1698,RSVP-ENCAPSULATION-1 +1699,RSVP-ENCAPSULATION-2 +1700,mps-raft +1701,l2tp / AOL +1702,deskshare +1703,hb-engine +1704,bcs-broker +1705,slingshot +1706,jetform +1707,vdmplay +1708,gat-lmd +1709,centra +1710,impera +1711,pptconference +1712,resource monitoring service +1713,ConferenceTalk +1714,sesi-lm +1715,houdini-lm +1716,xmsg +1717,fj-hdnet +1718,h323gatedisc +1719,h323gatestat +1720,h323hostcall +1721,caicci +1722,HKS License Manager +1723,pptp +1724,csbphonemaster +1725,iden-ralp +1726,IBERIAGAMES +1727,winddx +1728,TELINDUS +1729,CityNL License Management +1730,roketz +1731,MS Netmeeting / Audio call control / MSICCP +1732,proxim +1733,SIMS - SIIPAT Protocol for Alarm Transmission +1734,Camber Corporation License Management +1735,PrivateChat +1736,street-stream +1737,ultimad +1738,GameGen1 +1739,webaccess +1740,encore +1741,cisco-net-mgmt +1742,3Com-nsd +1743,Cinema Graphics License Manager +1744,ncpm-ft +1745,ISA Server proxy autoconfig / Remote Winsock +1746,ftrapid-1 +1747,ftrapid-2 +1748,oracle-em1 +1749,aspen-services +1750,Simple Socket Library's PortMaster +1751,SwiftNet +1752,Leap of Faith Research License Manager +1753,Translogic License Manager +1754,oracle-em2 +1755,Microsoft Streaming Server +1756,capfast-lmd +1757,cnhrp +1758,tftp-mcast +1759,SPSS License Manager +1760,www-ldap-gw +1761,cft-0 +1762,cft-1 +1763,cft-2 +1764,cft-3 +1765,cft-4 +1766,cft-5 +1767,cft-6 +1768,cft-7 +1769,bmc-net-adm +1770,bmc-net-svc +1771,vaultbase +1772,EssWeb Gateway +1773,KMSControl +1774,global-dtserv +1776,Federal Emergency Management Information System +1777,powerguardian +1778,prodigy-internet +1779,pharmasoft +1780,dpkeyserv +1781,answersoft-lm +1782,HP JetSend +1783,Port 04/14/00 fujitsu.co.jp +1784,Finle License Manager +1785,Wind River Systems License Manager +1786,funk-logger +1787,funk-license +1788,psmond +1789,hello +1790,Narrative Media Streaming Protocol +1791,EA1 +1792,ibm-dt-2 +1793,rsc-robot +1794,cera-bcm +1795,dpi-proxy +1796,Vocaltec Server Administration +1797,UMA +1798,Event Transfer Protocol +1799,NETRISK +1800,ANSYS-License manager +1801,Microsoft Message Queuing +1802,ConComp1 +1803,HP-HCIP-GWY +1804,ENL +1805,ENL-Name +1806,Musiconline +1807,Fujitsu Hot Standby Protocol +1808,Oracle-VP2 +1809,Oracle-VP1 +1810,Jerand License Manager +1811,Scientia-SDB +1812,RADIUS +1813,RADIUS Accounting / HackTool.SkSocket +1814,TDP Suite +1815,MMPFT +1816,HARP +1817,RKB-OSCS +1818,Enhanced Trivial File Transfer Protocol +1819,Plato License Manager +1820,mcagent +1821,donnyworld +1822,es-elmd +1823,Unisys Natural Language License Manager +1824,metrics-pas +1825,DirecPC Video +1826,ARDT +1827,ASI +1828,itm-mcell-u +1829,Optika eMedia +1830,Oracle Net8 CMan Admin +1831,Myrtle +1832,ThoughtTreasure +1833,udpradio +1834,ARDUS Unicast +1835,ARDUS Multicast +1836,ste-smsc +1837,csoft1 +1838,TALNET +1839,netopia-vo1 +1840,netopia-vo2 +1841,netopia-vo3 +1842,netopia-vo4 +1843,netopia-vo5 +1844,DirecPC-DLL +1850,GSI +1851,ctcd +1860,SunSCALAR Services +1861,LeCroy VICP +1862,techra-server +1863,MSN Messenger +1864,Paradym 31 Port +1865,ENTP +1870,SunSCALAR DNS Service +1871,Cano Central 0 +1872,Cano Central 1 +1873,Fjmpjps +1874,Fjswapsnp +1881,IBM MQSeries +1895,Vista 4GL +1899,MC2Studios +1900,SSDP +1901,Fujitsu ICL Terminal Emulator Program A +1902,Fujitsu ICL Terminal Emulator Program B +1903,Local Link Name Resolution +1904,Fujitsu ICL Terminal Emulator Program C +1905,Secure UP.Link Gateway Protocol +1906,TPortMapperReq +1907,IntraSTAR +1908,Dawn +1909,Global World Link +1910,ultrabac +1911,Starlight Networks Multimedia Transport Protocol +1912,rhp-iibp +1913,armadp +1914,Elm-Momentum +1915,FACELINK +1916,Persoft Persona +1917,nOAgent +1918,Candle Directory Service - NDS +1919,Candle Directory Service - DCH +1920,Candle Directory Service - FERRET +1921,NoAdmin +1922,Tapestry +1923,SPICE +1924,XIIP +1930,Drive AppServer +1931,AMD SCHED +1944,close-combat +1945,dialogic-elmd +1946,tekpls +1947,hlserver +1948,eye2eye +1949,ISMA Easdaq Live +1950,ISMA Easdaq Test +1951,bcs-lmserver +1952,mpnjsc +1953,Rapid Base +1961,BTS APPSERVER +1962,BIAP-MP +1963,WebMachine +1964,SOLID E ENGINE +1965,Tivoli NPM +1966,Slush +1967,SNS Quote +1972,Cache +1973,Data Link Switching Remote Access Protocol +1974,DRP +1975,TCO Flash Agent +1976,TCO Reg Agent +1977,TCO Address Book +1978,UniSQL +1979,UniSQL Java +1984,BB +1985,Hot Standby Router Protocol +1986,cisco license management +1987,cisco RSRB Priority 1 port +1988,cisco RSRB Priority 2 port +1989,MHSnet system +1990,cisco STUN Priority 1 port +1991,cisco STUN Priority 2 port +1992,IPsendmsg +1993,cisco SNMP TCP port +1994,cisco serial tunnel port +1995,cisco perf port +1996,cisco Remote SRB port +1997,cisco Gateway Discovery Protocol +1998,cisco X.25 service (XOT) +1999,cisco identification port / SubSeven (Windows Trojan) / Backdoor (Windows Trojan) +2000,Remotely Anywhere / VIA NET.WORKS PostOffice Plus +2001,Cisco mgmt / Remotely Anywhere +2002,globe +2003,GNU finger +2004,mailbox +2005,encrypted symmetric telnet/login +2006,invokator +2007,dectalk +2008,conf +2009,news +2010,search +2011,raid +2012,ttyinfo +2013,raid-am +2014,troff +2015,cypress +2016,bootserver +2017,cypress-stat +2018,terminaldb +2019,whosockami +2020,xinupageserver +2021,servexec +2022,down +2023,xinuexpansion3 +2024,xinuexpansion4 +2025,ellpack +2026,scrabble +2027,shadowserver +2028,submitserver +2030,device2 +2032,blackboard +2033,glogger +2034,scoremgr +2035,imsldoc +2038,objectmanager +2040,lam +2041,W32.Korgo Worm / interbase +2042,isis +2043,isis-bcast +2044,rimsl +2045,cdfunc +2046,sdfunc +2047,dls +2048,dls-monitor +2049,Network File System - Sun Microsystems +2053,Kerberos de-multiplexer +2054,distrib-net +2065,Data Link Switch Read Port Number +2067,Data Link Switch Write Port Number +2080,Wingate +2090,Load Report Protocol +2091,PRP +2092,Descent 3 +2093,NBX CC +2094,NBX AU +2095,NBX SER +2096,NBX DIR +2097,Jet Form Preview +2098,Dialog Port +2099,H.225.0 Annex G +2100,amiganetfs +2101,Microsoft Message Queuing / rtcm-sc104 +2102,Zephyr server +2103,Microsoft Message Queuing RPC / Zephyr serv-hm connection +2104,Zephyr hostmanager +2105,Microsoft Message Queuing RPC / MiniPay +2106,MZAP +2107,Microsoft Message Queuing Management / BinTec Admin +2108,Comcam +2109,Ergolight +2110,UMSP +2111,DSATP +2112,Idonix MetaNet +2113,HSL StoRM +2114,NEWHEIGHTS +2115,KDM / Bugs (Windows Trojan) +2116,CCOWCMR +2117,MENTACLIENT +2118,MENTASERVER +2119,GSIGATEKEEPER +2120,Quick Eagle Networks CP +2121,CCProxy FTP / SCIENTIA-SSDB +2122,CauPC Remote Control +2123,GTP-Control Plane (3GPP) +2124,ELATELINK +2125,LOCKSTEP +2126,PktCable-COPS +2127,INDEX-PC-WB +2128,Net Steward Control +2129,cs-live.com +2130,SWC-XDS +2131,Avantageb2b +2132,AVAIL-EPMAP +2133,ZYMED-ZPP +2134,AVENUE +2135,Grid Resource Information Server +2136,APPWORXSRV +2137,CONNECT +2138,UNBIND-CLUSTER +2139,IAS-AUTH +2140,IAS-REG +2141,IAS-ADMIND +2142,TDM-OVER-IP +2143,Live Vault Job Control +2144,Live Vault Fast Object Transfer +2145,Live Vault Remote Diagnostic Console Support +2146,Live Vault Admin Event Notification +2147,Live Vault Authentication +2148,VERITAS UNIVERSAL COMMUNICATION LAYER +2149,ACPTSYS +2150,DYNAMIC3D +2151,DOCENT +2152,GTP-User Plane (3GPP) +2165,X-Bone API +2166,IWSERVER +2180,Millicent Vendor Gateway Server +2181,eforward +2190,TiVoConnect Beacon +2191,TvBus Messaging +2200,ICI +2201,Advanced Training System Program +2202,Int. Multimedia Teleconferencing Cosortium +2213,Kali +2220,Ganymede +2221,Rockwell CSP1 +2222,Rockwell CSP2 +2223,Rockwell CSP3 +2232,IVS Video default +2233,INFOCRYPT +2234,DirectPlay +2235,Sercomm-WLink +2236,Nani +2237,Optech Port1 License Manager +2238,AVIVA SNA SERVER +2239,Image Query +2240,RECIPe +2241,IVS Daemon +2242,Folio Remote Server +2243,Magicom Protocol +2244,NMS Server +2245,HaO +2279,xmquery +2280,LNVPOLLER +2281,LNVCONSOLE +2282,LNVALARM +2283,Dumaru.Y (Windows trojan) / LNVSTATUS +2284,LNVMAPS +2285,LNVMAILMON +2286,NAS-Metering +2287,DNA +2288,NETML +2294,Konshus License Manager (FLEX) +2295,Advant License Manager +2296,Theta License Manager (Rainbow) +2297,D2K DataMover 1 +2298,D2K DataMover 2 +2299,PC Telecommute +2300,CVMMON +2301,Compaq HTTP +2302,Bindery Support +2303,Proxy Gateway +2304,Attachmate UTS +2305,MT ScaleServer +2306,TAPPI BoxNet +2307,pehelp +2308,sdhelp +2309,SD Server +2310,SD Client +2311,Message Service +2313,IAPP (Inter Access Point Protocol) +2314,CR WebSystems +2315,Precise Sft. +2316,SENT License Manager +2317,Attachmate G32 +2318,Cadence Control +2319,InfoLibria +2320,Siebel NS +2321,RDLAP over UDP +2322,ofsd +2323,3d-nfsd +2324,Cosmocall +2325,Design Space License Management +2326,IDCP +2327,xingcsm +2328,Netrix SFTM +2329,NVD +2330,TSCCHAT +2331,AGENTVIEW +2332,RCC Host +2333,SNAPP +2334,ACE Client Auth +2335,ACE Proxy +2336,Apple UG Control +2337,ideesrv +2338,Norton Lambert +2339,3Com WebView +2340,WRS Registry +2341,XIO Status +2342,Seagate Manage Exec +2343,nati logos +2344,fcmsys +2345,dbm +2346,Game Connection Port +2347,Game Announcement and Location +2348,Information to query for game status +2349,Diagnostics Port +2350,psbserver +2351,psrserver +2352,pslserver +2353,pspserver +2354,psprserver +2355,psdbserver +2356,GXT License Managemant +2357,UniHub Server +2358,Futrix +2359,FlukeServer +2360,NexstorIndLtd +2361,TL1 +2362,digiman +2363,Media Central NFSD +2364,OI-2000 +2365,dbref +2366,qip-login +2367,Service Control +2368,OpenTable +2369,ACS2000 DSP +2370,L3-HBMon +2381,Compaq HTTPS +2382,Microsoft OLAP +2383,Microsoft OLAP +2384,SD-REQUEST +2389,OpenView Session Mgr +2390,RSMTP +2391,3COM Net Management +2392,Tactical Auth +2393,MS OLAP 1 +2394,MS OLAP 2 +2395,LAN900 Remote +2396,Wusage +2397,NCL +2398,Orbiter +2399,FileMaker Inc. - Data Access Layer +2400,OpEquus Server +2401,cvspserver +2402,TaskMaster 2000 Server +2403,TaskMaster 2000 Web +2404,IEC870-5-104 +2405,TRC Netpoll +2406,JediServer +2407,Orion +2408,OptimaNet +2409,SNS Protocol +2410,VRTS Registry +2411,Netwave AP Management +2412,CDN +2413,orion-rmi-reg +2414,Interlingua +2415,COMTEST +2416,RMT Server +2417,Composit Server +2418,cas +2419,Attachmate S2S +2420,DSL Remote Management +2421,G-Talk +2422,CRMSBITS +2423,RNRP +2424,KOFAX-SVR +2425,Fujitsu App Manager +2426,Appliant TCP +2427,Media Gateway Control Protocol Gateway +2428,One Way Trip Time +2429,FT-ROLE +2430,venus +2431,venus-se +2432,codasrv +2433,codasrv-se +2434,pxc-epmap +2435,OptiLogic +2436,TOP/X +2437,UniControl +2438,MSP +2439,SybaseDBSynch +2440,Spearway Lockers +2441,pvsw-inet +2442,Netangel +2443,PowerClient Central Storage Facility +2444,BT PP2 Sectrans +2445,DTN1 +2446,bues_service +2447,OpenView NNM daemon +2448,hpppsvr +2449,RATL +2450,netadmin +2451,netchat +2452,SnifferClient +2453,madge-om +2454,IndX-DDS +2455,WAGO-IO-SYSTEM +2456,altav-remmgt +2457,Rapido_IP +2458,griffin +2459,Community +2460,ms-theater +2461,qadmifoper +2462,qadmifevent +2463,Symbios Raid +2464,DirecPC SI +2465,Load Balance Management +2466,Load Balance Forwarding +2467,High Criteria +2468,qip_msgd +2469,MTI-TCS-COMM +2470,taskman port +2471,SeaODBC +2472,C3 +2473,Aker-cdp +2474,Vital Analysis +2475,ACE Server +2476,ACE Server Propagation +2477,SecurSight Certificate Valifation Service +2478,SecurSight Authentication Server (SLL) +2479,SecurSight Event Logging Server (SSL) +2480,Lingwood's Detail +2481,Oracle GIOP +2482,Oracle GIOP SSL +2483,Oracle TTC +2484,Oracle TTC SSL +2485,Net Objects1 +2486,Net Objects2 +2487,Policy Notice Service +2488,Moy Corporation +2489,TSILB +2490,qip_qdhcp +2491,Conclave CPP +2492,GROOVE +2493,Talarian MQS +2494,BMC AR +2495,Fast Remote Services +2496,DIRGIS +2497,Quad DB +2498,ODN-CasTraq +2499,UniControl +2500,Resource Tracking system server +2501,Resource Tracking system client +2502,Kentrox Protocol +2503,NMS-DPNSS +2504,WLBS +2505,torque-traffic +2506,jbroker +2507,spock +2508,JDataStore +2509,fjmpss +2510,fjappmgrbulk +2511,Metastorm +2512,Citrix IMA +2513,Citrix ADMIN +2514,Facsys NTP +2515,Facsys Router +2516,Main Control +2517,H.323 Annex E call signaling transport +2518,Willy +2519,globmsgsvc +2520,pvsw +2521,Adaptec Manager +2522,WinDb +2523,Qke LLC V.3 +2524,Optiwave License Management +2525,MS V-Worlds +2526,EMA License Manager +2527,IQ Server +2528,NCR CCL +2529,UTS FTP +2530,VR Commerce +2531,ITO-E GUI +2532,OVTOPMD +2533,SnifferServer +2534,Combox Web Access +2535,W32.Beagle trojan / MADCAP +2536,btpp2audctr1 +2537,Upgrade Protocol +2538,vnwk-prapi +2539,VSI Admin +2540,LonWorks +2541,LonWorks2 +2542,daVinci +2543,REFTEK +2544,Novell ZEN +2545,sis-emt +2546,vytalvaultbrtp +2547,vytalvaultvsmp +2548,vytalvaultpipe +2549,IPASS +2550,ADS +2551,ISG UDA Server +2552,Call Logging +2553,efidiningport +2554,VCnet-Link v10 +2555,Compaq WCP +2556,W32.Beagle.N trojan / MADCAP / nicetec-nmsvc +2557,nicetec-mgmt +2558,PCLE Multi Media +2559,LSTP +2560,labrat +2561,MosaixCC +2562,Delibo +2563,CTI Redwood +2564,HP 3000 NS/VT block mode telnet +2565,Coordinator Server +2566,pcs-pcw +2567,Cisco Line Protocol +2568,SPAM TRAP +2569,Sonus Call Signal +2570,HS Port +2571,CECSVC +2572,IBP +2573,Trust Establish +2574,Blockade BPSP +2575,HL7 +2576,TCL Pro Debugger +2577,Scriptics Lsrvr +2578,RVS ISDN DCP +2579,mpfoncl +2580,Tributary +2581,ARGIS TE +2582,ARGIS DS +2583,MON / Wincrash2 +2584,cyaserv +2585,NETX Server +2586,NETX Agent +2587,MASC +2588,Privilege +2589,quartus tcl +2590,idotdist +2591,Maytag Shuffle +2592,netrek +2593,MNS Mail Notice Service +2594,Data Base Server +2595,World Fusion 1 +2596,World Fusion 2 +2597,Homestead Glory +2598,Citrix MA Client +2599,Meridian Data +2600,HPSTGMGR +2601,discp client +2602,discp server +2603,Service Meter +2604,NSC CCS +2605,NSC POSA +2606,Dell Netmon +2607,Dell Connection +2608,Wag Service +2609,System Monitor +2610,VersaTek +2611,LIONHEAD +2612,Qpasa Agent +2613,SMNTUBootstrap +2614,Never Offline +2615,firepower +2616,appswitch-emp +2617,Clinical Context Managers +2618,Priority E-Com +2619,bruce +2620,LPSRecommender +2621,Miles Apart Jukebox Server +2622,MetricaDBC +2623,LMDP +2624,Aria +2625,Blwnkl Port +2626,gbjd816 +2627,Moshe Beeri +2628,DICT +2629,Sitara Server +2630,Sitara Management +2631,Sitara Dir +2632,IRdg Post +2633,InterIntelli +2634,PK Electronics +2635,Back Burner +2636,Solve +2637,Import Document Service +2638,Sybase Anywhere +2639,AMInet +2640,Sabbagh Associates Licence Manager +2641,HDL Server +2642,Tragic +2643,GTE-SAMP +2644,Travsoft IPX Tunnel +2645,Novell IPX CMD +2646,AND Licence Manager +2647,SyncServer +2648,Upsnotifyprot +2649,VPSIPPORT +2650,eristwoguns +2651,EBInSite +2652,InterPathPanel +2653,Sonus +2654,Corel VNC Admin +2655,UNIX Nt Glue +2656,Kana +2657,SNS Dispatcher +2658,SNS Admin +2659,SNS Query +2660,GC Monitor +2661,OLHOST +2662,BinTec-CAPI +2663,BinTec-TAPI +2664,Command MQ GM +2665,Command MQ PM +2666,extensis +2667,Alarm Clock Server +2668,Alarm Clock Client +2669,TOAD +2670,TVE Announce +2671,newlixreg +2672,nhserver +2673,First Call 42 +2674,ewnn +2675,TTC ETAP +2676,SIMSLink +2677,Gadget Gate 1 Way +2678,Gadget Gate 2 Way +2679,Sync Server SSL +2680,pxc-sapxom +2681,mpnjsomb +2682,SRSP +2683,NCDLoadBalance +2684,mpnjsosv +2685,mpnjsocl +2686,mpnjsomg +2687,pq-lic-mgmt +2688,md-cf-HTTP +2689,FastLynx +2690,HP NNM Embedded Database +2691,IT Internet +2692,Admins LMS +2693,belarc-HTTP +2694,pwrsevent +2695,VSPREAD +2696,Unify Admin +2697,Oce SNMP Trap Port +2698,MCK-IVPIP +2699,Csoft Plus Client +2700,tqdata +2701,SMS Remote Control (control) +2702,SMS Remote Control (data) +2703,SMS Remote Control (chat) +2704,SMS Remote File Transfer +2705,SDS Admin +2706,NCD Mirroring +2707,EMCSYMAPIPORT +2708,Banyan-Net +2709,Supermon +2710,SSO Service +2711,SSO Control +2712,Axapta Object Communication Protocol +2713,Raven1 +2714,Raven2 +2715,HPSTGMGR2 +2716,Inova IP Disco +2717,PN REQUESTER +2718,PN REQUESTER 2 +2719,Scan & Change +2720,wkars +2721,Smart Diagnose +2722,Proactive Server +2723,WatchDog NT +2724,qotps +2725,SQL Analysis Services / MSOLAP PTP2 +2726,TAMS +2727,Media Gateway Control Protocol Call Agent +2728,SQDR +2729,TCIM Control +2730,NEC RaidPlus +2731,NetDragon Messanger +2732,G5M +2733,Signet CTF +2734,CCS Software +2735,Monitor Console +2736,RADWIZ NMS SRV +2737,SRP Feedback +2738,NDL TCP-OSI Gateway +2739,TN Timing +2740,Alarm +2741,TSB +2742,TSB2 +2743,murx +2744,honyaku +2745,W32.Beagle.C trojan) / URBISNET +2746,CPUDPENCAP +2747,yk.fujitsu.co.jp +2748,yk.fujitsu.co.jp +2749,yk.fujitsu.co.jp +2750,yk.fujitsu.co.jp +2751,yk.fujitsu.co.jp +2752,RSISYS ACCESS +2753,de-spot +2754,APOLLO CC +2755,Express Pay +2756,simplement-tie +2757,CNRP +2758,APOLLO Status +2759,APOLLO GMS +2760,Saba MS +2761,DICOM ISCL +2762,DICOM TLS +2763,Desktop DNA +2764,Data Insurance +2765,qip-audup +2766,Compaq SCP +2767,UADTC +2768,UACS +2769,Single Point MVS +2770,Veronica +2771,Vergence CM +2772,auris +2773,PC Backup +2774,PC Backup +2775,SMMP +2776,Ridgeway Systems & Software +2777,Ridgeway Systems & Software +2778,Gwen-Sonya +2779,LBC Sync +2780,LBC Control +2781,whosells +2782,everydayrc +2783,AISES +2784,world wide web - development +2785,aic-np +2786,aic-oncrpc - Destiny MCD database +2787,piccolo - Cornerstone Software +2788,NetWare Loadable Module - Seagate Software +2789,Media Agent +2790,PLG Proxy +2791,MT Port Registrator +2792,f5-globalsite +2793,initlsmsad +2794,aaftp +2795,LiveStats +2796,ac-tech +2797,esp-encap +2798,TMESIS-UPShot +2799,ICON Discover +2800,ACC RAID +2801,IGCP +2802,Veritas TCP1 +2803,btprjctrl +2804,Telexis VTU +2805,WTA WSP-S +2806,cspuni +2807,cspmulti +2808,J-LAN-P +2809,CORBA LOC +2810,Active Net Steward +2811,GSI FTP +2812,atmtcp +2813,llm-pass +2814,llm-csv +2815,LBC Measurement +2816,LBC Watchdog +2817,NMSig Port +2818,rmlnk +2819,FC Fault Notification +2820,UniVision +2821,vml_dms +2822,ka0wuc +2823,CQG Net/LAN +2826,slc systemlog +2827,slc ctrlrloops +2828,ITM License Manager +2829,silkp1 +2830,silkp2 +2831,silkp3 +2832,silkp4 +2833,glishd +2834,EVTP +2835,EVTP-DATA +2836,catalyst +2837,Repliweb +2838,Starbot +2839,NMSigPort +2840,l3-exprt +2841,l3-ranger +2842,l3-hawk +2843,PDnet +2844,BPCP POLL +2845,BPCP TRAP +2846,AIMPP Hello +2847,AIMPP Port Req +2848,AMT-BLC-PORT +2849,FXP +2850,MetaConsole +2851,webemshttp +2852,bears-01 +2853,ISPipes +2854,InfoMover +2856,cesdinv +2857,SimCtIP +2858,ECNP +2859,Active Memory +2860,Dialpad Voice 1 +2861,Dialpad Voice 2 +2862,TTG Protocol +2863,Sonar Data +2864,main 5001 cmd +2865,pit-vpn +2866,lwlistener +2867,esps-portal +2868,NPEP Messaging +2869,SSDP event notification / ICSLAP +2870,daishi +2871,MSI Select Play +2872,CONTRACT +2873,PASPAR2 ZoomIn +2874,dxmessagebase1 +2875,dxmessagebase2 +2876,SPS Tunnel +2877,BLUELANCE +2878,AAP +2879,ucentric-ds +2880,synapse +2881,NDSP +2882,NDTP +2883,NDNP +2884,Flash Msg +2885,TopFlow +2886,RESPONSELOGIC +2887,aironet +2888,SPCSDLOBBY +2889,RSOM +2890,CSPCLMULTI +2891,CINEGRFX-ELMD License Manager +2892,SNIFFERDATA +2893,VSECONNECTOR +2894,ABACUS-REMOTE +2895,NATUS LINK +2896,ECOVISIONG6-1 +2897,Citrix RTMP +2898,APPLIANCE-CFG +2899,case.nm.fujitsu.co.jp +2900,magisoft.com +2901,ALLSTORCNS +2902,NET ASPI +2903,SUITCASE +2904,M2UA +2905,M3UA +2906,CALLER9 +2907,WEBMETHODS B2B +2908,mao +2909,Funk Dialout +2910,TDAccess +2911,Blockade +2912,Epicon +2913,Booster Ware +2914,Game Lobby +2915,TK Socket +2916,Elvin Server +2917,Elvin Client +2918,Kasten Chase Pad +2919,ROBOER +2920,ROBOEDA +2921,CESD Contents Delivery Management +2922,CESD Contents Delivery Data Transfer +2923,WTA-WSP-WTP-S +2924,PRECISE-VIP +2925,Firewall Redundancy Protocol +2926,MOBILE-FILE-DL +2927,UNIMOBILECTRL +2928,REDSTONE-CPSS +2929,PANJA-WEBADMIN +2930,PANJA-WEBLINX +2931,Circle-X +2932,INCP +2933,4-TIER OPM GW +2934,4-TIER OPM CLI +2935,QTP +2936,OTPatch +2937,PNACONSULT-LM +2938,SM-PAS-1 +2939,SM-PAS-2 +2940,SM-PAS-3 +2941,SM-PAS-4 +2942,SM-PAS-5 +2943,TTNRepository +2944,Megaco H-248 +2945,H248 Binary +2946,FJSVmpor +2947,GPSD +2948,WAP PUSH +2949,WAP PUSH SECURE +2950,ESIP +2951,OTTP +2952,MPFWSAS +2953,OVALARMSRV +2954,OVALARMSRV-CMD +2955,CSNOTIFY +2956,OVRIMOSDBMAN +2957,JAMCT5 +2958,JAMCT6 +2959,RMOPAGT +2960,DFOXSERVER +2961,BOLDSOFT-LM +2962,IPH-POLICY-CLI +2963,IPH-POLICY-ADM +2964,BULLANT SRAP +2965,BULLANT RAP +2966,IDP-INFOTRIEVE +2967,SSC-AGENT +2968,ENPP +2969,UPnP / ESSP +2970,INDEX-NET +2971,Net Clip +2972,PMSM Webrctl +2973,SV Networks +2974,Signal +2975,Fujitsu Configuration Management Service +2976,CNS Server Port +2977,TTCs Enterprise Test Access Protocol - NS +2978,TTCs Enterprise Test Access Protocol - DS +2979,H.263 Video Streaming +2980,Instant Messaging Service +2981,MYLXAMPORT +2982,IWB-WHITEBOARD +2983,NETPLAN +2984,HPIDSADMIN +2985,HPIDSAGENT +2986,STONEFALLS +2987,IDENTIFY +2988,CLASSIFY +2989,ZARKOV +2990,BOSCAP +2991,WKSTN-MON +2992,ITB301 +2993,VERITAS VIS1 +2994,VERITAS VIS2 +2995,IDRS +2996,vsixml +2997,REBOL +2998,Real Secure +2999,RemoteWare Unassigned +3000,RemoteWare Client +3001,Phatbot Worm / Redwood Broker +3002,RemoteWare Server +3003,CGMS +3004,Csoft Agent +3005,Genius License Manager +3006,Instant Internet Admin +3007,Lotus Mail Tracking Agent Protocol +3008,Midnight Technologies +3009,PXC-NTFY +3010,Telerate Workstation +3011,Trusted Web +3012,Trusted Web Client +3013,Gilat Sky Surfer +3014,Broker Service +3015,NATI DSTP +3016,Notify Server +3017,Event Listener +3018,Service Registry +3019,Resource Manager +3020,CIFS +3021,AGRI Server +3022,CSREGAGENT +3023,magicnotes +3024,NDS_SSO +3025,Arepa Raft +3026,AGRI Gateway +3027,LiebDevMgmt_C +3028,LiebDevMgmt_DM +3029,LiebDevMgmt_A +3030,Arepa Cas +3031,AgentVU +3032,Redwood Chat +3033,PDB +3034,Osmosis AEEA +3035,FJSV gssagt +3036,Hagel DUMP +3037,HP SAN Mgmt +3038,Santak UPS +3039,Cogitate Inc. +3040,Tomato Springs +3041,di-traceware +3042,journee +3043,BRP +3045,ResponseNet +3046,di-ase +3047,Fast Security HL Server +3048,Sierra Net PC Trader +3049,NSWS +3050,gds_db +3051,Galaxy Server +3052,APCPCNS +3053,dsom-server +3054,AMT CNF PROT +3055,Policy Server +3056,CDL Server +3057,GoAhead FldUp +3058,videobeans +3059,qsoft +3060,interserver +3061,cautcpd +3062,ncacn-ip-tcp +3063,ncadg-ip-udp +3065,slinterbase +3066,NETATTACHSDMP +3067,W32.Korgo Worm / FJHPJP +3068,ls3 Broadcast +3069,ls3 +3070,MGXSWITCH +3075,Orbix 2000 Locator +3076,Orbix 2000 Config +3077,Orbix 2000 Locator SSL +3078,Orbix 2000 Locator SSL +3079,LV Front Panel +3080,stm_pproc +3081,TL1-LV +3082,TL1-RAW +3083,TL1-TELNET +3084,ITM-MCCS +3085,PCIHReq +3086,JDL-DBKitchen +3105,Cardbox +3106,Cardbox HTTP +3127,W32.Mydoom.A virus +3128,Squid HTTP Proxy / W32.Mydoom.B virus +3129,Master's Paradise (Windows Trojan) +3130,ICPv2 +3131,Net Book Mark +3141,VMODEM +3142,RDC WH EOS +3143,Sea View +3144,Tarantella +3145,CSI-LFAP +3147,RFIO +3148,NetMike Game Administrator +3149,NetMike Game Server +3150,NetMike Assessor Administrator +3151,NetMike Assessor +3180,Millicent Broker Server +3181,BMC Patrol Agent +3182,BMC Patrol Rendezvous +3262,NECP +3264,cc:mail/lotus +3265,Altav Tunnel +3266,NS CFG Server +3267,IBM Dial Out +3268,Microsoft Global Catalog +3269,Microsoft Global Catalog with LDAP/SSL +3270,Verismart +3271,CSoft Prev Port +3272,Fujitsu User Manager +3273,Simple Extensible Multiplexed Protocol +3274,Ordinox Server +3275,SAMD +3276,Maxim ASICs +3277,AWG Proxy +3278,LKCM Server +3279,admind +3280,VS Server +3281,SYSOPT +3282,Datusorb +3283,Net Assistant +3284,4Talk +3285,Plato +3286,E-Net +3287,DIRECTVDATA +3288,COPS +3289,ENPC +3290,CAPS LOGISTICS TOOLKIT - LM +3291,S A Holditch & Associates - LM +3292,Cart O Rama +3293,fg-fps +3294,fg-gip +3295,Dynamic IP Lookup +3296,Rib License Manager +3297,Cytel License Manager +3298,Transview +3299,pdrncs +3300,bmc-patrol-agent +3301,Unathorised use by SAP R/3 +3302,MCS Fastmail +3303,OP Session Client +3304,OP Session Server +3305,ODETTE-FTP +3306,MySQL +3307,OP Session Proxy +3308,TNS Server +3309,TNS ADV +3310,Dyna Access +3311,MCNS Tel Ret +3312,Application Management Server +3313,Unify Object Broker +3314,Unify Object Host +3315,CDID +3316,AICC/CMI +3317,VSAI PORT +3318,Swith to Swith Routing Information Protocol +3319,SDT License Manager +3320,Office Link 2000 +3321,VNSSTR +3325,isi.edu +3326,SFTU +3327,BBARS +3328,Eaglepoint License Manager +3329,HP Device Disc +3330,MCS Calypso ICF +3331,MCS Messaging +3332,MCS Mail Server +3333,DEC Notes +3334,Direct TV Webcasting +3335,Direct TV Software Updates +3336,Direct TV Tickers +3337,Direct TV Data Catalog +3338,OMF data b +3339,OMF data l +3340,OMF data m +3341,OMF data h +3342,WebTIE +3343,MS Cluster Net +3344,BNT Manager +3345,Influence +3346,Trnsprnt Proxy +3347,Phoenix RPC +3348,Pangolin Laser +3349,Chevin Services +3350,FINDVIATV +3351,BTRIEVE +3352,SSQL +3353,FATPIPE +3354,SUITJD +3355,Hogle (proxy backdoor) / Ordinox Dbase +3356,UPNOTIFYPS +3357,Adtech Test IP +3358,Mp Sys Rmsvr +3359,WG NetForce +3360,KV Server +3361,KV Agent +3362,DJ ILM +3363,NATI Vi Server +3364,Creative Server +3365,Content Server +3366,Creative Partner +3371,ccm.jf.intel.com +3372,Microsoft Distributed Transaction Coordinator (MSDTC) / TIP 2 +3373,Lavenir License Manager +3374,Cluster Disc +3375,VSNM Agent +3376,CD Broker +3377,Cogsys Network License Manager +3378,WSICOPY +3379,SOCORFS +3380,SNS Channels +3381,Geneous +3382,Fujitsu Network Enhanced Antitheft function +3383,Enterprise Software Products License Manager +3384,Cluster Management Services +3385,qnxnetman +3386,GPRS Data +3387,Back Room Net +3388,CB Server +3389,MS Terminal Server +3390,Distributed Service Coordinator +3391,SAVANT +3392,EFI License Management +3393,D2K Tapestry Client to Server +3394,D2K Tapestry Server to Server +3395,Dyna License Manager (Elam) +3396,Printer Agent +3397,Cloanto License Manager +3398,Mercantile +3399,CSMS +3400,CSMS2 +3401,filecast +3410,Backdoor.OptixPro.13 +3421,Bull Apprise portmapper +3454,Apple Remote Access Protocol +3455,RSVP Port +3456,VAT default data +3457,VAT default control +3458,D3WinOsfi +3459,TIP Integral +3460,EDM Manger +3461,EDM Stager +3462,EDM STD Notify +3463,EDM ADM Notify +3464,EDM MGR Sync +3465,EDM MGR Cntrl +3466,WORKFLOW +3467,RCST +3468,TTCM Remote Controll +3469,Pluribus +3470,jt400 +3471,jt400-ssl +3535,MS-LA +3563,Watcom Debug +3572,harlequin.co.uk +3672,harlequinorb +3689,Apple Digital Audio Access Protocol +3802,VHD +3845,V-ONE Single Port Proxy +3862,GIGA-POCKET +3875,PNBSCADA +3900,Unidata UDT OS +3984,MAPPER network node manager +3985,MAPPER TCP/IP server +3986,MAPPER workstation server +3987,Centerline +4000,Terabase +4001,Cisco mgmt / NewOak +4002,pxc-spvr-ft +4003,pxc-splr-ft +4004,pxc-roid +4005,pxc-pin +4006,pxc-spvr +4007,pxc-splr +4008,NetCheque accounting +4009,Chimera HWM +4010,Samsung Unidex +4011,Alternate Service Boot +4012,PDA Gate +4013,ACL Manager +4014,TAICLOCK +4015,Talarian Mcast +4016,Talarian Mcast +4017,Talarian Mcast +4018,Talarian Mcast +4019,Talarian Mcast +4045,nfs-lockd +4096,BRE (Bridge Relay Element) +4097,Patrol View +4098,drmsfsd +4099,DPCP +4132,NUTS Daemon +4133,NUTS Bootp Server +4134,NIFTY-Serve HMI protocol +4141,Workflow Server +4142,Document Server +4143,Document Replication +4144,Compuserve pc windows +4160,Jini Discovery +4199,EIMS ADMIN +4299,earth.path.net +4300,Corel CCam +4321,Remote Who Is +4333,mini-sql server +4343,UNICALL +4344,VinaInstall +4345,Macro 4 Network AS +4346,ELAN LM +4347,LAN Surveyor +4348,ITOSE +4349,File System Port Map +4350,Net Device +4351,PLCY Net Services +4353,F5 iQuery +4397,Phatbot Worm +4442,Saris +4443,Pharos +4444,AdSubtract / NV Video default +4445,UPNOTIFYP +4446,N1-FWP +4447,N1-RMGMT +4448,ASC Licence Manager +4449,PrivateWire +4450,Camp +4451,CTI System Msg +4452,CTI Program Load +4453,NSS Alert Manager +4454,NSS Agent Manager +4455,PR Chat User +4456,PR Chat Server +4457,PR Register +4500,sae-urn +4501,urn-x-cdchoice +4545,WorldScores +4546,SF License Manager (Sentinel) +4547,Lanner License Manager +4557,FAX transmission service +4559,HylaFAX client-service protocol +4567,TRAM +4568,BMC Reporting +4600,Piranha1 +4601,Piranha2 +4661,eDonkey2k +4662,eDonkey2k +4663,eDonkey +4665,eDonkey2k +4672,remote file access server +4675,eMule +4711,eMule +4751,W32.Beagle.V trojan +4772,eMule +4800,Icona Instant Messenging System +4801,Icona Web Embedded Chat +4802,Icona License System Server +4820,Backdoor.Tuxter +4827,HTCP +4837,Varadero-0 +4838,Varadero-1 +4868,Photon Relay +4869,Photon Relay Debug +4885,ABBS +4899,RAdmin Win32 remote control +4983,AT&T Intercom +5000,UPnP / filmaker.com / Socket de Troie (Windows Trojan) +5001,filmaker.com / Socket de Troie (Windows Trojan) +5002,radio free ethernet +5003,FileMaker Inc. - Proprietary transport +5004,avt-profile-1 +5005,avt-profile-2 +5006,wsm server +5007,wsm server ssl +5010,TelepathStart +5011,TelepathAttack +5020,zenginkyo-1 +5021,zenginkyo-2 +5042,asnaacceler8db +5050,Yahoo Messenger / multimedia conference control tool +5051,ITA Agent +5052,ITA Manager +5055,UNOT +5060,SIP +5069,I/Net 2000-NPR +5071,PowerSchool +5093,Sentinel LM +5099,SentLM Srv2Srv +5101,Yahoo! Messenger +5145,RMONITOR SECURE +5150,Ascend Tunnel Management Protocol +5151,ESRI SDE Instance +5152,ESRI SDE Instance Discovery +5165,ife_1corp +5190,America-Online +5191,AmericaOnline1 +5192,AmericaOnline2 +5193,AmericaOnline3 +5200,Targus AIB 1 +5201,Targus AIB 2 +5202,Targus TNTS 1 +5203,Targus TNTS 2 +5222,Jabber Server +5232,SGI Distribution Graphics +5236,padl2sim +5272,PK +5300,HA cluster heartbeat +5301,HA cluster general services +5302,HA cluster configuration +5303,HA cluster probing +5304,HA Cluster Commands +5305,HA Cluster Test +5306,Sun MC Group +5307,SCO AIP +5308,CFengine +5309,J Printer +5310,Outlaws +5311,TM Login +5373,W32.Gluber.B@mm +5400,Excerpt Search / Blade Runner (Windows Trojan) +5401,Excerpt Search Secure / Blade Runner (Windows Trojan) +5402,MFTP / Blade Runner (Windows Trojan) +5403,HPOMS-CI-LSTN +5404,HPOMS-DPS-LSTN +5405,NetSupport +5406,Systemics Sox +5407,Foresyte-Clear +5408,Foresyte-Sec +5409,Salient Data Server +5410,Salient User Manager +5411,ActNet +5412,Continuus +5413,WWIOTALK +5414,StatusD +5415,NS Server +5416,SNS Gateway +5417,SNS Agent +5418,MCNTP +5419,DJ-ICE +5420,Cylink-C +5421,Net Support 2 +5422,Salient MUX +5423,VIRTUALUSER +5426,DEVBASIC +5427,SCO-PEER-TTA +5428,TELACONSOLE +5429,Billing and Accounting System Exchange +5430,RADEC CORP +5431,PARK AGENT +5432,postgres database server +5435,Data Tunneling Transceiver Linking (DTTL) +5454,apc-tcp-udp-4 +5455,apc-tcp-udp-5 +5456,apc-tcp-udp-6 +5461,SILKMETER +5462,TTL Publisher +5465,NETOPS-BROKER +5490,Squid HTTP Proxy +5500,fcp-addr-srvr1 +5501,fcp-addr-srvr2 +5502,fcp-srvr-inst1 +5503,fcp-srvr-inst2 +5504,fcp-cics-gw1 +5510,ACE/Server Services +5520,ACE/Server Services +5530,ACE/Server Services +5540,ACE/Server Services +5550,ACE/Server Services / Xtcp 2.0x +5554,Sasser Worm FTP backdoor / SGI ESP HTTP +5555,Personal Agent / W32.Mimail.P@mm +5556,Mtbd (mtb backup) +5559,Enterprise Security Remote Install axent.com +5599,Enterprise Security Remote Install +5600,Enterprise Security Manager +5601,Enterprise Security Agent +5602,A1-MSC +5603,A1-BS +5604,A3-SDUNode +5605,A4-SDUNode +5631,pcANYWHEREdata +5632,pcANYWHEREstat +5678,LinkSys EtherFast Router Remote Administration / Remote Replication Agent Connection +5679,Direct Cable Connect Manager +5680,Canna (Japanese Input) +5713,proshare conf audio +5714,proshare conf video +5715,proshare conf data +5716,proshare conf request +5717,proshare conf notify +5729,Openmail User Agent Layer +5741,IDA Discover Port 1 +5742,IDA Discover Port 2 / Wincrash (Windows Trojan) +5745,fcopy-server +5746,fcopys-server +5755,OpenMail Desk Gateway server +5757,OpenMail X.500 Directory Server +5766,OpenMail NewMail Server +5767,OpenMail Suer Agent Layer (Secure) +5768,OpenMail CMTS Server +5771,NetAgent +5800,VNC Virtual Network Computing +5801,VNC Virtual Network Computing +5813,ICMPD +5859,WHEREHOO +5882,Y3k +5900,VNC Virtual Network Computing +5901,VNC Virtual Network Computing +5968,mppolicy-v5 +5969,mppolicy-mgr +5977,NCD preferences TCP port +5978,NCD diagnostic TCP port +5979,NCD configuration TCP port +5980,VNC Virtual Network Computing +5981,VNC Virtual Network Computing +5987,Solaris Web Enterprise Management RMI +5997,NCD preferences telnet port +5998,NCD diagnostic telnet port +5999,CVSup +6000,X-Windows / W32.LoveGate.ak virus +6001,Cisco mgmt +6003,Half-Life WON server +6063,X Windows System mit.edu +6064,NDL-AHP-SVC +6065,WinPharaoh +6066,EWCTSP +6067,SRB +6068,GSMP +6069,TRIP +6070,Messageasap +6071,SSDTP +6072,DIAGNOSE-PROC +6073,DirectPlay8 +6100,SynchroNet-db +6101,SynchroNet-rtc +6102,SynchroNet-upd +6103,RETS +6104,DBDB +6105,Prima Server +6106,MPS Server +6107,ETC Control +6108,Sercomm-SCAdmin +6109,GLOBECAST-ID +6110,HP SoftBench CM +6111,HP SoftBench Sub-Process Control +6112,dtspcd / Blizzard Battlenet +6123,Backup Express +6129,DameWare +6141,Meta Corporation License Manager +6142,Aspen Technology License Manager +6143,Watershed License Manager +6144,StatSci License Manager - 1 +6145,StatSci License Manager - 2 +6146,Lone Wolf Systems License Manager +6147,Montage License Manager +6148,Ricardo North America License Manager +6149,tal-pod +6253,CRIP +6321,Empress Software Connectivity Server 1 +6322,Empress Software Connectivity Server 2 +6346,Gnutella/Bearshare file sharing Application +6348,Limewire P2P +6389,clariion-evr01 +6400,saegatesoftware.com +6401,saegatesoftware.com +6402,saegatesoftware.com +6403,saegatesoftware.com +6404,saegatesoftware.com +6405,saegatesoftware.com +6406,saegatesoftware.com +6407,saegatesoftware.com +6408,saegatesoftware.com +6409,saegatesoftware.com +6410,saegatesoftware.com +6455,SKIP Certificate Receive +6456,SKIP Certificate Send +6471,LVision License Manager +6500,BoKS Master +6501,BoKS Servc +6502,BoKS Servm +6503,BoKS Clntd +6505,BoKS Admin Private Port +6506,BoKS Admin Public Port +6507,BoKS Dir Server Private Port +6508,BoKS Dir Server Public Port +6547,apc-tcp-udp-1 +6548,apc-tcp-udp-2 +6549,apc-tcp-udp-3 +6550,fg-sysupdate +6558,xdsxdm +6588,AnalogX Web Proxy +6665,Internet Relay Chat +6666,IRC / Windows Media Unicast Service +6667,IRC +6668,IRC +6669,IRC +6670,Vocaltec Global Online Directory / Deep Throat 2 (Windows Trojan) +6672,vision_server +6673,vision_elmd +6699,Napster +6700,Napster / Carracho (server) +6701,KTI/ICAD Nameserver +6701,Napster / Carracho (server) +6711,SubSeven (Windows Trojan) +6723,DDOS communication TCP +6767,BMC PERFORM AGENT +6768,BMC PERFORM MGRD +6776,SubSeven/BackDoor-G (Windows Trojan) +6777,W32.Beagle.A trojan +6789,IBM DB2 +6790,HNMP / IBM DB2 +6831,ambit-lm +6841,Netmo Default +6842,Netmo HTTP +6850,ICCRUSHMORE +6881,BitTorrent Network +6888,MUSE +6891,MS Messenger file transfer +6901,MS Messenger voice calls +6961,JMACT3 +6962,jmevt2 +6963,swismgr1 +6964,swismgr2 +6965,swistrap +6966,swispol +6969,acmsoda +6998,IATP-highPri +6999,IATP-normalPri +7000,IRC / file server itself +7001,WebLogic Server / Callbacks to cache managers +7002,WebLogic Server (SSL) / Half-Life Auth Server / Users & groups database +7003,volume location database +7004,AFS/Kerberos authentication service +7005,volume managment server +7006,error interpretation service +7007,Windows Media Services / basic overseer process +7008,server-to-server updater +7009,remote cache manager service +7010,onlinet uninterruptable power supplies +7011,Talon Discovery Port +7012,Talon Engine +7013,Microtalon Discovery +7014,Microtalon Communications +7015,Talon Webserver +7020,DP Serve +7021,DP Serve Admin +7070,ARCP +7099,lazy-ptop +7100,X Font Service +7121,Virtual Prototypes License Manager +7141,vnet.ibm.com +7161,Catalyst +7174,Clutild +7200,FODMS FLIP +7201,DLIP +7323,3.11 Remote Administration +7326,Internet Citizen's Band +7390,The Swiss Exchange swx.ch +7395,winqedit +7426,OpenView DM Postmaster Manager +7427,OpenView DM Event Agent Manager +7428,OpenView DM Log Agent Manager +7429,OpenView DM rqt communication +7430,OpenView DM xmpv7 api pipe +7431,OpenView DM ovc/xmpv3 api pipe +7437,Faximum +7491,telops-lmd +7511,pafec-lm +7544,FlowAnalyzer DisplayServer +7545,FlowAnalyzer UtilityServer +7566,VSI Omega +7570,Aries Kfinder +7588,Sun License Manager +7597,TROJAN WORM +7633,PMDF Management +7640,CUSeeMe +7777,Oracle App server / cbt +7778,Windows Media Services / Interwise +7781,accu-lmgr +7786,MINIVEND +7932,Tier 2 Data Resource Manager +7933,Tier 2 Business Rules Manager +7967,Supercell +7979,Micromuse-ncps +7980,Quest Vista +7999,iRDMI2 +8000,HTTP/iRDMI +8001,HTTP/VCOM Tunnel +8002,HTTP/Teradata ORDBMS +8007,Apache JServ Protocol +8008,HTTP Alternate +8009,Apache JServ Protocol +8010,Wingate HTTP Proxy +8032,ProEd +8033,MindPrint +8080,HTTP / HTTP Proxy +8081,HTTP / HTTP Proxy +8082,BlackICE Capture +8129,Snapstream PVS Server +8130,INDIGO-VRMI +8131,INDIGO-VBCP +8160,Patrol +8161,Patrol SNMP +8181,IPSwitch IMail / Monitor +8200,TRIVNET +8201,TRIVNET +8204,LM Perfworks +8205,LM Instmgr +8206,LM Dta +8207,LM SServer +8208,LM Webwatcher +8351,Server Find +8376,Cruise ENUM +8377,Cruise SWROUTE +8378,Cruise CONFIG +8379,Cruise DIAGS +8380,Cruise UPDATE +8383,Web Email +8400,cvd +8401,sabarsd +8402,abarsd +8403,admind +8431,Micro PC-Cilin +8450,npmp +8473,Virtual Point to Point +8484,Ipswitch IMail +8554,RTSP Alternate (see port 554) +8733,iBus +8763,MC-APPSERVER +8764,OPENQUEUE +8765,Ultraseek HTTP +8804,truecm +8866,W32.Beagle.B trojan +8880,CDDBP +8888,NewsEDGE server TCP / AnswerBook2 +8889,Desktop Data TCP 1 +8890,Desktop Data TCP 2 +8891,Desktop Data TCP 3: NESS application +8892,Desktop Data TCP 4: FARM product +8893,Desktop Data TCP 5: NewsEDGE/Web application +8894,Desktop Data TCP 6: COAL application +8900,JMB-CDS 1 +8901,JMB-CDS 2 +8967,Win32/Dabber (Windows worm) +8999,Firewall +9000,CSlistener +9001,cisco-xremote +9090,WebSM +9100,HP JetDirect +9160,NetLOCK1 +9161,NetLOCK2 +9162,NetLOCK3 +9163,NetLOCK4 +9164,NetLOCK5 +9200,WAP connectionless session service +9201,WAP session service +9202,WAP secure connectionless session service +9203,WAP secure session service +9204,WAP vCard +9205,WAP vCal +9206,WAP vCard Secure +9207,WAP vCal Secure +9273,BackGate (Windows rootkit) +9274,BackGate (Windows rootkit) +9275,BackGate (Windows rootkit) +9276,BackGate (Windows rootkit) +9277,BackGate (Windows rootkit) +9278,BackGate (Windows rootkit) +9280,HP JetDirect Embedded Web Server +9290,HP JetDirect +9291,HP JetDirect +9292,HP JetDirect +9321,guibase +9343,MpIdcMgr +9344,Mphlpdmc +9374,fjdmimgr +9396,fjinvmgr +9397,MpIdcAgt +9400,InCommand +9500,ismserver +9535,Remote man server +9537,Remote man server, testing +9594,Message System +9595,Ping Discovery Service +9600,MICROMUSE-NCPW +9753,rasadv +9876,Session Director +9888,CYBORG Systems +9898,MonkeyCom / Win32/Dabber (Windows worm) +9899,SCTP TUNNELING +9900,IUA +9909,domaintime +9950,APCPCPLUSWIN1 +9951,APCPCPLUSWIN2 +9952,APCPCPLUSWIN3 +9992,Palace +9993,Palace +9994,Palace +9995,Palace +9996,Sasser Worm shell / Palace +9997,Palace +9998,Distinct32 +9999,distinct / Win32/Dabber (Windows worm) +10000,Webmin / Network Data Management Protocol/ Dumaru.Y (Windows trojan) +10001,queue +10002,poker +10003,gateway +10004,remp +10005,Secure telnet +10007,MVS Capacity +10012,qmaster +10080,Amanda / MyDoom.B (Windows trojan) +10082,Amanda Indexing +10083,Amanda Tape Indexing +10113,NetIQ Endpoint +10114,NetIQ Qcheck +10115,Ganymede Endpoint +10128,BMC-PERFORM-SERVICE DAEMON +10202,Computer Associate License Manager +10203,Computer Associate License Manager +10204,Computer Associate License Manager +10288,Blocks +10520,Acid Shivers (Windows Trojan) +11000,IRISA +11001,Metasys +11111,Viral Computing Environment (VCE) +11117,W32.Beagle.L trojan / URBISNET +11367,ATM UHAS +11523,AOL / AdSubtract AOL Proxy +11720,h323 Call Signal Alternate +11722,RK Test +12000,IBM Enterprise Extender SNA XID Exchange +12001,IBM Enterprise Extender SNA COS Network Priority +12002,IBM Enterprise Extender SNA COS High Priority +12003,IBM Enterprise Extender SNA COS Medium Priority +12004,IBM Enterprise Extender SNA COS Low Priority +12172,HiveP +12345,Netbus (Windows Trojan) +12346,NetBus (Windows Trojan) +12348,BioNet (Windows Trojan) +12349,BioNet (Windows Trojan) +12361,Whack-a-mole (Windows Trojan) +12362,Whack-a-mole (Windows Trojan) +12753,tsaf port +12754,DDOS communication TCP +13160,I-ZIPQD +13223,PowWow Client +13224,PowWow Server +13326,game +13720,BPRD Protocol (VERITAS NetBackup) +13721,BPBRM Protocol (VERITAS NetBackup) +13722,BP Java MSVC Protocol +13782,VERITAS NetBackup +13783,VOPIED Protnocol +13818,DSMCC Config +13819,DSMCC Session Messages +13820,DSMCC Pass-Thru Messages +13821,DSMCC Download Protocol +13822,DSMCC Channel Change Protocol +14001,ITU SCCP (SS7) +14237,Palm Network Hotsync +14247,Mitglieder.H trojan +15104,DDOS communication TCP +16360,netserialext1 +16361,netserialext2 +16367,netserialext3 +16368,netserialext4 +16660,Stacheldraht distributed attack tool client +16959,Subseven DEFCON8 2.1 backdoor remote access tool +16991,INTEL-RCI-MP +17007,isode-dua +17219,Chipper +17300,Kuang2 (Windows trojan) +17569,Infector +17990,Worldspan gateway +18000,Beckman Instruments Inc. +18181,OPSEC CVP +18182,OPSEC UFP +18183,OPSEC SAM +18184,OPSEC LEA +18185,OPSEC OMI +18187,OPSEC ELA +18463,AC Cluster +18753,Shaft distributed attack tool handler agent +18888,APCNECMP +19216,BackGate (Windows rootkit) +19283,Key Server for SASSAFRAS +19315,Key Shadow for SASSAFRAS +19410,hp-sco +19411,hp-sca +19412,HP-SESSMON +19541,JCP Client +20000,DNP +20005,xcept4 (German Telekom's CEPT videotext service) +20031,BakBone NetVault +20034,NetBus 2 Pro (Windows Trojan) +20432,Shaft distributed attack client +20670,Track +20742,Mitglieder.E trojan +20999,At Hand MMP +21554,Girlfriend (Windows Trojan) +21590,VoFR Gateway +21845,webphone +21846,NetSpeak Corp. Directory Services +21847,NetSpeak Corp. Connection Services +21848,NetSpeak Corp. Automatic Call Distribution +21849,NetSpeak Corp. Credit Processing System +22000,SNAPenetIO +22001,OptoControl +22156,Phatbot Worm +22273,wnn6 +22289,Wnn6 (Chinese Input) +22305,Wnn6 (Korean Input) +22321,Wnn6 (Taiwanese Input) +22555,Vocaltec Web Conference +22800,Telerate Information Platform LAN +22951,Telerate Information Platform WAN +23005,W32.HLLW.Nettrash +23006,W32.HLLW.Nettrash +23432,Asylum +23476,Donald Dick +23477,Donald Dick +23485,Shareasa file sharing +24000,med-ltp +24001,med-fsp-rx +24002,med-fsp-tx +24003,med-supp +24004,med-ovw +24005,med-ci +24006,med-net-svc +24386,Intel RCI +24554,BINKP +25000,icl-twobase1 +25001,icl-twobase2 +25002,icl-twobase3 +25003,icl-twobase4 +25004,icl-twobase5 +25005,icl-twobase6 +25006,icl-twobase7 +25007,icl-twobase8 +25008,icl-twobase9 +25009,icl-twobase10 +25555,Mitglieder.D trojan +25793,Vocaltec Address Server +25867,WebCam32 Admin +26000,quake +26208,wnn6-ds +26274,Delta Source (Windows Trojan) +27347,SubSeven / Linux.Ramen.Worm (RedHat Linux) +27374,SubSeven / Linux.Ramen.Worm (RedHat Linux) +27665,Trinoo distributed attack tool Master server control port +27999,TW Authentication/Key Distribution and +30100,Netsphere (Windows Trojan) +30101,Netsphere (Windows Trojan) +30102,Netsphere (Windows Trojan) +30999,Kuang +31337,BO2K +31785,Hack-A-Tack (Windows Trojan) +31787,Hack-A-Tack (Windows Trojan) +31788,Hack-A-Tack (Windows Trojan) +31789,Hack-A-Tack (Windows Trojan) +31791,Hack-A-Tack (Windows Trojan) +32000,XtraMail v1.11 +32768,Filenet TMS +32769,Filenet RPC +32770,Filenet NCH +32771,Solaris RPC +32772,Solaris RPC +32773,Solaris RPC +32774,Solaris RPC +32775,Solaris RPC +32776,Solaris RPC +32777,Solaris RPC +32780,RPC +33434,traceroute use +34324,Big Gluck (Windows Trojan) +36865,KastenX Pipe +40421,Master's Paradise (Windows Trojan) +40422,Master's Paradise (Windows Trojan) +40423,Master's Paradise (Windows Trojan) +40426,Master's Paradise (Windows Trojan) +40841,CSCP +42424,ASP.NET Session State +43118,Reachout +43188,Reachout +44333,Kerio WinRoute Firewall Administration +44334,Kerio Personal Firewall Administration +44337,Kerio MailServer Administration +44444,Prosiak +44818,Rockwell Encapsulation +45092,BackGate (Windows rootkit) +45678,EBA PRISE +45966,SSRServerMgr +47262,Delta Source (Windows Trojan) +47557,Databeam Corporation +47624,Direct Play Server +47806,ALC Protocol +47808,Building Automation and Control Networks +48000,Nimbus Controller +48001,Nimbus Spooler +48002,Nimbus Hub +48003,Nimbus Gateway +49400,Compaq Insight Manager +49401,Compaq Insight Manager +50300,O&O Defrag +51515,Microsoft Operations Manager MOM-Clear +52673,Stickies +54283,SubSeven +54320,Orifice 2000 (TCP) +54321,Orifice 2000 (TCP) +60000,DeepThroat +65000,distributed attack tool / Devil (Windows Trojan) +65301,pcAnywhere-def +65506,PhatBot, Agobot, Gaobot (Windows trojans) diff --git a/panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.lock b/panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.lock new file mode 100644 index 00000000000..80f047aed59 --- /dev/null +++ b/panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.lock @@ -0,0 +1,65 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "proc-macro2" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tcp_shared_types" +version = "0.1.0" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-xid" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" diff --git a/panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.toml b/panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.toml new file mode 100644 index 00000000000..124d2ac4406 --- /dev/null +++ b/panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "tcp_shared_types" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde = { version = "1", features = ["derive"] } diff --git a/panda/plugins/print_tcp_servers/tcp_shared_types/src/lib.rs b/panda/plugins/print_tcp_servers/tcp_shared_types/src/lib.rs new file mode 100644 index 00000000000..6f5d221b79d --- /dev/null +++ b/panda/plugins/print_tcp_servers/tcp_shared_types/src/lib.rs @@ -0,0 +1,29 @@ +use serde::{Deserialize, Serialize}; +use std::net::Ipv4Addr; + +pub type Pid = u64; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct SocketInfo { + pub ip: Ipv4Addr, + pub port: u16, + pub pid: Option, + pub server: bool, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum Request { + /// Request a Vec be sent to a given channel + GetSocketList { channel_id: u32 }, + + /// Connect to the given TCP port at the provided IP and forward the connection + /// over the given channel + ForwardConnection { + ip: Ipv4Addr, + port: u16, + channel_id: u32, + }, + + /// Closes a socket so the TCP server knows the connection ended + CloseSocket { channel_id: u32 }, +} diff --git a/panda/plugins/print_tcp_servers/try_it.py b/panda/plugins/print_tcp_servers/try_it.py new file mode 100644 index 00000000000..f820664b019 --- /dev/null +++ b/panda/plugins/print_tcp_servers/try_it.py @@ -0,0 +1,25 @@ +from pandare import Panda + +panda = Panda(generic="x86_64") + +@panda.queue_blocking +def run_cmd(): + panda.revert_sync("root") + + def run(cmd): + print(panda.run_serial_cmd(cmd, no_timeout=True)) + + run("python3 -m http.server &") + + run("sleep 2") + + panda.load_plugin("print_tcp_servers", { + "print_sockets": True, + "forward_port": 8000, + "host_port": 4343 + }) + + run("cat") + panda.end_analysis() + +panda.run() diff --git a/panda/plugins/snake_hook/Cargo.lock b/panda/plugins/snake_hook/Cargo.lock index a0924079ab1..605dfa90f77 100644 --- a/panda/plugins/snake_hook/Cargo.lock +++ b/panda/plugins/snake_hook/Cargo.lock @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "inline-python" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c178e725a9d7a2cd53fedcc0411424c48b240f7d7416a4803a46381a0ef8788d" +checksum = "e2090a070ce14a62b0605bb08e545b28ff785b24b9fabfc56a402a5987e7a299" dependencies = [ "inline-python-macros", "pyo3", @@ -173,9 +173,9 @@ dependencies = [ [[package]] name = "inline-python-macros" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7156c4a14ca399598b2a2c5d26d8c421721661445a1c22e906d3aa77952610bc" +checksum = "f772582b7328d339524184f3980438daf380bf75edb05543356790192a17fafc" dependencies = [ "libc", "proc-macro2", From 32f9fe323ab2c8d75055926fbf1b30757d59032a Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 20 May 2022 15:10:57 -0400 Subject: [PATCH 52/79] Update TCP passthrough to use panda-rs 0.34 --- panda/plugins/print_tcp_servers/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/panda/plugins/print_tcp_servers/Cargo.toml b/panda/plugins/print_tcp_servers/Cargo.toml index a1f89c398ac..d2bdd029a07 100644 --- a/panda/plugins/print_tcp_servers/Cargo.toml +++ b/panda/plugins/print_tcp_servers/Cargo.toml @@ -8,8 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -#panda-re = { version = "0.26", default-features = false } -panda-re = { path = "../../../../panda-rs/panda-rs", default-features = false } +panda-re = { version = "0.34", default-features = false } bincode = "1" serde = { version = "1", features = ["derive"] } tabled = { version = "0.6", features = ["color"] } From f856c8451546f47cff0c29d0b0656519bca9a06f Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 9 Jun 2022 16:57:47 -0400 Subject: [PATCH 53/79] Rename print_tcp_servers to tcp_passthrough --- panda/plugins/config.panda | 2 +- .../Cargo.lock | 36 +++++++++++-------- .../Cargo.toml | 2 +- .../Makefile | 0 .../README.md | 0 panda/plugins/tcp_passthrough/cbindgen.toml | 7 ++++ .../tcp_passthrough/generate_header.sh | 3 ++ .../src/display.rs | 0 .../src/forward_socket.rs | 0 .../src/lib.rs | 2 +- .../src/send_ext.rs | 0 .../src/socket_list.rs | 0 .../src/tcp.csv | 0 .../plugins/tcp_passthrough/tcp_passthrough.h | 8 +++++ .../tcp_shared_types/Cargo.lock | 0 .../tcp_shared_types/Cargo.toml | 0 .../tcp_shared_types/src/lib.rs | 0 .../try_it.py | 8 +++-- panda/python/core/create_panda_datatypes.py | 1 + panda/python/core/pandare/panda.py | 2 ++ panda/python/core/setup.py | 8 +++++ panda/src/callbacks.c | 1 + 22 files changed, 60 insertions(+), 20 deletions(-) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/Cargo.lock (97%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/Cargo.toml (95%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/Makefile (100%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/README.md (100%) create mode 100644 panda/plugins/tcp_passthrough/cbindgen.toml create mode 100755 panda/plugins/tcp_passthrough/generate_header.sh rename panda/plugins/{print_tcp_servers => tcp_passthrough}/src/display.rs (100%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/src/forward_socket.rs (100%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/src/lib.rs (98%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/src/send_ext.rs (100%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/src/socket_list.rs (100%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/src/tcp.csv (100%) create mode 100644 panda/plugins/tcp_passthrough/tcp_passthrough.h rename panda/plugins/{print_tcp_servers => tcp_passthrough}/tcp_shared_types/Cargo.lock (100%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/tcp_shared_types/Cargo.toml (100%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/tcp_shared_types/src/lib.rs (100%) rename panda/plugins/{print_tcp_servers => tcp_passthrough}/try_it.py (68%) diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index 1704f016b38..d414c69e073 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -37,7 +37,7 @@ osi_test pri pri_dwarf pri_simple -print_tcp_servers +tcp_passthrough proc_start_linux proc_trace recctrl diff --git a/panda/plugins/print_tcp_servers/Cargo.lock b/panda/plugins/tcp_passthrough/Cargo.lock similarity index 97% rename from panda/plugins/print_tcp_servers/Cargo.lock rename to panda/plugins/tcp_passthrough/Cargo.lock index 5614c3e3add..6f4968914ae 100644 --- a/panda/plugins/print_tcp_servers/Cargo.lock +++ b/panda/plugins/tcp_passthrough/Cargo.lock @@ -352,7 +352,9 @@ checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" [[package]] name = "panda-re" -version = "0.33.0" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6848dfa0312ec610a889292351238c728a1e2622d9fbff94194475dc0eb29de0" dependencies = [ "array-init", "dirs", @@ -372,6 +374,8 @@ dependencies = [ [[package]] name = "panda-re-macros" version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29772398be20723c90088ae4380d62e25cefe54c174d9082532b258985e41d04" dependencies = [ "darling", "doc-comment", @@ -383,6 +387,8 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "papergrid" @@ -406,20 +412,6 @@ version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" -[[package]] -name = "print_tcp_servers" -version = "0.1.0" -dependencies = [ - "bincode", - "dashmap", - "once_cell", - "owo-colors", - "panda-re", - "serde", - "tabled", - "tcp_shared_types", -] - [[package]] name = "proc-macro2" version = "1.0.34" @@ -588,6 +580,20 @@ dependencies = [ "syn", ] +[[package]] +name = "tcp_passthrough" +version = "0.1.0" +dependencies = [ + "bincode", + "dashmap", + "once_cell", + "owo-colors", + "panda-re", + "serde", + "tabled", + "tcp_shared_types", +] + [[package]] name = "tcp_shared_types" version = "0.1.0" diff --git a/panda/plugins/print_tcp_servers/Cargo.toml b/panda/plugins/tcp_passthrough/Cargo.toml similarity index 95% rename from panda/plugins/print_tcp_servers/Cargo.toml rename to panda/plugins/tcp_passthrough/Cargo.toml index d2bdd029a07..b1e28e6f230 100644 --- a/panda/plugins/print_tcp_servers/Cargo.toml +++ b/panda/plugins/tcp_passthrough/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "print_tcp_servers" +name = "tcp_passthrough" version = "0.1.0" authors = ["Jordan McLeod "] edition = "2018" diff --git a/panda/plugins/print_tcp_servers/Makefile b/panda/plugins/tcp_passthrough/Makefile similarity index 100% rename from panda/plugins/print_tcp_servers/Makefile rename to panda/plugins/tcp_passthrough/Makefile diff --git a/panda/plugins/print_tcp_servers/README.md b/panda/plugins/tcp_passthrough/README.md similarity index 100% rename from panda/plugins/print_tcp_servers/README.md rename to panda/plugins/tcp_passthrough/README.md diff --git a/panda/plugins/tcp_passthrough/cbindgen.toml b/panda/plugins/tcp_passthrough/cbindgen.toml new file mode 100644 index 00000000000..dfad82285b5 --- /dev/null +++ b/panda/plugins/tcp_passthrough/cbindgen.toml @@ -0,0 +1,7 @@ +language = "C" +no_includes = true +after_includes = """// BEGIN_PYPANDA_NEEDS_THIS -- do not delete this comment bc pypanda +// api autogen needs it. And don't put any compiler directives +// between this and END_PYPANDA_NEEDS_THIS except includes of other +// files in this directory that contain subsections like this one.""" +trailer = "// END_PYPANDA_NEEDS_THIS -- do not delete this comment!\n" diff --git a/panda/plugins/tcp_passthrough/generate_header.sh b/panda/plugins/tcp_passthrough/generate_header.sh new file mode 100755 index 00000000000..5c6cdb5d8cb --- /dev/null +++ b/panda/plugins/tcp_passthrough/generate_header.sh @@ -0,0 +1,3 @@ +#!/bin/sh +cbindgen -o tcp_passthrough.h +echo "^^^ ignore those warnings thanks :)" diff --git a/panda/plugins/print_tcp_servers/src/display.rs b/panda/plugins/tcp_passthrough/src/display.rs similarity index 100% rename from panda/plugins/print_tcp_servers/src/display.rs rename to panda/plugins/tcp_passthrough/src/display.rs diff --git a/panda/plugins/print_tcp_servers/src/forward_socket.rs b/panda/plugins/tcp_passthrough/src/forward_socket.rs similarity index 100% rename from panda/plugins/print_tcp_servers/src/forward_socket.rs rename to panda/plugins/tcp_passthrough/src/forward_socket.rs diff --git a/panda/plugins/print_tcp_servers/src/lib.rs b/panda/plugins/tcp_passthrough/src/lib.rs similarity index 98% rename from panda/plugins/print_tcp_servers/src/lib.rs rename to panda/plugins/tcp_passthrough/src/lib.rs index 031c5c4dd33..aa164e4bd5f 100644 --- a/panda/plugins/print_tcp_servers/src/lib.rs +++ b/panda/plugins/tcp_passthrough/src/lib.rs @@ -35,7 +35,7 @@ fn send_request(req: Request) { } #[derive(PandaArgs)] -#[name = "print_tcp_servers"] +#[name = "tcp_passthrough"] struct Args { print_sockets: bool, forward_port: u32, diff --git a/panda/plugins/print_tcp_servers/src/send_ext.rs b/panda/plugins/tcp_passthrough/src/send_ext.rs similarity index 100% rename from panda/plugins/print_tcp_servers/src/send_ext.rs rename to panda/plugins/tcp_passthrough/src/send_ext.rs diff --git a/panda/plugins/print_tcp_servers/src/socket_list.rs b/panda/plugins/tcp_passthrough/src/socket_list.rs similarity index 100% rename from panda/plugins/print_tcp_servers/src/socket_list.rs rename to panda/plugins/tcp_passthrough/src/socket_list.rs diff --git a/panda/plugins/print_tcp_servers/src/tcp.csv b/panda/plugins/tcp_passthrough/src/tcp.csv similarity index 100% rename from panda/plugins/print_tcp_servers/src/tcp.csv rename to panda/plugins/tcp_passthrough/src/tcp.csv diff --git a/panda/plugins/tcp_passthrough/tcp_passthrough.h b/panda/plugins/tcp_passthrough/tcp_passthrough.h new file mode 100644 index 00000000000..42fdd179feb --- /dev/null +++ b/panda/plugins/tcp_passthrough/tcp_passthrough.h @@ -0,0 +1,8 @@ +// BEGIN_PYPANDA_NEEDS_THIS -- do not delete this comment bc pypanda +// api autogen needs it. And don't put any compiler directives +// between this and END_PYPANDA_NEEDS_THIS except includes of other +// files in this directory that contain subsections like this one. + +void print_socket_info(void); + +// END_PYPANDA_NEEDS_THIS -- do not delete this comment! diff --git a/panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.lock b/panda/plugins/tcp_passthrough/tcp_shared_types/Cargo.lock similarity index 100% rename from panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.lock rename to panda/plugins/tcp_passthrough/tcp_shared_types/Cargo.lock diff --git a/panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.toml b/panda/plugins/tcp_passthrough/tcp_shared_types/Cargo.toml similarity index 100% rename from panda/plugins/print_tcp_servers/tcp_shared_types/Cargo.toml rename to panda/plugins/tcp_passthrough/tcp_shared_types/Cargo.toml diff --git a/panda/plugins/print_tcp_servers/tcp_shared_types/src/lib.rs b/panda/plugins/tcp_passthrough/tcp_shared_types/src/lib.rs similarity index 100% rename from panda/plugins/print_tcp_servers/tcp_shared_types/src/lib.rs rename to panda/plugins/tcp_passthrough/tcp_shared_types/src/lib.rs diff --git a/panda/plugins/print_tcp_servers/try_it.py b/panda/plugins/tcp_passthrough/try_it.py similarity index 68% rename from panda/plugins/print_tcp_servers/try_it.py rename to panda/plugins/tcp_passthrough/try_it.py index f820664b019..7ea96a8ad45 100644 --- a/panda/plugins/print_tcp_servers/try_it.py +++ b/panda/plugins/tcp_passthrough/try_it.py @@ -13,12 +13,16 @@ def run(cmd): run("sleep 2") - panda.load_plugin("print_tcp_servers", { - "print_sockets": True, + panda.load_plugin("tcp_passthrough", { + "print_sockets": False, "forward_port": 8000, "host_port": 4343 }) + print("Before") + panda.plugins["tcp_passthrough"].print_socket_info() + print("After") + run("cat") panda.end_analysis() diff --git a/panda/python/core/create_panda_datatypes.py b/panda/python/core/create_panda_datatypes.py index ebabc1b7217..f83afa4ca66 100755 --- a/panda/python/core/create_panda_datatypes.py +++ b/panda/python/core/create_panda_datatypes.py @@ -381,6 +381,7 @@ def main(install=False,recompile=True): copy_ppp_header("%s/%s" % (PLUGINS_DIR+"/proc_start_linux", "proc_start_linux_ppp.h")) create_pypanda_header("%s/%s" % (PLUGINS_DIR+"/proc_start_linux", "proc_start_linux.h")) + create_pypanda_header("%s/%s" % (PLUGINS_DIR+"/tcp_passthrough", "tcp_passthrough.h")) copy_ppp_header("%s/taint2/taint2.h" % PLUGINS_DIR) with open(os.path.join(OUTPUT_DIR, "panda_datatypes.py"), "w") as pdty: diff --git a/panda/python/core/pandare/panda.py b/panda/python/core/pandare/panda.py index b552f6bb09e..4b16f873a79 100755 --- a/panda/python/core/pandare/panda.py +++ b/panda/python/core/pandare/panda.py @@ -671,6 +671,8 @@ def load_plugin(self, name, args={}): argstrs_ffi = [] if isinstance(args, dict): for k,v in args.items(): + if type(v) is bool: + v = "true" if v else "false" this_arg_s = "{}={}".format(k,v) this_arg = self.ffi.new("char[]", bytes(this_arg_s, "utf-8")) argstrs_ffi.append(this_arg) diff --git a/panda/python/core/setup.py b/panda/python/core/setup.py index 602d05d4de9..5a06376bd0a 100644 --- a/panda/python/core/setup.py +++ b/panda/python/core/setup.py @@ -62,6 +62,7 @@ def copy_objs(): softmmu = arch+"-softmmu" path = os.path.join(*[build_root, softmmu, libname]) plugindir = os.path.join(*[build_root, softmmu, "panda", "plugins"]) + guestplugindir = os.path.join(*[build_root, softmmu, "panda", "guest_plugins"]) llvm1 = os.path.join(*[build_root, softmmu, "llvm-helpers.bc1"]) llvm2 = os.path.join(*[build_root, softmmu, f"llvm-helpers-{arch}.bc"]) @@ -82,6 +83,11 @@ def copy_objs(): shutil.copytree(plugindir, new_plugindir, ignore=shutil.ignore_patterns('*.o', '*.d')) + new_guestplugindir = os.path.join(lib_dir, softmmu, "panda/guest_plugins") + print("\n\n") + print(guestplugindir, new_guestplugindir) + shutil.copytree(guestplugindir, new_guestplugindir, ignore=shutil.ignore_patterns('*.o', '*.d')) + # Strip libpandas and plugins to save space (Need <100mb for pypi) if pypi_build: check_output(f"find {lib_dir} -type f -executable -exec strip {{}} \;", shell=True) @@ -163,6 +169,8 @@ def run(self): 'data/*-softmmu/llvm-helpers*.bc*', # Llvm-helpers 'data/*-softmmu/panda/plugins/*', # All plugins 'data/*-softmmu/panda/plugins/**/*',# All plugin files + 'data/*-softmmu/panda/guest_plugins/*', # All plugins + 'data/*-softmmu/panda/guest_plugins/**/*',# All plugin files 'data/pypanda/include/*.h', # Includes files 'data/pc-bios/*', # BIOSes ]}, diff --git a/panda/src/callbacks.c b/panda/src/callbacks.c index a331b9fb9b0..deb9dc9412f 100644 --- a/panda/src/callbacks.c +++ b/panda/src/callbacks.c @@ -267,6 +267,7 @@ char *panda_guest_plugin_path(const char *plugin_name) { g_free(plugin_path); return path; } + printf("Failed to find guest plugin '%s' at '%s'", plugin_name, plugin_path); g_free(plugin_path); // Return null if plugin resolution failed. From cbe4f31f5d8afc5538569bd9686bcdaf55b1fd1a Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 10 Jun 2022 12:38:35 -0400 Subject: [PATCH 54/79] Add TCP passthrough python API prototype --- panda/plugins/tcp_passthrough/src/lib.rs | 77 ++++++++++++++++++- .../plugins/tcp_passthrough/tcp_passthrough.h | 28 +++++++ panda/plugins/tcp_passthrough/try_it.py | 72 +++++++++++++++-- 3 files changed, 165 insertions(+), 12 deletions(-) diff --git a/panda/plugins/tcp_passthrough/src/lib.rs b/panda/plugins/tcp_passthrough/src/lib.rs index aa164e4bd5f..6dd7e2bb4d6 100644 --- a/panda/plugins/tcp_passthrough/src/lib.rs +++ b/panda/plugins/tcp_passthrough/src/lib.rs @@ -1,6 +1,8 @@ use once_cell::sync::Lazy; use panda::{plugins::guest_plugin_manager::*, prelude::*}; +use std::ffi::CStr; use std::net::Ipv4Addr; +use std::os::raw::c_char; use std::sync::Mutex; mod display; @@ -9,19 +11,86 @@ mod send_ext; mod socket_list; use send_ext::SendExt; -use socket_list::on_get_socket_list; use tcp_shared_types::Request; +/// Request that a table of sockets be printed once guest execution resumes #[no_mangle] pub extern "C" fn print_socket_info() { - on_get_socket_list(display::print_table); + socket_list::on_get_socket_list(display::print_table); } -fn forward_socket(ip: Ipv4Addr, port: u16, host_port: u16) { +fn forward_socket_internal(ip: Ipv4Addr, port: u16, host_port: u16) { forward_socket::forward(ip, port, host_port); } +/// Information about a given socket binding +#[repr(C)] +pub struct SocketInfo { + pub ip: [u8; 4], + pub pid: u64, + pub port: u16, + pub server: bool, +} + +/// Provide a callback for receiving a socket list that will get called once the guest +/// resumes execution +#[no_mangle] +pub extern "C" fn on_get_socket_list(callback: extern "C" fn(*const SocketInfo, usize)) { + socket_list::on_get_socket_list(move |socket_list| { + let socket_list: Vec = socket_list + .into_iter() + .map( + |tcp_shared_types::SocketInfo { + ip, + port, + pid, + server, + }| { + SocketInfo { + ip: ip.octets(), + port, + pid: pid.unwrap_or(u64::MAX), + server, + } + }, + ) + .collect(); + + callback(socket_list.as_ptr(), socket_list.len()); + + drop(socket_list); + }) +} + +/// Forward a socket from the guest, returning true if no issue is hit. Returns `false` if +/// the IP address fails to parse. A null IP address is treated as 0.0.0.0 +/// +/// Guest must resume execution for an unspecified amount of time before TCP traffic +/// will actually be processed. +#[no_mangle] +pub unsafe extern "C" fn forward_socket( + ip: *const c_char, + guest_port: u16, + host_port: u16, +) -> bool { + let ip = if ip.is_null() { + "0.0.0.0".parse().unwrap() + } else { + let ip = CStr::from_ptr(ip); + + if let Ok(ip) = ip.to_str().unwrap().parse() { + ip + } else { + return false; + } + }; + + forward_socket_internal(ip, guest_port, host_port); + + true +} + #[channel_recv] fn main_channel_cb(_: u32, _: &[u8]) { // TODO: support for guest closing the socket @@ -57,7 +126,7 @@ fn init(_: &mut PluginHandle) { if forward_port != 0 { Lazy::force(&MAIN_CHANNEL); - forward_socket( + forward_socket_internal( "0.0.0.0".parse().unwrap(), forward_port, match host_port { diff --git a/panda/plugins/tcp_passthrough/tcp_passthrough.h b/panda/plugins/tcp_passthrough/tcp_passthrough.h index 42fdd179feb..3af6dc322cc 100644 --- a/panda/plugins/tcp_passthrough/tcp_passthrough.h +++ b/panda/plugins/tcp_passthrough/tcp_passthrough.h @@ -3,6 +3,34 @@ // between this and END_PYPANDA_NEEDS_THIS except includes of other // files in this directory that contain subsections like this one. +/** + * Information about a given socket binding + */ +typedef struct SocketInfo { + uint8_t ip[4]; + uint64_t pid; + uint16_t port; + bool server; +} SocketInfo; + +/** + * Request that a table of sockets be printed once guest execution resumes + */ void print_socket_info(void); +/** + * Provide a callback for receiving a socket list that will get called once the guest + * resumes execution + */ +void on_get_socket_list(void (*callback)(const struct SocketInfo*, uintptr_t)); + +/** + * Forward a socket from the guest, returning true if no issue is hit. Returns `false` if + * the IP address fails to parse. A null IP address is treated as 0.0.0.0 + * + * Guest must resume execution for an unspecified amount of time before TCP traffic + * will actually be processed. + */ +bool forward_socket(const char *ip, uint16_t guest_port, uint16_t host_port); + // END_PYPANDA_NEEDS_THIS -- do not delete this comment! diff --git a/panda/plugins/tcp_passthrough/try_it.py b/panda/plugins/tcp_passthrough/try_it.py index 7ea96a8ad45..50804ac4cb0 100644 --- a/panda/plugins/tcp_passthrough/try_it.py +++ b/panda/plugins/tcp_passthrough/try_it.py @@ -2,6 +2,56 @@ panda = Panda(generic="x86_64") +# ===================================================================== + +def extend_class(cls): + return lambda f: (setattr(cls, f.__name__, f) or f) + +# ===================================================================== + +from dataclasses import dataclass +from ipaddress import IPv4Address +from typing import Callable + +@dataclass +class SocketInfo: + ip: IPv4Address + pid: int + port: int + is_server: bool + + def from_ffi(raw): + ip = IPv4Address(bytes([raw.ip[i] for i in range(4)])) + pid = raw.pid + port = raw.port + is_server = raw.server + + return SocketInfo(ip, pid, port, is_server) + +@extend_class(Panda) +def forward_socket(self, guest_port: int, host_port: int): + self.plugins["tcp_passthrough"].forward_socket( + self.ffi.cast("const char*", self.ffi.NULL), + self.ffi.cast("uint16_t", guest_port), + self.ffi.cast("uint16_t", host_port) + ) + +@extend_class(Panda) +def on_get_socket_list(self, callback: Callable[[list], None]): + @self.ffi.callback("void(*)(const struct SocketInfo*, uintptr_t)") + def cb(ptr, length): + callback([SocketInfo.from_ffi(ptr[i]) for i in range(length)]) + + self.socket_list = (self.__dict__.get("socket_list") or []) + [cb] + + self.plugins["tcp_passthrough"].on_get_socket_list(cb) + +@extend_class(Panda) +def print_socket_info(self): + self.plugins["tcp_passthrough"].print_socket_info() + +# ===================================================================== + @panda.queue_blocking def run_cmd(): panda.revert_sync("root") @@ -13,15 +63,21 @@ def run(cmd): run("sleep 2") - panda.load_plugin("tcp_passthrough", { - "print_sockets": False, - "forward_port": 8000, - "host_port": 4343 - }) + panda.load_plugin("tcp_passthrough") + + # Print a table of the TCP servers in the guest + panda.print_socket_info() + + # Forward a socket from localhost:8000 in the guest to localhost:4343 on the host + panda.forward_socket(8000, 4343) - print("Before") - panda.plugins["tcp_passthrough"].print_socket_info() - print("After") + # print out the socket list ourselves too + @panda.on_get_socket_list + def callback(socket_info: list): + print(" Ip Address\tPID\tIs Server?") + print("====================================") + for socket in socket_info: + print(f" {socket.ip}:{socket.port}\t{socket.pid}\t{socket.is_server}") run("cat") panda.end_analysis() From ff534f8e68da70e75e491a09065aed57e7cd4388 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 10 Jun 2022 13:11:10 -0400 Subject: [PATCH 55/79] Clean up TCP passthrough python API example --- panda/plugins/tcp_passthrough/try_it.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/panda/plugins/tcp_passthrough/try_it.py b/panda/plugins/tcp_passthrough/try_it.py index 50804ac4cb0..34f48fdba1c 100644 --- a/panda/plugins/tcp_passthrough/try_it.py +++ b/panda/plugins/tcp_passthrough/try_it.py @@ -59,12 +59,12 @@ def run_cmd(): def run(cmd): print(panda.run_serial_cmd(cmd, no_timeout=True)) + # Start up an HTTP server as a background job run("python3 -m http.server &") + # Give the HTTP server time to start up before pulling socket info run("sleep 2") - panda.load_plugin("tcp_passthrough") - # Print a table of the TCP servers in the guest panda.print_socket_info() @@ -79,7 +79,9 @@ def callback(socket_info: list): for socket in socket_info: print(f" {socket.ip}:{socket.port}\t{socket.pid}\t{socket.is_server}") + # Injecting into a cat command, but this could be anything run("cat") + panda.end_analysis() panda.run() From 585a2a85389ff4fd20da84ba60f29d5dc7f917dc Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 17 Jun 2022 14:50:07 -0400 Subject: [PATCH 56/79] Move tcp_servers to public PANDA repo --- panda/guest_plugins/config.panda | 1 + panda/guest_plugins/tcp_servers/Cargo.lock | 217 ++++++++++++++++++ panda/guest_plugins/tcp_servers/Cargo.toml | 12 + panda/guest_plugins/tcp_servers/Makefile | 20 ++ .../tcp_servers/src/allow_cancel.rs | 110 +++++++++ panda/guest_plugins/tcp_servers/src/main.rs | 99 ++++++++ panda/plugins/rust_skeleton/Cargo.lock | 27 ++- panda/plugins/rust_skeleton/Cargo.toml | 2 +- panda/plugins/rust_skeleton/src/lib.rs | 14 +- 9 files changed, 485 insertions(+), 17 deletions(-) create mode 100644 panda/guest_plugins/tcp_servers/Cargo.lock create mode 100644 panda/guest_plugins/tcp_servers/Cargo.toml create mode 100644 panda/guest_plugins/tcp_servers/Makefile create mode 100644 panda/guest_plugins/tcp_servers/src/allow_cancel.rs create mode 100644 panda/guest_plugins/tcp_servers/src/main.rs diff --git a/panda/guest_plugins/config.panda b/panda/guest_plugins/config.panda index 837b01d97cf..9d5dd9d86f8 100644 --- a/panda/guest_plugins/config.panda +++ b/panda/guest_plugins/config.panda @@ -1 +1,2 @@ rust_example +tcp_servers diff --git a/panda/guest_plugins/tcp_servers/Cargo.lock b/panda/guest_plugins/tcp_servers/Cargo.lock new file mode 100644 index 00000000000..b49e3414388 --- /dev/null +++ b/panda/guest_plugins/tcp_servers/Cargo.lock @@ -0,0 +1,217 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "panda-channels" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94b07d8bcc852032a8deb91be9d2bbd59421d776a9edb42fc74b40816e7d940" +dependencies = [ + "lazy_static", + "parking_lot", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-net-tcp" +version = "1.0.0" +source = "git+https://github.com/panda-re/proc-net-tcp#87de3e9ce7adeda56d75c13dc0b510136ee675b2" + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "syn" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tcp_servers" +version = "0.1.0" +dependencies = [ + "bincode", + "panda-channels", + "proc-net-tcp", + "serde", + "tcp_shared_types", +] + +[[package]] +name = "tcp_shared_types" +version = "0.1.0" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-ident" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/guest_plugins/tcp_servers/Cargo.toml b/panda/guest_plugins/tcp_servers/Cargo.toml new file mode 100644 index 00000000000..c6d3ad6a69d --- /dev/null +++ b/panda/guest_plugins/tcp_servers/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "tcp_servers" +version = "0.1.0" +edition = "2021" + +[dependencies] +panda-channels = "0.2" +bincode = "1" +serde = { version = "1", features = ["derive"] } + +proc-net-tcp = { git = "https://github.com/panda-re/proc-net-tcp" } +tcp_shared_types = { path = "../../plugins/tcp_passthrough/tcp_shared_types" } diff --git a/panda/guest_plugins/tcp_servers/Makefile b/panda/guest_plugins/tcp_servers/Makefile new file mode 100644 index 00000000000..1458392b517 --- /dev/null +++ b/panda/guest_plugins/tcp_servers/Makefile @@ -0,0 +1,20 @@ +# Remember to: +# * Add your plugin name to config.panda +# * Keep your plugin name the same as the folder name and Cargo.toml package name + +# Output build artifacts to the build directory +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +# recompile if any of the src/*.rs files changed, or Cargo.toml +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_DEPS=$(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + +$(PLUGIN_OUT_PATH): BUILD_RESULT="$(PLUGIN_ARTIFACTS_DIR)/$(TARGET_TRIPLE)/release/$(PLUGIN_NAME)" +$(PLUGIN_OUT_PATH): $(PLUGIN_DEPS) + @echo " CARGO $(PLUGIN_NAME) (${TARGET_TRIPLE})" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --target=$(TARGET_TRIPLE) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @mkdir -p $(PLUGIN_BIN_DIR) + @cp -p $(BUILD_RESULT) $@ diff --git a/panda/guest_plugins/tcp_servers/src/allow_cancel.rs b/panda/guest_plugins/tcp_servers/src/allow_cancel.rs new file mode 100644 index 00000000000..83da71f9661 --- /dev/null +++ b/panda/guest_plugins/tcp_servers/src/allow_cancel.rs @@ -0,0 +1,110 @@ +use std::io::{self, Read, Seek, SeekFrom, Write}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; + +pub struct AllowCancel(T, Arc); + +#[derive(Clone)] +pub struct CancelSignal(Arc); + +impl CancelSignal { + pub fn cancel(&self) { + self.0.store(true, Ordering::SeqCst) + } +} + +impl Clone for AllowCancel { + fn clone(&self) -> Self { + Self(self.0.clone(), Arc::clone(&self.1)) + } +} + +impl AllowCancel { + pub fn new(io: T) -> Self { + Self(io, Arc::new(AtomicBool::new(false))) + } + + pub fn cancel_signal(&self) -> CancelSignal { + CancelSignal(Arc::clone(&self.1)) + } + + pub fn with_signal(self, cancel_signal: CancelSignal) -> Self { + Self(self.0, cancel_signal.0) + } +} + +macro_rules! dbg { + ($expr:expr) => { + //panda_channels::Channel::main(&format!( + // "[{}:{}] {} = {:?}", + // file!(), + // line!(), + // stringify!($expr), + // $expr, + //)) + }; +} + +impl Write for AllowCancel { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + if !self.1.load(Ordering::SeqCst) { + dbg!(buf.len()); + + self.0.write(buf) + } else { + Err(io::Error::new( + io::ErrorKind::ConnectionAborted, + "Connection ended", + )) + } + } + + fn flush(&mut self) -> io::Result<()> { + if !self.1.load(Ordering::SeqCst) { + dbg!("flushing"); + + self.0.flush() + } else { + Err(io::Error::new( + io::ErrorKind::ConnectionAborted, + "Connection ended", + )) + } + } +} + +impl Read for AllowCancel { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + if !self.1.load(Ordering::SeqCst) { + //dbg!(buf.len()); + + self.0.read(buf).map(|len| { + if len != 0 { + dbg!(len); + } + + len + }) + } else { + Err(io::Error::new( + io::ErrorKind::ConnectionAborted, + "Connection ended", + )) + } + } +} + +impl Seek for AllowCancel { + fn seek(&mut self, pos: SeekFrom) -> io::Result { + if !self.1.load(Ordering::SeqCst) { + self.0.seek(pos) + } else { + Err(io::Error::new( + io::ErrorKind::ConnectionAborted, + "Connection ended", + )) + } + } +} diff --git a/panda/guest_plugins/tcp_servers/src/main.rs b/panda/guest_plugins/tcp_servers/src/main.rs new file mode 100644 index 00000000000..4b2c4927410 --- /dev/null +++ b/panda/guest_plugins/tcp_servers/src/main.rs @@ -0,0 +1,99 @@ +use panda_channels::{Channel, RawChannel}; +use proc_net_tcp::socket_info; + +use std::collections::HashMap; +use std::mem::transmute; +use std::net::{Ipv4Addr, TcpStream}; + +use tcp_shared_types::{Request, SocketInfo}; + +mod allow_cancel; +use allow_cancel::{AllowCancel, CancelSignal}; + +fn recv_request(mut channel: &mut Channel) -> Request { + loop { + if let Ok(request) = bincode::deserialize_from(&mut channel) { + break request; + } + + std::thread::sleep(std::time::Duration::from_millis(10)); + } +} + +fn build_socket_list_packet() -> Vec { + let sockets = socket_info() + .into_iter() + .filter_map(|socket| { + socket.ok().map(|socket| SocketInfo { + ip: *socket.local_address.ip(), + port: socket.local_address.port(), + pid: socket.owning_pid, + server: socket.is_listening(), + }) + }) + .collect::>(); + + bincode::serialize(&sockets).unwrap() +} + +fn forward_connection(ip: Ipv4Addr, port: u16, channel_id: u32) -> CancelSignal { + let raw = unsafe { transmute(channel_id) }; + + let mut write_channel = AllowCancel::new(Channel::from_raw(raw)); + let mut read_channel = write_channel.clone(); + + let cancel_signal = write_channel.cancel_signal(); + + let write_socket = TcpStream::connect((ip, port)).unwrap(); + let read_socket = write_socket.try_clone().unwrap(); + + let mut read_socket = AllowCancel::new(read_socket).with_signal(cancel_signal.clone()); + let mut write_socket = AllowCancel::new(write_socket).with_signal(cancel_signal.clone()); + + std::thread::spawn(move || { + let _ = std::io::copy(&mut read_channel, &mut write_socket); + }); + + std::thread::spawn(move || { + let _ = std::io::copy(&mut read_socket, &mut write_channel); + }); + + cancel_signal +} + +fn main() { + let mut channel = Channel::main("tcp_servers").unwrap(); + let mut active_sockets = HashMap::new(); + + loop { + let request = recv_request(&mut channel); + + // debug?? + //let _ = Channel::main(&format!("Request: {:?}", request)); + //panda_channels::debug_output(&); + match request { + Request::GetSocketList { channel_id } => { + eprintln!("Getting socket list..."); + let socket_list_channel: RawChannel = unsafe { transmute(channel_id) }; + + socket_list_channel.write_packet(&build_socket_list_packet()); + } + + Request::ForwardConnection { + ip, + port, + channel_id, + } => { + let cancel_signal = forward_connection(ip, port, channel_id); + + active_sockets.insert(channel_id, cancel_signal); + } + + Request::CloseSocket { channel_id } => { + if let Some(socket) = active_sockets.remove(&channel_id) { + socket.cancel(); + } + } + } + } +} diff --git a/panda/plugins/rust_skeleton/Cargo.lock b/panda/plugins/rust_skeleton/Cargo.lock index 20f84875f86..f50fe556365 100644 --- a/panda/plugins/rust_skeleton/Cargo.lock +++ b/panda/plugins/rust_skeleton/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "array-init" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6945cc5422176fc5e602e590c2878d2c2acd9a4fe20a4baa7c28022521698ec6" + [[package]] name = "bitflags" version = "1.2.1" @@ -182,17 +188,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + [[package]] name = "panda-re" -version = "0.14.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03153860245f365c1f01452404eddd0a0741beafd88acf6e6afe167d1ac6c874" +checksum = "6848dfa0312ec610a889292351238c728a1e2622d9fbff94194475dc0eb29de0" dependencies = [ + "array-init", "dirs", "glib-sys", "inventory", "lazy_static", "libloading", + "once_cell", "panda-re-macros", "panda-re-sys", "paste", @@ -203,21 +217,22 @@ dependencies = [ [[package]] name = "panda-re-macros" -version = "0.10.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ebc6c9d873a7285c7a09bfe4c80dc80efa8d3ea28bcb18a1d6a933dd3242be" +checksum = "29772398be20723c90088ae4380d62e25cefe54c174d9082532b258985e41d04" dependencies = [ "darling", "doc-comment", + "proc-macro2", "quote", "syn", ] [[package]] name = "panda-re-sys" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9fe3ab684d3cf027c816a724de1ea40373b6438dc2240d64bdca0ca99f2e01" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "paste" diff --git a/panda/plugins/rust_skeleton/Cargo.toml b/panda/plugins/rust_skeleton/Cargo.toml index e213def62c5..251bce5f44d 100644 --- a/panda/plugins/rust_skeleton/Cargo.toml +++ b/panda/plugins/rust_skeleton/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.14.0", default-features = false } +panda-re = { version = "0.34.0", default-features = false } [features] default = ["x86_64"] diff --git a/panda/plugins/rust_skeleton/src/lib.rs b/panda/plugins/rust_skeleton/src/lib.rs index 91a376fc22b..0648edae7d3 100644 --- a/panda/plugins/rust_skeleton/src/lib.rs +++ b/panda/plugins/rust_skeleton/src/lib.rs @@ -1,16 +1,10 @@ use panda::prelude::*; #[panda::init] -fn init(_: &mut PluginHandle) -> bool { +fn init(_: &mut PluginHandle) { println!("Initialized!"); - true } -#[panda::uninit] -fn exit(_: &mut PluginHandle) { - println!("Exiting"); -} - -#[panda::before_block_exec] -fn bbe(_cpu: &mut CPUState, _tb: &mut TranslationBlock){ -} +//#[panda::before_block_exec] +//fn bbe(_cpu: &mut CPUState, _tb: &mut TranslationBlock){ +//} From 80f162163b12c47e9af1d5959029f4c0706847e0 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 17 Jun 2022 15:18:40 -0400 Subject: [PATCH 57/79] Add TCP passthrough API to pypanda --- panda/plugins/tcp_passthrough/try_it.py | 65 ++------------------ panda/python/core/pandare/panda.py | 2 + panda/python/core/pandare/tcp_passthrough.py | 41 ++++++++++++ panda/python/examples/tcp_passthrough.py | 34 ++++++++++ 4 files changed, 83 insertions(+), 59 deletions(-) create mode 100644 panda/python/core/pandare/tcp_passthrough.py create mode 100644 panda/python/examples/tcp_passthrough.py diff --git a/panda/plugins/tcp_passthrough/try_it.py b/panda/plugins/tcp_passthrough/try_it.py index 34f48fdba1c..deb08c83362 100644 --- a/panda/plugins/tcp_passthrough/try_it.py +++ b/panda/plugins/tcp_passthrough/try_it.py @@ -2,77 +2,24 @@ panda = Panda(generic="x86_64") -# ===================================================================== - -def extend_class(cls): - return lambda f: (setattr(cls, f.__name__, f) or f) - -# ===================================================================== - -from dataclasses import dataclass -from ipaddress import IPv4Address -from typing import Callable - -@dataclass -class SocketInfo: - ip: IPv4Address - pid: int - port: int - is_server: bool - - def from_ffi(raw): - ip = IPv4Address(bytes([raw.ip[i] for i in range(4)])) - pid = raw.pid - port = raw.port - is_server = raw.server - - return SocketInfo(ip, pid, port, is_server) - -@extend_class(Panda) -def forward_socket(self, guest_port: int, host_port: int): - self.plugins["tcp_passthrough"].forward_socket( - self.ffi.cast("const char*", self.ffi.NULL), - self.ffi.cast("uint16_t", guest_port), - self.ffi.cast("uint16_t", host_port) - ) - -@extend_class(Panda) -def on_get_socket_list(self, callback: Callable[[list], None]): - @self.ffi.callback("void(*)(const struct SocketInfo*, uintptr_t)") - def cb(ptr, length): - callback([SocketInfo.from_ffi(ptr[i]) for i in range(length)]) - - self.socket_list = (self.__dict__.get("socket_list") or []) + [cb] - - self.plugins["tcp_passthrough"].on_get_socket_list(cb) - -@extend_class(Panda) -def print_socket_info(self): - self.plugins["tcp_passthrough"].print_socket_info() - -# ===================================================================== - @panda.queue_blocking def run_cmd(): panda.revert_sync("root") - def run(cmd): - print(panda.run_serial_cmd(cmd, no_timeout=True)) - # Start up an HTTP server as a background job - run("python3 -m http.server &") + panda.run_serial_cmd("python3 -m http.server &") # Give the HTTP server time to start up before pulling socket info - run("sleep 2") + panda.run_serial_cmd("sleep 2") # Print a table of the TCP servers in the guest - panda.print_socket_info() + panda.tcp.print_socket_info() # Forward a socket from localhost:8000 in the guest to localhost:4343 on the host - panda.forward_socket(8000, 4343) + panda.tcp.forward_socket(8000, 4343) # print out the socket list ourselves too - @panda.on_get_socket_list + @panda.tcp.on_get_socket_list def callback(socket_info: list): print(" Ip Address\tPID\tIs Server?") print("====================================") @@ -80,7 +27,7 @@ def callback(socket_info: list): print(f" {socket.ip}:{socket.port}\t{socket.pid}\t{socket.is_server}") # Injecting into a cat command, but this could be anything - run("cat") + panda.run_serial_cmd("cat", no_timeout=True) panda.end_analysis() diff --git a/panda/python/core/pandare/panda.py b/panda/python/core/pandare/panda.py index 4b16f873a79..bb85617841d 100755 --- a/panda/python/core/pandare/panda.py +++ b/panda/python/core/pandare/panda.py @@ -38,6 +38,7 @@ from .asyncthread import AsyncThread from .qcows import Qcows from .arch import ArmArch, Aarch64Arch, MipsArch, Mips64Arch, X86Arch, X86_64Arch +from .tcp_passthrough import TcpPassthrough, SocketInfo # Might be worth importing and auto-initilizing a PLogReader # object within Panda for the current architecture? @@ -90,6 +91,7 @@ def __init__(self, arch="i386", mem="128M", self.os_type = os self.qcow = qcow self.plugins = plugin_list(self) + self.tcp = TcpPassthrough(self) self.expect_prompt = expect_prompt self.lambda_cnt = 0 self.__sighandler = None diff --git a/panda/python/core/pandare/tcp_passthrough.py b/panda/python/core/pandare/tcp_passthrough.py new file mode 100644 index 00000000000..a9cc1b1d438 --- /dev/null +++ b/panda/python/core/pandare/tcp_passthrough.py @@ -0,0 +1,41 @@ +from dataclasses import dataclass +from ipaddress import IPv4Address +from typing import Callable + +@dataclass +class SocketInfo: + ip: IPv4Address + pid: int + port: int + is_server: bool + + def from_ffi(raw): + ip = IPv4Address(bytes([raw.ip[i] for i in range(4)])) + pid = raw.pid + port = raw.port + is_server = raw.server + + return SocketInfo(ip, pid, port, is_server) + +class TcpPassthrough: + def __init__(self, panda): + self.panda = panda + + def forward_socket(self, guest_port: int, host_port: int): + self.panda.plugins["tcp_passthrough"].forward_socket( + self.panda.ffi.cast("const char*", self.panda.ffi.NULL), + self.panda.ffi.cast("uint16_t", guest_port), + self.panda.ffi.cast("uint16_t", host_port) + ) + + def on_get_socket_list(self, callback: Callable[[list], None]): + @self.panda.ffi.callback("void(*)(const struct SocketInfo*, uintptr_t)") + def cb(ptr, length): + callback([SocketInfo.from_ffi(ptr[i]) for i in range(length)]) + + self.socket_list = (self.__dict__.get("socket_list") or []) + [cb] + + self.panda.plugins["tcp_passthrough"].on_get_socket_list(cb) + + def print_socket_info(self): + self.panda.plugins["tcp_passthrough"].print_socket_info() diff --git a/panda/python/examples/tcp_passthrough.py b/panda/python/examples/tcp_passthrough.py new file mode 100644 index 00000000000..deb08c83362 --- /dev/null +++ b/panda/python/examples/tcp_passthrough.py @@ -0,0 +1,34 @@ +from pandare import Panda + +panda = Panda(generic="x86_64") + +@panda.queue_blocking +def run_cmd(): + panda.revert_sync("root") + + # Start up an HTTP server as a background job + panda.run_serial_cmd("python3 -m http.server &") + + # Give the HTTP server time to start up before pulling socket info + panda.run_serial_cmd("sleep 2") + + # Print a table of the TCP servers in the guest + panda.tcp.print_socket_info() + + # Forward a socket from localhost:8000 in the guest to localhost:4343 on the host + panda.tcp.forward_socket(8000, 4343) + + # print out the socket list ourselves too + @panda.tcp.on_get_socket_list + def callback(socket_info: list): + print(" Ip Address\tPID\tIs Server?") + print("====================================") + for socket in socket_info: + print(f" {socket.ip}:{socket.port}\t{socket.pid}\t{socket.is_server}") + + # Injecting into a cat command, but this could be anything + panda.run_serial_cmd("cat", no_timeout=True) + + panda.end_analysis() + +panda.run() From d18e7418bd2cf28fc86f3fe175c9c80367e3eee3 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 17 Jun 2022 15:32:33 -0400 Subject: [PATCH 58/79] Add documentation to pypanda TCP passthrough API --- panda/python/core/pandare/tcp_passthrough.py | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/panda/python/core/pandare/tcp_passthrough.py b/panda/python/core/pandare/tcp_passthrough.py index a9cc1b1d438..1ebcdf2c986 100644 --- a/panda/python/core/pandare/tcp_passthrough.py +++ b/panda/python/core/pandare/tcp_passthrough.py @@ -4,12 +4,26 @@ @dataclass class SocketInfo: + ''' + Information about a socket running in the guest. + + Fields: + * `ip`: `IPv4Address` - the IP address within the guest being bound to + * `pid`: `int` - the Process ID of the process which is bound to the socket + * `port`: `int` - the TCP port (0-65565) within the guest being used + * `is_server`: `bool` - Whether the socket within the guest is a listener or an outgoing connection + ''' + ip: IPv4Address pid: int port: int is_server: bool def from_ffi(raw): + ''' + Takes a C FFI instances of SocketInfo and converts it to a python-native type + ''' + ip = IPv4Address(bytes([raw.ip[i] for i in range(4)])) pid = raw.pid port = raw.port @@ -18,10 +32,24 @@ def from_ffi(raw): return SocketInfo(ip, pid, port, is_server) class TcpPassthrough: + ''' + Object to interact with the `tcp_passthrough` PANDA plugin. An instance can be found + at `panda.tcp`, where `panda` is a `Panda` object. + ''' + def __init__(self, panda): self.panda = panda def forward_socket(self, guest_port: int, host_port: int): + ''' + Forward TCP connections performed on a host port to a TCP server running in the + guest. This could, for example, be used to allow access to a guest HTTP server. + + ``` + # Allow connecting to the guest localhost:80 via the host localhost:8500 + panda.tcp.forward_socket(80, 8500) + ``` + ''' self.panda.plugins["tcp_passthrough"].forward_socket( self.panda.ffi.cast("const char*", self.panda.ffi.NULL), self.panda.ffi.cast("uint16_t", guest_port), @@ -29,6 +57,17 @@ def forward_socket(self, guest_port: int, host_port: int): ) def on_get_socket_list(self, callback: Callable[[list], None]): + ''' + Request a list of sockets from the guest, running a provided callback when they + are available. The callback is given a `list` of `SocketInfo`s. + + ``` + @panda.tcp.on_get_socket_list + def with_sockets(sockets): + for socket in sockets: + print(f"Socket bound on guest port {socket.port}") + ``` + ''' @self.panda.ffi.callback("void(*)(const struct SocketInfo*, uintptr_t)") def cb(ptr, length): callback([SocketInfo.from_ffi(ptr[i]) for i in range(length)]) @@ -38,4 +77,12 @@ def cb(ptr, length): self.panda.plugins["tcp_passthrough"].on_get_socket_list(cb) def print_socket_info(self): + ''' + Request that a list of sockets in the guest is printed as a table to stdout, + including information about what the given port is typically reserved for. + + ``` + panda.tcp.print_socket_info() + ``` + ''' self.panda.plugins["tcp_passthrough"].print_socket_info() From a6f9aac94db93d99b58684cfc8a00b460bdfa5dd Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 13 Jul 2022 14:00:58 -0400 Subject: [PATCH 59/79] Switch TCP passthrough default binding address --- panda/plugins/tcp_passthrough/src/forward_socket.rs | 13 ++++++++++--- panda/plugins/tcp_passthrough/src/lib.rs | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/panda/plugins/tcp_passthrough/src/forward_socket.rs b/panda/plugins/tcp_passthrough/src/forward_socket.rs index b3afc9d135e..ff024539d3f 100644 --- a/panda/plugins/tcp_passthrough/src/forward_socket.rs +++ b/panda/plugins/tcp_passthrough/src/forward_socket.rs @@ -20,10 +20,17 @@ fn incoming_tcp(channel_id: u32, data: &[u8]) { } } -pub fn forward(ip: Ipv4Addr, guest_port: u16, host_port: u16) { +pub fn forward(ip: Ipv4Addr, guest_port: u16, host_port: u16, localhost_only: bool) { thread::spawn(move || { - let listener = - TcpListener::bind(("localhost", host_port)).expect("Could not bind to host port"); + let listener = TcpListener::bind(( + if localhost_only { + "localhost" + } else { + "0.0.0.0" + }, + host_port, + )) + .expect("Could not bind to host port"); eprintln!("Listening on localhost:{}...", host_port); for stream in listener.incoming() { diff --git a/panda/plugins/tcp_passthrough/src/lib.rs b/panda/plugins/tcp_passthrough/src/lib.rs index 6dd7e2bb4d6..53a5b8f91a4 100644 --- a/panda/plugins/tcp_passthrough/src/lib.rs +++ b/panda/plugins/tcp_passthrough/src/lib.rs @@ -21,7 +21,7 @@ pub extern "C" fn print_socket_info() { } fn forward_socket_internal(ip: Ipv4Addr, port: u16, host_port: u16) { - forward_socket::forward(ip, port, host_port); + forward_socket::forward(ip, port, host_port, false); } /// Information about a given socket binding From 3c8ca5d932193cb18fb8e45304c4042ebd2146d1 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 18 Jul 2022 15:16:46 -0400 Subject: [PATCH 60/79] Fix MIPS builds of linjector/guest_plugin_manager --- panda/guest_plugins/config.panda | 4 ++-- .../guest_plugin_manager/src/hyp_regs.rs | 6 ++++++ panda/plugins/linjector/src/lib.rs | 2 +- panda/plugins/linjector/src/syscalls.rs | 4 ++++ panda/plugins/linjector/src/syscalls/mips.rs | 17 +++++++++++++++++ 5 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 panda/plugins/linjector/src/syscalls/mips.rs diff --git a/panda/guest_plugins/config.panda b/panda/guest_plugins/config.panda index 9d5dd9d86f8..2059d06a26b 100644 --- a/panda/guest_plugins/config.panda +++ b/panda/guest_plugins/config.panda @@ -1,2 +1,2 @@ -rust_example -tcp_servers +#rust_example +#tcp_servers diff --git a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs index 5be443a5267..de632505818 100644 --- a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs +++ b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs @@ -16,6 +16,9 @@ pub const REG_ORDER: [Reg; 5] = [RAX, RBX, RCX, RDX, RDI]; #[cfg(feature = "arm")] pub const REG_ORDER: [Reg; 5] = [R0, R1, R2, R3, R4]; +#[cfg(feature = "mips")] +pub const REG_ORDER: [Reg; 5] = [V0, A0, A1, A2, A3]; + // =================== Return Value =================== #[cfg(feature = "i386")] pub const RET_REG: Reg = EAX; @@ -26,6 +29,9 @@ pub const RET_REG: Reg = RAX; #[cfg(feature = "arm")] pub const RET_REG: Reg = R0; +#[cfg(feature = "mips")] +pub const RET_REG: Reg = V0; + pub fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { let reg_to_read = REG_ORDER[num]; get_reg(cpu, reg_to_read) as usize diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index a83c703bbbe..4b641c88214 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -89,7 +89,7 @@ extern "C" fn on_sys_enter( // Once we inject to a process stop looking for syscalls to inject into SYSCALLS.remove_callback_on_all_sys_enter(on_sys_enter); - log::trace!("Attempting injection into syscall {}", syscall_num); + log::debug!("Attempting injection into syscall {}", syscall_num); let file_data = args::elf_to_inject(); // Inject our syscall chain into the current system call. This injector diff --git a/panda/plugins/linjector/src/syscalls.rs b/panda/plugins/linjector/src/syscalls.rs index 6b821bc0728..cf046618f8b 100644 --- a/panda/plugins/linjector/src/syscalls.rs +++ b/panda/plugins/linjector/src/syscalls.rs @@ -20,6 +20,10 @@ mod sys_nums; #[path = "syscalls/arm.rs"] mod sys_nums; +#[cfg(feature = "mips")] +#[path = "syscalls/arm.rs"] +mod sys_nums; + use sys_nums::*; const NULL: target_ulong = 0; diff --git a/panda/plugins/linjector/src/syscalls/mips.rs b/panda/plugins/linjector/src/syscalls/mips.rs new file mode 100644 index 00000000000..0c540f5ff44 --- /dev/null +++ b/panda/plugins/linjector/src/syscalls/mips.rs @@ -0,0 +1,17 @@ +use panda::prelude::*; + +pub(crate) const GETPID: target_ulong = 4020; +pub(crate) const MMAP: target_ulong = 4090; +pub(crate) const WRITE: target_ulong = 4004; +pub(crate) const EXECVE: target_ulong = 4011; +pub(crate) const MEMFD_CREATE: target_ulong = 4354; +pub(crate) const CHDIR: target_ulong = 4012; +pub(crate) const SETSID: target_ulong = 4066; +pub(crate) const OPEN: target_ulong = 4005; +pub(crate) const CLOSE: target_ulong = 4006; + +pub(crate) const PROT_READ: target_ulong = 1; +pub(crate) const PROT_WRITE: target_ulong = 2; + +pub(crate) const MAP_SHARED: target_ulong = 0x1; +pub(crate) const MAP_ANON: target_ulong = 0x800; From 45df478f940978890478dcbc4a82e38db20c87b5 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 20 Jul 2022 17:24:31 -0400 Subject: [PATCH 61/79] Fix build errors caused by unsupported guest agent architectures --- panda/guest_plugins/config.panda | 2 +- panda/guest_plugins/panda.mak | 16 +++++++++++-- panda/guest_plugins/tcp_servers/Cargo.lock | 2 -- panda/guest_plugins/tcp_servers/Cargo.toml | 3 ++- panda/plugins/frida/Cargo.toml | 1 + panda/plugins/guest_plugin_example/Cargo.toml | 1 + panda/plugins/guest_plugin_manager/Cargo.toml | 1 + .../guest_plugin_manager/src/hyp_regs.rs | 16 +++++++++++-- panda/plugins/guest_shell/Cargo.toml | 1 + panda/plugins/hyperfuse/Cargo.toml | 1 + panda/plugins/linjector/Cargo.lock | 8 +------ panda/plugins/linjector/Cargo.toml | 4 +++- panda/plugins/linjector/src/lib.rs | 24 ++++++++++++++----- panda/plugins/linjector/src/syscalls.rs | 12 ++++++++-- .../plugins/linjector/src/syscalls/aarch64.rs | 17 +++++++++++++ .../plugins/linjector/src/syscalls/mips64.rs | 17 +++++++++++++ panda/plugins/tcp_passthrough/Cargo.toml | 1 + 17 files changed, 103 insertions(+), 24 deletions(-) create mode 100644 panda/plugins/linjector/src/syscalls/aarch64.rs create mode 100644 panda/plugins/linjector/src/syscalls/mips64.rs diff --git a/panda/guest_plugins/config.panda b/panda/guest_plugins/config.panda index 2059d06a26b..f785445e0ce 100644 --- a/panda/guest_plugins/config.panda +++ b/panda/guest_plugins/config.panda @@ -1,2 +1,2 @@ #rust_example -#tcp_servers +tcp_servers diff --git a/panda/guest_plugins/panda.mak b/panda/guest_plugins/panda.mak index d7df87caaab..c84fb4c1014 100644 --- a/panda/guest_plugins/panda.mak +++ b/panda/guest_plugins/panda.mak @@ -12,8 +12,17 @@ PLUGIN_TARGET_DIR=panda/guest_plugins PLUGIN_BIN_DIR=$(PLUGIN_TARGET_DIR)/bin PLUGIN_OUT_PATH=$(PLUGIN_BIN_DIR)/$(PLUGIN_NAME) -CARGO_TARGET_ARMV5TE_UNKNOWN_LINUX_MUSLEABI_LINKER ?= "arm-linux-musleabi-cc" -CARGO_TARGET_ARMV5TE_UNKNOWN_LINUX_MUSLEABI_RUSTFLAGS = "-C target-cpu=arm926ej-s" +export CARGO_TARGET_ARMV5TE_UNKNOWN_LINUX_MUSLEABI_LINKER ?= arm-linux-musleabi-cc +export CARGO_TARGET_ARMV5TE_UNKNOWN_LINUX_MUSLEABI_RUSTFLAGS = -C target-cpu=arm926ej-s + +export CARGO_TARGET_MIPS_UNKNOWN_LINUX_MUSL_LINKER ?= mips-linux-musl-cc +#export CARGO_TARGET_MIPS_UNKNOWN_LINUX_MUSL_RUSTFLAGS = "-C linker=mips-linux-musl-cc" + +export CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER ?= mipsel-linux-musl-cc + +export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER ?= aarch64-linux-musl-cc + +export CARGO_TARGET_MIPS64_UNKNOWN_LINUX_MUSLABI64_LINKER ?= mips64-linux-musl-cc BUILD_TARGET=$(addprefix build-,$(TARGET_NAME)) @@ -39,3 +48,6 @@ build-mipsel: $(PLUGIN_OUT_PATH) build-mips64: TARGET_TRIPLE=mips64-unknown-linux-muslabi64 build-mips64: $(PLUGIN_OUT_PATH) + +# Do not build for PowerPC +build-ppc: ; diff --git a/panda/guest_plugins/tcp_servers/Cargo.lock b/panda/guest_plugins/tcp_servers/Cargo.lock index b49e3414388..0889d5d838e 100644 --- a/panda/guest_plugins/tcp_servers/Cargo.lock +++ b/panda/guest_plugins/tcp_servers/Cargo.lock @@ -63,8 +63,6 @@ dependencies = [ [[package]] name = "panda-channels" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a94b07d8bcc852032a8deb91be9d2bbd59421d776a9edb42fc74b40816e7d940" dependencies = [ "lazy_static", "parking_lot", diff --git a/panda/guest_plugins/tcp_servers/Cargo.toml b/panda/guest_plugins/tcp_servers/Cargo.toml index c6d3ad6a69d..e6539748930 100644 --- a/panda/guest_plugins/tcp_servers/Cargo.toml +++ b/panda/guest_plugins/tcp_servers/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -panda-channels = "0.2" +#panda-channels = "0.2" +panda-channels = { path = "/home/jmcleod/dev/panda-channels" } bincode = "1" serde = { version = "1", features = ["derive"] } diff --git a/panda/plugins/frida/Cargo.toml b/panda/plugins/frida/Cargo.toml index 3706da5502b..a7c8a783ec0 100644 --- a/panda/plugins/frida/Cargo.toml +++ b/panda/plugins/frida/Cargo.toml @@ -23,3 +23,4 @@ ppc = ["panda-re/ppc"] mips = ["panda-re/mips"] mipsel = ["panda-re/mipsel"] aarch64 = ["panda-re/aarch64"] +mips64 = ["panda-re/mips64"] diff --git a/panda/plugins/guest_plugin_example/Cargo.toml b/panda/plugins/guest_plugin_example/Cargo.toml index ca478581961..c9147ac88eb 100644 --- a/panda/plugins/guest_plugin_example/Cargo.toml +++ b/panda/plugins/guest_plugin_example/Cargo.toml @@ -21,3 +21,4 @@ ppc = ["panda-re/ppc"] mips = ["panda-re/mips"] mipsel = ["panda-re/mipsel"] aarch64 = ["panda-re/aarch64"] +mips64 = ["panda-re/mips64"] diff --git a/panda/plugins/guest_plugin_manager/Cargo.toml b/panda/plugins/guest_plugin_manager/Cargo.toml index 8b4d1f6be96..04de54370a2 100644 --- a/panda/plugins/guest_plugin_manager/Cargo.toml +++ b/panda/plugins/guest_plugin_manager/Cargo.toml @@ -25,3 +25,4 @@ ppc = ["panda-re/ppc"] mips = ["panda-re/mips"] mipsel = ["panda-re/mipsel"] aarch64 = ["panda-re/aarch64"] +mips64 = ["panda-re/mips64"] diff --git a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs index de632505818..2a19e082f50 100644 --- a/panda/plugins/guest_plugin_manager/src/hyp_regs.rs +++ b/panda/plugins/guest_plugin_manager/src/hyp_regs.rs @@ -16,9 +16,15 @@ pub const REG_ORDER: [Reg; 5] = [RAX, RBX, RCX, RDX, RDI]; #[cfg(feature = "arm")] pub const REG_ORDER: [Reg; 5] = [R0, R1, R2, R3, R4]; -#[cfg(feature = "mips")] +#[cfg(any(feature = "mips", feature = "mipsel", feature = "mips64"))] pub const REG_ORDER: [Reg; 5] = [V0, A0, A1, A2, A3]; +#[cfg(feature = "aarch64")] +pub const REG_ORDER: [Reg; 5] = [X0, X1, X2, X3, X4]; + +#[cfg(feature = "ppc")] +pub const REG_ORDER: [Reg; 5] = [R3, R4, R5, R6, R7]; + // =================== Return Value =================== #[cfg(feature = "i386")] pub const RET_REG: Reg = EAX; @@ -29,9 +35,15 @@ pub const RET_REG: Reg = RAX; #[cfg(feature = "arm")] pub const RET_REG: Reg = R0; -#[cfg(feature = "mips")] +#[cfg(any(feature = "mips", feature = "mipsel", feature = "mips64"))] pub const RET_REG: Reg = V0; +#[cfg(feature = "aarch64")] +pub const RET_REG: Reg = X0; + +#[cfg(feature = "ppc")] +pub const RET_REG: Reg = R3; + pub fn get_hyp_reg(cpu: &mut CPUState, num: usize) -> usize { let reg_to_read = REG_ORDER[num]; get_reg(cpu, reg_to_read) as usize diff --git a/panda/plugins/guest_shell/Cargo.toml b/panda/plugins/guest_shell/Cargo.toml index 2cb6bb759b0..f11c725961c 100644 --- a/panda/plugins/guest_shell/Cargo.toml +++ b/panda/plugins/guest_shell/Cargo.toml @@ -21,3 +21,4 @@ ppc = ["panda-re/ppc"] mips = ["panda-re/mips"] mipsel = ["panda-re/mipsel"] aarch64 = ["panda-re/aarch64"] +mips64 = ["panda-re/mips64"] diff --git a/panda/plugins/hyperfuse/Cargo.toml b/panda/plugins/hyperfuse/Cargo.toml index 58bf22cc165..b8b9dab060c 100644 --- a/panda/plugins/hyperfuse/Cargo.toml +++ b/panda/plugins/hyperfuse/Cargo.toml @@ -30,3 +30,4 @@ ppc = ["panda-re/ppc"] mips = ["panda-re/mips"] mipsel = ["panda-re/mipsel"] aarch64 = ["panda-re/aarch64"] +mips64 = ["panda-re/mips64"] diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index 27eb628998f..53f0797d17b 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -376,9 +376,7 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056bd47b4532e1e2c06492ad6b7ee1ecd253a744e8018844e68a0b654ea80b6f" +version = "0.35.0" dependencies = [ "array-init", "async-trait", @@ -402,8 +400,6 @@ dependencies = [ [[package]] name = "panda-re-macros" version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29772398be20723c90088ae4380d62e25cefe54c174d9082532b258985e41d04" dependencies = [ "darling", "doc-comment", @@ -415,8 +411,6 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index 1901f28cc85..a38807f146e 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,7 +8,8 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.33.0", default-features = false, features = ["syscall-injection"] } +#panda-re = { version = "0.33.0", default-features = false, features = ["syscall-injection"] } +panda-re = { path = "/home/jmcleod/dev/panda-rs/panda-rs", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" @@ -25,3 +26,4 @@ ppc = ["panda-re/ppc"] mips = ["panda-re/mips"] mipsel = ["panda-re/mipsel"] aarch64 = ["panda-re/aarch64"] +mips64 = ["panda-re/mips64"] diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 4b641c88214..a24da806782 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -1,24 +1,28 @@ use panda::{ - current_asid, - enums::MemRWStatus, - mem::virtual_memory_write, - plugins::osi::OSI, + current_asid, enums::MemRWStatus, mem::virtual_memory_write, + plugins::osi::OSI, prelude::*, sys::get_cpu, +}; + +#[cfg(not(feature = "ppc"))] +use panda::{ plugins::syscalls2::SYSCALLS, - prelude::*, - sys::get_cpu, syscall_injection::{fork, run_injector}, }; use std::sync::atomic::{AtomicBool, Ordering}; mod args; + +#[cfg(not(feature = "ppc"))] mod syscalls; +#[cfg(not(feature = "ppc"))] use syscalls::{ chdir, close, do_execve, do_memfd_create, do_mmap, do_write, getpid, open, setsid, O_CLOEXEC, O_CREAT, O_RDWR, O_TRUNC, PAGE_SIZE, }; +#[cfg(not(feature = "ppc"))] /// mmap a buffer and ensure it's paged in, then return the address to it async fn get_guest_buffer() -> target_ptr_t { // mmap in a new page @@ -68,6 +72,7 @@ panda::export_ppp_callback! { pub(crate) fn before_guest_inject(cpu: &mut CPUState); } +#[cfg(not(feature = "ppc"))] extern "C" fn on_sys_enter( cpu: &mut CPUState, pc: SyscallPc, @@ -235,6 +240,7 @@ extern "C" fn on_sys_enter( static LOADED: AtomicBool = AtomicBool::new(false); +#[cfg(not(feature = "ppc"))] #[panda::init] fn init(_: &mut PluginHandle) -> bool { if LOADED.swap(true, Ordering::SeqCst) { @@ -257,5 +263,11 @@ fn init(_: &mut PluginHandle) -> bool { true } +#[cfg(feature = "ppc")] +#[panda::init] +fn init(_: &mut PluginHandle) -> bool { + panic!("linjector not supported on PowerPC") +} + #[panda::uninit] fn exit(_: &mut PluginHandle) {} diff --git a/panda/plugins/linjector/src/syscalls.rs b/panda/plugins/linjector/src/syscalls.rs index cf046618f8b..5ba9ac0f6fe 100644 --- a/panda/plugins/linjector/src/syscalls.rs +++ b/panda/plugins/linjector/src/syscalls.rs @@ -20,8 +20,16 @@ mod sys_nums; #[path = "syscalls/arm.rs"] mod sys_nums; -#[cfg(feature = "mips")] -#[path = "syscalls/arm.rs"] +#[cfg(any(feature = "mips", feature = "mipsel"))] +#[path = "syscalls/mips.rs"] +mod sys_nums; + +#[cfg(feature = "mips64")] +#[path = "syscalls/mips64.rs"] +mod sys_nums; + +#[cfg(feature = "aarch64")] +#[path = "syscalls/aarch64.rs"] mod sys_nums; use sys_nums::*; diff --git a/panda/plugins/linjector/src/syscalls/aarch64.rs b/panda/plugins/linjector/src/syscalls/aarch64.rs new file mode 100644 index 00000000000..781a05afeb4 --- /dev/null +++ b/panda/plugins/linjector/src/syscalls/aarch64.rs @@ -0,0 +1,17 @@ +use panda::prelude::*; + +pub(crate) const GETPID: target_ulong = 0xAC; +pub(crate) const MMAP: target_ulong = 222; +pub(crate) const WRITE: target_ulong = 64; +pub(crate) const EXECVE: target_ulong = 221; +pub(crate) const MEMFD_CREATE: target_ulong = 279; +pub(crate) const CHDIR: target_ulong = 49; +pub(crate) const SETSID: target_ulong = 157; +pub(crate) const OPEN: target_ulong = 0x400; +pub(crate) const CLOSE: target_ulong = 0x39; + +pub(crate) const PROT_READ: target_ulong = 1; +pub(crate) const PROT_WRITE: target_ulong = 2; + +pub(crate) const MAP_SHARED: target_ulong = 1; +pub(crate) const MAP_ANON: target_ulong = 0x20; diff --git a/panda/plugins/linjector/src/syscalls/mips64.rs b/panda/plugins/linjector/src/syscalls/mips64.rs new file mode 100644 index 00000000000..780119d5ba7 --- /dev/null +++ b/panda/plugins/linjector/src/syscalls/mips64.rs @@ -0,0 +1,17 @@ +use panda::prelude::*; + +pub(crate) const GETPID: target_ulong = 5038; +pub(crate) const MMAP: target_ulong = 5009; +pub(crate) const WRITE: target_ulong = 5001; +pub(crate) const EXECVE: target_ulong = 5057; +pub(crate) const MEMFD_CREATE: target_ulong = 5314; +pub(crate) const CHDIR: target_ulong = 5078; +pub(crate) const SETSID: target_ulong = 5110; +pub(crate) const OPEN: target_ulong = 5002; +pub(crate) const CLOSE: target_ulong = 5003; + +pub(crate) const PROT_READ: target_ulong = 1; +pub(crate) const PROT_WRITE: target_ulong = 2; + +pub(crate) const MAP_SHARED: target_ulong = 1; +pub(crate) const MAP_ANON: target_ulong = 0x800; diff --git a/panda/plugins/tcp_passthrough/Cargo.toml b/panda/plugins/tcp_passthrough/Cargo.toml index b1e28e6f230..41bff9ea788 100644 --- a/panda/plugins/tcp_passthrough/Cargo.toml +++ b/panda/plugins/tcp_passthrough/Cargo.toml @@ -28,3 +28,4 @@ ppc = ["panda-re/ppc"] mips = ["panda-re/mips"] mipsel = ["panda-re/mipsel"] aarch64 = ["panda-re/aarch64"] +mips64 = ["panda-re/mips64"] From 682c4c52521d6893a3ffaa5168e699886ba5183b Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 28 Jul 2022 14:01:03 -0400 Subject: [PATCH 62/79] Add install script for musl toolchains --- panda/scripts/musl_toolchains.sh | 337 +++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100755 panda/scripts/musl_toolchains.sh diff --git a/panda/scripts/musl_toolchains.sh b/panda/scripts/musl_toolchains.sh new file mode 100755 index 00000000000..e23ad58494f --- /dev/null +++ b/panda/scripts/musl_toolchains.sh @@ -0,0 +1,337 @@ +#!/bin/bash + +TARGETS=(i486-linux-musl-cross mips-linux-musl-cross mipsel-linux-musl-cross mips64-linux-musl-cross arm-linux-musleabi-cross aarch64-linux-musl-cross) + +bold=$(tput bold) +red=$(tput setaf 1) +cyan=$(tput setaf 6) +normal=$(tput sgr0) + +CMD_NAME="./musl_toolchains.sh" + +function error { + >&2 echo "${bold}${red}error${normal}: $@" +} + +function suggest { + >&2 echo " ${bold}${cyan}help${normal}: $@" +} + +function help { + >&2 echo "${bold}Usage:${normal}" + >&2 echo " ${CMD_NAME} [subcommand]" + >&2 echo "" + >&2 echo "${bold}Subcommands:${normal}" + >&2 echo " install Install all needed musl toolchains to the current directory" + >&2 echo " uninstall Remove all installed musl toolchains from the current directory" + >&2 echo " list List the musl toolchains supported or installed by this script" + >&2 echo " check-installed Checks if a target or set of targets are installed" + >&2 echo " help Print this help text" +} + +function install_help { + >&2 echo "${bold}Usage:${normal}" + >&2 echo " ${CMD_NAME} install [args]" + >&2 echo "" + >&2 echo "Install all the toolchains supported by this script" + >&2 echo "" + >&2 echo "${bold}Arguments:${normal}" + >&2 echo " --help Print this help text" + >&2 echo " --to Install the toolchains inside of the directory (default: cwd)" +} + +function uninstall_help { + >&2 echo "${bold}Usage:${normal}" + >&2 echo " ${CMD_NAME} uninstall [args]" + >&2 echo "" + >&2 echo "Uninstall all the toolchains supported by this script" + >&2 echo "" + >&2 echo "${bold}Arguments:${normal}" + >&2 echo " --help Print this help text" + >&2 echo " --from Uninstall any toolchains inside of the directory (default: cwd)" +} + +function list_targets_help { + >&2 echo "${bold}Usage:${normal}" + >&2 echo " ${CMD_NAME} list [args]" + >&2 echo "" + >&2 echo "List the target triples supported or installed by this script" + >&2 echo "" + >&2 echo "${bold}Arguments:${normal}" + >&2 echo " --help Print this help text" + >&2 echo " --installed Show only installed targets" + >&2 echo " --in When checking for installed toolchains, look inside of the directory (default: cwd)" +} + +function check_installed_help { + >&2 echo "${bold}Usage:${normal}" + >&2 echo " ${CMD_NAME} check-installed [args]" + >&2 echo "" + >&2 echo "Checks if a set of targets are installed" + >&2 echo "" + >&2 echo "${bold}Arguments:${normal}" + >&2 echo " --help Print this help text" + >&2 echo " --all Check that all available targets are selected" + >&2 echo " --in When checking for installed toolchains, look inside of the directory (default: cwd)" + >&2 echo " A list of targets to check are installed" +} + +function install { + cwd=`pwd` + args=("$@") + + while [[ ${#args[@]} -ne 0 ]] + do + case ${args[0]} in + "--help" | "-h") + install_help + exit 0 + ;; + "--to") + cwd="${args[1]}" + args=("${args[@]:2}") + ;; + *) + error "Found '${args[0]}'" + install_help + exit 1 + ;; + esac + done + + if [[ $cwd == "" ]] + then + error "empty directory to install to" + exit 1 + fi + + if ! [[ -d $cwd ]] + then + >&2 echo "Directory '$cwd' does not exist, creating for you..." + mkdir -p $cwd + fi + + path_prefix="" + + for target in ${TARGETS[@]} + do + full_path="$cwd/$target/bin" + if [ -d $full_path ] + then + echo "$target is already installed" + else + echo "${bold}Downloading $target...${normal}" + curl -o "$cwd/$target.tgz" https://musl.cc/$target.tgz && tar -xzf "$cwd/$target.tgz" + rm "$cwd/$target.tgz" + fi + + path_prefix="$full_path:$path_prefix" + done + + QUOTE='"' + DOLLAR='$' + + >&2 echo "" + >&2 echo "${bold}Add to PATH using:${normal}" + echo " export PATH=${QUOTE}${path_prefix}${DOLLAR}PATH${QUOTE}" +} + +function uninstall { + cwd=`pwd` + args=("$@") + + while [[ ${#args[@]} -ne 0 ]] + do + case ${args[0]} in + "--help" | "-h") + uninstall_help + exit 0 + ;; + "--from") + cwd="${args[1]}" + args=("${args[@]:2}") + ;; + *) + error "Found '${args[0]}'" + uninstall_help + exit 1 + ;; + esac + done + + if [[ $cwd == "" ]] + then + error "empty directory to uninstall from" + exit 1 + fi + + for target in ${TARGETS[@]} + do + full_path="$cwd/$target/bin" + if [ -d $full_path ] + then + rm -rf "$cwd/$target" && echo "Removed $target" + >/dev/null 2>/dev/null rm $target.tgz || true + else + >/dev/null 2>/dev/null rm $target.tgz || true + fi + done + + echo "" + echo "All targets uninstalled" +} + +function list_targets { + check_installed=false + cwd_set=false + + cwd=`pwd` + args=("$@") + + while [[ ${#args[@]} -ne 0 ]] + do + case ${args[0]} in + "--help" | "-h") + list_targets_help + exit 0 + ;; + "--installed") + check_installed=true + args=("${args[@]:1}") + ;; + "--in") + cwd_set=true + cwd="${args[1]}" + args=("${args[@]:2}") + ;; + *) + error "Found '${args[0]}', unexpected for 'list' subcommand" + list_targets_help + exit 1 + ;; + esac + done + + if [[ $cwd_set = true && $check_installed = false ]] + then + error "'--in' was passed, requires '--installed' to be passed as well" + exit 1 + fi + + at_least_one_installed=false + + for target in ${TARGETS[@]} + do + full_path="$cwd/$target/bin" + + if [[ $check_installed = false || -d $full_path ]] + then + echo $target + at_least_one_installed=true + fi + done + + if [[ $check_installed = true && $at_least_one_installed = false ]] + then + >&2 echo "${bold}No targets installed${normal}" + fi +} + +containsElement () { + local e match="$1" + shift + + for e; do [[ "$e" == "$match" ]] && return 0; done + + return 1 +} + +function check_installed { + check_installed=false + cwd_set=false + + cwd=`pwd` + args=("$@") + + selected_targets=() + + while [[ ${#args[@]} -ne 0 ]] + do + case ${args[0]} in + "--help" | "-h") + check_installed_help + exit 0 + ;; + "--all") + check_all=true + args=("${args[@]:1}") + ;; + "--in") + cwd="${args[1]}" + args=("${args[@]:2}") + ;; + *) + if containsElement "${args[0]}" "${TARGETS[@]}"; then + selected_targets+=("${args[0]}") + args=("${args[@]:1}") + else + error "Found '${args[0]}', unexpected for 'check-installed' subcommand, not a valid flag or target name" + suggest "use '${CMD_NAME} list' to see a list of valid targets" + >&2 echo "" + check_installed_help + exit 1 + fi + ;; + esac + done + + if [[ $check_all = true ]]; then + selected_targets=("${TARGETS[@]}") + fi + + if [[ ${#selected_targets[@]} -eq 0 ]]; then + error "No targets specified" + suggest "pass '--all' or a space-separated list of toolchain names" + exit 1 + fi + + for target in ${selected_targets[@]} + do + full_path="$cwd/$target/bin" + + if ! [[ -d $full_path ]] + then + error "Toolchain '$target' is not installed in '$cwd'" + exit 1 + fi + done + + >&2 echo "All toolchains are installed." +} + +if [[ $# -lt 1 ]] +then + help + exit 1 +fi + +case $1 in + help | "-h" | "--help") + help + ;; + list) + list_targets ${@:2} + ;; + install) + install ${@:2} + ;; + uninstall | remove | delete) + uninstall ${@:2} + ;; + "check-installed") + check_installed ${@:2} + ;; + *) + >&2 echo "Invalid usage" + help +esac From 548070f983f1d84359c2bc0d6667c35d812696be Mon Sep 17 00:00:00 2001 From: jamcleod Date: Tue, 2 Aug 2022 20:12:55 -0400 Subject: [PATCH 63/79] Fix regression in linjector --- panda/plugins/linjector/Cargo.lock | 8 +++++++- panda/plugins/linjector/Cargo.toml | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index 53f0797d17b..09eadca2d3f 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -376,7 +376,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.35.0" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ef6b74de7d4809607e9b029016c74342680159366ef7d2bdd5ae9bd1ff6416" dependencies = [ "array-init", "async-trait", @@ -400,6 +402,8 @@ dependencies = [ [[package]] name = "panda-re-macros" version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29772398be20723c90088ae4380d62e25cefe54c174d9082532b258985e41d04" dependencies = [ "darling", "doc-comment", @@ -411,6 +415,8 @@ dependencies = [ [[package]] name = "panda-re-sys" version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00ee000dc315bf4a0a55d78b6d97456a7540d6ed01768da5f5aa89fdb660783" [[package]] name = "parking_lot" diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index a38807f146e..2da887b2aa8 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,8 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -#panda-re = { version = "0.33.0", default-features = false, features = ["syscall-injection"] } -panda-re = { path = "/home/jmcleod/dev/panda-rs/panda-rs", default-features = false, features = ["syscall-injection"] } +panda-re = { version = "0.36.0", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" From aa56b767371fa163cf96616b072385c16930fa3f Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 3 Aug 2022 12:36:40 -0400 Subject: [PATCH 64/79] Fix panda-channels version for tcp guest plugin --- panda/guest_plugins/tcp_servers/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/panda/guest_plugins/tcp_servers/Cargo.toml b/panda/guest_plugins/tcp_servers/Cargo.toml index e6539748930..6ec634079ae 100644 --- a/panda/guest_plugins/tcp_servers/Cargo.toml +++ b/panda/guest_plugins/tcp_servers/Cargo.toml @@ -4,8 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -#panda-channels = "0.2" -panda-channels = { path = "/home/jmcleod/dev/panda-channels" } +panda-channels = "0.3" bincode = "1" serde = { version = "1", features = ["derive"] } From 6fa613237c26d93721c33e0f419480df54080f77 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 3 Aug 2022 12:59:10 -0400 Subject: [PATCH 65/79] Add libfuse-dev to PANDA dependencies --- panda/dependencies/ubuntu:18.04_build.txt | 3 +++ panda/dependencies/ubuntu:20.04_build.txt | 3 +++ panda/guest_plugins/tcp_servers/Cargo.lock | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/panda/dependencies/ubuntu:18.04_build.txt b/panda/dependencies/ubuntu:18.04_build.txt index b284ce0b4cc..a40e5dd2948 100644 --- a/panda/dependencies/ubuntu:18.04_build.txt +++ b/panda/dependencies/ubuntu:18.04_build.txt @@ -25,6 +25,9 @@ protobuf-compiler python3-dev zip +# hyperfuse build deps +libfuse-dev + # pypanda dependencies python3-setuptools python3-wheel diff --git a/panda/dependencies/ubuntu:20.04_build.txt b/panda/dependencies/ubuntu:20.04_build.txt index c9bd9e14bbf..92331eeb02d 100644 --- a/panda/dependencies/ubuntu:20.04_build.txt +++ b/panda/dependencies/ubuntu:20.04_build.txt @@ -21,6 +21,9 @@ python3-dev libpixman-1-dev zip +# hyperfuse build deps +libfuse-dev + # pypanda dependencies python3-setuptools python3-wheel diff --git a/panda/guest_plugins/tcp_servers/Cargo.lock b/panda/guest_plugins/tcp_servers/Cargo.lock index 0889d5d838e..cc542916090 100644 --- a/panda/guest_plugins/tcp_servers/Cargo.lock +++ b/panda/guest_plugins/tcp_servers/Cargo.lock @@ -62,7 +62,9 @@ dependencies = [ [[package]] name = "panda-channels" -version = "0.2.0" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529d17650397380d80c95c6027ffcb48eaf4095a0c513eb7e827f0c3c0e52e9c" dependencies = [ "lazy_static", "parking_lot", From 2455d05baf3117644fdb9274c85500b0a248dfc6 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 3 Aug 2022 13:38:39 -0400 Subject: [PATCH 66/79] Move guest_daemon in-tree --- panda/guest_plugins/config.panda | 1 + panda/guest_plugins/guest_daemon/Cargo.lock | 256 ++++++++++++++++++ panda/guest_plugins/guest_daemon/Cargo.toml | 10 + panda/guest_plugins/guest_daemon/Makefile | 20 ++ .../guest_plugins/guest_daemon/src/loader.rs | 14 + panda/guest_plugins/guest_daemon/src/main.rs | 108 ++++++++ 6 files changed, 409 insertions(+) create mode 100644 panda/guest_plugins/guest_daemon/Cargo.lock create mode 100644 panda/guest_plugins/guest_daemon/Cargo.toml create mode 100644 panda/guest_plugins/guest_daemon/Makefile create mode 100644 panda/guest_plugins/guest_daemon/src/loader.rs create mode 100644 panda/guest_plugins/guest_daemon/src/main.rs diff --git a/panda/guest_plugins/config.panda b/panda/guest_plugins/config.panda index f785445e0ce..af2bf46fe04 100644 --- a/panda/guest_plugins/config.panda +++ b/panda/guest_plugins/config.panda @@ -1,2 +1,3 @@ #rust_example tcp_servers +guest_daemon diff --git a/panda/guest_plugins/guest_daemon/Cargo.lock b/panda/guest_plugins/guest_daemon/Cargo.lock new file mode 100644 index 00000000000..9055ba55ef2 --- /dev/null +++ b/panda/guest_plugins/guest_daemon/Cargo.lock @@ -0,0 +1,256 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "daemonize-me" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583332de51377006c0faf944fedde7edbfb857d6f79034925eab804cc97470ec" +dependencies = [ + "libc", + "nix", + "snafu", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "guest_daemon" +version = "0.1.0" +dependencies = [ + "daemonize-me", + "libloading", + "memfd", + "panda-channels", +] + +[[package]] +name = "instant" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" + +[[package]] +name = "libloading" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "memfd" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6627dc657574b49d6ad27105ed671822be56e0d2547d413bfbf3e8d8fa92e7a" +dependencies = [ + "libc", +] + +[[package]] +name = "nix" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" +dependencies = [ + "bitflags", + "cc", + "cfg-if 0.1.10", + "libc", + "void", +] + +[[package]] +name = "panda-channels" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94b07d8bcc852032a8deb91be9d2bbd59421d776a9edb42fc74b40816e7d940" +dependencies = [ + "lazy_static", + "parking_lot", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + +[[package]] +name = "snafu" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" +dependencies = [ + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/panda/guest_plugins/guest_daemon/Cargo.toml b/panda/guest_plugins/guest_daemon/Cargo.toml new file mode 100644 index 00000000000..f8d0f6886b2 --- /dev/null +++ b/panda/guest_plugins/guest_daemon/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "guest_daemon" +version = "0.1.0" +edition = "2018" + +[dependencies] +panda-channels = "0.2" +memfd = "0.4.0" +libloading = "0.7" +daemonize-me = "1" diff --git a/panda/guest_plugins/guest_daemon/Makefile b/panda/guest_plugins/guest_daemon/Makefile new file mode 100644 index 00000000000..1458392b517 --- /dev/null +++ b/panda/guest_plugins/guest_daemon/Makefile @@ -0,0 +1,20 @@ +# Remember to: +# * Add your plugin name to config.panda +# * Keep your plugin name the same as the folder name and Cargo.toml package name + +# Output build artifacts to the build directory +PLUGIN_ARTIFACTS_DIR = $(PLUGIN_TARGET_DIR)/$(PLUGIN_NAME)/target + +# recompile if any of the src/*.rs files changed, or Cargo.toml +RUST_SOURCE = $(wildcard $(PLUGIN_DIR)/src/*.rs) +PLUGIN_DEPS=$(RUST_SOURCE) $(PLUGIN_DIR)/Cargo.toml + +$(PLUGIN_OUT_PATH): BUILD_RESULT="$(PLUGIN_ARTIFACTS_DIR)/$(TARGET_TRIPLE)/release/$(PLUGIN_NAME)" +$(PLUGIN_OUT_PATH): $(PLUGIN_DEPS) + @echo " CARGO $(PLUGIN_NAME) (${TARGET_TRIPLE})" + @CARGO_TERM_PROGRESS_WHEN=never cargo build --release \ + --target=$(TARGET_TRIPLE) \ + --manifest-path=$(PLUGIN_DIR)/Cargo.toml \ + --target-dir=$(PLUGIN_ARTIFACTS_DIR) + @mkdir -p $(PLUGIN_BIN_DIR) + @cp -p $(BUILD_RESULT) $@ diff --git a/panda/guest_plugins/guest_daemon/src/loader.rs b/panda/guest_plugins/guest_daemon/src/loader.rs new file mode 100644 index 00000000000..1ce073662d2 --- /dev/null +++ b/panda/guest_plugins/guest_daemon/src/loader.rs @@ -0,0 +1,14 @@ +use memfd::MemfdOptions; +use std::{io::Write, os::unix::prelude::AsRawFd, process::Command}; + +pub(crate) fn load_plugin(payload: Vec) { + let plugin_file = MemfdOptions::new().create("pluginfd").unwrap(); + let fd = plugin_file.as_raw_fd(); + let mut plugin_file = plugin_file.into_file(); + + plugin_file.write_all(&payload).unwrap(); + + Command::new(format!("/proc/self/fd/{}", fd)) + .spawn() + .unwrap(); +} diff --git a/panda/guest_plugins/guest_daemon/src/main.rs b/panda/guest_plugins/guest_daemon/src/main.rs new file mode 100644 index 00000000000..289f68088d0 --- /dev/null +++ b/panda/guest_plugins/guest_daemon/src/main.rs @@ -0,0 +1,108 @@ +#![feature(asm)] +use panda_channels::{get_main_raw_channel, hypercall, RawChannel}; + +mod loader; + +enum PacketKind { + LoadPlugin = 0, +} + +struct Packet { + kind: PacketKind, + payload: Vec, +} + +impl PacketKind { + fn from(kind: u32) -> Option { + match kind { + 0 => Some(Self::LoadPlugin), + _ => None, + } + } +} + +fn split_header(header: [u8; 8]) -> ([u8; 4], [u8; 4]) { + let [x1, x2, x3, x4, y1, y2, y3, y4] = header; + + ([x1, x2, x3, x4], [y1, y2, y3, y4]) +} + +use memfd::MemfdOptions; +use std::{ + io::Write, os::unix::prelude::AsRawFd, path::Path, process::Command, thread, time::Duration, +}; +fn read_packet(reader: &mut RawChannel) -> Option { + //let plugin_file = MemfdOptions::new() + // .close_on_exec(true) + // .create("pluginfd") + // .unwrap(); + //let fd = plugin_file.as_raw_fd(); + //let mut plugin_file = plugin_file.into_file(); + let mut temp_buf = vec![0u8; 4096 as _]; + temp_buf.fill(1); + + let mut payload = vec![]; + loop { + // println!("top of loop"); + // let mut header = [0u8; 8]; + match reader.read_packet(&mut temp_buf) { + 0 => break, + _ => { + payload.write_all(&temp_buf).unwrap(); + //plugin_file.write_all(&payload).unwrap(); + } + } + } + + if payload.is_empty() { + return None; + } + + println!("got to bottom. executing"); + + //println!("fd: {}", fd); + //let fds = std::fs::read_dir("/proc/self/fd") + // .unwrap() + // .map(|entry| entry.unwrap().path()) + // .collect::>(); + //dbg!(&fds); + //println!("path: /proc/self/fd/{}", fd); + + //dbg!(Path::new(&format!("/proc/self/fd/{}", fd)).exists()); + //Command::new(format!("/proc/self/fd/{}", fd)) + // .spawn() + // .unwrap(); + + Some(Packet { + kind: PacketKind::LoadPlugin, + payload, + }) +} + +fn main() { + eprintln!("at main.rs in guest_daemon"); + + eprintln!("Daemonizing..."); + daemonize_me::Daemon::new() + .start() + .expect("Failed to daemonize"); + eprintln!("Finished daemonizing"); + + while !hypercall::start() { + thread::yield_now(); + } + + let mut channel = get_main_raw_channel("guest_daemon").unwrap(); + + loop { + match read_packet(&mut channel) { + Some(Packet { + kind: PacketKind::LoadPlugin, + payload, + }) => loader::load_plugin(payload), + None => { + thread::sleep(Duration::from_millis(10)); + } + } + } +} From edac98a2e5da75b407f52fca80d0400038c87ff7 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 3 Aug 2022 13:49:12 -0400 Subject: [PATCH 67/79] Remove unneeded nightly feature from guest_daemon --- panda/guest_plugins/guest_daemon/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/panda/guest_plugins/guest_daemon/src/main.rs b/panda/guest_plugins/guest_daemon/src/main.rs index 289f68088d0..6be1828a068 100644 --- a/panda/guest_plugins/guest_daemon/src/main.rs +++ b/panda/guest_plugins/guest_daemon/src/main.rs @@ -1,4 +1,3 @@ -#![feature(asm)] use panda_channels::{get_main_raw_channel, hypercall, RawChannel}; mod loader; From b9326a30dba49ee726a631cdc5a76715264ce417 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 3 Aug 2022 13:54:59 -0400 Subject: [PATCH 68/79] Clean up guest_daemon warnings --- panda/guest_plugins/guest_daemon/src/main.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/panda/guest_plugins/guest_daemon/src/main.rs b/panda/guest_plugins/guest_daemon/src/main.rs index 6be1828a068..7b83f3b2dfc 100644 --- a/panda/guest_plugins/guest_daemon/src/main.rs +++ b/panda/guest_plugins/guest_daemon/src/main.rs @@ -1,4 +1,5 @@ use panda_channels::{get_main_raw_channel, hypercall, RawChannel}; +use std::{io::Write, thread, time::Duration}; mod loader; @@ -11,25 +12,6 @@ struct Packet { payload: Vec, } -impl PacketKind { - fn from(kind: u32) -> Option { - match kind { - 0 => Some(Self::LoadPlugin), - _ => None, - } - } -} - -fn split_header(header: [u8; 8]) -> ([u8; 4], [u8; 4]) { - let [x1, x2, x3, x4, y1, y2, y3, y4] = header; - - ([x1, x2, x3, x4], [y1, y2, y3, y4]) -} - -use memfd::MemfdOptions; -use std::{ - io::Write, os::unix::prelude::AsRawFd, path::Path, process::Command, thread, time::Duration, -}; fn read_packet(reader: &mut RawChannel) -> Option { //let plugin_file = MemfdOptions::new() // .close_on_exec(true) From 2eb59d1c5b6117da8a2776460408a130d9365ee4 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 8 Aug 2022 12:00:51 -0400 Subject: [PATCH 69/79] Fix linjector arm support --- panda/guest_plugins/guest_daemon/Cargo.lock | 5 ++- panda/guest_plugins/guest_daemon/Cargo.toml | 3 +- .../guest_plugins/guest_daemon/src/loader.rs | 44 ++++++++++++++++--- panda/guest_plugins/rust_example/Cargo.toml | 2 +- panda/plugins/linjector/Cargo.lock | 4 +- panda/plugins/linjector/Cargo.toml | 2 +- 6 files changed, 46 insertions(+), 14 deletions(-) diff --git a/panda/guest_plugins/guest_daemon/Cargo.lock b/panda/guest_plugins/guest_daemon/Cargo.lock index 9055ba55ef2..d826ae5eaef 100644 --- a/panda/guest_plugins/guest_daemon/Cargo.lock +++ b/panda/guest_plugins/guest_daemon/Cargo.lock @@ -48,6 +48,7 @@ name = "guest_daemon" version = "0.1.0" dependencies = [ "daemonize-me", + "libc", "libloading", "memfd", "panda-channels", @@ -117,9 +118,9 @@ dependencies = [ [[package]] name = "panda-channels" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a94b07d8bcc852032a8deb91be9d2bbd59421d776a9edb42fc74b40816e7d940" +checksum = "529d17650397380d80c95c6027ffcb48eaf4095a0c513eb7e827f0c3c0e52e9c" dependencies = [ "lazy_static", "parking_lot", diff --git a/panda/guest_plugins/guest_daemon/Cargo.toml b/panda/guest_plugins/guest_daemon/Cargo.toml index f8d0f6886b2..d262ac88a6a 100644 --- a/panda/guest_plugins/guest_daemon/Cargo.toml +++ b/panda/guest_plugins/guest_daemon/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.0" edition = "2018" [dependencies] -panda-channels = "0.2" +panda-channels = "0.3" memfd = "0.4.0" libloading = "0.7" daemonize-me = "1" +libc = "0.2" diff --git a/panda/guest_plugins/guest_daemon/src/loader.rs b/panda/guest_plugins/guest_daemon/src/loader.rs index 1ce073662d2..5b38c926dfd 100644 --- a/panda/guest_plugins/guest_daemon/src/loader.rs +++ b/panda/guest_plugins/guest_daemon/src/loader.rs @@ -1,14 +1,44 @@ use memfd::MemfdOptions; -use std::{io::Write, os::unix::prelude::AsRawFd, process::Command}; +use std::{ + fs, + io::Write, + os::unix::{fs::OpenOptionsExt, prelude::AsRawFd}, + process::Command, +}; pub(crate) fn load_plugin(payload: Vec) { - let plugin_file = MemfdOptions::new().create("pluginfd").unwrap(); - let fd = plugin_file.as_raw_fd(); - let mut plugin_file = plugin_file.into_file(); + let (path, mut file) = if let Ok(plugin_file) = MemfdOptions::new().create("pluginfd") { + let fd = plugin_file.as_raw_fd(); - plugin_file.write_all(&payload).unwrap(); + (format!("/proc/self/fd/{}", fd), plugin_file.into_file()) + } else { + match fs::OpenOptions::new() + .create(true) + .write(true) + .mode(0o777) + .custom_flags(libc::O_CLOEXEC) + .open("/tmp/plugin_file") + { + Ok(file) => (String::from("/tmp/plugin_file"), file), + Err(err) => { + eprintln!("Failed to write to /tmp"); + panic!("{:?}", err); + } + } + }; - Command::new(format!("/proc/self/fd/{}", fd)) + file.write_all(&payload).unwrap(); + let _ = file.flush(); + let _ = file.sync_all(); + + let mut file = Some(file); + + if path.starts_with("/tmp") { + drop(file.take()); + } + + eprintln!("Running guest plugin..."); + Command::new(path) .spawn() - .unwrap(); + .expect("Failed to run guest plugin"); } diff --git a/panda/guest_plugins/rust_example/Cargo.toml b/panda/guest_plugins/rust_example/Cargo.toml index c4467703851..193c1885fe7 100644 --- a/panda/guest_plugins/rust_example/Cargo.toml +++ b/panda/guest_plugins/rust_example/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -panda-channels = "0.2" +panda-channels = "0.3" diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index 09eadca2d3f..3aa7f1ebb20 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -376,9 +376,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ef6b74de7d4809607e9b029016c74342680159366ef7d2bdd5ae9bd1ff6416" +checksum = "b094a991ea9676cab2aca1281d22246883ed325a43b5fc0de413d03c1ea1a5be" dependencies = [ "array-init", "async-trait", diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index 2da887b2aa8..8981e36b357 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.36.0", default-features = false, features = ["syscall-injection"] } +panda-re = { version = "0.37.0", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" From af9c8d69052cbb2a155316554e2154cc739a99b0 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 15 Aug 2022 16:24:57 -0400 Subject: [PATCH 70/79] Fix libc version for mips64 --- panda/guest_plugins/guest_daemon/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/panda/guest_plugins/guest_daemon/Cargo.lock b/panda/guest_plugins/guest_daemon/Cargo.lock index d826ae5eaef..eadba358711 100644 --- a/panda/guest_plugins/guest_daemon/Cargo.lock +++ b/panda/guest_plugins/guest_daemon/Cargo.lock @@ -71,9 +71,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.102" +version = "0.2.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" +checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" [[package]] name = "libloading" From 30e56c3e8bd2d739954ce5734873ce28e7764294 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 15 Aug 2022 17:23:03 -0400 Subject: [PATCH 71/79] Disable guest plugin building if toolchains not installed --- panda/Makefile.panda.target | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/panda/Makefile.panda.target b/panda/Makefile.panda.target index 834746e2e9a..57d6a722d27 100644 --- a/panda/Makefile.panda.target +++ b/panda/Makefile.panda.target @@ -165,8 +165,53 @@ ifdef EXTRA_GUEST_PLUGINS_PATH ALL_GUEST_PLUGIN_RULES+=$(EXTRA_GUEST_PLUGIN_SUBDIR_RULES) endif +ifeq ($(TARGET_NAME),i386) + GUEST_CC=i486-linux-musl-gcc + GUEST_RUST_TARGET=i686-unknown-linux-musl +else ifeq ($(TARGET_NAME),x86_64) + GUEST_RUST_TARGET=mipsel-unknown-linux-musl +else ifeq ($(TARGET_NAME),mips) + GUEST_CC=mips-linux-musl-gcc + GUEST_RUST_TARGET=mips-unknown-linux-musl +else ifeq ($(TARGET_NAME),mipsel) + GUEST_CC=mipsel-linux-musl-gcc + GUEST_RUST_TARGET=mipsel-unknown-linux-musl +else ifeq ($(TARGET_NAME),mips64) + GUEST_CC=mips64-linux-musl-gcc + GUEST_RUST_TARGET=mips64-unknown-linux-muslabi64 +else ifeq ($(TARGET_NAME),arm) + GUEST_CC=arm-linux-musleabi-gcc + GUEST_RUST_TARGET=armv5te-unknown-linux-musleabi +else ifeq ($(TARGET_NAME),aarch64) + GUEST_CC=aarch64-linux-musl-gcc + GUEST_RUST_TARGET=aarch64-unknown-linux-musl +endif + +HAS_GUEST_TOOLCHAIN="no" +ifeq ($(TARGET_NAME),x86_64) + HAS_GUEST_TOOLCHAIN="yes" +else ifeq ($(TARGET_NAME),ppc) + HAS_GUEST_TOOLCHAIN="no" + GUEST_PLUGIN_DISABLE_REASON="unsupported on ppc" +else ifneq (, $(shell which $(GUEST_CC))) + ifeq (, $(shell rustup target list --installed | grep $(GUEST_RUST_TARGET))) + GUEST_PLUGIN_DISABLE_REASON="rust target ${GUEST_RUST_TARGET} not installed" + HAS_GUEST_TOOLCHAIN="no" + else + HAS_GUEST_TOOLCHAIN="yes" + endif +else + GUEST_PLUGIN_DISABLE_REASON="musl toolchain not in PATH" +endif + +ifeq ($(HAS_GUEST_TOOLCHAIN),"yes") build_guest_plugins: $(ALL_GUEST_PLUGIN_RULES) @echo "GUEST_PLUGINS: ${PANDA_GUEST_PLUGINS} ${EXTRA_GUEST_PLUGINS}" +else +build_guest_plugins: + @echo "GUEST_PLUGINS: disabled on arch ${TARGET_NAME}, ${GUEST_PLUGIN_DISABLE_REASON}" +endif + guest-plugin-%: $(call quiet-command,mkdir -p ../panda/guest_plugins/$*,) From 0ac8097cd9d27b689edf7079b1eec19839bdef9e Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 15 Aug 2022 17:57:55 -0400 Subject: [PATCH 72/79] Fix assumption that x86_64 musl Rust target is installed --- panda/Makefile.panda.target | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/panda/Makefile.panda.target b/panda/Makefile.panda.target index 57d6a722d27..0576cdfcb2f 100644 --- a/panda/Makefile.panda.target +++ b/panda/Makefile.panda.target @@ -189,7 +189,12 @@ endif HAS_GUEST_TOOLCHAIN="no" ifeq ($(TARGET_NAME),x86_64) - HAS_GUEST_TOOLCHAIN="yes" + ifeq (, $(shell rustup target list --installed | grep $(GUEST_RUST_TARGET))) + GUEST_PLUGIN_DISABLE_REASON="rust target ${GUEST_RUST_TARGET} not installed" + HAS_GUEST_TOOLCHAIN="no" + else + HAS_GUEST_TOOLCHAIN="yes" + endif else ifeq ($(TARGET_NAME),ppc) HAS_GUEST_TOOLCHAIN="no" GUEST_PLUGIN_DISABLE_REASON="unsupported on ppc" From 3e1fbcab9bb47fc3a257e3db4d7ade9dc36dc973 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Tue, 16 Aug 2022 01:35:36 -0400 Subject: [PATCH 73/79] Fix x86_64 musl Rust target typo --- panda/Makefile.panda.target | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/Makefile.panda.target b/panda/Makefile.panda.target index 0576cdfcb2f..f036bc068c7 100644 --- a/panda/Makefile.panda.target +++ b/panda/Makefile.panda.target @@ -169,7 +169,7 @@ ifeq ($(TARGET_NAME),i386) GUEST_CC=i486-linux-musl-gcc GUEST_RUST_TARGET=i686-unknown-linux-musl else ifeq ($(TARGET_NAME),x86_64) - GUEST_RUST_TARGET=mipsel-unknown-linux-musl + GUEST_RUST_TARGET=x86_64-unknown-linux-musl else ifeq ($(TARGET_NAME),mips) GUEST_CC=mips-linux-musl-gcc GUEST_RUST_TARGET=mips-unknown-linux-musl From 81752afc4ba1d2420a8a4222043e676f0fdcc9c2 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Wed, 7 Sep 2022 13:35:23 -0400 Subject: [PATCH 74/79] Update linjector's panda-rs version --- panda/plugins/linjector/Cargo.toml | 2 +- panda/plugins/linjector/src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/panda/plugins/linjector/Cargo.toml b/panda/plugins/linjector/Cargo.toml index 8981e36b357..20e981ade48 100644 --- a/panda/plugins/linjector/Cargo.toml +++ b/panda/plugins/linjector/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -panda-re = { version = "0.37.0", default-features = false, features = ["syscall-injection"] } +panda-re = { version = "0.38.0", default-features = false, features = ["syscall-injection"] } once_cell = "1.8.0" object = "0.26.2" lazy_static = "1.4.0" diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index a24da806782..4ddf2d39847 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -42,7 +42,8 @@ async fn get_guest_buffer() -> target_ptr_t { fn current_process_name(cpu: &mut CPUState) -> String { let proc = OSI.get_current_process(cpu); - proc.get_name().into_owned() + proc.map(|name| name.get_name().into_owned()) + .unwrap_or_default() } /// Convert to bytes and add null terminator From 10fbc7c290f5d68235142ca56a898f31958c1ee2 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 8 Sep 2022 12:41:11 -0400 Subject: [PATCH 75/79] Separate linjector from guest plugin manager --- panda/plugins/guest_plugin_manager/README.md | 2 + .../src/guest_plugin_manager.rs | 40 +++++++++---------- panda/plugins/linjector/Cargo.lock | 4 +- panda/plugins/linjector/README.md | 4 ++ panda/plugins/linjector/src/args.rs | 15 ++++++- panda/plugins/linjector/src/lib.rs | 8 ++-- panda/python/examples/guest_shell.py | 6 ++- panda/python/examples/hyperfuse.py | 4 ++ panda/python/examples/tcp_passthrough.py | 21 +++++++++- 9 files changed, 74 insertions(+), 30 deletions(-) diff --git a/panda/plugins/guest_plugin_manager/README.md b/panda/plugins/guest_plugin_manager/README.md index 2875f5ca57c..5a6e48a76c6 100644 --- a/panda/plugins/guest_plugin_manager/README.md +++ b/panda/plugins/guest_plugin_manager/README.md @@ -14,6 +14,8 @@ to load the "Guest Daemon", an executable running the guest responsible for hand the spawning of future guest processes and is responsible for communicating with the guest_plugin_manager directly. +**Note:** injection of `guest_daemon` plugin must be done before guest plugin manager takes effect. + ## APIs and Callbacks --- diff --git a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs index f310d0f1837..41868b1fc43 100644 --- a/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/guest_plugin_manager.rs @@ -118,26 +118,26 @@ fn init(_: &mut PluginHandle) -> bool { lazy_static::initialize(&ARGS); interface::daemon_manager::init(); - let guest_binary = guest_plugin_path("guest_daemon") - .expect("Failed to retrieve guest_daemon guest plugin path") - .to_string_lossy() - .into_owned(); - - assert!( - panda::os::family().is_linux(), - "Guest plugin manager currently only supports Linux" - ); - - std::thread::spawn(|| { - // TODO: automatically decide which process to inject into - panda::require_plugin(&Linjector { - guest_binary, - proc_name: ARGS.proc_name.clone(), - }); - - PppCallback::new() - .before_guest_inject(|cpu| on_guest_agent_load::trigger(cpu)); - }); + //let guest_binary = guest_plugin_path("guest_daemon") + // .expect("Failed to retrieve guest_daemon guest plugin path") + // .to_string_lossy() + // .into_owned(); + + //assert!( + // panda::os::family().is_linux(), + // "Guest plugin manager currently only supports Linux" + //); + + //std::thread::spawn(|| { + // // TODO: automatically decide which process to inject into + // panda::require_plugin(&Linjector { + // guest_binary, + // proc_name: ARGS.proc_name.clone(), + // }); + + // PppCallback::new() + // .before_guest_inject(|cpu| on_guest_agent_load::trigger(cpu)); + //}); true } diff --git a/panda/plugins/linjector/Cargo.lock b/panda/plugins/linjector/Cargo.lock index 3aa7f1ebb20..2250e0b1dbe 100644 --- a/panda/plugins/linjector/Cargo.lock +++ b/panda/plugins/linjector/Cargo.lock @@ -376,9 +376,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "panda-re" -version = "0.37.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b094a991ea9676cab2aca1281d22246883ed325a43b5fc0de413d03c1ea1a5be" +checksum = "b59ef8fd95e7cecece17cf5d4d1c9aeafe79f020cc2b622cec18dd0a903b44ce" dependencies = [ "array-init", "async-trait", diff --git a/panda/plugins/linjector/README.md b/panda/plugins/linjector/README.md index 421b035b2e9..af971ae6d1f 100644 --- a/panda/plugins/linjector/README.md +++ b/panda/plugins/linjector/README.md @@ -9,3 +9,7 @@ together in order to run the provided executable. It is not recommended to use t * `guest_binary` - string, the path of the executable to load into the guest * `proc_name` - string, the process name to inject into. Defaults to `[any]`. * `require_root` - bool, whether or not to require the process being injected into to have a UID of root + +### Compatibility + +Currently linjector only has support for x86_64 and arm guests. For other targets one may need to provide their own process injection mechanism. diff --git a/panda/plugins/linjector/src/args.rs b/panda/plugins/linjector/src/args.rs index be857afe713..f740916a27a 100644 --- a/panda/plugins/linjector/src/args.rs +++ b/panda/plugins/linjector/src/args.rs @@ -1,6 +1,10 @@ use once_cell::sync::OnceCell; +use panda::plugins::guest_plugin_manager::guest_plugin_path; use panda::prelude::*; +use std::fs; +use std::path::Path; + static ELF_TO_INJECT: OnceCell> = OnceCell::new(); #[derive(PandaArgs)] @@ -26,7 +30,16 @@ pub fn ensure_init() { pub fn load_elf() { log::info!("Loading binary: {:?}", ARGS.guest_binary); - ELF_TO_INJECT.get_or_init(|| std::fs::read(&ARGS.guest_binary).unwrap()); + + let binary_name = &ARGS.guest_binary; + + let guest_binary = match guest_plugin_path(binary_name) { + Some(path) => path.to_string_lossy().into_owned(), + None if Path::new(binary_name).exists() => binary_name.clone(), + None => panic!("Failed to get binary {:?}", binary_name), + }; + + ELF_TO_INJECT.get_or_init(|| fs::read(&guest_binary).unwrap()); } pub fn elf_to_inject() -> &'static [u8] { diff --git a/panda/plugins/linjector/src/lib.rs b/panda/plugins/linjector/src/lib.rs index 4ddf2d39847..f37592a7df2 100644 --- a/panda/plugins/linjector/src/lib.rs +++ b/panda/plugins/linjector/src/lib.rs @@ -200,8 +200,8 @@ extern "C" fn on_sys_enter( log::debug!("Child process began"); log::debug!( "Child process pid: {:#x?}, Child's parent: {:#x?}", - OSI.get_current_process(cpu).pid, - OSI.get_current_process(cpu).ppid, + OSI.get_current_process(cpu).map(|proc| proc.pid), + OSI.get_current_process(cpu).map(|proc| proc.ppid), ); log::debug!("Child asid: {:#x?}", panda::current_asid(cpu)); @@ -230,8 +230,8 @@ extern "C" fn on_sys_enter( let cpu = unsafe { &mut *get_cpu() }; log::debug!( "Parent process pid: {:#x?}, Parent's parent: {:#x?}", - OSI.get_current_process(cpu).pid, - OSI.get_current_process(cpu).ppid, + OSI.get_current_process(cpu).map(|proc| proc.pid), + OSI.get_current_process(cpu).map(|proc| proc.ppid), ); log::debug!("Parent asid: {:#x?}", panda::current_asid(cpu)); diff --git a/panda/python/examples/guest_shell.py b/panda/python/examples/guest_shell.py index 430ad373af5..8963b47e35b 100644 --- a/panda/python/examples/guest_shell.py +++ b/panda/python/examples/guest_shell.py @@ -6,14 +6,18 @@ os.remove("/tmp/guest_shell.sock") panda = Panda(generic="x86_64") -panda.load_plugin("guest_shell") @panda.queue_blocking def run_cmd(): panda.revert_sync("root") + panda.load_plugin("guest_shell") # if it's worth running it's worth running twice # (don't ask, and definitely don't remove either line) + panda.load_plugin("linjector", { + "guest_binary": "guest_daemon", + "proc_name": "cat" + }) panda.run_serial_cmd("cat", no_timeout=True) panda.run_serial_cmd("cat", no_timeout=True) diff --git a/panda/python/examples/hyperfuse.py b/panda/python/examples/hyperfuse.py index d840aa4cbbe..9ec21609eea 100644 --- a/panda/python/examples/hyperfuse.py +++ b/panda/python/examples/hyperfuse.py @@ -10,6 +10,10 @@ def run_cmd(): # if it's worth running it's worth running twice # (don't ask, and definitely don't remove either line) + panda.load_plugin("linjector", { + "guest_binary": "guest_daemon", + "proc_name": "cat" + }) panda.run_serial_cmd("cat", no_timeout=True) panda.run_serial_cmd("cat", no_timeout=True) diff --git a/panda/python/examples/tcp_passthrough.py b/panda/python/examples/tcp_passthrough.py index deb08c83362..98aedcaed51 100644 --- a/panda/python/examples/tcp_passthrough.py +++ b/panda/python/examples/tcp_passthrough.py @@ -2,10 +2,20 @@ panda = Panda(generic="x86_64") +page = "

Guest Web Server

CPU Info:

" + @panda.queue_blocking def run_cmd(): panda.revert_sync("root") + panda.run_serial_cmd("echo '
' > cpuinfo.html")
+    panda.run_serial_cmd("cat /proc/cpuinfo >> cpuinfo.html")
+    panda.run_serial_cmd("echo '
' >> cpuinfo.html") + panda.run_serial_cmd(f"echo '{page}' > index.html") + + #print(panda.run_serial_cmd("mknod -m 777 fifo p")) + #print(panda.run_serial_cmd("head -c10000 fifo | netcat -l -k localhost 1234 > fifo")) + # Start up an HTTP server as a background job panda.run_serial_cmd("python3 -m http.server &") @@ -15,8 +25,11 @@ def run_cmd(): # Print a table of the TCP servers in the guest panda.tcp.print_socket_info() - # Forward a socket from localhost:8000 in the guest to localhost:4343 on the host - panda.tcp.forward_socket(8000, 4343) + # Forward a socket from localhost:8000 in the guest to localhost:8000 on the host + panda.tcp.forward_socket(8000, 8000) + + # Forward a socket from localhost:1234 in the guest to localhost:1234 on the host + panda.tcp.forward_socket(1234, 1234) # print out the socket list ourselves too @panda.tcp.on_get_socket_list @@ -27,6 +40,10 @@ def callback(socket_info: list): print(f" {socket.ip}:{socket.port}\t{socket.pid}\t{socket.is_server}") # Injecting into a cat command, but this could be anything + panda.load_plugin("linjector", { + "guest_binary": "guest_daemon", + "proc_name": "cat" + }) panda.run_serial_cmd("cat", no_timeout=True) panda.end_analysis() From 3840f1a35af834aca997d8b17fe0072e8018ac75 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 13 Oct 2022 15:56:42 -0400 Subject: [PATCH 76/79] Fix guest_plugin docs link --- panda/docs/guest_plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/docs/guest_plugins.md b/panda/docs/guest_plugins.md index 696e684073f..74cd40bfa32 100644 --- a/panda/docs/guest_plugins.md +++ b/panda/docs/guest_plugins.md @@ -231,7 +231,7 @@ To build, we go through the standard PANDA build process: #### Testing Our Guest Plugin -The easiest way to test our plugin will be with a pypanda script. An example script can be found in [`panda/plugins/guest_plugin_example/try_it.py`](/panda/panda/plugins/guest_plugin_example/try_it.py). +The easiest way to test our plugin will be with a pypanda script. An example script can be found in [`panda/plugins/guest_plugin_example/try_it.py`](/panda/plugins/guest_plugin_example/try_it.py). ```python from pandare import Panda From c29c59eada5ec9ed292d1ae26508f65f08aafc89 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 13 Oct 2022 15:58:58 -0400 Subject: [PATCH 77/79] Add libfuse-dev to 22.04 build requirements --- panda/dependencies/ubuntu:22.04_build.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/panda/dependencies/ubuntu:22.04_build.txt b/panda/dependencies/ubuntu:22.04_build.txt index 57a682f20da..453514816a1 100644 --- a/panda/dependencies/ubuntu:22.04_build.txt +++ b/panda/dependencies/ubuntu:22.04_build.txt @@ -21,6 +21,9 @@ python3-dev libpixman-1-dev zip +# hyperfuse build deps +libfuse-dev + # pypanda dependencies python3-setuptools python3-wheel From df7b92a8afc6a00eff45c9ac30fff03ecb534480 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Thu, 13 Oct 2022 16:00:57 -0400 Subject: [PATCH 78/79] Remove outdated commented code from guest_plugin_manager --- panda/guest_plugins/guest_daemon/src/main.rs | 24 ------------------- .../src/interface/daemon_manager.rs | 12 +--------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/panda/guest_plugins/guest_daemon/src/main.rs b/panda/guest_plugins/guest_daemon/src/main.rs index 7b83f3b2dfc..c527819d346 100644 --- a/panda/guest_plugins/guest_daemon/src/main.rs +++ b/panda/guest_plugins/guest_daemon/src/main.rs @@ -13,24 +13,15 @@ struct Packet { } fn read_packet(reader: &mut RawChannel) -> Option { - //let plugin_file = MemfdOptions::new() - // .close_on_exec(true) - // .create("pluginfd") - // .unwrap(); - //let fd = plugin_file.as_raw_fd(); - //let mut plugin_file = plugin_file.into_file(); let mut temp_buf = vec![0u8; 4096 as _]; temp_buf.fill(1); let mut payload = vec![]; loop { - // println!("top of loop"); - // let mut header = [0u8; 8]; match reader.read_packet(&mut temp_buf) { 0 => break, _ => { payload.write_all(&temp_buf).unwrap(); - //plugin_file.write_all(&payload).unwrap(); } } } @@ -39,21 +30,6 @@ fn read_packet(reader: &mut RawChannel) -> Option { return None; } - println!("got to bottom. executing"); - - //println!("fd: {}", fd); - //let fds = std::fs::read_dir("/proc/self/fd") - // .unwrap() - // .map(|entry| entry.unwrap().path()) - // .collect::>(); - //dbg!(&fds); - //println!("path: /proc/self/fd/{}", fd); - - //dbg!(Path::new(&format!("/proc/self/fd/{}", fd)).exists()); - //Command::new(format!("/proc/self/fd/{}", fd)) - // .spawn() - // .unwrap(); - Some(Packet { kind: PacketKind::LoadPlugin, payload, diff --git a/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs b/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs index ff5b0fd9c14..cdd0bf279f5 100644 --- a/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs +++ b/panda/plugins/guest_plugin_manager/src/interface/daemon_manager.rs @@ -35,19 +35,10 @@ extern "C" fn read_callback( pub fn load_binary(binary_path: &str) { if Path::new(binary_path).is_file() { if let Ok(binary) = std::fs::read(binary_path) { - for chunk in binary.chunks(4096){ - // let mut buf = - // u32::to_le_bytes(PacketKind::LoadPlugin as u32).to_vec(); - // buf.extend(u32::to_le_bytes(chunk.len() as u32).to_vec()); + for chunk in binary.chunks(4096) { let cd = CHANNEL_DESC.get().unwrap(); - // publish_message_to_guest(*cd, buf); publish_message_to_guest(*cd, chunk.to_owned()); } - // let mut buf = - // u32::to_le_bytes(PacketKind::LoadPlugin as u32).to_vec(); - // buf.extend(u32::to_le_bytes(0 as u32).to_vec()); - // let cd = CHANNEL_DESC.get().unwrap(); - // publish_message_to_guest(*cd, buf); } else { panic!("Failed to read binary at {}", binary_path); } @@ -61,4 +52,3 @@ pub fn init() { .set(add_channel(Some(CHANNEL_NAME), read_callback)) .unwrap(); } - From 8bd67a24b61c34a526342d326e758de0502545ea Mon Sep 17 00:00:00 2001 From: jamcleod Date: Mon, 17 Oct 2022 14:12:46 -0400 Subject: [PATCH 79/79] Add check for guest plugins to setup.py --- panda/python/core/setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/panda/python/core/setup.py b/panda/python/core/setup.py index 5a06376bd0a..dbb3a3c4a97 100644 --- a/panda/python/core/setup.py +++ b/panda/python/core/setup.py @@ -86,7 +86,8 @@ def copy_objs(): new_guestplugindir = os.path.join(lib_dir, softmmu, "panda/guest_plugins") print("\n\n") print(guestplugindir, new_guestplugindir) - shutil.copytree(guestplugindir, new_guestplugindir, ignore=shutil.ignore_patterns('*.o', '*.d')) + if os.path.exists(guestplugindir): + shutil.copytree(guestplugindir, new_guestplugindir, ignore=shutil.ignore_patterns('*.o', '*.d')) # Strip libpandas and plugins to save space (Need <100mb for pypi) if pypi_build: