只贡献了一个二血的弟弟,见证了协会高光时刻

TIM截图20200803113828

Ohhhhhhhh~~~!!!

W&MCTF_Dalabengba

Dalabengba

Description

Play game and get flag!
attachment
The flag was divided into three parts, the format is WMCTF{part1+part2=part3}.

https://www.youtube.com/watch?reload=9&v=NYNLq2AIw_s
https://music.163.com/#/song?id=521493845

imgTry to fix the bug in the gane to start your journey?

imgAbout English version:We quickly made the English version of the game, please put this data package where it should be to patch the game. http://cos.wmctf.wetolink.com/data.rar

Analyze

首先开局下载得到一个游戏,然后有图标可得是一个rpgmaker制作的游戏,但是他是打包好的一共36M这么大的游戏,这里使用EnigmaVBUnpacker可以将其解包得到原始数据文件,但是就算是解包成功了,也还是无法进入游戏,说是找不到某文件的png,然后打开该路径就会发现只有xxx.rpgmvp的文件在那,看样子是没有解密成功,然后上网查询后是data/system.json文件中的encryptionKey来控制解密,但是打开后发现其为···"windowTone":[0,0,0,0],"hasEncryptedImages":true,"hasEncryptedAudio":true,"encryptionKey":""},encryptionKey为空,所以估计是要去找encryptionKey来解密游戏,但是找是找不到的,于是我找了个rpgmaker mv 1.6.1版本的来对比实验,配合上已有的解密代码,发现其加密核心一句为:

/**
     * (Re)-Encrypt a RPG-Make-File-ArrayBuffer
     *
     * @param {ArrayBuffer} arrayBuffer - Array-Buffer of the File
     * @returns {ArrayBuffer} - Encrypted Array-Buffer with the Fake-Header
     */
    Decrypter.prototype.encrypt = function(arrayBuffer) {
        if(! arrayBuffer)
            throw new ErrorException('File is empty or can\'t be read by your Browser...', 1);

        // Encrypt the File beginning
        arrayBuffer = this.xOrBytes(arrayBuffer);

        // Create Header
        var fakeHeader = this.buildFakeHeader();

        // Add Fake-Header in Front then the File
        var tmpInt8Array = new Uint8Array(arrayBuffer.byteLength + this.getHeaderLen());
        tmpInt8Array.set(fakeHeader, 0);
        tmpInt8Array.set(new Uint8Array(arrayBuffer), this.getHeaderLen());

        // Check if header is valid
        var header = new Uint8Array(tmpInt8Array.buffer, 0, this.getHeaderLen());
        if(! this.verifyFakeHeader(header))
            throw new ErrorException(
                'Fake-Header don\'t matches the Template-Fake-Header... Please report this Bug',
                3
            );

        return tmpInt8Array.buffer;
    };

    /**
     * XOR x Bytes (x = header-length-bytes)
     *
     * @param {ArrayBuffer} arrayBuffer - Array-Buffer where bytes should be XORed
     * @returns {ArrayBuffer} - Array-Buffer with XORed Bytes
     */
    Decrypter.prototype.xOrBytes = function(arrayBuffer) {
        var view = new DataView(arrayBuffer);

        if(arrayBuffer) {
            var byteArray = new Uint8Array(arrayBuffer);
            // console.log(this.getHeaderLen());
            // console.log(byteArray);
            for(var i = 0; i < this.getHeaderLen(); i++) {
                console.log(byteArray[i]);
                byteArray[i] = byteArray[i] ^ parseInt(this.encryptionCodeArray[i], 16);
                console.log(byteArray[i]);
                view.setUint8(i, byteArray[i]);
            }
        }

        return arrayBuffer;
    }
}

可以看到其加密极度憨批,就是加上自己的头,然后后面bytearray数组与密钥异或得到第二列的加密“校验位”数据,所以我们只需要原图的bytearray和校验位的数据异或一下即可得到密钥,bytearray用js版的RPG-Maker-MV-Decrypter修改下源码即可获得,校验位就是直接读取16进制后的16~32位数据,python写下脚本得到encryptionKey

a = [0x7e,0x15,0xdc,0x75,0x87,0x1c,0x96,0xf2,0x58,0xe7,0x27,0x0d,0x64,0x9c,0xb2,0xf9]
b = [137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82]
res = ''
for i in range(16):
    res+=hex(a[i]^b[i])[2:].zfill(2)
print(res)

得到encryptionKeyf74592328a168cf858e7270078d4f6ab,进入游戏后迅速开挂过完全剧情,得到3处flag:

Solve

part1:

最后的空中宫殿NPC移动轨迹得Pr1nCe5(S)5(s)

part2:

解密后根目录文件有过part2且宝箱hint为

image-20200803122546690

得知为Java得盲水印隐写,通过https://github.com/ww23/BlindWatermark/releases/tag/v0.0.3项目可以得到水印图像

ren

反色处理+补充识别位得:

solved

再用zxing扫描得到part2:W@rR1or

part3:

文件通过crypto解密,密钥为国王说的那句话的去除大写字母倒叙16进制转换,其密钥为:Y0u_@re_5o_bRaVE,解密后是一堆不可见字符,分别是tab和空格,换成0和1后得到

100110101111011010101110000001000001011010000110011011101010011000000100011001101111011010101110011101100010011000000100100101100010111010000100100001001000010010000100100001001000010001010000
01010000
01010000
01010000
000011101000011001001110001011101100110001011100111010100001011001001110010010100100111001001110010011100111111001010000

然后再倒叙二进制转字符串再倒叙得到

You have found it!!!!!!






part3:WhrRrrr~

得到part3:WhrRrrr~

(ps:赛后去问(打)出题人得知其实有个工具是s3cr3t可以直接得到part3的解密

最终fuzz一下part1可以得到flag

flag

WMCTF{Pr1nCe5s+W@rR1or=WhrRrrr~}