家用主機秘辛13:欺騙系統核心

家用主機秘辛13:欺騙系統核心

在先前的系列文章中,提到了幾種PSP的破解案例,在接下來的2篇文章中,筆者將會介紹原文作者Acid_Snake挑選的2個程式範例,在這幾個範例中,可以更進一步看到PSP韌體設計的安全缺陷,以及駭客們如何運用這些漏洞開發出破解程式。

前情提要:

家用主機秘辛1:任天堂紅白機導致的破解風潮

家用主機秘辛2:紅白機的防拷晶片歷史

家用主機秘辛3:正版比盜版問題更多,破解萬惡10NES晶片

家用主機秘辛4:進入光碟時代,PS的保護機制

家用主機秘辛5:數秒內抽換光碟, PS 盜版片也能騙過驗證機制

家用主機秘辛6:最暢銷主機 PS2 的大後門,用壞軌光碟 Swap Magic 破解

家用主機秘辛7:PS2安裝假OS,從記憶卡開機

家用主機秘辛8:PS2連DVD播放功能都暗藏玄機

家用主機秘辛09:大門忘記上鎖的PSP

家用主機秘辛10:緩衝區溢位突破天際

家用主機秘辛11:破解之神Dark_Alex登場

家用主機秘辛12:試玩版遊戲提供免費漏洞

愚蠢錯誤一籮筐

我將跳過由davee利用5.03版本韌體漏洞開發的checkHEN,因為我想把各種破解方式分成2大類。由於後期PSP主機更改了安全機制,所以無法將自製韌體永久性地安裝在主機中,但是PSP 3000型主機還是具有可用的核心漏洞與HEN漏洞(例如之後發展LCFW)。直到6.20版韌體推出後,開發者Total_Noob將6.35版以下韌體可用核心漏洞公開,但由他本人所開發的HEN只能於6.20版韌體中執行。

雖然6.XX年代還有許多其他有趣的故事可以慢慢聊,比如Total_Noob、Neur0n、Team PRO、HBL等等,但是我只想專注於核心漏洞,因為這和系列文章有著共同的主題,就是Sony所犯下的於愚蠢錯誤。這次的問題圍繞在有1個參數檢查被漏掉了。

家用主機秘辛13:欺騙系統核心

▲HEN為Homebrew Enabler的縮寫。這種破解程式大多只有取得使用者模式權限,能夠讓PSP執行自製程式,但可能無法執行遊戲的備份檔案。

用memset覆蓋記憶體內容

這個案例是5.03版韌體核心漏洞,我忘了最初發現的開發者是誰,然而davee利用了這個漏洞開發了HEN。這個核心漏洞存在psheet.prx模組的sceDRMInstallGetFileInfo函數中。它的程式碼如下:

sceDRMInstallGetFileInfo:

...

0x000000E0: 0xAFB40010 '....' - sw $s4, 16($sp)

0x000000E4: 0x34620108 '..b4' - ori $v0, $v1, 0x108

0x000000E8: 0x00C0A021 '!...' - move $s4, $a2

0x000000EC: 0xAFB3000C '....' - sw $s3, 12($sp)

0x000000F0: 0x00A09821 '!...' - move $s3, $a1

0x000000F4: 0xAFB10004 '....' - sw $s1, 4($sp)

0x000000F8: 0x00E08821 '!...' - move $s1, $a3

...

0x00000140: 0x02602821 '!(`.' - move $a1, $s3

0x00000144: 0x02402021 '! @.' - move $a0, $s2

0x00000148: 0x02803021 '!0..' - move $a2, $s4

0x0000014C: 0x0C0001E8 '....' - jal sub_000007A0

0x00000150: 0x02203821 '!8 .' - move $a3, $s1

我將部分程式碼省略掉,所以能把出問題的sceIoOpen參數看得更加清楚。假設sceIoOpen會去呼叫另一個子程式以及sub_000007A0,並回傳「argument 0」,之後我們輸入argument 1、argument 2,以及arg3至該程式。然後我們看看sub_000007A0會發生什麼事。

; Subroutine sub_000007A0 - Address 0x000007A0

sub_000007A0: ; Refs: 0x0000014C

...

0x000007C0: 0x00E09821 '!...' - move $s3, $a3

...

0x000007EC: 0x24060108 '...$' - li $a2, 264

0x000007F0: 0x02602021 '! `.' - move $a0, $s3

0x000007F4: 0x0C000928 '(...' - jal memset

0x000007F8: 0x00002821 '!(..' - move $a1, $zr

這個子程式會呼叫memset 2次,在第二次呼叫memset時,arg0(即寫入的目的位置)的數值將由第三個傳入該子程式的參數決定,而這個參數就是我們先前傳入sceDRMInstallGetFileInfo的arg3,由於該動作並沒有經過全盤檢查,所以我們可以透過memset,將包括核心記憶體位置在內大約66條指令強制寫入0。感謝Sony!

家用主機秘辛13:欺騙系統核心

▲memset指令可以將指定範圍內的位置寫入特定值,經常用於將位元組的位元值初始化為0。(圖片來源:Microsoft Developer Network

下集預告:繼續欺騙系統核心

原文刊載於

http://wololo.net/2014/01/18/10-days-of-hacking-day-5-the-psp-part-2

感謝原文作者Acid_Snake同意轉載

Original article by Acid_Snake. Translate by konamigood.

延伸閱讀:

【模擬器改造】掌機性能大提升:PlayStation Portable篇

挑戰 Apple TV,Sony 發表 PS Vita TV 提供影音串流服務,還能用電視玩 PS Vita、PSP 遊戲

PSP 退休後,刷機做3種進階利用,實測給你看

國寶大師 李文恩
作者

電腦王特約作者,專門負責硬派內容,從處理器、主機板到開發板、零組件,尖端科技都一手包辦,最近的研究計畫則包括Windows 98復活與AI圖像生成。

使用 Facebook 留言
發表回應
謹慎發言,尊重彼此。按此展開留言規則