2014 HITCON stkof writeup

【pwn学习】堆溢出(三)- Unlink和UAF的相关题目

题目链接

1、查看安全策略

root@kali:~/ctf/Other/pwn/heap# checksec stkof
[*] '/root/ctf/Other/pwn/heap/stkof'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

可以看到是64位系统,同时开启了canary和NX

2、静态分析

[0x00400c58]> afl
0x00400840    1 42           entry0
0x004007c0    1 6            sym.imp.__libc_start_main
0x00400750    1 6            sym.imp.free
0x00400760    1 6            sym.imp.puts
0x00400770    1 6            sym.imp.fread
0x00400780    1 6            sym.imp.strlen
0x00400790    1 6            sym.imp.__stack_chk_fail
0x004007a0    1 6            sym.imp.printf
0x004007b0    1 6            sym.imp.alarm
0x004007d0    1 6            sym.imp.fgets
0x004007e0    1 6            sym.imp.atoll
0x00400800    1 6            sym.imp.malloc
0x00400810    1 6            sym.imp.fflush
0x00400820    1 6            sym.imp.atol
0x00400830    1 6            sym.imp.atoi
0x00400c58   21 250          main
0x00400910    8 122  -> 90   entry.init0
0x004008f0    3 28           entry.fini0
0x00400870    4 50   -> 41   fcn.00400870
0x004007f0    1 6            loc.imp.__gmon_start
0x00400936    6 178          fcn.00400936
0x004009e8   13 287          fcn.004009e8
0x00400b07    8 162          fcn.00400b07
0x00400ba9   11 175          fcn.00400ba9
0x00400720    3 26           fcn.00400720
0x0040092a    5 134  -> 67   fcn.0040092a

调用的函数里,有几个函数可以注意一下

  • mallocfree 涉及到堆

    [0x00400c58]> axt sym.imp.malloc
    fcn.00400936 0x40097c [CALL] call sym.imp.malloc
    [0x00400c58]> axt sym.imp.free
    fcn.00400b07 0x400b7a [CALL] call sym.imp.free
    
  • alarm,alarm的libc地址加上5就可以得到system函数。

  • puts,经常用来泄露libc基址

下面来梳理一下程序的功能

  • 首先会读取一个长度小于10的字符串,然后把这个字符串转化为整数,我们暂且把这个数命名为input_NUM

  • 判断input_NUM的值

    if input_NUM == 1:
    		res = handle_1() 			#	fcn.00400936()
    elif input_NUM == 2:
        res = handle_2()      # fcn.004009e8()
    elif input_NUM == 3:
    		res = handle_3()      # fcn.00400b07()
    elif input_NUM == 4:
    		res = handle_4()      # fcn.00400ba9()
    else:
    		res = -1		
    
  • 判断res的值

    if res == 0:
    		puts("OK")
    else:
    		puts("FAIL")
    
  • 接下来分别看下几个分支的函数的作用

    • handle_1:用户输入一个数字,然后程序会使用malloc分配对应大小的内存,分配成功的话返回0,否则返回-1;之后程序会打印本次创建的chunk的序号

    • Handle_2:

      offset = 用户输入数字 	
      
      if input_NUM < 0x100001:
      		if 地址 [0x602140 + offset * 8] 储存的值 != 0:
              inputCount = 用户输入数字
              逐个字节把inputCount个字节的内容写入对应的chunk中
              写入成功则return 0
      else:
      		ret = -1
      
    • handle_3: 用户输入一个数字offset,如果地址[0x602140 + offset * 8] 储存的值不为0,则释放[0x602140 + offset * 8]地址对应的chunk,并且将地址[0x602140 + offset * 8]置为0。

    • handle_4: 用户输入一个数字offset,如果地址[0x602140 + offset * 8] 储存的值不为0,则计算[0x602140 + offset * 8]地址开始的字符串长度,如果长度小于4,则输出//TODO,否则输出...

  1. 动态调试

    利用gdb动态调试程序,首先明确了几个函数的功能,

    • 用户输入数字1~4选择功能
      • 功能1 - 分配内存:进入功能后,用户输入一个数字来定义malloc()分配的大小,并返回创建的chunk的序号;
      • 功能2 - 写入数据:进入功能或,用户首先输入chunk的序号来选择要写入的目标,然后输入一个数字表示要写入的字节数目,最后输入要写入的字符串;
      • 功能3 - 释放内存:进入功能后,用户输入要释放的chunk的序号来执行free(chunk)的操作;
      • 功能4 - 数据长度:进入功能后,用户输入目标chunk的序号,程序会计算字符串的长度,长度小于4输出//Todo,否则输出...
    • 使用一个数组储存每个创建的chunk的指针,我们暂且称这个数组为global

    程序启动后的堆分配如下所示

    pwndbg> heap
    Allocated chunk | PREV_INUSE
    Addr: 0xe05000
    Size: 0x1011
    
    Top chunk | PREV_INUSE
    Addr: 0xe056a0
    Size: 0x20961
    

    alloc了一个chunk后会额外添加一个缓冲,此后再分配的时候会依次往后添加

    pwndbg> heap
    Allocated chunk | PREV_INUSE
    Addr: 0xe05000
    Size: 0x1011
    
    Allocated chunk | PREV_INUSE
    Addr: 0xe06010
    Size: 0x111
    
    Allocated chunk | PREV_INUSE
    Addr: 0xe06120
    Size: 0x411
    
    Allocated chunk | PREV_INUSE
    Addr: 0xe06530
    Size: 0x41
    
    Allocated chunk | PREV_INUSE
    Addr: 0xe06570
    Size: 0x91
    
    Top chunk | PREV_INUSE
    Addr: 0xe06600
    Size: 0x20a01
    
  2. payload

    from pwn import *
    
    class EXP():
      def __init__(self):
        self.conn = process('./stkof')
        
      def _chunk_ptr(self, seq):
        return 0x602140 + seq * 8
        
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Morphy_Amo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值