固件安全

一、前言

本日學習記錄

二、復現

1、SCTF 2020 Password Lock

題目描述

這是一個STM32F103C8T6 MCU密碼鎖它具有4個按鍵,分別爲1, 2, 3, 4. 分別對應GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4flag1格式爲SCTF{正確的按鍵密碼}輸入正確的密碼, 它將通過串口(PA9–TX)發送flag2

解題思路

題目附件給出了一個Intel hex文件,並且給出了芯片信息我們可以確定程序的內存佈局和外設寄存器與內存的對應。而逆向的關鍵就是讀懂程序代碼的含義,接下來我們將逐步分析這個hex文件。

1. hex文件結構

Intel hex文件格式由純文本構成,其中包含了程序的加載地址和程序入口地址等信息,讀懂這些信息可以幫助我們快速定位程序的起始入口而不用在ida中進行配置。

  • 讀懂Intel hex文件

我們可以使用文本編輯器打開題目附件,其中關鍵信息如下所示:

:020000040800F2
...
...
:04000005080000ED02
:00000001FF

  • 程序加載地址爲0x08000000

  • 程序入口地址爲0x080000ED

  • 程序以:00000001FF結尾

  • 其餘全是文件數據

2、內存佈局

查找芯片手冊的網站:https://www.alldatasheet.com/在裏面我們可以找到STM32F103C8T6的手冊,第一頁發現我們需要的一些信息

  • Flash memory:32-to-128 Kbytes

  • SRAM:6-to-20 Kbytes

31頁的Memory Map可以讓我們更加直觀的瞭解到內存的詳細布局

綜上所述我們得到了程序的完整內存佈局信息:

  • Flash Memory: 0x8000000 ~ 0x801FFFF (128K)

  • SRAM: 0x20000000 ~ 0x20004FFF (20K)

  • Peripherals: 0x40000000 ~ 0x40023400

【----幫助網安學習,以下所有學習資料免費領!關注我,私信回覆“資料”獲取!】

 ① 網安學習成長路徑思維導圖

 ② 60+網安經典常用工具包

 ③ 100+SRC漏洞分析報告

 ④ 150+網安攻防實戰技術電子書

 ⑤ 最權威CISSP 認證考試指南+題庫

 ⑥ 超1800頁CTF實戰技巧手冊

 ⑦ 最新網安大廠面試題合集(含答案)

 ⑧ APP客戶端安全檢測指南(安卓+IOS)

3、IDA分析

經過剛纔的分析我們瞭解了程序的內存佈局,其中Flash段除了包含代碼,還有中斷向量表。Periphers段中的寄存器是我們在逆向過程中需要對齊有大體瞭解。而對於hex文件的分析我們瞭解到除了加載地址和入口地址,其他的所有內容都不在hex文件中,所以我們需要手動配置這些內存佈局信息來告訴IDA怎麼識別。 打開ida工具,根據剛纔的手冊中我們可以查到芯片是arm32 Armv7-M架構,如下圖所示進行配置選擇然後單擊ok

可以看到已經能識別出一部分函數,其中start函數的地址與我們分析hex文件結構時找到的程序入口地址相同。

如果hex文件中沒有給出入口地址信息我們也可以通過尋找RESET中斷處理函數來確定程序入口函數。其中RESET中斷函數的地址可以在STM32中文參考手冊V10.pdf中找到相關信息

參考 STM32 中斷向量表的位置 、重定向 中我們可以瞭解到在中斷向量表中RESET的地址0x8000004的地址是固定的,而可變的是程序的加載地址。我們跳轉到0x8000004這個地址上,按鍵盤D鍵將上面的數據分成4字節形式找到reset的地址爲0x8000101

跳轉到RESET中斷處理函數,存在兩次跳轉。第一次跳轉到nullsub_1上並將下一條指令地址放入LR寄存器,nullsub_1函數的作用是跳回LR寄存器中的地址,所以第一跳沒有意義。第二次跳轉就是我們的start地址,所以完全可以利用此方式定位到程序的入口地址。

一直跟着入口地址走就能找到這個程序的main函數所在,但是進來之後可以發現左邊這一大片紅色的標記,觀察這些紅色區域其實就是IDA沒有識別的地址,也就是我們之前分析內存佈局需要添加的內存段。

我們在IDA中新建Segment,如下圖所示:

這時只要我們再次點擊F5即可讓這些紅色的標識變成正常識別的內存了

4、修復中斷向量表

使用IDApython恢復程序入口地址之前的信息

for i in range(0x8000000,0x80000eb,1): 
del_items(i)
for i in range(0x8000000,0x80000eb,4):
create_dword(i)

修復完成後我們觀察這裏面的地址,會發現有很多重複的地址0x800016D,跟進去會發現這些地址中沒有定義函數功能。繼續查看中斷向量表會發現下面幾個不同的內存地址

參考 STM32中文參考手冊V10.pdf中的內容我們可以查找到這些就是EXTI的中斷處理函數地址

  • stm32-EXTI

跟進這些函數地址會發現IDA並沒有將其識別爲函數,所以我們先在函數起始地址處按P鍵,然後進行反彙編即可看到這些中斷處理函數,這裏我以EXTI_4的中斷處理函數爲例來簡單介紹一下這些中斷處理函數的功能。

int EXTI_4()
{
int result; // r0

EXTI_LINE = 16;
switch ( sum )
{
case 1:
unk_20000006 = 116;
return sum++ + 1;
case 2:
unk_20000010 = 95;
return sum++ + 1;
case 4:
unk_2000000E = unk_20000001;
return sum++ + 1;
default:
result = 0;
sum = 0;
break;
}
return result;
}

程序一開始先設置了中斷/事件線,EXTI_4的中斷/事件線爲0x10,然後使用一塊內存(這裏記作sum)來作爲累加數的保存位置。我們可以看到當sum中的值爲1、2、4時sum的值會+1,如果不是的話則會重新開始。所以我們可以判斷出1、2、4就是EXTI_4出現在密碼中的位數,同理其他的三個按鈕也是一樣的,通過這些順序我們可以得到最終的flag爲flag{1442413},並且我們可以發現在main函數中程序先模擬輸入了一次密碼,通過將上面的值與EXTI_LINE進行對應也能得到flag值。

2、2021 HWS 入營賽-STM32

經過了上一題的入門接下來我們再來一道題目練習一下,打開IDA類型選擇小段arm32,架構選擇ARMv7-M架構。

接下來設置程序的加載地址和讀取地址設置爲0x8000000,加載地址是指IDA加載的分析地址是多少,而Input File是指固件要從什麼位置開始加載,設置好以後我們點擊OK完成設置。

進入以後會發現IDA沒有識別出任何函數,不用擔心我們可以通過定位reset的中斷處理來找到main函數的位置。將0x8000004地址處的字節變成4字節,得到reset中斷處理函數地址0x8000101

可以發現地址的結尾是奇數位,在arm中這代表了thumb模式。我們可以在0x8000101地址按下C鍵即可生成代碼

一直跟着程序流走我們就能找到main函數所在位置sub_80003C0,並且在其中發現了需要逆向的函數sub_8000314

_BYTE *sub_8000314()
{
_BYTE *v0; // r4
char *v1; // r5
int v2; // r6
char v3; // t1

v0 = (_BYTE *)sub_80003F0(48);
v1 = &byte_8000344;
v2 = 0;
while ( v2++ != 0 )
{
v3 = *v1++;
*v0++ = (v3 ^ 0x1E) + 3;
sub_8000124(v1);
}
return v0;
}

寫出解題腳本即可獲得flag值

li = [0x7D, 0x77, 0x40, 0x7A, 0x66, 0x30, 0x2A, 0x2F, 0x28, 0x40, 0x7E, 0x30, 0x33, 0x34, 0x2C, 0x2E, 0x2B, 0x28, 0x34, 0x30, 0x30, 0x7C, 0x41, 0x34, 0x28, 0x33, 0x7E, 0x30, 0x34, 0x33, 0x33, 0x30, 0x7E, 0x2F, 0x31, 0x2A, 0x41, 0x7F, 0x2F, 0x28, 0x2E, 0x64]
print(''.join(chr((i ^ 0x1E) + 3) for i in li))

更多靶場實驗練習、網安學習資料請訪問 合天網安實驗室。

舉報/反饋
相關文章