Adversarial C2 Protocol Implemented in Zig
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Use Client as var type instead of singleton

+31 -28
+26 -23
src/Client.zig
··· 1 1 const base64Enc = std.base64.Base64Encoder.init(std.base64.standard_alphabet_chars, '='); 2 2 const base64Dec = std.base64.Base64Decoder.init(std.base64.standard_alphabet_chars, '='); 3 3 4 - var rand: ?Random = null; 5 - var socket: ?gcat.nic.RawSocket = null; 4 + rand: Random, 5 + socket: gcat.nic.RawSocket, 6 + 7 + const Self = @This(); 6 8 7 9 const max_message_size = 2048; 8 10 9 - pub fn init() !void { 11 + pub fn init(interface_name: [:0]const u8) !Self { 10 12 var prng = Random.DefaultPrng.init(blk: { 11 13 var seed: u64 = undefined; 12 14 try posix.getrandom(mem.asBytes(&seed)); 13 15 break :blk seed; 14 16 }); 15 - rand = prng.random(); 17 + const rand = prng.random(); 18 + 19 + const socket: gcat.nic.RawSocket = try .init(interface_name); 16 20 17 - socket = try .init("enp7s0"); 21 + return .{ 22 + .rand = rand, 23 + .socket = socket, 24 + }; 18 25 } 19 26 20 - pub fn deinit() void { 21 - socket.?.deinit(); 27 + pub fn deinit(self: *Self) void { 28 + self.socket.deinit(); 22 29 } 23 30 24 31 /// Used for relay messages and connection handshake. 25 32 /// Assumes Client .init has been called. 26 - fn broadcastInitialInterestMessage(msg_bytes: []align(@alignOf(SaprusMessage)) u8) !void { 33 + fn broadcastInitialInterestMessage(self: *Self, msg_bytes: []align(@alignOf(SaprusMessage)) u8) !void { 27 34 var packet_bytes: [max_message_size]u8 = comptime blk: { 28 35 var b: [max_message_size]u8 = @splat(0); 29 36 ··· 63 70 const saprus_start_byte = 42; 64 71 @memcpy(packet_bytes[saprus_start_byte .. saprus_start_byte + msg_bytes.len], msg_bytes); 65 72 66 - try socket.?.linkLayer().send(packet_bytes[0 .. saprus_start_byte + msg_bytes.len]); 73 + try self.socket.linkLayer().send(packet_bytes[0 .. saprus_start_byte + msg_bytes.len]); 67 74 } 68 75 69 76 // fn broadcastSaprusMessage(msg_bytes: []align(@alignOf(SaprusMessage)) u8) !void {} ··· 100 107 _ = try sock.sendTo(dest_addr, msg_bytes); 101 108 } 102 109 103 - pub fn sendRelay(payload: []const u8, dest: [4]u8) !void { 110 + pub fn sendRelay(self: *Self, payload: []const u8, dest: [4]u8) !void { 104 111 var buf: [max_message_size]u8 align(@alignOf(SaprusMessage)) = undefined; 105 112 const msg_bytes = buf[0..try SaprusMessage.calcSize( 106 113 .relay, ··· 112 119 relay.dest = dest; 113 120 _ = base64Enc.encode(relay.getPayload(), payload); 114 121 115 - try broadcastInitialInterestMessage(msg_bytes); 122 + try self.broadcastInitialInterestMessage(msg_bytes); 116 123 } 117 124 118 - fn randomPort() u16 { 119 - var p: u16 = 0; 120 - if (rand) |r| { 121 - p = r.intRangeAtMost(u16, 1024, 65000); 122 - } else unreachable; 123 - 124 - return p; 125 + fn randomPort(self: Self) u16 { 126 + return self.rand.intRangeAtMost(u16, 1024, 65000); 125 127 } 126 128 127 129 pub fn sendInitialConnection( 130 + self: Self, 128 131 payload: []const u8, 129 132 output_bytes: []align(@alignOf(SaprusMessage)) u8, 130 133 initial_port: u16, 131 134 ) !*SaprusMessage { 132 - const dest_port = randomPort(); 135 + const dest_port = self.randomPort(); 133 136 const msg_bytes = output_bytes[0..try SaprusMessage.calcSize( 134 137 .connection, 135 138 base64Enc.calcSize(payload.len), ··· 146 149 return msg; 147 150 } 148 151 149 - pub fn connect(payload: []const u8) !?SaprusConnection { 150 - const initial_port = randomPort(); 152 + pub fn connect(self: Self, payload: []const u8) !?SaprusConnection { 153 + const initial_port = self.randomPort(); 151 154 152 155 var initial_conn_res: ?*SaprusMessage = null; 153 156 ··· 165 168 try sock.bind(bind_addr); 166 169 167 170 var sent_msg_bytes: [max_message_size]u8 align(@alignOf(SaprusMessage)) = undefined; 168 - const msg = try sendInitialConnection(payload, &sent_msg_bytes, initial_port); 171 + const msg = try self.sendInitialConnection(payload, &sent_msg_bytes, initial_port); 169 172 170 173 var response_buf: [max_message_size]u8 align(@alignOf(SaprusMessage)) = undefined; 171 174 _ = try sock.receive(&response_buf); // Ignore message that I sent. ··· 174 177 initial_conn_res = try .networkBytesAsValue(response_buf[0..len]); 175 178 176 179 // Complete handshake after awaiting response 177 - try broadcastSaprusMessage(msg.asBytes(), randomPort()); 180 + try broadcastSaprusMessage(msg.asBytes(), self.randomPort()); 178 181 179 182 if (false) { 180 183 return initial_conn_res.?;
+5 -5
src/main.zig
··· 42 42 }; 43 43 defer res.deinit(); 44 44 45 - try SaprusClient.init(); 46 - defer SaprusClient.deinit(); 47 - 48 45 if (res.args.help != 0) { 49 46 return clap.help(std.io.getStdErr().writer(), clap.Help, &params, .{}); 50 47 } 51 48 49 + var client = try SaprusClient.init("enp7s0"); 50 + defer client.deinit(); 51 + 52 52 if (res.args.relay) |r| { 53 53 const dest = parseDest(res.args.dest); 54 - try SaprusClient.sendRelay( 54 + try client.sendRelay( 55 55 if (r.len > 0) r else "Hello darkness my old friend", 56 56 dest, 57 57 ); 58 58 // std.debug.print("Sent: {s}\n", .{r}); 59 59 return; 60 60 } else if (res.args.connect) |c| { 61 - _ = SaprusClient.connect(if (c.len > 0) c else "Hello darkness my old friend") catch |err| switch (err) { 61 + _ = client.connect(if (c.len > 0) c else "Hello darkness my old friend") catch |err| switch (err) { 62 62 error.WouldBlock => null, 63 63 else => return err, 64 64 };