QiwiCTF2016 Writeup – [Web] javascript

題目

網頁中提供一個欄位讓使用者輸入 Key, 程式會驗證是否正確
而這把 key 就是 這題的 flag.

過程

該檢查函數資料如下

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('18 10(){1a(1b("%o%p%9%3%8%g%a%9%0%1%9%3%a%5%1%6%e%8%2%7%0%F%b%0%0%0%0%j%4%2%0%3%c%4%2%e%0%d%0%G%u%M%D%1c%1d%N%16%11%13%14%17%15%R%w%19%1p%1l%Q%1m%P%1n%U%12%X%V%Y%4%i%3%5%1%o%t%c%g%z%1o%m%1e%9%a%L%1k%2%e%8%p%j%A%1j%1f%E%q%l%s%v%O%1g%n%1h%I%Z%r%1i%d%G%f%b%0%0%0%0%j%4%2%0%1%9%3%a%5%1%5%0%d%0%C%B%f%b%0%0%0%0%j%4%2%0%3%0%d%0%q%f%b%0%0%0%0%A%c%g%m%1%0%6%3%0%k%0%e%8%2%h%m%1%9%t%8%c%7%0%F%b%0%0%0%0%0%0%0%0%j%4%2%0%i%q%0%d%0%e%8%2%h%3%c%4%2%D%a%5%1%u%8%6%3%r%r%7%f%b%0%0%0%0%0%0%0%0%j%4%2%0%i%l%0%d%0%e%8%2%h%3%c%4%2%D%a%5%1%u%8%6%3%r%r%7%f%b%0%0%0%0%0%0%0%0%j%4%2%0%i%s%0%d%0%e%8%2%h%3%c%4%2%D%a%5%1%u%8%6%3%r%r%7%f%b%0%0%0%0%0%0%0%0%j%4%2%0%i%p%o%0%d%0%6%i%q%0%k%k%0%l%n%7%0%r%0%6%6%i%l%0%J%J%0%q%7%0%k%k%0%I%7%0%r%0%6%i%s%0%J%J%0%q%7%f%b%0%0%0%0%0%0%0%0%j%4%2%0%g%q%0%d%0%6%i%p%o%0%K%0%6%n%v%0%k%k%0%l%I%7%7%0%y%y%0%l%I%f%b%0%0%0%0%0%0%0%0%j%4%2%0%g%l%0%d%0%6%i%p%o%0%K%0%6%n%v%0%k%k%0%l%s%7%7%0%y%y%0%l%s%f%b%0%0%0%0%0%0%0%0%j%4%2%0%g%s%0%d%0%g%e%w%4%w%6%i%l%7%0%T%0%n%O%0%S%0%6%i%p%o%0%K%0%6%n%v%0%k%k%0%n%7%7%0%y%y%0%n%f%b%0%0%0%0%0%0%0%0%j%4%2%0%g%v%0%d%0%g%e%w%4%w%6%i%s%7%0%T%0%n%O%0%S%0%6%i%p%o%0%K%0%n%v%7%f%b%0%0%0%0%0%0%0%0%1%9%3%a%5%1%5%C%1%9%3%a%5%1%5%h%m%1%9%t%8%c%B%0%d%0%3%c%4%2%e%h%3%c%4%2%u%8%6%g%q%7%f%b%0%0%0%0%0%0%0%0%1%9%3%a%5%1%5%C%1%9%3%a%5%1%5%h%m%1%9%t%8%c%B%0%d%0%3%c%4%2%e%h%3%c%4%2%u%8%6%g%l%7%f%b%0%0%0%0%0%0%0%0%1%9%3%a%5%1%5%C%1%9%3%a%5%1%5%h%m%1%9%t%8%c%B%0%d%0%3%c%4%2%e%h%3%c%4%2%u%8%6%g%s%7%f%b%0%0%0%0%0%0%0%0%1%9%3%a%5%1%5%C%1%9%3%a%5%1%5%h%m%1%9%t%8%c%B%0%d%0%3%c%4%2%e%h%3%c%4%2%u%8%6%g%v%7%f%b%0%0%0%0%H%b%0%0%0%0%2%1%8%p%2%9%0%1%9%3%a%5%1%5%h%z%a%g%9%6%G%G%7%f%b%0%H%b%g%o%0%6%1%9%3%a%5%1%6%3%8%o%h%L%4%e%e%A%a%2%5%h%j%4%m%p%1%7%0%d%d%0%x%4%z%Q%s%w%11%w%z%3%z%N%A%5%N%Z%o%X%E%M%g%Y%9%U%E%V%E%Q%q%R%P%M%p%x%7%F%4%m%1%2%8%6%x%P%c%4%8%0%2%g%t%c%8%W%x%7%f%H%1%m%e%1%F%4%m%1%2%8%6%x%12%2%a%9%t%0%L%4%e%e%A%a%2%5%W%x%7%f%H%0%b"))}10();',62,88,'20|65|72|63|61|64|28|29|74|6E|6F|0A|68|3D|73|3B|69|2E|62|76|3C|31|6C|36|66|75|30|2B|32|67|41|33|4E|22|3E|6A|77|5D|5B|43|7A|7B|27|7D|38|7C|26|70|42|46|34|54|52|4D|3A|3F|56|59|21|58|5A|39|check|48|57|49|4A|4C|47|4B|function|4F|eval|unescape|44|45|6D|79|35|37|2F|78|71|51|53|55|6B|50'.split('|'),0,{}))

我們可以透過以下兩種方法解開 packer
1. 透過 unPacker
2. 將 eval 改為 console.log 然後執行, 重複這個動作直到內容完全解開

解開後我們可以得到下列的結果

function encode(str) 
    {
        var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
        var encoded = [];
        var c = 0;
        while (c < str.length) 
        {
                var b0 = str.charCodeAt(c++);
                var b1 = str.charCodeAt(c++);
                var b2 = str.charCodeAt(c++);
                var buf = (b0 << 16) + ((b1 || 0) << 8) + (b2 || 0);
                var i0 = (buf & (63 << 18)) >> 18;
                var i1 = (buf & (63 << 12)) >> 12;
                var i2 = isNaN(b1) ? 64 : (buf & (63 << 6)) >> 6;
                var i3 = isNaN(b2) ? 64 : (buf & 63);
                encoded[encoded.length] = chars.charAt(i0);
                encoded[encoded.length] = chars.charAt(i1);
                encoded[encoded.length] = chars.charAt(i2);
                encoded[encoded.length] = chars.charAt(i3);

    }
        return encoded.join('');

}
if (encode(ctf.password.value) == "ajR2NHNjcjFwdF9fXzBiZnVzYzR0MTBu")
    {
    alert("That right!");
}
else
    {
    alert("Wrong password!");
}

當中可以得知程式會判斷輸入值encode後是否為 ajR2NHNjcjFwdF9fXzBiZnVzYzR0MTBu
接著觀察 encode 的動作方式, 然後就發現他其實是 base64 encode

Flag

j4v4scr1pt___0bfusc4t10n