当前位置:网站首页>CTF競賽題解之stm32逆向入門

CTF競賽題解之stm32逆向入門

2022-07-04 23:08:00 合天網安實驗室

固件安全

一、前言

本日學習記錄

二、複現

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

【----幫助網安學習,以下所有學習資料免費領!加weix:yj009991,備注“ csdn ”獲取!】

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

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

 ③ 100+SRC漏洞分析報告

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

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

 ⑥ 超1800頁CTF實戰技巧手册
 

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))
原网站

版权声明
本文为[合天網安實驗室]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/185/202207042246542551.html