View

[Dreamhack] funjs 문제 풀이

wrwrwrwr97 2023. 9. 4. 16:44

https://dreamhack.io/wargame/challenges/116/

 

funjs

Description 입력 폼에 데이터를 입력하여 맞으면 플래그, 틀리면 NOP !을 출력하는 HTML 페이지입니다. main 함수를 분석하여 올바른 입력 값을 찾아보세요 !

dreamhack.io

 

HTML 페이지 main 함수를 분석하여 올바른 입력 값을 찾아 입력하면 FLAG가 나오는 문제이다.

HTML 페이지를 열면 입력하는 부분이 계속 움직인다. 코드에서 moveBox 부분이 움직이게 하는 부분인거 같은데 필요없어 보이니 지워서 안 움직이게 했다.

빈 칸에 값을 넣고 submit 버튼을 클릭하면 해당 값을 비교하여 FLAG 또는 NOP ! 을 출력하는 것 같다.

 

올바르지 않은 값 입력

원하는 값과 다른 값을 입력하면 NOP ! 문자열이 있는 이미지를 출력한다. 

코드를 보면 텍스트를 이미지로 만드는 함수 부분이 있다.

 

아래는 분석해야 할 main 함수 부분이다.

더보기
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);
    }

 

개발자 도구에서 60번째 줄 (if문) 에 브레이크포인트를 걸고 값을 넣어보면 입력한 값인 "o"가 flag에 들어있는 것을 확인할 수 있다. 

Step into (F11)를 사용해서 실행하다 보면 _0x374fd6(0x17c) length를 반환하는 것을 알 수 있다.

해당 if문 부분은 입력한 값 (flag) 의 길이가 0x24 (36) 이 맞는지 확인하는 부분이고 아니면 NOP ! 이미지를 출력하는 부분이다.

 

 

입력한 값 (flag) 길이가 36인 값을 입력하면 바로 다음 for문으로 가는 것을 확인할 수 있다. 

임의의 길이가 36인 값 입력

 

해당 for 문은 입력 값 길이 (_0x374fd6(0x17c) 가 length 반환) 만큼 반복하는 부분이다.

디버깅 해보면서 for문 안 if문을 보면 _0x374fd6(0x176)charCodeAt 을 반환하는 것을 알 수 있다.

※ charCodeAt은 index에 해당하는 문자의 unicode 값을 리턴

 

charCodeAt 반환 확인

 

 

flag.charCodeAt(i) 를 의미하고 입력한 문자열에서 각 문자마다 charCodeAt 값을 operator ~~ 연산 값과 비교하는 것이다. 비교한 값이 다르면 NOP ! 이미지를 출력한다.

연산 값과 다른 경우 NOP ! 반환

 

 

디버깅을 계속 해보면 i가 0일때 operator ~~ 부분은 0x4949[0] + 0x42931[0]를 한 값이라는 것을 알 수 있다.

0x4949[0] + 0x42931[0]

0x20 + 0x24를 10진수로 바꾸면 32 + 36 이고 합치면 68이다. 그런데 모든 값을 더하는 것이 아닌 매번 연산이 달라진다.

operator 부분

연산 부분을 보면 +, -, *, ^ 가 있고 디버깅 해보면 +, -, *, ^ 순으로 진행된다.

if 문 안 operator 부분을 보면 i % operator.length 에 따라 연산 식이 바뀌는데 operator 길이가 4 이므로 i % 4의 결과에 따라 연산이 바뀐다.

ex) i % 4 = 0 → + ,   i % 4 = 1 → -,  i % 4 = 2 → *,  i % 4 = 3 → ^ 

 

이제 나머지에 따라 _0x4949와 _0x42931 배열 연산을 다르게 하여 문자열을 구하면 FLAG를 얻을 수 있다.

※ JavaScript에서 String.fromCharCode를 사용하면 unicode를 문자로 바꿀 수 있다.

 

Share Link
reply
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31