Adversarial C2 Protocol Implemented in Zig
0
fork

Configure Feed

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

Detect interface and use real mac

+74 -32
+74 -32
src/main.zig
··· 147 147 } 148 148 149 149 fn setPayloadLen(self: *@This(), len: usize) void { 150 - self.ip.len = @intCast(len + @sizeOf(@TypeOf(self.udp)) + @sizeOf(@TypeOf(self.ip))); 151 - self.udp.len = @intCast(len + @sizeOf(@TypeOf(self.udp))); 150 + self.ip.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8) + (@bitSizeOf(@TypeOf(self.ip)) / 8)); 151 + self.udp.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8)); 152 152 } 153 153 }; 154 + 155 + var socket: RawSocket = try .init(); 156 + defer socket.deinit(); 154 157 155 158 var headers: EthIpUdp = .{ 156 - .src_mac = undefined, // TODO: REAL MAC 159 + .src_mac = socket.mac, 157 160 .ip = .{ 158 161 .id = 0, 159 162 .src_addr = rand.int(u32), ··· 191 194 192 195 std.debug.print("full message = {any}\n", .{full_msg}); 193 196 194 - var socket: RawSocket = try .init("enp7s0"); 195 - defer socket.deinit(); 196 197 try socket.send(full_msg); 197 198 return; 198 199 } ··· 229 230 230 231 std.debug.print("full message = {any}\n", .{full_msg}); 231 232 232 - var socket: RawSocket = try .init("enp7s0"); 233 - defer socket.deinit(); 234 233 try socket.send(full_msg); 235 234 return; 236 235 } ··· 268 267 const RawSocket = struct { 269 268 fd: i32, 270 269 sockaddr_ll: std.posix.sockaddr.ll, 270 + mac: [6]u8, 271 271 272 - fn init(ifname: []const u8) !RawSocket { 273 - const socket: i32 = @intCast(std.os.linux.socket(AF.PACKET, SOCK.RAW, 0)); 272 + const IFF_LOOPBACK = 0x8; 273 + 274 + const ifconf = extern struct { 275 + ifc_len: i32, 276 + ifc_ifcu: extern union { 277 + ifcu_buf: ?[*]u8, 278 + ifcu_req: ?[*]std.os.linux.ifreq, 279 + }, 280 + }; 281 + 282 + fn init() !RawSocket { 283 + const socket: i32 = @intCast(std.os.linux.socket(std.posix.AF.PACKET, std.posix.SOCK.RAW, 0)); 284 + if (socket < 0) return error.SocketError; 285 + 286 + // 1. Enumerate interfaces 287 + var ifreq_storage: [16]std.os.linux.ifreq = undefined; 288 + var ifc = ifconf{ 289 + .ifc_len = @sizeOf(@TypeOf(ifreq_storage)), 290 + .ifc_ifcu = .{ .ifcu_req = &ifreq_storage }, 291 + }; 274 292 275 - var ifr: std.posix.ifreq = std.mem.zeroInit(std.posix.ifreq, .{}); 276 - @memcpy(ifr.ifrn.name[0..ifname.len], ifname); 277 - ifr.ifrn.name[ifname.len] = 0; 278 - try std.posix.ioctl_SIOCGIFINDEX(socket, &ifr); 293 + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFCONF, @intFromPtr(&ifc)) != 0) { 294 + return error.NicError; 295 + } 296 + 297 + const count = @divExact(ifc.ifc_len, @sizeOf(std.os.linux.ifreq)); 298 + var target_ifr: ?std.os.linux.ifreq = null; 299 + 300 + for (ifreq_storage[0..@intCast(count)]) |ifr| { 301 + var temp_ifr = ifr; 302 + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFFLAGS, @intFromPtr(&temp_ifr)) == 0) { 303 + // Cast the packed flags to u16 to match the kernel's ifr_flags size 304 + const flags: u16 = @bitCast(temp_ifr.ifru.flags); 305 + if (flags & IFF_LOOPBACK != 0) continue; 306 + 307 + target_ifr = ifr; 308 + break; 309 + } 310 + } 311 + 312 + var ifr = target_ifr orelse return error.NoInterfaceFound; 313 + 314 + // 2. Get Interface Index 315 + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFINDEX, @intFromPtr(&ifr)) != 0) { 316 + return error.NicError; 317 + } 279 318 const ifindex: i32 = ifr.ifru.ivalue; 280 319 281 - var rval = std.posix.errno(std.os.linux.ioctl(socket, std.os.linux.SIOCGIFFLAGS, @intFromPtr(&ifr))); 282 - switch (rval) { 283 - .SUCCESS => {}, 284 - else => { 285 - return error.NicError; 286 - }, 320 + // 3. Get Real MAC Address 321 + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFHWADDR, @intFromPtr(&ifr)) != 0) { 322 + return error.NicError; 323 + } 324 + var mac: [6]u8 = ifr.ifru.hwaddr.data[0..6].*; 325 + std.mem.reverse(u8, &mac); 326 + 327 + // 4. Set Flags (Promiscuous/Broadcast) 328 + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFFLAGS, @intFromPtr(&ifr)) != 0) { 329 + return error.NicError; 287 330 } 288 331 ifr.ifru.flags.BROADCAST = true; 289 332 ifr.ifru.flags.PROMISC = true; 290 - rval = std.posix.errno(std.os.linux.ioctl(socket, std.os.linux.SIOCSIFFLAGS, @intFromPtr(&ifr))); 291 - switch (rval) { 292 - .SUCCESS => {}, 293 - else => { 294 - return error.NicError; 295 - }, 333 + if (std.os.linux.ioctl(socket, std.os.linux.SIOCSIFFLAGS, @intFromPtr(&ifr)) != 0) { 334 + return error.NicError; 296 335 } 297 - std.debug.print("ifindex: {}\n", .{ifindex}); 336 + 298 337 const sockaddr_ll = std.posix.sockaddr.ll{ 299 338 .family = std.posix.AF.PACKET, 300 339 .ifindex = ifindex, 301 340 .protocol = std.mem.nativeToBig(u16, @as(u16, std.os.linux.ETH.P.IP)), 302 - .halen = 0, //not used 303 - .addr = .{ 0, 0, 0, 0, 0, 0, 0, 0 }, //not used 304 - .pkttype = 0, //not used 305 - .hatype = 0, //not used 341 + .halen = 0, 342 + .addr = .{ 0, 0, 0, 0, 0, 0, 0, 0 }, 343 + .pkttype = 0, 344 + .hatype = 0, 306 345 }; 307 - _ = std.os.linux.bind(socket, @ptrCast(&sockaddr_ll), @sizeOf(@TypeOf(sockaddr_ll))); 346 + 347 + const bind_ret = std.os.linux.bind(socket, @ptrCast(&sockaddr_ll), @sizeOf(@TypeOf(sockaddr_ll))); 348 + if (bind_ret != 0) return error.BindError; 308 349 309 350 return .{ 310 351 .fd = socket, 311 352 .sockaddr_ll = sockaddr_ll, 353 + .mac = mac, 312 354 }; 313 355 } 314 356 ··· 333 375 self.fd, 334 376 buf.ptr, 335 377 buf.len, 336 - 0, // flags 378 + 0, 337 379 null, 338 380 null, 339 381 );