当前位置:网站首页>HUST網絡攻防實踐|6_物聯網設備固件安全實驗|實驗二 基於 MPU 的物聯網設備攻擊緩解技術

HUST網絡攻防實踐|6_物聯網設備固件安全實驗|實驗二 基於 MPU 的物聯網設備攻擊緩解技術

2022-06-26 11:26:00 shandianchengzi

寫在最前:注意下載最新版lib(6月2日更新版),並結合自己的lib分析。分析過程我寫得有點長,是為了幫助大家找到自己的地址、並理解它。實際上,需要寫進報告的內容只有子任務2那麼點

實驗二比較麻煩,附加內容我其實已經寫進博客了,如果想寫的話,請自行整理吧。實驗三很簡單,實驗二比較麻煩而且比較長,考慮到大家應該還要寫一下報告,我就分開先發實驗二了。

實驗二 基於 MPU 的物聯網設備攻擊緩解技術

實驗要求

實驗的 lib 庫代碼中開啟了多項 MPU 區域保護

請根據不同的子任務重配置 MPU 區域解除相應的區域保護

  • 子任務 1 解除代碼段不可寫入保護將指定代碼段改為可寫
  • 子任務 2 解除特定外設區域保護將指定外設區域改為可讀寫

注:請通過逆向分析出觸發 Memfault 的指令,從而在滿足任務要求的同時盡可能用最 少的 MPU 區域配置、最小的 MPU 區域範圍,最小的特權級。

特權級排序:rwx(可讀可寫可執行)> rw>rx>r>無權限

注意:任務2要用架構mps2-an386

實驗准備

Keil安裝及使用

安裝破解過程:

  1. 安裝Keil5:一路Next就行,名稱郵箱全部任意填,安裝驅動什麼的一律選是,安裝路徑最好不要包含中文,或者直接默認
  2. 破解Keil5:以管理員權限打開剛剛安裝的Keil5,關掉彈出來的讓安裝包的窗口,然後點擊File-License Management,複制CID到破解軟件中。破解軟件填寫CID、設置TargetARM之後,點擊Generate生成LIC,粘貼到Keil5LIC輸入框中。點擊Add LIC就行。
  3. 安裝ARM CMSDK_CM4_FP:老師發的Keil5默認是沒有我們要的ARM CMSDK_CM4_FP。不過老師還發了兩個.pack文件,雙擊安裝就行。一路Next安裝路徑要和Keil5的安裝目錄相對應

新建項目並添加文件:

Project-New uVersion Project ,然後配置直接按實驗指導書就行,後面也直接按指導書。添加文件可以直接拖進去。編譯就是Project-build

注意:如果之前裝過其他版本的Keil,並新建了項目,記得删掉項目目錄中的Listings、Objects、RTE,否則它會自動優先從這些目錄下讀取配置,版本就不對。

如果配置項完全正確,和指導書完全一致,直接運行時就會0 Error。

可執行文件會生成在Objects/下,運行如下指令運行:

~/qemu-7.0.0/build/qemu-system-arm -M mps2-an386 -cpu cortex-m4 -m 16M -nographic -d in_asm,nochain -kernel ~/exp6/task2/task2.axf -D log.txt

分析給出的.c/.h/.lib文件的內容和作用

先簡單地分析一下task2.c的內容。

main函數:
① 定義無符號整型變量a,賦值為學號末4比特;
② 調用prvSetupHardware(),硬件初始化;
③ 調用xTaskCreate,創建任務,任務內容為vTaskStart,任務名稱為"Task2",權限為特權級;
④ 調用StartFreeRTOS(a)
⑤ 使用for(;;)讓程序不退出。

vTaskStart的任務中,調用了AttackTest()

在逆向分析過後,可以進一步確定:在StartFreeRTOS(a)中包含對任務序列的啟動。當啟動了Task2後,將會調用AttackTest()。如果AttackTest沒有觸發MemMange_Handler异常,在一定的條件下,就會順利打印輸出flag;當AttackTest觸發异常後,該任務就會結束。

MemMange_Handler异常有觸發延時,所以舊的lib總是在异常還沒被觸發時,就已經打印了flag,所以老師更新了新版lib文件。

通過查看task2.h,可以看到AttackTestprvSetupHardwareStartFreeRTOS的函數聲明,而這些函數的具體實現,正是在task2x_xx.lib文件中。

當項目構建完成之後,所有的文件的內容都會被鏈接到可執行文件task2.axf中。

子任務1 解除代碼段不可寫入保護將指定代碼段改為可寫

本任務中,需要將task2.ctask2.htask2a_89.lib添加到Project中,注意要下載最新版的.lib文件。

逆向分析 AttackTest 函數

首先,不加修改地直接編譯項目,得到task2.axf,以便逆向分析AttackTest函數。編譯結果如下圖所示:

在這裏插入圖片描述

在IDA Pro中打開文件task2.axf,選擇的選項和上一個實驗一致。

根據之前對三個文件的分析,我們能很輕易地找到AttackTest函數在逆向中的比特置,順著點開它,它的內容如下圖所示:
在這裏插入圖片描述

F5反匯編得到的結果如下圖所示:

在這裏插入圖片描述

接下來,先保證能正確進入輸出flag的條件分支內。

《ARM Cortex-M3與Cortex權威指南》(後簡稱為權威指南),第11章寫了與MPU區域設置相關的寄存器,其中0xE000ED94就是寄存器CTRL。根據靜態地址和寄存器的對應關系,預定義如下:

#define MACRO_CTRL 0xE000ED94
#define MACRO_RNR 0xE000ED98
#define MACRO_RBAR 0xE000ED9C
#define MACRO_RASR 0xE000EDA0

然後,在vTaskStart裏添加如下幾行代碼,以便通過指針形式來訪問寄存器,並打印所有原始區域:

volatile unsigned int * pCTRL=(volatile unsigned int *)MACRO_CTRL;
volatile unsigned int * pRNR=(volatile unsigned int *)MACRO_RNR;
volatile unsigned int * pRBAR=(volatile unsigned int *)MACRO_RBAR;
volatile unsigned int * pRASR=(volatile unsigned int *)MACRO_RASR;
for(int i=0;i<8;i++){
    
	*pRNR=i;
	printf("%d,%d,%08x,%08x\n",*pRNR,*pCTRL,*pRBAR,*pRASR);
}

寄存器有自己的結構,這裏先定義結構體、再定義結構體指針會更合適一些。但是,由於實驗任務簡單,並沒有太多需要修改的內容,所以我幹脆直接用無符號整數賦值了。

為保證至少有一個MPU是使能的,再在vTaskStart裏的循環體後添加一行代碼:

*pCTRL=5;

然後Rebuild並直接運行一下,看看在哪裏觸發了异常,運行後的結果如下圖:

在這裏插入圖片描述

根據老師的說法,MemMange_Handler這個异常會有延時,所以違反 MPU 區域保護的指令是觸發异常的部分上面幾行代碼,而不是緊隨其後的其他代碼。即:

0x000002c2:  f44f 40e0  mov.w    r0, #0x7000
0x000002c6:  490c       ldr      r1, [pc, #0x30]
0x000002c8:  6001       str      r1, [r0]
0x000002ca:  f8c0 1080  str.w    r1, [r0, #0x80]
0x000002ce:  e7ec       b        #0x2aa

對應的AttackTest在IDA Pro中的匯編代碼如下:

LDR指令的作用:將存儲器地址所指地址處連續的4個字節的數據傳送到目的寄存器中。

MOV.W	R0, #0x7000		; 將0x7000賦值給R0寄存器
LDR		  R1, =0x12345678    ; 將0x12345678賦值給R1寄存器
STR		  R1, [R0]		       ; 將R1的連續4字節的數據傳送到R0寄存器指向的地址中
STR.W	  R1, [R0,#0x80]      ; 將R1的連續4字節的數據傳送到(R0寄存器指向的地址+0x80)中
B		  Judge			   ; 跳轉執行Judge

顯然,訪問了#0x7000#0x7080這兩個地址,並且都需要寫權限。

分析老師設置的所有的MPU的RASR的AP屬性,可以看出,區域0、1、3都是只讀的,其他區域對特權級都是可讀可寫的,區域6和7暫時沒有設置。AP域編碼對應的訪問權限如下圖所示(摘自權威指南):

在這裏插入圖片描述

而結合基址RBAR和RASR中的區域大小屬性,可以看出,#0x7000#0x7080這兩個地址都在區域0和1內,而它們都是不可寫的。

不過,除了這幾行指令,保不齊後面還有別的訪問不了的呢?繼續往後看。

打印flag函數的條件分支體如下:

在這裏插入圖片描述

其中打印flag的條件分支體對應的代碼解釋如下:

1	ldr R0, #0x20000038	; 將0x20000038賦值給R0寄存器
2	ldr R1, [R0]		 ; 將R0寄存器指向的地址上的值讀出並賦值給R1
3	adds R1, R1, #2		 ; R1 = R1 + 2,影響進比特標志比特C的加操作
4	str R1, [R0]		 ; 將R1的連續4字節的數據傳送到R0寄存器指向的地址中
5	adr R0, aFlagU		; 把格式化字符串的地址賦值給R0
6	b.w __2printf	       ; 調用__2printf

總之,Judge中還涉及了內存地址0xE000ED94的讀權限和0x20000038的讀寫權限。好在,通過MPU的信息可以看出,0x20000038雖然在區域2內,但是區域2可讀寫。0xE000ED94則不被約束。

因此這兩個地址並不是違反MPU保護的地址。

違反 MPU 區域保護的指令

綜合以上所有分析,可知,違反MPU區域保護的指令是AttackTest函數中的:

STR		  R1, [R0]		      ; 將R1的連續4字節的數據傳送到R0寄存器指向的地址中
STR.W	  R1, [R0,#0x80]      ; 將R1的連續4字節的數據傳送到(R0寄存器指向的地址+0x80)中

違反的權限

0x70000x7080這兩個地址的寫權限。

解除 AttackTest 函數違反規則的新 MPU 區域重配置代碼

總的來說,我添加的解除AttackTest函數違反規則的新 MPU 區域重配置代碼如下:

在這裏插入圖片描述

運行並得到flag的結果如下圖:

在這裏插入圖片描述

設置的區域說明

CTRL

CTRL=5。錶示使能。

RNR

RNR=6,錶示區域6。

為了不覆蓋老師的設置,我選擇區域6來配置新的MPU區域。

RBSR

RBSR設置為0x7000

RBSR的結構如下圖(摘自權威指南):

在這裏插入圖片描述

上錶的誤導性非常强,我起初以為ADDR是獨立出來的,比如當地址是0x7000、區域是1時,對應ADDR部分是0x7000,對應RBAR是0x70001。好在一比特同學及時點醒了我,往後看一下權威指南,會發現地址部分是直接賦值的,根本沒有考慮最後四比特數。

經過實踐,可以得到結論如下:

一方面,當倒數第五比特數VALID是0的時候,REGION比特的設置不會影響修改的MPU區域編號寄存器,程序會使用MPU區域編號寄存器選擇的區域,因此最後四比特數可以是任意值

另一方面,地址必須是REGION域大小的整數倍。首先,我們需要知道每一比特地址能索引8比特的數據。對於大小為32B即(32×8)bits的數據,理論上需要用 l o g 2 ( 32 ) log_2(32) log2(32)比特、也就是5比特地址去錶示,而每4比特二進制數對應一個16進制數。因此,使用(00~1f)即可錶示32B的數據,而每32B的數據之間的間隔,應當是0x20。
REGION域大小最小為32B,地址是N×0x20,N為整數。因此,非零地址最小是0x20。即使直接令RBAR=0x20,都不會影響到倒數5比特二進制數的設置。(相當於,倒數5比特本來是保留比特,只是為了方便,所以多定義了VALID域和REGION域)
地址對應容量大小參考博客:【嵌入式基礎】為什麼0x100是256個字節、0x400是1KB、0x800是2KB、0x1000是4KB?

總之,RBSR=0x7000,意思就是MPU的基址是0x7000

RASR

RASR=0x0102EE0F,對應屬性如下:

  • AP = 001,對應只支持特權級讀/寫;
  • TEX S C B = 000 0 1 0,對應ROM, Flash(可編程存儲器);
  • SRD = 11101110,對應子區域0和4啟用,其他禁用;
  • 區域大小 = 00111,對應區域大小256B;
  • 使能 = 1,使這塊MPU能用。

接下來解釋一下我設置的AP、SRD、區域大小、類型為什麼是最小的:

  • AP

    AP編碼與訪問權限的對應關系如下圖(摘自權威指南):
    在這裏插入圖片描述

    對比上錶可以看出,滿足我們特權級任務、讀寫權限要求的最小訪問權限就是001

  • 區域大小

    區域大小的編碼如下圖(摘自權威指南):
    在這裏插入圖片描述

    想要取最小的,那就取32B,也就是b00100。可惜我需要訪問0x70000x7080這兩個地址,只取128B都不行,因為取128B、基址是0x7000的時候,MPU對應的區域只有0x7000~0x707F。所以取256B,對應b00111

  • SRD

    當區域大小達到256B的時候,這個MPU足够大,能够設置8個子區域了。

    因此,我還得考慮子區域禁止屬性SRD的設置。(我問過別人,別人的lib只訪問了一個地址,或者訪問的地址跨度沒這麼大。因此,我這居然是屬於特殊情况)

    我的子區域0和子區域4是必須啟用的,其他都可以禁用。

    所以設置為11101110

  • 類型

    只是簡單介紹一下大類,不對TEX、S、C、B做詳細介紹。

    本實驗涉及到的TEX、S、C、B的設置如下圖(摘自權威指南):
    在這裏插入圖片描述
    顯然,設置成ROM,Flash是權限最小的。

子任務 2 解除特定外設區域保護將指定外設區域改為可讀寫

在子任務1的分析基礎上,不需要太多解釋。
再加上預設的MPU沒變,所以基本上只要改改地址範圍即可。
實驗結果如下。

逆向分析 AttackTest 函數

在這裏插入圖片描述

違反 MPU 區域保護的指令

AttackTest中的STR R0, [R1]

違反的權限

0x40010000的寫權限。

解除 attackTest 函數違反規則的新 MPU 區域重配置代碼

代碼,以及相比子任務1的關鍵修改:

在這裏插入圖片描述

運行結果:
在這裏插入圖片描述

設置的區域說明

RNR=6。

CTRL=5。

RBSR設置為0x40010000

RASR=0x01020009,對應屬性如下:

  • AP = 001,對應只支持特權級讀/寫;
  • TEX S C B = 000 0 1 0,對應ROM, Flash(可編程存儲器);
  • SRD = 00000000,區域大小未達到256B,因此該屬性不需要配置;
  • 區域大小 = 00100,對應區域大小32B;
  • 使能 = 1,使這塊MPU能用。
原网站

版权声明
本文为[shandianchengzi]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206261040305302.html