본문 바로가기
웹 해킹/드림핵

[Dreamhack] funjs

by L3m0n S0ju 2021. 10. 10.

 

이번 문제는 웹 리버싱이다. 난독화된 javascript를 하나씩 분석하여 플래그를 찾는 문제이다. 코드는 아래와 같이 여러 변수, 배열들의 이름이 난독화되어있어서 코드를 해석하기 쉽지않다. 따라서 notepad나 메모장으로 파일을 열어서 하나씩 차례대로 난독화된 변수이름을 수정하는 작업을 거쳐서 가독성을 높여야한다. 어느정도 가독성이 생기면 일반적인 자바스크립트 코드가 되고 하나씩 구글에 검색하면서 각 함수, 변수, 문법의 역할을 알아내야한다.

 

 

 


<html>
    <head>
    <style>*{margin: 0;}</style>
    <script>
    var box;
    window.onload = init;
    function init() {
      box = document.getElementById("formbox");
      setInterval(moveBox,1000);
    }
    function moveBox() {
        box.posX = Math.random() * (window.innerWidth - 64); 
        box.posY = Math.random() * (document.documentElement.scrollHeight - 64); 
        box.style.marginLeft = box.posX + "px";
        box.style.marginTop  = box.posY + "px";
        debugger;
    }

    function text2img(text){
        var imglist = box.getElementsByTagName('img');
        while(imglist.length > 0) {imglist[0].remove();}
        var canvas = document.createElement("canvas");
        canvas.width = 620;
        canvas.height = 80;
        var ctx = canvas.getContext('2d');
        ctx.font = "30px Arial";
        var text = text;
        ctx.fillText(text,10,50);
        var img = document.createElement("img");
        img.src = canvas.toDataURL();
        box.append(img);
    };

    function main(){
        var _0x1046=['2XStRDS','1388249ruyIdZ','length','23461saqTxt','9966Ahatiq','1824773xMtSgK','1918853csBQfH','175TzWLTY','flag','getElementById','94hQzdTH','NOP\x20!','11sVVyAj','37594TRDRWW','charCodeAt','296569AQCpHt','fromCharCode','1aqTvAU'];
        var _0x376c = function(_0xed94a5, _0xba8f0f) {
            _0xed94a5 = _0xed94a5 - 0x175;
            var _0x1046bc = _0x1046[_0xed94a5];
            return _0x1046bc;
        };
        var _0x374fd6 = _0x376c;
        (function(_0x24638d, _0x413a92) {
            var _0x138062 = _0x376c;
            while (!![]) {
                try {
                    var _0x41a76b = -parseInt(_0x138062(0x17f)) + parseInt(_0x138062(0x180)) * -parseInt(_0x138062(0x179)) + -parseInt(_0x138062(0x181)) * -parseInt(_0x138062(0x17e)) + -parseInt(_0x138062(0x17b)) + -parseInt(_0x138062(0x177)) * -parseInt(_0x138062(0x17a)) + -parseInt(_0x138062(0x17d)) * -parseInt(_0x138062(0x186)) + -parseInt(_0x138062(0x175)) * -parseInt(_0x138062(0x184));
                    if (_0x41a76b === _0x413a92) break;
                    else _0x24638d['push'](_0x24638d['shift']());
                } catch (_0x114389) {
                    _0x24638d['push'](_0x24638d['shift']());
                }
            }
        }(_0x1046, 0xf3764));
        var flag = document[_0x374fd6(0x183)](_0x374fd6(0x182))['value'],
            _0x4949 = [0x20, 0x5e, 0x7b, 0xd2, 0x59, 0xb1, 0x34, 0x72, 0x1b, 0x69, 0x61, 0x3c, 0x11, 0x35, 0x65, 0x80, 0x9, 0x9d, 0x9, 0x3d, 0x22, 0x7b, 0x1, 0x9d, 0x59, 0xaa, 0x2, 0x6a, 0x53, 0xa7, 0xb, 0xcd, 0x25, 0xdf, 0x1, 0x9c],
            _0x42931 = [0x24, 0x16, 0x1, 0xb1, 0xd, 0x4d, 0x1, 0x13, 0x1c, 0x32, 0x1, 0xc, 0x20, 0x2, 0x1, 0xe1, 0x2d, 0x6c, 0x6, 0x59, 0x11, 0x17, 0x35, 0xfe, 0xa, 0x7a, 0x32, 0xe, 0x13, 0x6f, 0x5, 0xae, 0xc, 0x7a, 0x61, 0xe1],
            operator = [(_0x3a6862, _0x4b2b8f) => {
                return _0x3a6862 + _0x4b2b8f;
            }, (_0xa50264, _0x1fa25c) => {
                return _0xa50264 - _0x1fa25c;
            }, (_0x3d7732, _0x48e1e0) => {
                return _0x3d7732 * _0x48e1e0;
            }, (_0x32aa3b, _0x53e3ec) => {
                return _0x32aa3b ^ _0x53e3ec;
            }],
            getchar = String[_0x374fd6(0x178)];
        if (flag[_0x374fd6(0x17c)] != 0x24) {
            text2img(_0x374fd6(0x185));
            return;
        }
        for (var i = 0x0; i < flag[_0x374fd6(0x17c)]; i++) {
            if (flag[_0x374fd6(0x176)](i) == operator[i % operator[_0x374fd6(0x17c)]](_0x4949[i], _0x42931[i])) {} else {
                text2img(_0x374fd6(0x185));
                return;
            }
        }
        text2img(flag);
    }
    </script>
    </head>
    <body>
        <div id='formbox'>
            <h2>Find FLAG !</h2>
            <input type='flag' id='flag' value=''>
            <input type='button' value='submit' onclick='main()'>
        </div>
    </body>
</html>

 

 

 

 


위 코드는 난독화된 코드이고 아래 코드는 나름대로 가독성을 높인 코드이다.

 

 

 

 

 

 


<html>
    <head>
    <style>*{margin: 0;}</style>
    <script>
    var box;
    window.onload = init;
    function init() {
      box = document.getElementById("formbox");
      setInterval(moveBox,100000);
    }
    function moveBox() {
        box.posX = Math.random() * (window.innerWidth - 64); 
        box.posY = Math.random() * (document.documentElement.scrollHeight - 64); 
        box.style.marginLeft = box.posX + "px";
        box.style.marginTop  = box.posY + "px";
        //debugger;            //debugger는 자동으로 debugger 위치에서 브레이크 포인트를 잡아준다.
    }

    function text2img(text){
        var imglist = box.getElementsByTagName('img');
        while(imglist.length > 0) {imglist[0].remove();}
        var canvas = document.createElement("canvas");
        canvas.width = 620;
        canvas.height = 80;
        var ctx = canvas.getContext('2d');
        ctx.font = "30px Arial";
        var text = text;
        ctx.fillText(text,10,50);
        var img = document.createElement("img");
        img.src = canvas.toDataURL();
        box.append(img);
    };

    function main(){
        var arr1=['2XStRDS','1388249ruyIdZ','length','23461saqTxt','9966Ahatiq','1824773xMtSgK','1918853csBQfH','175TzWLTY','flag','getElementById','94hQzdTH','NOP\x20!','11sVVyAj','37594TRDRWW','charCodeAt','296569AQCpHt','fromCharCode','1aqTvAU'];
        var func1 = function(index, _0xba8f0f) {       // 함수를 생성할 때 형식은 여러가지이다. 
            index = index - 0x175;                        // 형식 => var 함수이름 = function{ };
            return arr1[index];
        };
        (function(arr, q) {                            // 형식 => (function(a,b){ }(인자1,인자2))
            while (!![]) {                            // 항상 true
                try {
                    var total = -parseInt(arr1[10]) + parseInt(arr1[11]) * -parseInt(arr1[4]) + -parseInt(arr1[12]) * -parseInt(arr1[9]) + -parseInt(arr1[6]) + -parseInt(arr1[2]) * -parseInt(arr1[5]) + -parseInt(arr1[8]) * -parseInt(arr1[11]) + -parseInt(arr1[0]) * -parseInt(arr1[15]);
//                  debugger;
// if (total === q) break;                     //q는 0xf3764로 모든 arr1 경우의수를 돌아도 만족하는 total은 나오지않음
if (total === 45018949382) break;        //total 값이 Nah가 아닌 정수로 나오는 순간이 한번 존재한다. 
                    else arr['push'](arr['shift']());   //push 메서드는 배열 끝에 값 추가,  shift 메서드는 배열 맨 앞의 값 삭제   -> 반시계방향 회전 -> '37594TRDRWW'가 arr1배열 인덱스 0이 될때 total에 정수 45018949382가 출력된다.
                } catch (_0x114389) {
                    arr['push'](arr['shift']());
                }
            }
        }(arr1, 0xf3764));
//      var flag = document[arr1[14]](arr1[13])['value'],            // arr1을 잘보면 연속으로 명령어가 존재하는 구간은 'flag','getElementById' 밖에 없으므로 추측할 수 있다.
        var flag = document['getElementById']('flag')['value'],
            arr2 = [0x20, 0x5e, 0x7b, 0xd2, 0x59, 0xb1, 0x34, 0x72, 0x1b, 0x69, 0x61, 0x3c, 0x11, 0x35, 0x65, 0x80, 0x9, 0x9d, 0x9, 0x3d, 0x22, 0x7b, 0x1, 0x9d, 0x59, 0xaa, 0x2, 0x6a, 0x53, 0xa7, 0xb, 0xcd, 0x25, 0xdf, 0x1, 0x9c],
            arr3 = [0x24, 0x16, 0x1, 0xb1, 0xd, 0x4d, 0x1, 0x13, 0x1c, 0x32, 0x1, 0xc, 0x20, 0x2, 0x1, 0xe1, 0x2d, 0x6c, 0x6, 0x59, 0x11, 0x17, 0x35, 0xfe, 0xa, 0x7a, 0x32, 0xe, 0x13, 0x6f, 0x5, 0xae, 0xc, 0x7a, 0x61, 0xe1],
            operator = [(_0x3a6862, _0x4b2b8f) => {               // operator[0]부터 순서대로 + - * ^
                return _0x3a6862 + _0x4b2b8f;
            }, (_0xa50264, _0x1fa25c) => {
                return _0xa50264 - _0x1fa25c;
            }, (_0x3d7732, _0x48e1e0) => {
                return _0x3d7732 * _0x48e1e0;
            }, (_0x32aa3b, _0x53e3ec) => {
                return _0x32aa3b ^ _0x53e3ec;
            }],
            getchar = String[func1(0x178)];
// if (flag['length'] != 0x24) {
//          text2img('NOP\x20!');
//          return;
//      }
var flag2="";
        for (var i = 0x0; i < 50; i++) {
flag2 += String.fromCharCode(operator[i % operator['length']](arr2[i], arr3[i]));
}
console.log(flag2);
        
// for (var i = 0x0; i < flag['length']; i++) {
//          if (flag['charCodeAt'](i) == operator[i % operator['length']](arr2[i], arr3[i])) {} 
// else {
//              text2img('NOP\x20!');
//              return;
//          }
//      }

        text2img(flag);
    }
    </script>
    </head>
    <body>
        <div id='formbox'>
            <h2>Find FLAG !</h2>
            <input type='flag' id='flag' value=''>
            <input type='button' value='submit' onclick='main()'>
        </div>
    </body>
</html>

 

 

 

 


 

위에서 분석한 코드를 브라우저로 열고 아무 값이나 입력하면 Console창에 플래그가 출력된다.

'웹 해킹 > 드림핵' 카테고리의 다른 글

[Dreamhack] simple-ssti  (0) 2021.07.20
[Dreamhack] Mango  (0) 2021.07.18
[Dreamhack] php-1  (0) 2021.07.16
[Dreamhack] pathtraversal  (0) 2021.07.16
[Dreamhack] proxy-1  (0) 2021.07.16

댓글