I made a recursive approach:
with recur (dias, texto, nivel, d1,d2) as
(select last_day(d1)-d1 as dias, to_char(d1,'yyyymm')||'-' as texto, 0 as nivel, d1,d2 from dates union all --first date
select case when (d2-trunc(add_months(d1, nivel+1),'month')+1) > extract(day from last_day(add_months(d1, nivel+1)))
then extract(day from last_day(add_months(d1, nivel+1)))
else d2-trunc(add_months(d1, nivel+1),'month')+1 end as dias,
to_char(add_months(d1, nivel+1),'yyyymm')||'-' as texto, nivel+1 as nivel ,d1,d2 from recur where trunc(add_months(d1, nivel+1),'month') < d2 --last month
)
select d1, d2,listagg(texto||to_char(dias),',') within group (order by nivel) as resultado
from recur
group by d1,d2
order by d1,d2;
OUTPUT for 25 May 2016 to 08 Jun 2016
25-MAY-16 08-JUN-16 201605-6,201606-8
OUTPUT for 25 May 2016 to 08 Jul 2017
25-MAY-16 08-JUL-17 201605-6,201606-30,201607-31,201608-31,201609-30,201610-31,201611-30,201612-31,201701-31,201702-28,201703-31,201704-30,201705-31,201706-30,201707-8