Try this:
;with cte as (
select cast('2017-01-01' as date) as [FirstOfMonth]
union all
select dateadd(month, 1, FirstOfMonth) from cte
where datepart(year, FirstOfMonth) < 2018
)
select FirstOfMonth,
dateadd(day, -1, LEAD(FirstOfMonth, 1) over (order by FirstOfMonth))
from cte
First part gets you first days of all months in 2017 plus first of Jan. of 2018. Second part gets the day before, i.e. last day of the month.
Try this and you'll get better understanding :) Only thing is, that you have to exclude last record, which is 2018-01-01 :)