Smartisan是手機(jī)中為數(shù)不多傾心于工業(yè)設(shè)計(jì)和用戶(hù)體驗(yàn)的。老羅跨界過(guò)猛,也難免導(dǎo)致其最初的想法和現(xiàn)實(shí)存在差距。bootloader到底鎖還是不鎖,甚至曾被一個(gè)T1用戶(hù)弄上法庭來(lái)質(zhì)問(wèn)。
當(dāng)然,能從認(rèn)為加鎖是對(duì)系統(tǒng)的不自信,到后來(lái)發(fā)現(xiàn)解鎖是安全隱患,絕對(duì)是個(gè)進(jìn)步(loser口中的打臉)。技術(shù)層面來(lái)說(shuō),究竟T系列手機(jī)的bootloader能不能解鎖呢?答案是,能。或者說(shuō),本來(lái)不能,但由于bootloader里存在的兩個(gè)漏洞,恰好可解。
分析bootloader
正像Smartisan OS本身,其ROM目錄結(jié)構(gòu)也是極簡(jiǎn)的。firmware-update目錄下emmc_appsboot.mbn就是bootloader鏡像。由于是ELF格式,不需要更多的處理,就能逆向出不錯(cuò)的代碼結(jié)構(gòu)。無(wú)論是T1還是T2,bootloader的代碼差不多,下面的分析選擇的是T2的2.6版的ROM。
和很多高通芯片的手機(jī)一樣,T2的bootloader是基于高通開(kāi)源的lk。所以參考源碼,可以很快梳理出bootloader的執(zhí)行流程。啟動(dòng)后,根據(jù)按鍵組合,決定是否進(jìn)入recovery,如果繼續(xù)留在bootloader模式,就會(huì)注冊(cè)一系列fastboot command,循環(huán)等待用戶(hù)輸入,決定下一步動(dòng)向,如圖1。
圖1.注冊(cè)fastboot command
顯然,control_flag為0的話,cmd_table中只有前四條命令被注冊(cè),后續(xù)命令就都無(wú)法使用了。通過(guò)觀察cmd_table(如圖2),可以發(fā)現(xiàn)那些真正令人激動(dòng)的函數(shù)(比如oem unlock)都在比較靠后的位置上。
圖2.fastboot可以注冊(cè)的命令列表
在搞清楚control_flag這個(gè)全局標(biāo)記到底何去何從之前,不如先探探這僅存四條命令的究竟。reboot,reboot-bootloader命令正像他們的名字一樣無(wú)趣,flash看起來(lái)就很有故事了。
執(zhí)行flash命令時(shí),如果control_flag為0,那就只能寫(xiě)一個(gè)名為security的分區(qū)。而control_flag為1時(shí),所有其他分區(qū)就都可以寫(xiě)了,如圖3所示:
圖3.寫(xiě)分區(qū)時(shí)的判斷
聯(lián)想之前fastboot command注冊(cè)的過(guò)程,control_flag為0時(shí),絕大部分功能無(wú)效,且分區(qū)不可寫(xiě),control_flag應(yīng)該就是is_allow_unlock,即bootloader是否上鎖的標(biāo)記。系統(tǒng)啟動(dòng)時(shí),is_allow_unlock默認(rèn)置0。當(dāng)flash了security分區(qū)后,is_allow_unlock會(huì)有一次賦值操作,并且一旦賦值為1,就會(huì)提示解鎖成功,如圖4所示:
圖4.對(duì)security分區(qū)的檢測(cè),判斷是否可以解鎖
分析到這里基本可以肯定,T2提供了解鎖功能,關(guān)鍵是寫(xiě)入security分區(qū)的內(nèi)容是否能夠經(jīng)得住考驗(yàn)。
解鎖bootloader
verify_security()函數(shù)比較復(fù)雜,涉及很多密碼學(xué)算法的演繹。好在它使用的是openssl的標(biāo)準(zhǔn)庫(kù)函數(shù),識(shí)別起來(lái)有章可循。security分區(qū)內(nèi)容采用的是RSA+MD5簽名校驗(yàn)。合理的猜測(cè)是,官方本來(lái)設(shè)計(jì)的解鎖流程其他廠商類(lèi)似,即用戶(hù)提交手機(jī)的序列號(hào)等信息,然后通過(guò)unlock時(shí)輸入廠商給的解鎖碼(根據(jù)序列號(hào)計(jì)算出來(lái)的簽名信息),實(shí)現(xiàn)解鎖。只不過(guò)這一次解鎖碼是通過(guò)寫(xiě)入security分區(qū)實(shí)現(xiàn)輸入。
security[128](security分區(qū)第128字節(jié))是RSA初始化函數(shù)選擇的依據(jù),security[129]作為序列號(hào)長(zhǎng)度。然后factory[5](factory分區(qū)的第5字節(jié))起始的序列號(hào)作為MD5的計(jì)算依據(jù),得到的hash值和security[0-127]簽名信息驗(yàn)證的結(jié)果做比,相同返回1,否則返回0。這幾乎是每個(gè)簽名驗(yàn)證的都在用的標(biāo)準(zhǔn)化流程,采用的算法成熟,且由openssl實(shí)現(xiàn)(難怪發(fā)布會(huì)幾百萬(wàn)門(mén)票錢(qián)捐給了openssl),基本不會(huì)有瑕疵。由于bootloader只存放了公鑰e,沒(méi)有私鑰d,手機(jī)用戶(hù)自己是沒(méi)辦法構(gòu)造出128字節(jié)的簽名信息的。
不過(guò),由于代碼上一些不大不小的問(wèn)題,我們恰好可以繞過(guò)這些限制,構(gòu)造出和序列號(hào)無(wú)關(guān)的通用解鎖碼。首先在RSA初始化時(shí),如圖5和6,當(dāng)security[128]為66和67以外的數(shù)值時(shí),初始化函數(shù)被選擇為sub_F924A90。
圖5.根據(jù)security[128]指定的函數(shù)來(lái)初始化RSA密鑰
圖6.RSA密鑰初始化
跟進(jìn)sub_F924A90后,可以看見(jiàn)圖6所示的密鑰填充,BN_bin2bn是openssl的庫(kù)函數(shù),用于將內(nèi)存中存放的Big-Endian字符數(shù)組轉(zhuǎn)化為Bignum類(lèi)型,方便RSA的內(nèi)部計(jì)算。私鑰d填寫(xiě)的是偽數(shù)值,但p和q都填寫(xiě)的是真值。側(cè)面說(shuō)明寫(xiě)這段代碼的人不太了解RSA,畢竟其安全性完全依賴(lài)于大數(shù)分解的NP難,而現(xiàn)在n的兩個(gè)素?cái)?shù)因子p和q都給了,雖然本意是加快計(jì)算速度,但私鑰d也就因而可以從公鑰e推出來(lái)了,d=e-1mod (p-1)(q-1),這就導(dǎo)致了第一個(gè)邏輯漏洞,用于偽造簽名。
接下來(lái),如圖7,完成了RSA的初始化以后,會(huì)接著從factory分區(qū)讀取數(shù)據(jù):
圖7. 讀取factory
分區(qū),得到序列號(hào),然后計(jì)算MD5
究竟從factory分區(qū)讀取多少字節(jié)是可控的,由security[129]決定。讀取出來(lái)正常應(yīng)該是一串字母開(kāi)頭后接一串?dāng)?shù)字的序列號(hào),MD5后得到一串16字節(jié)的hash。最后利用RSA的公鑰驗(yàn)證security[0-127]的128字節(jié)簽名是否屬于hash。
由于security[129]完全可控,就導(dǎo)致了第二個(gè)邏輯漏洞。如果該數(shù)指定為0,則MD5是針對(duì)一個(gè)空字符串進(jìn)行計(jì)算的,計(jì)算結(jié)果總是d41d8cd98f00b204e9800998ecf8427e。所以無(wú)論是哪臺(tái)手機(jī),factory分區(qū)內(nèi)容如何,簽名驗(yàn)證將總是針對(duì)常量進(jìn)行。只要構(gòu)造該常量的簽名寫(xiě)入security分區(qū),就能夠完成解鎖。
為了減少padding,encoding等一系列開(kāi)發(fā)可能造成的不確定性,在生成解鎖碼時(shí),同樣采用openssl的代碼實(shí)現(xiàn),示例如下:
#include
#include
#include
#include
#include
unsignedcharm3_n[128] = {\
0xA4,0x0C, 0x69, 0x70, 0x25, 0x4F, 0x36, 0x49, 0x8E,\
0x83,0x4B, 0x74, 0x9A, 0x75, 0xC9, 0xF4, 0x7F, 0xE5,\
0x62,0xA8, 0xDE, 0x11, 0x13, 0x03, 0x57, 0x89, 0x31,\
0xCB,0x58, 0x84, 0xC8, 0x26, 0xBA, 0x2B, 0x60, 0xB5,\
0xB8, 0xA5, 0xD9, 0xBD, 0x27, 0x48, 0x3D,0x33, 0x38,\
0xA1,0x72, 0x62, 0x64, 0x87, 0x5E, 0x71, 0xF4, 0x1F,\
0xCB,0x68, 0x83, 0x92, 0xEA, 0x4B, 0xFF, 0x06, 0x38,\
0xAF,0xD5, 0x65, 0x55, 0x94, 0x04, 0x91, 0x88, 0xF7,\
0xA4,0x57, 0x72, 0x29, 0xFE, 0xEA, 0xB1, 0x27, 0x25,\
0xC1,0x12, 0x7D, 0x16, 0x6F, 0x13, 0xAF, 0xE2, 0x00,\
0x8D,0x5E, 0xA4, 0x0A, 0xB6, 0xF3, 0x71, 0x97, 0xC0,\
0xB0,0x60, 0xF5, 0x7C, 0x7F, 0xAA, 0xC4, 0x64, 0x20,\
0x3F,0x52, 0x0A, 0xA3, 0xC3, 0xEF, 0x18, 0xB6, 0x45,\
0x7D,0x72, 0x1E, 0xE2, 0x61, 0x0C, 0xD0, 0xD9, 0x1D,\
0xD0,0x5B\
};
unsignedcharm3_e[1] = {3};
unsignedcharm3_d[128] = {\
0x6d,0x5d,0x9b,0xa0,0x18,0xdf,0x79,0x86,0x5f,0x02,0x32,0x4d,0xbc,0x4e,0x86,0xa2,\
0xff,0xee,0x41,0xc5,0xe9,0x60,0xb7,0x57,0x8f,0xb0,0xcb,0xdc,0xe5,0xad,0xda,0xc4,\
0x7c,0x1c,0xeb,0x23,0xd0,0x6e,0x91,0x28,0xc4,0xda,0xd3,0x77,0x7b,0x16,0x4c,0x41,\
0x98,0x5a,0x3e,0xf6,0xa2,0xbf,0xdc,0xf0,0x57,0xb7,0x46,0xdd,0x54,0xae,0xd0,0x74,\
0x27,0xaa,0xad,0xf9,0xb9,0x33,0x8f,0x29,0x3b,0xf2,0xee,0x97,0x03,0x0b,0x5c,0xfc,\
0x92,0x95,0x6f,0x05,0xcd,0xbf,0x1c,0x77,0x16,0xce,0xd9,0x13,0xfb,0xf2,0x8f,0x74,\
0x09,0xca,0x78,0xf0,0xc7,0x4a,0xc2,0xc5,0xed,0x58,0xc1,0xfa,0xa1,0x6f,0x64,0x26,\
0x73,0x75,0x73,0x97,0x21,0xb4,0x01,0x13,0xad,0xd7,0xd5,0xbc,0x22,0x75,0x00,0xcb,\
};
intmain(intargc,char*argv[]) {
MD5_CTX md5ctx;
unsignedchardigest[MD5_DIGEST_LENGTH];
unsignedcharsigret[128];
unsignedintsiglen;
unsignedchartestdata;
MD5_Init(&md5ctx);
MD5_Update(&md5ctx, &testdata, 0);
MD5_Final(digest, &md5ctx);
RSA *rsa =RSA_new();
rsa->n =BN_bin2bn(m3_n, 128, rsa->n);
rsa->e =BN_bin2bn(m3_e, 1, rsa->e);
rsa->d =BN_bin2bn(m3_d, 128, rsa->d);
RSA_sign(4,digest, 16, sigret, &siglen, rsa);
FILE *fp =fopen("security.img","wb");
fwrite(sigret, siglen, 1, fp);
fwrite("\\x40\\x00", 2, 1, fp);
fclose(fp);
return0;
}
刷入security.img后,手機(jī)就可以解鎖了。雖然上述分析是基于T2的ROM,T1也完全適用。如圖8所示,T1刷入security.img同樣可以解鎖。
圖8. T1刷入security.img后解鎖
圖9.T2刷入security.img后解鎖
And Then Some
2014年老羅在微博上提過(guò)關(guān)于bootloader方面的打算,“官方會(huì)提供 boot loader,方便你刷機(jī),只是刷機(jī)后會(huì)失?!保猿醮鶵OM里的確如我們所見(jiàn)保留了解鎖bootloader的功能。2016年有人因?yàn)樘峁┙怄i而狀告Smartisan,老羅勝訴后說(shuō)道“我在微博上說(shuō)過(guò)做bootloader,但技術(shù)部門(mén)因安全考慮否決了,我代表我自己道歉?!保钥隙ㄊ侨∠嗽摴δ?。盡管官方從來(lái)沒(méi)有發(fā)布過(guò)任何解鎖的方法,底層代碼倒是可以清晰反映出這段經(jīng)歷。
對(duì)于T1和T2,2.6.7是最后一個(gè)可以解鎖的ROM版本號(hào),2.6.8開(kāi)始,fastboot command列表被改寫(xiě)為圖10所示內(nèi)容,大部分指令被閹:
圖10. 2.6.8后的版本中fastboot已經(jīng)沒(méi)有什么實(shí)質(zhì)功能了
所以如果要解鎖3.x的Smartisan OS,可以下載2.6.7的ROM完成降級(jí),畢竟舊版本的ROM同樣帶有簽名,使用recovery時(shí)允許刷入手機(jī)。更新到舊版的bootloader后,再用fastboot flash security security.img進(jìn)行解鎖。解鎖后,每次升級(jí)用第三方無(wú)簽名驗(yàn)證的recovery,更新除bootloader以外的模塊即可。這樣即便最新系統(tǒng)暫時(shí)沒(méi)有公開(kāi)的內(nèi)核漏洞,也能root。
一般的Android手機(jī),只要有簽名認(rèn)證的老版本bootloader里有漏洞,在系統(tǒng)沒(méi)有開(kāi)啟限制(比如SW_ID)時(shí),總可以通過(guò)降級(jí),解鎖,然后升級(jí)回新系統(tǒng),刷入supersu的方式root。
本文為企業(yè)推廣,本網(wǎng)站不做任何建議,僅提供參考,作為信息展示!
推薦閱讀:萊蕪信息港
網(wǎng)友評(píng)論
請(qǐng)登錄后進(jìn)行評(píng)論|
0條評(píng)論
請(qǐng)文明發(fā)言,還可以輸入140字
您的評(píng)論已經(jīng)發(fā)表成功,請(qǐng)等候?qū)徍?/p>
小提示:您要為您發(fā)表的言論后果負(fù)責(zé),請(qǐng)各位遵守法紀(jì)注意語(yǔ)言文明