本題解完有劇情對話喔!
Can you break into this super secure portal? https://2019shell1.picoctf.com/problem/47277/ (link) or http://2019shell1.picoctf.com:47277
你能破解這個超”安全”的入口嗎? 連結在此: https://2019shell1.picoctf.com/problem/47277/ (link) or http://2019shell1.picoctf.com:47277
What is obfuscation?
本題延續自 # 02. dont-use-client-side。打開網頁的原始碼會發現也很像,只是在引用javascript 部份看起怪怪的,這是因為這裡的 javascript 使用混淆器(也就是提示裡說的 obfuscation)來重新編碼過,因此這一題的解法就是如何拆解排版並拆解編碼。
首先為了能更容易理解程式碼,先使用
Online Javascript Formatter將 javascript 美化排版。以下是排版後的結果,只截取重要的部份:
var _0x5a46 = ['29871}', '_again_d', 'this', 'Password\x20Verified', 'Incorrect\x20password', 'getElementById', 'value', 'substring', 'picoCTF{', 'not_this'];
function verify() {
checkpass = document[_0x4b5b('0x0')]('pass')[_0x4b5b('0x1')];
split = 0x4;
if (checkpass[_0x4b5b('0x2')](0x0, split * 0x2) == _0x4b5b('0x3')) {
if (checkpass[_0x4b5b('0x2')](0x7, 0x9) == '{n') {
if (checkpass[_0x4b5b('0x2')](split * 0x2, split * 0x2 * 0x2) == _0x4b5b('0x4')) {
同樣是 verify() 的功能在對比使用者的密碼,只是這裡的問題是編碼過後的內容不易理解。對照第一部份的文字宣告,可以得知這裡把變數都藏在變數中。而且其他的程式碼還會將此重新排序。
p.s. 這次的密碼較短,雖然能從 _0x5a46 宣告的變數組合就能推敲出 flag ,以下還是照較笨的方法一步步拼湊。
後續的解題會使用開發者工具的另一個強項”Console”,能夠在此頁面輸入指令,例如查詢 javascript 的變數。這對後續拆解的幫助很大,可以先試試看如何使用。
開始依照程式的順序解出明碼
split = 0x4;
if (checkpass[_0x4b5b('0x2')](0x0, split * 0x2) == _0x4b5b('0x3')) {
// _0x4b5b('0x2') 是 substring ,可以使用console 顯示 出來,或是對比其中一個判斷式也有提示。
// _0x4b5b('0x3') 是 picoCTF{
substring (0,8) = picoCTF{
p.s. 注意 substring 的位置算法是從0開始算起,參數中的結尾不包刮該字元。
if (checkpass[_0x4b5b('0x2')](0x7, 0x9) == '{n') {
substring (7,9) ={n
if (checkpass[_0x4b5b('0x2')](split * 0x2, split * 0x2 * 0x2) == _0x4b5b('0x4')) {
// _0x4b5b('0x4') 是 not_this
substring (8,16) =not_thi
if (checkpass[_0x4b5b('0x2')](0x3, 0x6) == 'oCT') {
substring (3,6) = oCT
if (checkpass[_0x4b5b('0x2')](split * 0x3 * 0x2, split * 0x4 * 0x2) == _0x4b5b('0x5')) {
// _0x4b5b('0x5') 是 29871}
substring (24,32) =29871}
if (checkpass['substring'](0x6, 0xb) == 'F{not') {
substring (6,11) =F{not)
if (checkpass[_0x4b5b('0x2')](split * 0x2 * 0x2, split * 0x3 * 0x2) == _0x4b5b('0x6')) {
// _0x4b5b('0x6') 是 _again_d
substring (16,24) =_again_d
if (checkpass[_0x4b5b('0x2')](0xc, 0x10) == _0x4b5b('0x7')) {
// _0x4b5b('0x7') 是 this
substring (12,16) =this
填入每個位置的字串即可得知 flag
後記:
本題不需要更改變數值,如果日後需要可以利用即時編輯 javascript 的功能。不過這裡需要事先設定,詳細步驟請參考如何打開 local overrides,成功設定的話,之後即可在開發著工具下的”Source”面板中新增修改 javascript。
picoCTF{not_this_again_d29871}
注意每個人不同
SYSTEM UPDATE: Factory at maximum capacity, cancelling lockdown…
SYSTEM UPDATE: Cannot unlock. Power drain detected. Source: Power Room.
「GO TO SLEEP.」
「A」
「GO TO SLEEP.」
「DIf you’re in there, I’m sticking to the plan. And if it’s the Nameless or whatever you call yourselves that I’m talking to.」
「GO TO SLEEP.」
「DApparently you’ve been in my head. You know what’s coming for you.」
SYSTEM UPDATE: Power Room unlocked.
「GO TO SLEEP.」
「GO TO SLEEP.」
「GO TO SLEEP.」