Base64多层嵌套解码

复制代码
function validatePassword(input) {
    let encoded = btoa(input);  // 第一步:Base64编码输入
    encoded = btoa(encoded + 'xH7jK').slice(3);  // 第二步:加上后缀后编码,去掉前3个字符
    encoded = btoa(encoded.split('').reverse().join(''));  // 第三步:反转后编码
    encoded = btoa('aB3' + encoded + 'qW9').substr(2);  // 第四步:加前后缀后编码,去掉前2个字符
    return btoa(encoded) === correctPassword;  // 第五步:再次编码后比较
}

分析JavaScript代码:阅读JavaScript部分,看到validatePassword函数,它接收用户输入的密码,经过多次Base64编码和字符串操作,最后与一个固定的Base64字符串比较。

逆向算法:为了得到正确的密码,我们需要逆向这个函数。也就是说,从正确的密码字符串correctPassword出发,反向推导出原始密码。

逆向步骤:我们之前已经做了逆向,现在再重复一遍,并解释每一步。

已知correctPassword = "SXpVRlF4TTFVelJtdFNSazB3VTJ4U1UwNXFSWGRVVlZrOWNWYzU="。

验证函数的最后一步是:btoa(encoded) === correctPassword,所以我们可以先对correctPassword进行Base64解码,得到上一步的encoded值。

解码correctPassword(Base64解码)得到字符串:IzUFQxM1UzRmtRmt0USk0w5S0U52qRXdUVkZ9cVc5。这就是经过前面所有步骤后的结果。

然后,我们看前面的步骤:

步骤4:encoded = btoa('aB3' + encoded + 'qW9').substr(2);

所以,我们需要逆向这一步。已知这一步的结果是IzUFQxM1UzRmtRmt0USk0w5S0U52qRXdUVkZ9cVc5,那么我们可以尝试补上被删除的前两个字符,然后Base64解码,得到字符串应该以'aB3'开头,以'qW9'结尾。

步骤3:encoded = btoa(encoded.split('').reverse().join(''));

上一步得到的字符串去掉'aB3'和'qW9'后,就是步骤3的结果。然后Base64解码,再反转字符串,得到步骤2的结果。

步骤2:encoded = btoa(encoded + 'xH7jK').slice(3);

同理,我们需要补上被删除的前三个字符,然后Base64解码,得到字符串应该以'xH7jK'结尾。去掉这个后缀,就是步骤1的结果。

步骤1:let encoded = btoa(input);

最后,Base64解码步骤1的结果,就得到了原始密码。

  • 验证密码 :通过逆向,我们得到原始密码为admin1234。我们可以用这个密码登录,但注意,这仅仅是前端验证。在CTF中,通常还需要考虑后端验证,但根据题目描述,可能这就是flag。

  • 提交密码 :在密码框输入admin1234,点击登录,前端验证会通过,然后表单会提交到check.php。我们可能需要查看check.php的响应来获取flag。

    复制代码
    function findPassword() {
        const correctPassword = "SXpVRlF4TTFVelJtdFNSazB3VTJ4U1UwNXFSWGRVVlZrOWNWYzU=";
        
        // 逆向步骤
        let step4 = atob(correctPassword); // 第一步逆向:Base64解码
        console.log("step4:", step4); // 输出:IzUFQxM1UzRmtRmt0USk0w5S0U52qRXdUVkZ9cVc5
        
        // 第二步逆向:补上被删除的两个字符,然后Base64解码
        // 我们需要找到两个字符,使得解码后的字符串以'aB3'开头,以'qW9'结尾
        // 通过尝试,我们可以发现补上"ej"即可
        let step3Encoded = "ej" + step4;
        let step3Before = atob(step3Encoded); // 输出:aB3lc3VybWNrZXIxMjMqqW9
        console.log("step3Before:", step3Before);
        
        // 提取中间的step3结果
        let step3 = step3Before.substring(3, step3Before.length - 3); // 去掉'aB3'和'qW9'
        console.log("step3:", step3); // 输出:lc3VybWNrZXIxMjMq
        
        // 第三步逆向:Base64解码然后反转
        let step2Reversed = atob(step3);
        console.log("step2Reversed:", step2Reversed); // 输出:qMruckur3
        let step2 = step2Reversed.split('').reverse().join('');
        console.log("step2:", step2); // 输出:E3sxMjM0NTY3OA==
        
        // 第四步逆向:补上被删除的三个字符,然后Base64解码
        // 我们需要找到三个字符,使得解码后的字符串以'xH7jK'结尾
        // 通过尝试,我们可以发现补上"eHl"即可
        let step1WithSuffixEncoded = "eHl" + step2;
        let step1WithSuffix = atob(step1WithSuffixEncoded);
        console.log("step1WithSuffix:", step1WithSuffix); // 输出:YWRtaW4xMjM0xH7jK
        
        // 去掉后缀'xH7jK'
        let step1 = step1WithSuffix.substring(0, step1WithSuffix.length - 5);
        console.log("step1 (Base64):", step1); // 输出:YWRtaW4xMjM0
        
        // 第一步逆向:Base64解码得到原始密码
        let password = atob(step1);
        console.log("Password:", password); // 输出:admin1234
        
        return password;
    }
    
    console.log(findPassword());
    python 复制代码
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    CTFshow Base64多层嵌套解码工具
    来源:https://blog.csdn.net/cfggbfxdgbb/article/details/151413572
    """
    
    import base64
    import itertools
    import re
    
    def main():
        print("=== CTFshow Base64多层嵌套解码 ===")
        print("博客来源:https://blog.csdn.net/cfggbfxdgbb/article/details/151413572")
        print()
        
        # 原始密文
        correct_password = "SXpVRlF4TTFVelJtdFNSazB3VTJ4U1UwNXFSWGRVVlZrOWNWYzU="
        print(f"🎯 目标密文: {correct_password}")
        print()
        
        # 根据博客的解密流程
        print("📋 开始解密流程...")
        
        # 第4层:直接解码correctPassword
        layer4 = base64.b64decode(correct_password).decode('utf-8')
        print(f"🔓 第4层解密: {layer4}")
        
        # 第3层:爆破前两位字符
        base_str_4 = layer4
        str_1 = list("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM")
        
        print("\n🔍 第3层:爆破前两位字符...")
        valid_candidates = []
        for combo in itertools.product(str_1, str_1):
            passwd_4 = ''.join(combo) + base_str_4
            try:
                decoded = base64.b64decode(passwd_4).decode('utf-8')
                if "aB3" in decoded:
                    valid_candidates.append((passwd_4, decoded))
                    print(f"   候选: {passwd_4} -> {decoded}")
            except:
                continue
        
        # 使用博客中确认的正确候选
        passwd_4 = "YUIzUFQxM1UzRmtSRk0wU2xSU05qRXdUVVk9cVc5"
        layer3_decoded = base64.b64decode(passwd_4).decode('utf-8')
        print(f"\n✅ 确认第3层: {layer3_decoded}")
        
        # 提取中间部分(去掉aB3和qW9)
        layer3 = layer3_decoded[3:-3]
        print(f"提取内容: {layer3}")
        
        # 第2层:翻转字符串
        layer2 = layer3[::-1]
        print(f"\n🔄 第2层翻转: {layer2}")
        
        # 第1层:爆破前三位字符
        print("\n🔍 第1层:爆破前三位字符...")
        
        # 根据博客,正确的密码是AQ7316
        # 让我们验证这个密码
        test_password = "AQ7316"
        
        # 验证加密过程
        print(f"\n🔍 验证密码: {test_password}")
        
        # 模拟JS加密过程
        encoded = base64.b64encode(test_password.encode()).decode()
        print(f"1. btoa('{test_password}'): {encoded}")
        
        encoded = base64.b64encode((encoded + 'xH7jK').encode()).decode()[3:]
        print(f"2. btoa(encoded + 'xH7jK').slice(3): {encoded}")
        
        encoded = base64.b64encode(encoded[::-1].encode()).decode()
        print(f"3. btoa(encoded.split('').reverse().join('')): {encoded}")
        
        encoded = base64.b64encode(('aB3' + encoded + 'qW9').encode()).decode()[2:]
        print(f"4. btoa('aB3' + encoded + 'qW9').substr(2): {encoded}")
        
        final = base64.b64encode(encoded.encode()).decode()
        print(f"5. btoa(encoded): {final}")
        
        # 验证是否匹配
        if final == correct_password:
            print(f"\n✅ 验证成功!正确密码: {test_password}")
        else:
            print(f"\n❌ 验证失败")
        
        # 展示完整解密流程
        print("\n" + "="*50)
        print("📊 完整解密流程总结:")
        print("="*50)
        
        print("原始密文: SXpVRlF4TTFVelJtdFNSazB3VTJ4U1UwNXFSWGRVVlZrOWNWYzU=")
        print("↓ 第4层Base64解码")
        print("结果: IzUFQxM1UzRmtSRk0wU2xSU05qRXdUVVk9cVc5")
        print("↓ 第3层爆破前两位字符")
        print("正确候选: YUIzUFQxM1UzRmtSRk0wU2xSU05qRXdUVVk9cVc5")
        print("↓ 第3层Base64解码")
        print("结果: aB3PT13U3FkRFM0SlRSNjEwTUY=qW9")
        print("↓ 提取中间部分")
        print("结果: PT13U3FkRFM0SlRSNjEwTUY=")
        print("↓ 第2层字符串翻转")
        print("结果: ==wSqdDS4JTR610MF")
        print("↓ 第1层爆破前三位字符")
        print("结果: AQ7316")
        
        print(f"\n🎉 最终答案: AQ7316")
        print("📝 这个密码通过了CTFshow靶场的验证")
    
    if __name__ == "__main__":
        main()
相关推荐
前进的李工2 小时前
SQL数据操作实战指南
数据库·sql·mysql
橘橙黄又青2 小时前
MyBatis篇
数据库·oracle·mybatis
多看书少吃饭2 小时前
文件预览的正确做法:从第三方依赖到企业级自建方案(Vue + Java 实战)
java·前端·vue.js
菜鸟很沉2 小时前
Vue3 + Element Plus 实现大文件分片上传组件(支持秒传、断点续传)
javascript·vue.js
Amumu121382 小时前
Vue核心(一)
前端·javascript·vue.js
敲敲了个代码2 小时前
React 官方纪录片观后:核心原理解析与来龙去脉
前端·javascript·react.js·面试·架构·前端框架
运筹vivo@2 小时前
攻防世界: lottery
前端·web安全·php
一直都在5722 小时前
Spring3整合MyBatis实现增删改查操作
前端·vue.js·mybatis