微慑信息网

[记录] 2024羊城杯部分writeup

数据安全1

处理数据解题脚本:

import re

# 分类规则函数
def classify(value):
    if value.isdigit() and 1 <= int(value) <= 10000:
        return 1  # 区间值1-10000
    elif len(value) == 32 and re.match(r'^[a-f0-9]{32}$', value):
        return 2  # 32位md5
    elif re.match(r'^[\u4e00-\u9fa5]+$', value) and value not in ["男", "女"]:
        return 3  # 中文但不是"男"和"女"
    elif value in ["男", "女"]:
        return 4  # "男"或"女"
    elif len(value) == 8 and value.isdigit():
        return 5  # 长度为8且全为数字
    elif len(value) == 18 and (value.isdigit() or re.match(r'^\d{17}[a-zA-Z]$', value)):
        return 6  # 长度为18且全为数字或仅包含1个字母
    elif len(value) == 11 and value.isdigit():
        return 7  # 长度为11且全为数字
    else:
        return 8  # 其余的放第八位

# 排序函数
def sort_line(line):
    elements = line.split(',')
    sorted_elements = sorted(elements, key=classify)
    return '\t'.join(sorted_elements)

# 文件处理函数
def process_file(input_file, output_file):
    with open(input_file, 'r', encoding='utf-8') as infile, open(output_file, 'w', encoding='utf-8') as outfile:
        for line in infile:
            sorted_line = sort_line(line.strip())
            outfile.write(sorted_line + '\n')

# 输入文件名和输出文件名
input_file = 'res.txt'
output_file = 'sorted_res.txt'

# 处理文件
process_file(input_file, output_file)

print(f"数据已成功处理并保存到 {output_file}")

数据安全2

这道题是队友做的,摘抄网上记录之:

处理数据解题脚本:

(先用自带的tshark和python的pyshark模块进行wireshark文件的内容的读取)

import pyshark
import json

cap = pyshark.FileCapture(input_file='data.pcapng', tshark_path='D:\\Wireshark\\tshark.exe',use_json=True,include_raw=True)
file_path = 'data.pcapng'
json_data_list = []

for packet in cap:
    print(packet)
    try:
        raw_packet = packet.get_raw_packet()
        json_start = raw_packet.index(b'{"')  # 查找 JSON 数据的起始位置
        json_data = raw_packet[json_start:]  # 提取 JSON 数据
        print(json_data)  # 调试输出 JSON 数据
        json_data_list.append(json_data.decode('utf-8'))  # 存储 JSON 数据到列表中
    except Exception as e:
        print(f"异常: {e}")

# 将提取的 JSON 数据保存到 JSON 文件中
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(json_data_list, f, ensure_ascii=False, indent=4)

得到了data.json文件,然后通过python进行数据清洗:

import csv
import json

xishu=[7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
jiaoyan=["1","0","X","9","8","7","6","5","4","3","2"]
alpha="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
digit="0123456789"
dot=[' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']
phone=[734, 735, 736, 737, 738, 739, 747, 748, 750, 751, 752, 757, 758, 759, 772,778, 782, 783, 784, 787, 788, 795, 798, 730, 731, 732, 740, 745, 746, 755,756, 766, 767, 771, 775, 776, 785, 786, 796, 733, 749, 753, 773, 774, 777,780, 781, 789, 790, 791, 793, 799]

def check(data):
    for i in dot:
        if i in data[0] or i in data[1] or i in data[2] or i in data[3] or i in data[4] or i in data[5]:
            return 0
    for i in data[1]:
        if i in digit or i in alpha:
            return 0
    if data[2]!="男" and data[2]!="女":
        return 0
    if data[3] not in data[4]:
        return 0
    if (data[2]=="男" and int(data[4][-2])%2==0) or (data[2]=="女" and int(data[4][-2])%2==1):
        return 0
    sum=0
    for i in range(len(data[4])-1):
        sum += (int(data[4][i])*xishu[i])
    if jiaoyan[sum%11]!=data[4][-1]:
        return 0
    if int(data[5][:3]) not in phone:
        return 0
    return 1

# 读取 JSON 文件
with open('data.json', 'r', encoding='utf-8') as f:
    data_list = json.load(f)

# 处理数据
new_data = []
for item in data_list:
    # 将字典转换为列表
    item=json.loads(item)
    data = [item.get('username', ''), item.get('name', ''), item.get('sex', ''), item.get('birth', ''), item.get('idcard', ''), item.get('phone', '')]
    print(data)  # 打印数据以检查转换结果
    if len(data) == 6:
        if not check(data):
            new_data.append(data)

# 将结果写入 CSV 文件
with open('person_data2.csv', mode='w', newline='', encoding='utf-8') as file:
    csv_writer = csv.writer(file)
    # 写入 CSV 文件的表头
    csv_writer.writerow(['username', 'name', 'sex', 'birth', 'idcard', 'phone'])
    # 写入数据
    csv_writer.writerows(new_data)

print("检查结果已保存到 'person_data2.csv' 文件中。")

数据安全3

这道题是队友做的,摘抄网上记录之:

处理数据解题脚本:

(在输入了所有内容信息之后,还会有一个判断,说是用户名不存在或者是输入密码:。如果有密码我们就要把密码拿下来,然后再切片、截取到题目所需要的位置,如果没有就正常删除)

import csv
import urllib.parse
import hashlib

xishu=[7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
jiaoyan=["1","0","X","9","8","7","6","5","4","3","2"]
alpha="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
digit="0123456789"
dot=[' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']
phone=[734, 735, 736, 737, 738, 739, 747, 748, 750, 751, 752, 757, 758, 759, 772,778, 782, 783, 784, 787, 788, 795, 798, 730, 731, 732, 740, 745, 746, 755,756, 766, 767, 771, 775, 776, 785, 786, 796, 733, 749, 753, 773, 774, 777,780, 781, 789, 790, 791, 793, 799]

def md5_encrypt(input_string):
    # 创建一个md5 hash对象
    md5_hash = hashlib.md5()

    # 更新hash对象以字符串值(需要先编码为字节串)
    md5_hash.update(input_string.encode('utf-8'))

    # 获取十六进制数格式的hash值,并转换为小写
    return md5_hash.hexdigest()
def check(data):
    for i in dot:
        if i in data[0] or i in data[1] or i in data[2] or i in data[3] or i in data[4]:
            return 0
    for i in data[2]:
        if i in digit or i in alpha:
            return 0
    sum=0
    for i in range(len(data[3])-1):
        sum += (int(data[3][i])*xishu[i])
    if jiaoyan[sum%11]!=data[3][-1]:
        return 0
    if int(data[4][:3]) not in phone:
        return 0
    return 1

def read_log_until_next_bracket(filepath):
    new=[['username','password','name','idcard','phone']]
    """
    读取指定的日志文件,在遇到包含'username'的行时,继续读取直到遇到下一个'['符号或文件结束。
    """
    try:
        with open(filepath, 'r', encoding='utf-8') as file:
            current_block = ""  # 用于存储从'username'开始到'['之前的所有内容
            reading = False  # 标记是否开始读取块

            for line in file:
                if "username" in line:
                    # 如果当前行包含'username',则开始读取块
                    reading = True
                    current_block += line  # 添加当前行到块中
                elif "\\xe6\\x82\\xa8\\xe8\\xbe\\x93\\xe5\\x85\\xa5\\xe7\\x9a\\x84\\xe7\\x94" in line:
                    current_block = ""
                    reading = False
                elif reading:
                    # 如果已经开始读取块,则继续添加行到块中
                    if "\\xe5\\xaf\\x86\\xe7\\xa0\\x81\\xe4\\xb8\\xba" in line:
                        # 如果当前行包含'[',则停止读取块并打印
                        # 注意:这里只打印到'['之前的部分(如果需要)
                        # 或者你可以选择保留整个块直到'['
                        idx = line.find("\\xe5\\xaf\\x86\\xe7\\xa0\\x81\\xe4\\xb8\\xba")
                        if idx != -1:  # 确保'['确实存在
                            current_block += line
                            tmp=(current_block.strip()[143:])  # 打印并去除首尾空白
                            edx = line
                            tmp=(tmp.split('&'))
                            tmp[3]=(tmp[3].split('\n'))
                            tmp.append(tmp[3])
                            tmp[3]=tmp[4][0]
                            tmp[4]=tmp[4][-1][-30:][:-2]
                            tmp[4]=tmp[4].split(": ")[1]
                            tmp.append(tmp[4])
                            tmp[4]=tmp[3]
                            tmp[3]=tmp[2]
                            tmp[2]=tmp[1]
                            tmp[1]=tmp[5]
                            tmp.pop()
                            tmp[0]=urllib.parse.unquote(tmp[0][9:])
                            tmp[2] = urllib.parse.unquote(tmp[2][5:])
                            tmp[3] = urllib.parse.unquote(tmp[3][7:])
                            tmp[4] = urllib.parse.unquote(tmp[4][6:])
                            if not check(tmp):
                                current_block = ""
                                tmp=[]
                                reading = False
                                continue
                            if len(tmp[0])==1:
                                pass
                            elif len(tmp[0])==2:
                                tmp[0]=tmp[0][0]+"*"
                            else:
                                tmp[0]=tmp[0][0]+(len(tmp[0])-2)*"*"+tmp[0][-1]

                            tmp[1]=md5_encrypt(tmp[1])

                            if len(tmp[2])==2:
                                tmp[2]=tmp[2][0]+"*"
                            else:
                                tmp[2]=tmp[2][0] + (len(tmp[2])-2)*"*"+tmp[2][-1]
                            tmp[3]="******"+tmp[3][6:10]+"********"
                            tmp[4]=tmp[4][:3]+"****"+tmp[4][-4:]
                            new.append(tmp)
                            current_block = ""  # 重置块
                            reading = False  # 停止读取
                    else:
                        current_block += line  # 否则,继续添加整行到块中
            print(new)
            with open("person_data2.csv", mode='w', newline='', encoding='utf-8') as file:
                csv_writer = csv.writer(file)
                csv_writer.writerows(new)

    except FileNotFoundError:
        print(f"文件 {filepath} 未找到。")

    # 调用函数,传入日志文件路径

read_log_until_next_bracket('error.log')

题目:miaoro

附件是一个流量包:直接扔进wireshark 可正常打开。跟踪tcp流,在第4个流看到攻击流量,通过返回的信息<h3>Roles you DON’T have</h3>,查询后出现apache Shiro 关键字,因此考虑是Shinro 相关漏洞利用。

继续跟踪tcp流量,在第6个流最后一个请求后返回为0 不再提示需要登录,因此漏洞利用成功,继续跟踪之后的流量,看一下都做了哪些操作:

在第7个流看到新的头部参数 GWHT 明显带有YCB2024的提示后面为base64,因此解码得到,执行了 whoami 命令,并得到正确的返回:

第8个流执行 echo 1234 返回0 执行成功

第9个流执行 net user 查询系统用户

第10个流执行 echo Th15_11111111s_pP@sssssw000rd!!!>pass.txt 返回0执行成功。这里“Th15_11111111s_pP@sssssw000rd!!!”是一个重要的信息。

 

第11个流 获取了test.txt 文件正常返回,没啥信息

第12个流  执行ipconfig

第13个流 获取secret.txt文件,需要将该文件导出。

通过对返回的内容拼接后进行base64解码 发现关键信息:

存在倒序的zip数据包特征,处理后得到一个加密的压缩包,输入前面字节10获得的密码,解压得到一张png图片

图片图像看上去比较混乱,由于是png图片,观察图片格式,对图片的高宽进行互换

调整宽带为1404 并调整高度为380(随便,宽度要对):

通过在线试图得到猫字符的线索:

跟随这张图片得到链接

https://shejijingsai.com/2019/07/277603.html

在页面中翻查到,A-Z的猫字符原设计图,根据这个设计图,识别图片中为:EBOFDELQDIAA}得到后一半flag

还差一半的flag ,Shiro是通过cookiela加载攻击载荷,之前分析第6个流最后一次请求返回为0显示攻击成功,之后的cookie都使用了这个攻击载荷,因此我们想看这个攻击载荷中是否存在信息,但cookie是加密的需要进行解密,通过 https://vulsee.com/tools/shiroDe/shiroDecrypt.html 可实现内置的64个key进行爆破,最终在攻击载荷中我们得到了前半部分flag:DASCTF{B916CFEB-C40F-45D6-A7BC-

最终本题的Flag为:DASCTF{B916CFEB-C40F-45D6-A7BC-EBOFDELQDIAA}

题目:so much

解压附件得到一个c2hpZnQh.ad1的文件,文件名像是base编码过的,解码后得到shift!,这是一个很重要的提示,后续解题过程中要用到。通过010EDITOR打开,观注文件头和文件尾的信息

 

这里提示 the key is 1234567 really?,结合文件名的shift!,可以想到有一个密码是!@#¥%……&.

根据已知信息继续跟进:文件头部提示ADCRYPT。通过查询得知需要使用FTK Imager打开

通过FTK Imager 4.7.14(低版本打开会报错) 取证工具打开镜像,输入前面得知的密码:!@#$%^&,成功打开磁盘镜像。这个磁盘镜像总计有344个后缀名为crypto的加密文件,需要解密。导出文件后,发现,文件名为顺序增长,代表了一个顺序,而文件被修改时间只有分别为16:19 和16:20这明显代表了二进制数据。同时我们通过导出对所有文件的hash值列表,发现只有2个hash值,这也印证了我们的猜测。

根据已有的信息,按照文件名顺序进行排序,并替换文件0的hash 为0 另外一个hash值为1,得到下图:

组合后的二进制串为:

01110100011010000110010101011111011010110110010101111001010111110110100101110011010111110011011100110000001100000011001000110010001110010110001100110000001101010011001101100010001101000110010101100010011000100110001101100110001100010110000100110011011000110110001100110011001101110110001100110011001110000011100101100011001101000110011001100001

得到一个key:the_key_is_700229c053b4ebbcf1a3cc37c389c4fa,因此判断需要这个key对crypto后缀的文件进行解密。

查询crypto后缀文件解密工具

由此可知下载encrypto工具,安装后对文件0.crypto 和1.crypto进行解密:

由此得到完整的flag: DASCTF{85235bd803c2a0662b771396bce9968f}

题目:hiden

解压附件得到两个文件,一个为txt 一个为wav文件;

其中txt文件名比较奇怪,应该是解题的提示,txt文件内容无法解读:

看文件内容和排列,貌似为一段代码进行了字符替换。判断首行为6字符+空格+4字符,加之本地另外一个附件为.wav 根据这个特征假定首行为python 代码 import wave,通过假设,发现 G与i直间的ASCII值相差为34.由于文件名为60=?+?,因此初步判断经过2次rot变换,因此通过该值可得到60-34=?*2,得出其中一个为13,另一个为47.通过执行rot47后再次执行rot13,得到还原后的代码:

import wave 
with open('flag.txt', 'rb') as f:
    txt_data = f.read()
    file_len = len(txt_data)
    txt_data = file_len.to_bytes(3, byteorder = 'little') + txt_data
with wave.open("test.wav", "rb") as f:
    attrib = f.getparams()    
    wav_data = bytearray( f.readframes(-1) )
for index in range(len(txt_data)):
    wav_data[index * 4] = txt_data[index]  
with wave.open("hiden.wav", "wb") as f:
    f.setparams(attrib) 
f.writeframes(wav_data)

解读代码:

打开一个flag.txt,读取文本内容,并统计文本长度。

txt_data = file_len.to_bytes(3, byteorder = ‘little’) + txt_data意思是封装新txt_data字符串,将字符串长度附加在原来文本之前,长度为3字节,little参数表示存储格式为小端存储,即最高有效位存储在3字节的末端,最低有效位存储在3字节的开头具体如下:比如文本DASCTF{qa-2236-v7-9ffg-wdfhk}长度为29,经过该运算后,变成:

‘\x1d\x00\x00DASCTF{qa-2236-v7-9ffg-wdfhk}’ 其中\x1d 为长度存储在高位上。

将字符串格式化后,脚本打开了名为test.wav的文件,并读取音频帧并将其转换为可变的字节数组(bytearray),通过遍历文本数据,将其字节逐个写入音频数据的每隔4个字节的位置。

根据解读结果我们可以按照以下两种方式进行:

0X01:

由于是直接写入,因此并未对flag内容进行改变,因此直接使用010editer打开hiden.wav,翻查

每隔3个字节取一个字符得到flag:DASCTF{12jkl-456m78-90n1234}}

0x02:

编写脚本从hiden.wav中还原flag.txt:

import wave
with wave.open('hiden.wav','rb') as f:
    attrib=f.getparams()
    data=bytearray(f.readframes(-1))
txt_len=int.from_bytes(data[0:3],'little') +30//这里有坑,长度被修改了,因此+30
contents=bytearray()
for index in range(3,txt_len):
    contents.append(data[index*4])
print(contents)

得到flag:DASCTF{12jkl-456m78-90n1234}

 

 

 

 

 

 

 

 

 

 

 

 

 

赞(0) 打赏
转载请附本站链接,未经允许不得转载,,谢谢:微慑信息网-VulSee.com » [记录] 2024羊城杯部分writeup

评论 抢沙发

微慑信息网 专注工匠精神

微慑信息网-VulSee.com-关注前沿安全态势,聚合网络安全漏洞信息,分享安全文档案例

访问我们联系我们

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册