1. 程式人生 > >Linux pwn入門教程——CTF比賽

Linux pwn入門教程——CTF比賽

要想理解棧溢位,首先必須理解在彙編層面上的函式進入與返回。首先我們用一個簡單執行一次回顯輸入的程式hello開始。用IDA載入hello,定位到main函式後我們發現這個程式的邏輯十分簡單,呼叫函式hello獲取輸入,然後輸出“hello,”加上輸入的名字後退出。使用F5看反彙編後的C程式碼可以非常方便的看懂邏輯。


我們選中IDA-View視窗或者按Tab鍵切回到彙編視窗,在main函式的call hello一行下斷點,開啟32位的docker環境,啟動除錯伺服器後直接按F9進行除錯。


如圖,這是當前IDA的介面。在這張圖中我們需要重點注意到的東西有棧視窗,EIP暫存器,EBP暫存器和ESP暫存器。
首先我們可以看到EIP暫存器始終指向下一條將要執行的指令,也就是說如果我們可以通過某種方式修改EIP暫存器的值,我們就可以控制整個程式的執行,從而”pwn”掉程式(要驗證這一點,我們可以在EIP後面的數字上點選右鍵選擇Modify value.......

把數值改成080484DE然後F9繼續執行,從而跳過call hello一行)。
剩下的東西都和棧相關。顧名思義,棧就是一個數據結構中的棧結構,遵循先入後出的規則。這個棧的最小單位是函式棧幀。一個函式棧幀的結構如圖所示:

區域性變數1....................區域性變數m區域性變數nEBPEIP引數1.......引數n

棧的生長方式是向低地址生長,也就是說這張圖的方向和IDA中棧視窗的方向是一樣的,越往上地址值越小。同樣的,新入棧的棧幀在IDA的視窗中會把原來的棧幀“壓”在下面。ESP和EBP兩個暫存器負責標定當前棧幀的範圍。圖中標黑的部分即為實際上ESP和EBP中間的最大區域(為了方便講解,我們把EIP和引數也列入一個函式的函式棧幀)。圖中的區域性變數和引數很好理解,但EBP和EIP又是什麼意思呢?我們回到IDA除錯視窗。按照程式的邏輯,接下來應該是執行call hello這行指令呼叫hello這個函式,函式執行完後回到下一行的mov eax, 0,其地址為080484DE.然後我們再把當前ESP和EBP的值記下來(受地址空間隨機化ASLR的影響,每臺電腦每次執行到此處的ESP和EBP值不一定相同),然後按F7進入hello函式。


如圖,執行完call hello這一行指令後發生瞭如下改變。由此我們可以得知call指令是可以改變EIP“始終指向下一條指令地址”的行為的,且call指令會把call下一條指令地址壓棧。我們可以理解為call hello等價於push eip; mov eip, [hello]。所以我們的第一個問題“棧幀中的EIP是什麼意思”的回答就是:棧幀中的EIP是call指令的下一條指令的地址。我們繼續F8單步執行。


如圖,通過依次執行三條指令,程式為hello函式開闢了新的棧幀,同時把原來的棧幀,即執行了call hello函式的main函式的棧幀的棧底EBP儲存到棧中。繼續往下執行到read函式,然後隨便輸入一些比較有標誌性的內容,比如12345678,我們就會發現儲存輸入的區域性變數buf就在這片新開闢的棧幀中。


我們已經接觸到了棧幀的開闢與被使用情況,接下來我們再通過除錯繼續學習棧幀的銷燬。繼續F8到leave一行,此時我們會發現棧幀再次回到了剛執行完sub esp, 18h的狀態。
執行完leave一行指令後棧幀被銷燬,整體狀態回到了call hello執行前的狀態。即leave指令相當於add esp, xxh; mov esp, ebp; pop ebp


再次F8,發現EIP指向了call hello的下一行指令,同時棧中儲存的EIP值被彈出,棧頂地址+4. 即retn等同於pop eip


此時hello函式程式碼執行完畢,控制流程返回到了呼叫hello函式的main函式中。

0x01 棧溢位實戰

通過上一節的除錯,我們大概理解了函式棧的初始化和銷燬過程。我們發現隨著我們的輸入變多,輸入的內容離棧上儲存的EIP地址越來越近,那麼我們可不可以通過輸入修改掉棧上的EIP地址,從而在retn指令執行完後“pwn”掉程式呢?我們按Ctrl+F2結束掉當前的除錯,再試一次。為了節約時間,這回我們直接把斷點下在hello函式裡的call _read一行。
啟動除錯,程式中斷後介面如下


通過觀察read函式的引數和棧中的儲存的EIP地址,我們計算出兩者的偏移是0x16個位元組,也就是說輸入0x16=22個位元組的資料,我們的輸入就會和棧中的EIP“接上”,輸入22+4=26個位元組,我們的輸入就會覆蓋掉EIP。那麼我們構造payload為‘A’*22+‘B’*4,即AAAAAAAAAAAAAAAAAAAAAABBBB,根據我們的推測,在EIP暫存器指向retn指令所在地址時,棧頂應該是‘BBBB’。即retn執行完之後,EIP裡的值將不再是圖中框起來的080484DE,而是42424242(BBBB的ASCII值),按F8使IDA掛起,在docker環境中輸入payload


棧中的EIP果然按照我們的推測被修改成42424242了。顯然,這是一個非法的記憶體地址,它所在的記憶體頁此時對我們來說並沒有訪問許可權,所以我們執行完retn後程序將會報錯。


選擇OK,繼續F8並且選擇將錯誤傳遞給系統,這個程序接收到訊號後將會結束,除錯結束。我們通過一個程式本身的bug構造了一個特殊輸入結束掉了它。

0x02 結合pwntools打造一個遠端程式碼執行漏洞exp

通過上一節的內容,我們已經可以做到遠端使一個程式崩潰。不要小看這個成果。如果我們能挖掘到安全軟體或者系統的漏洞從而使其崩潰,我們就可以讓某些保護失效,從而使後面的入侵更加輕鬆。當然,我們也不應該滿足於這個成果,如果可以繼續擴大這個漏洞的利用面,製造一個著名的RCE(遠端程式碼執行),為所欲為,豈不是更好?當然,CTF中的絕大部分pwn題也同樣需要通過暴露給玩家的一個IP地址和埠號的組合,通過對埠上執行的程式進行挖掘,使用挖掘到的漏洞使程式執行不該執行的程式碼,從而獲取到flag,這也是我們學習的目標。
為了降低難度,我在編寫hello這個小程式的時候已經預先埋了一個後門——位於0804846B的名為getShell的函式。


如圖,這個函式唯一的作用就是呼叫system("/bin/sh")開啟一個bash shell,從而可以執行shell命令與系統本身進行互動


正常的程式流程並不會呼叫這個函式,所以我們將會利用上一節中發現的漏洞劫持程式執行流程,從而執行getShell函式。
首先我們把hello的IO轉發到10001埠上


然後我們從docker環境中獲取其ip地址(我的是172.17.0.2,不同環境下可能不同)

然後在kali中啟動python,匯入pwntools庫並且開啟一個與docker環境10001埠(即hello程式)的連線


此時我們可以像上一篇文章一樣開啟IDA進行附加除錯,在這裡我就不再次演示了。從上一節的分析我們知道payload的組成應該是22個任意字元+地址。但是我們要怎麼把16進位制數表示的地址轉換成4個位元組的字串呢?我們可以選用structs庫,當然pwntools提供了一個更方便的函式p32()(即pack32位地址,同樣的還有unpack32位地址的u32()以及不同位數的p16(),p64()等等),所以我們的payload就是22*'A'+p32(0x0804846B)


由於讀取輸入的函式是read,我們在輸入時不需要以回車作為結束符(printf,getc,gets等則需要),我們使用程式碼io.send(payload)向程式傳送payload


由於我在這裡沒有設定IDA附加除錯,顯然程式也不會被斷點中斷,那麼這個時候hello回顯我們的輸入之後應該成功地被payload劫持,跳轉到getShell函式上了。為了與被pwn掉的hello進行互動,我們使用io.interactive()


可以看到我們已經成功地pwn掉了這個程式,取得了其所在環境的控制權。為了增加一點氣氛,我們在/home下面放了一個flag檔案。讓我們來看一下flag是啥


如圖,我們成功地做出了第一個pwn題。為了加深對棧溢位的理解,我選了幾個真實的CTF賽題作為作業,注意不要將思維固定在獲取shell上哦。

附件(課後例題和練習題在原文底部,非常重要,請務必學習後下載練習)

Linux pwn入門教程(1)--棧溢位基礎_白帽子技術/思路_i春秋社群-分享你的技術,為安全加點溫度​bbs.ichunqiu.com圖示黑客如何學起?​www.zhihu.com圖示

相關推薦

Linux pwn入門教程——CTF比賽

要想理解棧溢位,首先必須理解在彙編層面上的函式進入與返回。首先我們用一個簡單執行一次回顯輸入的程式hello開始。用IDA載入hello,定位到main函式後我們發現這個程式的邏輯十分簡單,呼叫函式hello獲取輸入,然後輸出“hello,”加上輸入的名字後退出。使用F5看反彙編後的C程式碼可以非常方便的看

Linux pwn入門教程——格式化字符串漏洞

發現 都是 檢查 循環 我們 編譯 bbs 阻止 可見 本文作者:Tangerine@SAINTSEC 原文來自:https://bbs.ichunqiu.com/thread-42943-1-1.html 0×00 printf函數中的漏洞printf函數族是一個在C編程

Linux pwn入門教程(0)——環境配置

作者:[email protected]0×00前言作為一個畢業一年多的辣雞CTF選手,一直苦於pwn題目的入門難,入了門更難的問題。本來網上關於pwn的資料就比較零散,而且經常會碰到師傅們堪比解題過程略的writeup和沒有註釋,存在大量硬編碼偏移的指令碼,還有練

Linux pwn入門教程(6)——格式化字串漏洞

0x00 printf函式中的漏洞 printf函式族是一個在C程式設計中比較常用的函式族。通常來說,我們會使用printf([格式化字串],引數)的形式來進行呼叫,例如 char s[20] = “Hello world!\n”; printf(“%s”, s);

Linux快速入門教程-進程管理ipcs命令學習

Linux Linux入門 Linux運維 Linux命令 使用Linux系統必備的技能之一就是Linux進程管理,系統運行的過程正是無數進程在運行的過程。這些進程的運行需要占用系統的內存等資源,做好系統進程的管理,對於我們合理分配、使用系統資源有非常大的意義。今天我們來看進程管理命令中的ip

PWN入門教程分享

Linux pwn入門教程(1)——棧溢位基礎 URL:https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=42241&highlight=pwn Linux pwn入門教程(2)——shellcode的使用,原理與變形

Linux Capabilities 入門教程:概念篇

原文連結:Linux Capabilities 入門教程:概念篇 Linux 是一種安全的作業系統,它把所有的系統許可權都賦予了一個單一的 root 使用者,只給普通使用者保留有限的許可權。root 使用者擁有超級管理員許可權,可以安裝軟體、允許某些服務、管理使用者等。 作為普通使用者,如果想執行某些只有

Linux Capabilities 入門教程:基礎實戰篇

該系列文章總共分為三篇: Linux Capabilities 入門教程:概念篇 Linux Capabilities 入門教程:基礎實戰篇 待續... 上篇文章介紹了 Linux capabilities 的誕生背景和基本原理,本文將會通過具體的示例來展示如何檢視和設定檔案的 capabilities。

Linux Cgroup 入門教程:cpuset

這是 Cgroup 系列的第四篇,往期回顧: + [Linux Cgroup 入門教程:基本概念](https://fuckcloudnative.io/posts/understanding-cgroups-part-1-basics/) + [Linux Cgroup 入門教程:CPU](https:/

Linux Capabilities 入門教程:進階實戰篇

> 原文連結:[https://fuckcloudnative.io/posts/linux-capabilities-in-practice-2/](https://fuckcloudnative.io/posts/linux-capabilities-in-practice-2/) 該系列文章總共分為三

linux學習入門標準教程(2)

linux標準教程Linux系統篇2.1 Linux系統管理經過前兩章的學習,咱們現已可以獨立裝置Linux體系,現已把握了Linux學習的竅門,那接下來,咱們將體系的來了解Linux體系各目錄、權限及常用命令的運用。2.1. 1 Linux目錄初識通過前面的學習,我們已經能夠獨立安裝完一個linux

ctf比賽linux文件監控和恢復shell

shell then bash ctf tdi don 文件恢復 ech 目錄 之前參加ctf比賽時候臨時寫的,有很多不足,不過可以用,就貼出來分享給大家,希望對大家有幫助。 腳本一:記錄當前目錄情況 #!/bin/bashfunction getdir(){ for

Unix/Linux環境C程式設計入門教程 2 CentOS環境搭建

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Unix/Linux環境C程式設計入門教程 26 字元數字那些事兒

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Linux小小白入門教程(三):Linux資料夾

學習一個作業系統的使用,最先應該搞清楚的是他的C盤、D盤、E盤。 一、Linux的資料夾 Linux和Windows最大的區別是,Windows有C盤、D盤的概念,但是在Linux上沒有碟符的概念。Linux只有一個碟符,那就是“/”。你沒有看錯,就是一個斜杆。這個

Linux小小白入門教程(二):Linux系統安裝

學些Linux最好的方式就是實際操作一番。所以安裝Linux是必然,否則永遠學不會。考慮到學習的方便性,我們將會使用虛擬機器來安裝Linux作業系統。 下載CentOS7系統映象 為了降低大家學習成本,建議大家安裝的Linux版本統一為Centos 7 。下載地址自

自學自用 = 網易雲課堂(細說Linux-從入門到精通視頻教程

lin date upd kcon size route zip rep 系統 視頻地址 https://study.163.com/course/courseMain.htm?courseId=983014 介紹 本篇博客,旨在記錄視頻學習的要點,所以格式隨意,且沒有文字

Linux真小白入門教程第二集——LINUX發行版本

Linux完整的系統包被稱為發行版 不同的Linux發行版會滿足不同的具體需求,大多數的發行版都是為某個特定使用者群定製的。 完整的核心Linux發行版:含核心、一個或者多個圖形化桌面以及預編譯好的幾乎所有能見到的Linux應用,比如:Debian(商用產品發行版)和RedHat

Linux真小白入門教程第一集——什麼是LINUX

Linux是一款作業系統: 包含以下四個模組: 模組一: Linux核心:是Linux系統的核心,控制著計算機系統上的所有硬體和軟體,負責硬體的分配和軟體的執行 又分為四個細分功能: 系統記憶體管理: 核心不僅可以管理伺服器上的實體記憶體,還可以建

Linux真小白入門教程第十集——環境變數

對於Linux來說,很多程式和指令碼都要通過環境變數來獲取系統的資訊、儲存臨時資料和配置資訊。 bash shell有一個叫做環境變數的特性來儲存有關shell會話和工作環境的資訊,它允許你在記憶體中儲存資料,以便shell指令碼能夠訪問到他們,這也是持久儲存資料的簡便方法。 bash