相關文章

8164131c29cb930b7f7a89d5206ca00c 本系列文章的原文作者Acid_Snake在介紹PSP破解時,相當用心地了挑選了2個漏洞的實例,雖然這部分的文章比較艱澀,但是筆者還是在這邊把第二個案例介紹一下。下篇連載主題將是Wii的破解,內容就會比較有趣啦。

前情提要:

家用主機秘辛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:試玩版遊戲提供免費漏洞

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

忘記檢查參數

第二個要說明的PSP破解案例,是由Total_Noob公布的6.20版韌體核心漏洞,davee在這裡http://lolhax.org/2010/12/23/arcanum寫到了該漏洞的深入說明。這個漏洞位於sceUtility_private_764F5A3C,我將程式有趣的部分節錄於下。

sceUtility_private_764F5A3C:

...

0x00002800: 0x0C002229 ')"..' - jal scePower_driver_1A41E0ED

0x00002804: 0x001BDAC0 '....' - sll $k1, $k1, 11

...

這段程式會將k1向左推移11個bit,這是Sony用來過濾掉核心記憶體位置中不想要的指標,核心記憶體位置永遠會從0×8(也就是2進位的1000)開始。當我們從使用者模式中呼叫核心函數,去中斷記憶體管理,將k1設為0×100000,然後當該函數被向左推移了11個bit之後,它就會變成0×80000000,如果你將1個指標傳入核心記憶體位置,它看起來就會像0x8XXXXXXX。

接下來如果你把這個指標和k1的值做AND的邏輯運算,得到的結果將會是0×80000000,然而當該指標的開頭不是8,或是數字更大,進行邏輯運算得到的結果就會是0。

PSP會檢查這個運算結果,並透過two’s complement(以2進位表現其正負號的方式)檢驗其正負值,當所有開頭為0的數值為正數,開頭為1則為負數。如果我們輸入1個核心記憶體位置指標,然後得到的數質為負數,核心就會回傳錯誤訊息。關鍵來了,Sony必需檢查每一個回傳訊息,然而他們偶爾會忘記要這樣做。

在這個案例中,Sony忘了某些檢查工作,然而當我們在k1推移後馬上檢查該函數的話,我們就會看到下面的樣子。

scePowerRegisterCallback:

...

0x00000800: 0x001BDAC0 '....' - sll $k1, $k1, 11

...

這個函數將會重覆進行1次k1推移,如果先前k1的值是0×80000000的話,第二次推移後會變成0×40000000000,然而PSP是台32bit的機器,k1的暫存空間也是32bit,所以它無法處理這個數值,該數值就會溢出並變成0,所以可以讓所有的檢查都強制通過,最後可以引導至下方的程式片段。

loc_000008D8: ; Refs: 0x000008A4

0x000008D8: 0xAC710000 '..q.' - sw $s1, 0($v1)

0x000008DC: 0x02202021 '! .' - move $a0, $s1

0x000008E0: 0x00008021 '!...' - move $s0, $zr

0x000008E4: 0xAC600004 '..`.' - sw $zr, 4($v1)

0x000008E8: 0x8CB10204 '....' - lw $s1, 516($a1)

0x000008EC: 0xAC60000C '..`.' - sw $zr, 12($v1)

0x000008F0: 0xAC710008 '..q.' - sw $s1, 8($v1)

0x000008F4: 0x8CA50204 '....' - lw $a1, 516($a1)

這段程式會在指標$v1所指向的記憶體位置儲存許多數值,由於我們可以控制這些記憶體位置,所以我們可以隨心所欲覆寫核心記憶體位置。

接下來談談最後一個例子,這是由some1在httpstorage中發現的漏洞。sceHttpStorageOpen這個函數只會檢查其中的參數(arg),不會對k1進行任何檢查,當結果數值不是0或1的時候,函數「應該」要回傳錯誤訊息,還是說「這個函數有這樣做」嗎?

我們來看看函數「應該」要回傳錯誤訊息的例子。

loc_0000005C: ; Refs: 0x00000034 0x000000D4

; Data ref 0x000009F0 ... 0xFFFFFFFF 0xFFFFFFFF 0x00000000 0x00000000

0x0000005C: 0x267409F0 '..t&' - addiu $s4, $s3, 2544

0x00000060: 0x02348821 '!.4.' - addu $s1, $s1, $s4

0x00000064: 0x8E240000 '..$.' - lw $a0, 0($s1)

0x00000068: 0x04820005 '....' - bltzl $a0, loc_00000080

0x0000006C: 0x0240D821 '!.@.' - move $k1, $s2

0x00000070: 0x0C0001B3 '....' - jal IoFileMgrForKernel_810C4BC3

0x00000074: 0x2413FFFF '...$' - li $s3, -1

0x00000078: 0xAE330000 '..3.' - sw $s3, 0($s1)

0x0000007C: 0x0240D821 '!.@.' - move $k1, $s2

程式會讀取1個全域的值,並將它加到$s1之中,然後把-1存到該記憶體位置,這個核心漏洞就是修改這個全域的值,讓$s1的結果成為我們想要修改的核心記憶體位置,然後讓VFPU可以把-1(2進位中的0xFFFFFFFF)當做vsync 0xFFFF指令使用。

我不懂如果Sony知道某些參數是他們不希望看到的情況,為何還會寫出這種程式,不過也感謝他們再一次失誤,讓我們有核心漏洞與6.39版韌體的降級程式可以用。Sony真的犯下太多愚蠢失誤,讓我們可以完全取得核心權限,整個kermit_wlan模組也充分問題,Sony沒有對任何我們輸入的arg、k1進行檢查,這就像他們把整個PSP部門的工作人員炒魷魚,留下的聘顧人員對PSP系統安全一無所知。在這邊我只講到PSP的破解部分,至於深入PS Vita的部分就先跳過。

▲感謝Sony一直在各版本韌體提供破解漏洞,讓玩家可以執行各種自製程式。圖中為修改佈景主題的CXMB。

▲玩家也可以使用類似Free Cheat之類的工具程式,修改遊戲金錢或體力等數值。

下集預告:硬體架構不變的Wii

原文刊載於

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種進階利用,實測給你看

使用 Facebook 留言

發表回應

謹慎發言,尊重彼此。按此展開留言規則