1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#[cfg(feature = "windows")]
mod win;

#[cfg(feature = "cyphers")]
pub use cyphres as cypher;
pub mod err;

use cyphres::{Payload, RawPayload};
use err::*;

pub struct ProcessId(pub u32);

pub struct Shellcode(pub RawPayload);
impl Shellcode {
    pub fn raw(&self) -> &RawPayload {
        &self.0
    }

    pub fn into_raw(self) -> RawPayload {
        self.0
    }
}
impl From<RawPayload> for Shellcode {
    fn from(value: RawPayload) -> Self {
        Self(value)
    }
}
impl From<&[u8]> for Shellcode {
    fn from(value: &[u8]) -> Self {
        Self(value.into())
    }
}
impl Payload for Shellcode {}

platform_impl! {
    fn find_process(name: &str) -> Result<ProcessId, FindProcessError>;
    fn inject(pid: ProcessId, shellcode: Shellcode) -> Result<(), InjectionError>;
}

#[macro_export(local_inner_macros)]
macro_rules! platform_impl {
    ( $(fn $fn:ident $(< $($ name:ident $(: $type:ident)? ),*>)? ($($argname:ident : $argtype:ty),* ) $( -> $ret:ty )? ; )*) => {
        use cfg_if::*;
        $(
            pub fn $fn$(<$($name$(: $type)?),*>)?($($argname: $argtype),*) $( -> $ret )? {
                cfg_if! {
                    if #[cfg(feature = "windows")] {
                        win::$fn($($argname),*)
                    }else {
                        no_platform_impl()
                    }
                }
            }
        )*
    };
}

#[allow(dead_code)]
fn no_platform_impl() -> ! {
    panic!("You need to enable a platform feature to use this function: cargo run ... -features `windows`")
}