Adversarial C2 Protocol Implemented in Zig
0
fork

Configure Feed

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

+156 -28
+156 -28
src/Client.zig
··· 29 29 /// Used for relay messages and connection handshake. 30 30 /// Assumes Client .init has been called. 31 31 fn broadcastInitialInterestMessage(self: *Self, msg_bytes: []align(@alignOf(SaprusMessage)) u8) !void { 32 - var packet_bytes: [max_message_size]u8 = comptime blk: { 33 - var b: [max_message_size]u8 = @splat(0); 32 + const writer = self.writer; 34 33 35 - // Destination MAC addr to FF:FF:FF:FF:FF:FF 36 - for (0..6) |i| { 37 - b[i] = 0xff; 38 - } 34 + const UdpHeaders = packed struct { 35 + dest_mac: u48, // [6]u8 39 36 40 - // Set Ethernet type to IPv4 41 - b[0x0c] = 0x08; 42 - b[0x0d] = 0x00; 37 + src_mac: u48, // [6]u8 43 38 44 - // Set IPv4 version to 4 45 - b[0x0e] = 0x45; 39 + ether_type: u16, 40 + ip_version: u4, 41 + header_length: u4, 42 + type_of_service: u8, 43 + total_length: u16, 46 44 47 - // Destination broadcast 48 - for (0x1e..0x22) |i| { 49 - b[i] = 0xff; 50 - } 45 + identification: u16, 46 + ethernet_flags: u3, 47 + fragment_offset: u13, 48 + ttl: u8, 49 + protocol: u8, 51 50 52 - // Set TTL 53 - b[0x16] = 0x40; 51 + header_checksum: u16, // [2]u8 52 + src_ip: u16, // [2]u8 53 + dest_ip: u16, // [2]u8 54 + 55 + src_port: u16, // [2]u8 56 + dest_port: u16, // [2]u8 57 + length: u16, 54 58 55 - // Set IPv4 protocol to UDP 56 - b[0x17] = 0x11; 59 + checksum: u16, // [2]u8 57 60 58 - // Set interest filter value to 8888. 59 - b[0x24] = 0x22; 60 - b[0x25] = 0xb8; 61 - break :blk b; 61 + fn init( 62 + in: struct { 63 + dest_mac: [6]u8, 64 + src_mac: [6]u8, 65 + ether_type: u16, 66 + ip_version: u4, 67 + header_length: u4 = 0, 68 + type_of_service: u4 = 0, 69 + total_length: usize, 70 + identification: u16 = 0, 71 + ethernet_flags: u3 = 0, 72 + fragment_offset: u13 = 0, 73 + ttl: u8 = 0, 74 + protocol: u8 = 0, 75 + header_checksum: [2]u8 = .{ 0, 0 }, 76 + src_ip: [2]u8, 77 + dest_ip: [2]u8, 78 + src_port: [2]u8, 79 + dest_port: [2]u8, 80 + length: usize, 81 + checksum: [2]u8 = .{ 0, 0 }, 82 + }, 83 + ) @This() { 84 + return .{ 85 + .dest_mac = @bitCast(in.dest_mac), 86 + .src_mac = @bitCast(in.src_mac), 87 + .ether_type = in.ether_type, 88 + .ip_version = in.ip_version, 89 + .header_length = in.header_length, 90 + .type_of_service = in.type_of_service, 91 + .total_length = @intCast(in.total_length), 92 + .identification = in.identification, 93 + .ethernet_flags = in.ethernet_flags, 94 + .fragment_offset = in.fragment_offset, 95 + .ttl = in.ttl, 96 + .protocol = in.protocol, 97 + .header_checksum = @bitCast(in.header_checksum), 98 + .src_ip = @bitCast(in.src_ip), 99 + .dest_ip = @bitCast(in.dest_ip), 100 + .src_port = @bitCast(in.src_port), 101 + .dest_port = @bitCast(in.dest_port), 102 + .length = @intCast(in.length), 103 + .checksum = @bitCast(in.checksum), 104 + }; 105 + } 62 106 }; 107 + 108 + const total_len = (@bitSizeOf(UdpHeaders) / 8) + msg_bytes.len; 109 + std.debug.assert(writer.buffer.len >= total_len); 110 + _ = writer.consumeAll(); 111 + 112 + const headers: UdpHeaders = .init(.{ 113 + .dest_mac = .{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 114 + .src_mac = blk: { 115 + const r_bytes = try writer.writableArray(6); 116 + self.rand.bytes(r_bytes); 117 + break :blk r_bytes.*; 118 + }, 119 + .ether_type = 0x0800, 120 + .ip_version = 0x4, 121 + .header_length = 0x5, 122 + .total_length = total_len - 8, // 8 is the ethernet frame length (macs + type) 123 + .protocol = 0x11, 124 + .src_ip = .{ 0, 0 }, 125 + .dest_ip = .{ 0, 0 }, 126 + .src_port = .{ 0, 0 }, 127 + .dest_port = .{ 0xb8, 0x22 }, 128 + .length = msg_bytes.len, 129 + }); 130 + 131 + _ = try writer.write(&@as([@bitSizeOf(UdpHeaders) / 8]u8, @bitCast(headers))); 132 + 133 + // try writer.writeStruct(headers, .big); 134 + 135 + // // Ensure buffer is large enough 136 + // std.debug.assert(writer.buffer.len > 38 + msg_bytes.len); 137 + 138 + // // Ensure writer is clean 139 + // writer.consumeAll(); 140 + 141 + // // Destination MAC addr to FF:FF:FF:FF:FF:FF 142 + // try writer.write(); 143 + 144 + // // Source MAC to random bytes 145 + // { 146 + // } 147 + 148 + // // 96 bits 149 + 150 + // // Set EtherType to IPv4 151 + // try writer.write(.{ 0x08, 0x00 }); 152 + 153 + // // 112 bits 154 + 155 + // // Set IPv4 version to 4 156 + // try writer.writeByte(0x45); 157 + 158 + // // 120 bits 159 + 160 + // // Unset section (Version, IHL, ToS) 161 + // writer.advance(2); 162 + 163 + // // 136 bits 164 + 165 + // // Total length 166 + // try write.writeInt(u16, 38 + msg_bytes.len); 167 + 168 + // // Destination broadcast 169 + // writer.splatByte(0xff, 0x22 - 0x1e); 170 + 171 + // var packet_bytes: [_]u8 = comptime blk: { 172 + // var b: [max_message_size]u8 = @splat(0); 173 + 174 + // for (0x1e..0x22) |i| { 175 + // b[i] = 0xff; 176 + // } 177 + 178 + // // Set TTL 179 + // b[0x16] = 0x40; 180 + 181 + // // Set IPv4 protocol to UDP 182 + // b[0x17] = 0x11; 183 + 184 + // // Set interest filter value to 8888. 185 + // b[0x24] = 0x22; 186 + // b[0x25] = 0xb8; 187 + // break :blk &b; 188 + // }; 63 189 var msg: *SaprusMessage = try .bytesAsValue(msg_bytes); 64 190 try msg.networkFromNativeEndian(); 65 191 defer msg.nativeFromNetworkEndian() catch unreachable; 66 192 193 + std.debug.print("headers: {x}\n", .{@as([@bitSizeOf(UdpHeaders) / 8]u8, @bitCast(headers))}); 194 + std.debug.print("bytes: {x}\n", .{writer.buffer[0..writer.end]}); 195 + _ = try writer.write(msg_bytes); 196 + 67 197 // The byte position within the packet that the saprus message starts at. 68 - const saprus_start_byte = 42; 69 - @memcpy(packet_bytes[saprus_start_byte .. saprus_start_byte + msg_bytes.len], msg_bytes); 70 - 71 - const writer = self.writer; 72 - _ = try writer.write(packet_bytes[0 .. saprus_start_byte + msg_bytes.len]); 198 + // const saprus_start_byte = 42; 199 + // @memcpy(packet_bytes[saprus_start_byte .. saprus_start_byte + msg_bytes.len], msg_bytes); 200 + // _ = try writer.write(packet_bytes[0 .. saprus_start_byte + msg_bytes.len]); 73 201 try writer.flush(); 74 202 } 75 203