1. 程式人生 > >花式棧溢位技巧----partial overwrite

花式棧溢位技巧----partial overwrite

學習資料:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/others/#partial-overwrite

                  https://bbs.ichunqiu.com/thread-43627-1-1.html

                  https://www.jianshu.com/p/c3624f5dd583

partial overwrite 這種技巧在很多地方都適用, 這裡先以棧上的 partial overwrite 為例來介紹這種思想

我們知道, 在程式開啟了 PIE 保護時 (PIE enabled) 高位的地址會發生隨機化, 用來由於受到堆疊和libc地址可預測的困擾,但低位的偏移是始終固定的, 也就是說如果我們能更改低位的偏移, 就可以在一定程度上控制程式的執行流, 繞過 PIE 保護

那麼就清楚了,這種繞過方法是主要爭對PIE保護的,partial write(部分寫入)就是一種利用了PIE技術缺陷的bypass技術

開啟給的例子

拖進IDA找棧溢位漏洞

第一個read函式可以惡意溢位,第二個read函式百分之百溢位

搜字串可以搜到我們想要的,同時檔案中也包含system函式

可以發現先直接呼叫函式A3E就好,只要把rip改過去就好

在輸入之前, 程式對棧空間進行了清零, 這樣我們就無法通過列印棧上資訊來 leak binary 或者 libc 的基址了

那咋辦,這裡從大佬那裡看到了printf函式的小技巧

printf 使用 %s 時, 遇到 \0 結束, 覆蓋 canary 低位為非 0 值, canary 就可以被 printf 打印出來了,我們把低位資料改一改就可以

研究一波怎麼改

先是打斷點就已經坑到我了,因為有PIE保護,後來聽大佬的方法是先把程式打斷點打炸,然後再vmmap,然後重打斷點,重新執行才行

彙編程式碼可以看見buf的地址放在rsi上

輸入a的話低位肯定是0x61是非0的

Canary保護機制的原理,是在一個函式入口處從fs段內獲取一個隨機值,一般存到EBP - 0x4(32位)或RBP - 0x8(64位)的位置, 如果攻擊者利用棧溢位修改到了這個值,導致該值與存入的值不一致,__stack_chk_fail函式將丟擲異常並退出程式

這樣只要接收'a' * (0x30 - 0x8 + 1) 後的 7 位, 再加上最低位的 '\0', 我們就恢復出程式的 canary 了,為啥是七位呢,因為cannary低位是\x00,printf不就停止輸出了麼,那我們乾脆只要七位好了

第二次read的時候我們可以觀察到返回地址與 get shell 函式的地址只有低位的 16 bit 不同, 如果覆寫低 16 bit 為 0x0A3E, 就有一定的機率 get shell,那我們不斷迴圈直到成功就好了

exp

while True:
    try:
        payload='a'*(0x30-0x08+1)
        cn.recvuntil('Input your Name:')
        cn.send(payload)
        cn.recvuntil('a'*(0x30-0x08+1))
        canary = '\0' + cn.recvn(7)
        success(canary.encode('hex'))
        cn.sendafter(":\n", 'a' * (0x30 - 0x8) + canary + 'bbbbbbbb' + '\x3E\x0A')
        cn.interactive()
    except Exception as e:
        cn.close()
        print e