刚想起来发
user-id:芝士雪豹
雪豹
这道题没啥意思,存粹为了套拿450分。知识点属于重复知识点,见谅:
拿到附件,用360解压缩、winrar打开显示有密码,用7z打开显示为空,猜测是文件结构遭到破坏,用010editor查看后发现该文件出现了3个压缩文件头,而没有一个文件头,用010定位之后将两处0x73修改为0x74
修改完成后即可无密码解压,解压出来一个jpg图片一个压缩包,其中jpg图片备注中写到weak pass
查看jpg结构,发现尾部有一串oursecret特征
弱密码猜测,密码为123456
得到LcWhEQAACMPAWRiOa7DdX8SgngvbeQQ=
,放进cyberchef自动解析,可知是经过base64+raw压缩后的一串字符串,原内容为higher!higher!
但将其作为密码并不能解开压缩包,因此猜测是修改jpg图片的高度,将其随便修改一个较高的高度再去观察图片
解压后得到hint.txt和一个{num}-secret.zip文件,其中hint.txt内容为解题不会一蹴而就,答案隐藏在每个角落
,该hint结合zip文件最内部解压文件一起使用。此时需要对该文件进行解压(代码见后)。解压到最内层得到0.txt,0.txt内容如下:·hint:something fell on the road,the flag is not at the end
,提示flag不在最后面,在路上。意味着解压过程中存在隐写。编写解压代码时经过解压测试发现并没有额外的文件,再任意观察几个zip文件并不能发现有额外的数据,但在观察zip文件属性时,发现修改时间有所不同。
import os
import zipfile
import time
from tqdm import tqdm
flag = ''
for name in tqdm(range(49183,-1,-1)):
filename = f'{name}-secret.zip'
fz = zipfile.ZipFile(filename, 'r')
fz.extractall()
for info in fz.infolist():
t = info.date_time
times = int(time.mktime(t + (0, 0, 0)))
if(times == 1682907238):
flag += '1'
elif (times == 1682907232):
flag += '0'
else:
break
fz.close()
os.remove(filename)
flag = '0' + flag
fw = open('outs.txt','w').write(flag)
约4分钟后即可得到outs.txt文件,将文件内输出的内容放进cyberchef进行转码,该文件开头为1f 8b 08,经查询为gz文件头,保存
解压出来发现是png文件,因此手动加上.png拓展名
这个图很明显是隐写软件ImageIn,使用软件解得到以下内容
🍙🍶📃🛁 😁🐰🐷💺 👎🍏 🏄🙅🍈🍈🐱🌿🐷💀💀🃏☎🎐🐷❤☎👗🐅🐅😲🐅👗☔🚒🐸👎🍏🌿 🃏🍶📃 🌿🐷🚈🎒 🐷 💺🍶🍶🍨 🍨🐷🃏🚇🚇
I forgot my key, but it seems there is still a way
中间有空格,排除emoji-aes,尝试base100也无果,提示有key,可得知是codemoji加密的内容,根据代码编写cracker或用别人写好的进行自动爆破解密即可得到flag(添加链接描述)
哦?摩斯密码?
老折磨了,娓娓道来
首先这个附件能发现创建时间是2022年5月4日,众所周知去年我出的第一个擂台题就是这样的类型,详情可以见ISCC2022 MISC wp
好,那么这里我就直接拿我以前的脚本撸,但是不行。
这里一共思考了7种思路,都不行,结果让他撑到了9点,可惜了。这种题要的就是排除错误的思路
思路0:解摩斯,字频统计,尝试后发现得到一句话,这句话很重要,最后要用,也没有卡住我(后面再说),但是并不是flag,因此排除掉
思路1:读取掩码类型,可能为8进制,尝试后发现掩码等级都是M,然后用了M0 M2 M4 M5 M7,每个文件夹3个图,最多125种可能性,但是一共只有112个排列组合(好像是),因此排除掉
思路2:读取图片种类,猜测为x进制。尝试后发现一共7种,7**3>256,6**3<256,本来以为是7进制,但是实际输出后发现开头的数字从0-6都有,那么6开头必然大于256,所以此思路排除掉
思路3:读取出现的01串,可以发现在思路0中有0和1而不是o和i。因此读取翻译出来的01串,结果是6301个字符,拿去分解发现是质数,如果在开头添上0也不能整除,因此排除掉该思路
思路4:读取摩斯转码后为FLAG的文件夹,并计算间隔。这里我读取了含有摩斯转码后为FLAG的文件夹,例如第2个文件夹含有FLAG,以此类推,然后计算2-0 = 2.编写脚本后测试发现输出1-16,虽然符合16进制但是并不平均,因此排除掉这个思路
思路5:将思路4和思路3结合起来,把出现FLAG的文件夹出现的01串结合起来,发现也无法被8整除
思路6:由于上面字频统计,发现其实除了FLAG以外,其他都是很美观的数字,因此猜测和FLAG有关,但是刚刚已经考虑过很多次了,并且查看了文件夹发现带有FLAG文件时间与其他6种都不同,再发现这里一共有3个文件,结合摩斯密码,猜测并写出以下脚本,其中的库我并没有略掉,是在做上面几种思路时一并带上的
import pyzbar.pyzbar as pyzbar
from PIL import Image
from tqdm import tqdm
import os
from collections import Counter
flag = ''
textment = []
tmp = 0
for i in range(4716):
path = f'./flag/{str(i)}/'
file_list = os.listdir(path)
this_bit = ''
for j in file_list:
img = Image.open(f'{path}{j}')
texts = pyzbar.decode(img)
for text in texts:
if(text[0].decode() == '..-. .-.. .- --.'):
print(j[0],end='')
输出
12222322222322222312222312222312222322222312222312222312222312222322222322222312222312222312222312222322222322222322222312222312222312222322222322222312222312222312222312222322222322222322222312222322222312222322222312222312222322222322222322222322222312222322222312222322222312222322222322222312222312222322222322222312222322222322222312222312222322222322222312222322222322222312222312222322222312222312222322222322222312222312222312222322222312222312222312222312222312222312222312222322222322222322222312222322222322222312222312222322222322222312222312222312222322222322222322222322222312222322222322222312222322222312222312222322222312222322222312222312222312222312222312222312222322222322222312222312222312222322222312222312222322222312222312222322222322222312222312222322222312222322222312222322222312222312222322222322222322222312222322222312222312222322222312222322222322222312222312222312222322222322222312222312222322222312222312222322222322222312222322222312222322222322222312222322222322222312222322222312222312222322222312222312222322222312222312222322222312222322222322222322222312222322222312222322222322222322222312222312222312222312222322222312222322222322222322222312222312222322222322222322222312222312222312222312222312222322222322222322222312222322222322222312222312222312222322222312222312222312222312222322222322222322222312222312222322222322222312222322222322222312222312222322222312222312222322222312222312222312222322222312222312222322222312222312222322222322222312222322222312222312222312222322222312222312222322222322222312222312222312222312222322222322222312222322222312222312222322222312222322222322222312222312222322222312222322222312222322222312222312222322222322222322222312222312222312222312222312222322222312222322222322222312222312222322222322222312222322222322222312222322222312222312222312222312222322222312222
太规整了,然后1转换为. 2转换为- 3作为分隔符,得到
10011101111001111000111001111000101011000010101001100100110010011011001110111111100010011001110000100101101011111100111011011001101010110001011010011100110110010100100101101101101000101000111101000110001111100010011101111000110010011011011101101100101110110011110010110100110101011000111110100110010010111101
发现不能被8整除,但是能被7整除,也就是7bit
直接解base64解不开,猜测要密码,但是不是Salt经过base64开的头,猜测是这个网站http://tool.chacuo.net/cryptaes
然后先尝试了ISCC作为密码不对,又想着之前词频得到一个this no flag,既然不是flag那你一定是key吧,因此作为key得到flag
ඞ
呃,个人感觉出的不是很好(尤其是mod文件夹有我id),其实本来是想拿450的但是没想到4小时半被解了
首先是给了一个内存镜像和一个unity的mod文件夹。
首先分析内存镜像
然后pslist
扫桌面
然后用dumpfiles导出
python /home/mumuzi/volatility/vol.py -f WIN-R9BQP0T43U9-20230504-051452.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000007fd19210 -D ./
python /home/mumuzi/volatility/vol.py -f WIN-R9BQP0T43U9-20230504-051452.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000007d631b90 -D ./
hint的内容为:4 player,1 game.
zip:
解压那个mod后找到plugins文件夹,里面有个TownOfUs.dll,使用dnspy打开逆向.因为提到了伪装者了名字,所以在里面寻找角色
找到TownOfUs.Roles\Impostor
得到密码为susofyou,解开zip,打开压缩包里面的python文件
import hashlib
#analyze the .pcap answer the question
code = '' #join the game's Game code(eg:ABCD)
voted = ''#who was voted in this game(the game's name)(eg:dingzhen)
howtowin = ''#how win this game?choose:(crew_vote/crew_task/imp_vote/imp_task/imp_disconnect/crew_disconnect)(eg:imp_task)
tasks_num = ''#how many tasks were done?(eg:5)
flag = hashlib.md5((code+voted+howtowin+tasks_num).encode()).hexdigest()#eg:md5('ABCDdingzhenimp_task5') = ca90ed3a8c98ef30af3b44643de8512e
print(f'your flag is ISCC{{{flag}}}')#eg:your flag is ISCC{ca90ed3a8c98ef30af3b44643de8512e}
这里提示需要分析pcap文件,再结合之前发现在运行wireshark,因此过滤.pcap文件并导出
拿到out9.pcap,删掉末尾额外的00数据即可开始分析,由于全是UDP流量且不清楚该游戏流量,因此在github上找
这里我不知道有wireshark的插件我淦,我是手动分析的。插件链接:https://github.com/cybershard/wireshark-amongus
发现协议分析wiki:https://github.com/roobscoob/among-us-protocol
首先回答第一个问题,代码是多少
如果用插件能直接看到(后面2 3 4问我都不使用插件分析)
不用插件的话得用脚本
import struct
CHAR_SET = "QWXRTYLPESDFGHUJKZOCVBINMA"
def int_to_code(game_id):
if game_id < -1:
# Version 2 codes will always be negative
first_two = game_id & 0x3FF
last_four = (game_id >> 10) & 0xFFFFF
return ''.join([CHAR_SET[first_two % 26],
CHAR_SET[first_two // 26],
CHAR_SET[last_four % 26],
CHAR_SET[(last_four // 26) % 26],
CHAR_SET[(last_four // 676) % 26],
CHAR_SET[last_four // 17576]
])
else:
return struct.pack("<i", game_id).decode('utf-8')
print(int_to_code(?????????))
但是不知道???的数据,因此查看wiki,可知id是在第7-10字节57 60 d9 81
小端存储,可得0x81d96057
print(2**32 - 0x81d96057)
#2116460457
因此可得???中应该填-2116460457,得到代码为SRLBOW
接着我们要知道每个人的id,通过过滤data.data[14] == 06可知道人物所对应的id,这里我过滤udp.stream eq 2 && data.data[14] == 06
0x08 -> 谁是内鬼
0x0b -> 弗莱格在哪
0x0e -> 弗莱格有两部分
然后这里发现有个用户名ISCC,但是这里没有,说明ISCC是主机
请时刻注意player id、net id的区别
第二问是问谁被投票出去了,能够发现id为0e的人在聊天中发了一句"vote iscc",即弗莱格有两部分发了这句话
然后还能发现一具尸体,是player id为01的,是0e的人报的告
根据以上几个图结合起来可知ISCC被票出去了
第三题问how to win,并且给出了结果。其实根据第二题能够得到是crew_vote,但还是分析一下
过滤一下data.data[5] == 08
可以看见该字节是00,即crew_vote
最后问tasks_num,意思是问做了多少个任务
使用过滤udp.stream eq 6 && data.data[5:5] == 05:57:60:d9:81 && data.data[12]==02 && data.data[14]==01
可以看见id为0e和0b的做了id为01的任务(刷卡),即2个任务
因此得到答案为2
G9的钢琴曲
第一部分是一个密码题,能够搜到是个原题https://www.ctfiot.com/75798.html
然后改一下pad和root = f.small_roots(X=2^472, epsilon=0.03)[0]
,如下,sage使用
from Crypto.Util.number import *
out =[(2172252055704676687457456207934570002654428519127702486311980109116704284191676330440328812486703915927053358543917713596131304154696440247623888101060090049, 2108637380559167544966298857366809660819309447678518955440217990535095703498823529603132157555536540927898101378853427638496799467186376541583898176373756917, 1103840869050032098984210850630584416814272073121760519116633450832540460407682739594980752914408375293588645043889636184344774987897378026909963273402766561), (2000124088829445641229622245114189828522912764366697463519930724825924163986998694550757186794149331654420524788899548639866463311104678617705042675360057243, 1665549488322348612920659576773850703765765307223600084262385091708189142517147893842872604879786471376822691498663100028754092239272226011616462859779271025, 990627294315894701092445987317798430568264256978762186489740206376279178571289900941886873570710241025125621594301020499270029956301204583788447662869037315), (1303516450844607175859180241406482278674954250245197644105258810912430306740632927947088058701010631209652921073238771523431247167608544636294883977018097199, 1119758042346732592435539174564881640374540951155805649314246375263320107846465196580695284748429608544175058830657524095385658523219250943378976577225782230, 598915905620934628053505443816290720352232457144997188593150390072666051798491983452700635551081569466232682512362475354896855707688259553722701065491789402), (2463333340881549805545364706970314608937871808508385657282029236077808399479795853056347857164089991597487727014937851894809199639758978587612411591527423763, 673590616457425981268507673967667728811152404125286063856277932080928372715113304373395326309595915550999528364692493169822993967220858400311382215177833045, 208198360150172881237486434064181246031019081636219908755237161625039285165750040108367852136975511290424988781713799103150982065579123496034803730006273360)]
# clean data
ns = [o[0] for o in out]
rs = [o[1] for o in out]
cs = [o[2] for o in out]
# calculate T_i for each polynomial
calcT = lambda idx : crt([0 if i != idx else 1 for i in range(4)], ns)
# calculate Ts
T = [calcT(i) for i in range(len(ns))]
# construct the final polynomial
f = 0
P.<x> = PolynomialRing(Zmod(prod(ns)))
# use pad to add known bits
pad = bytes_to_long(b'ISCC' + b'\x00' * 59)
m = x + pad
# construct g(x)
for i in range(4):
f += T[i] * (m^4 + 3*m^2 + rs[i]*m - cs[i])
root = f.small_roots(X=2^472, epsilon=0.03)[0]
m = m(root)
print(long_to_bytes(int(m)))
解完得到密码ISCC_Y0u_R3alLy_KnOw_CoPPersm1th
然后得到一个压缩包和一个hint.txt,说实话看不出来hint.txt是个什么东西,但是压缩包是个很明显的使用Cloakify加密的,因此使用其解python3 .\decloakify.py .\music.rar .\ciphers\desserts outs.rar
解出来发现是个wav,不过不重要了。查看文件结构发现开头有-和+
猜测是转01
只不过没想到出题人到这一步就没有继续套了。
BNG
首先观察文件头,能够发现蓝色部分是bzip文件头,开头是PNG改过的文件头,接着红框部分09应该是代表IHDR的长度,后面的0x6b 0x60分别代表宽高,再下一个字节0x18暂且理解成24位(RGB)
接着蓝框前面有个0x065e,根据bzip的长度可以得知0x065e是bzip的数据块长度,接着看文件尾
通过长度计算得知,从红框部分开始就不属于bzip数据,再观察几个bng文件能够发现红框的第一个字节一直处于可打印字符范围,将其打印出来
passwd = ''
for i in range(472):
f = open(f'./bngs/{i}.bng', 'rb').read()
passwd += chr(f[-15])
print(passwd)
得到Vm1wR2EwNUhTWGxVYms1cFRUSjRWbFl3WkRSWFJteHpZVVZPYWxadGVIcFdNbmgzWVRBeFZrNVdaRnBXVmxwUVdWVmFTbVF3TVZWWGJHUlRUVEJLVVZkV1dsWmtNbEY1Vkd0c1ZHSkdXazlaVjNSaFYwWmFSMVp0Um1wTmF6VllWVEkxVTJFeFNsVldiVGxhWWtkU2RscFdXbHBsVjFKSFZHeHdWMDFHY0RWV1JscGhWakZhZEZOc1ZsTmlSVnBZV1ZSS1UyTldVbGRYYkU1WFZtczFlbFl5TVRSV01WcEhWMnhrVjJKVVFqUlVWVnBTWlVaT2NscEhjRlJTVkZaYVYxWlNSMU14U1hoVmJrNVhWMGRvY1ZacVFscE5iRnBYVlZoa1VWVlVNRGs9
解多次base64得到my secret password:e4b1d28dd6c14f9893e255d46ed19298
根据猜测和思路分析,这些png图片恢复之后可能存在隐写或者OCR,首先提取出bzip部分并修改为.bz2解压,得到以下数据(这里以0.bng、1.bng为例)
可以观察到开头第一个字节随机,接着几个字节固定然后到第一行最后一个字节FF
根据题目描述,抄的png部分应该是png头+IHDR+DATA(bz2)+IEND
而jpg部分为DEFLATE,根据猜测是huffman。
然后根据分析,第二个字节0x0d代表的是huffman tree size,紧接着的0xd字节代表huffman tree length,再后面的数据是文件的数据,即前面部分抄的是jpg的DHT部分,至于为什么有那么多00字节,是因为没有经过游程编码来进行预处理
这里能够找到网上的一份脚本https://www.cnblogs.com/kentle/p/14725589.html
根据脚本分析,第一个字节是padding字节。
即padding + ht_size + ht_length + data
将脚本里的OVO.py抄下来保存为OVO.py,接着自己写一份脚本(注意创建imgs文件夹)
然后得到的图片发现是0-f,因此使用easyocr进行ocr,
import bz2
import zlib
from OVO import OVO
import os
from PIL import Image
from tqdm import tqdm
import struct
import easyocr
for i in tqdm(range(472)):
f = open(f'./bngs/{i}.bng', 'rb').read()
h,w = f[0xf],f[0xb]
length = f[0x17]*256+f[0x18]
bz2_data = f[0x19:0x19+length]
decompressed_bz2 = bz2.decompress(bz2_data)
fw = open(f'./imgs/{i}.data','wb').write(decompressed_bz2)
OVO.decode(source_path=f'./imgs/{i}.data', target_path=f'./imgs/{i}_dec.data', mode=0)
ft = open(f'./imgs/{i}_dec.data','rb').read()
img = Image.new('RGB', (w, h))
for y in range(h):
for x in range(w):
index = (y * w + x) * 3
r, g, b = struct.unpack('BBB', ft[index:index + 3])
img.putpixel((x, y), (r, g, b))
img.save(f'./imgs/{i}_.png')
os.remove(f'./imgs/{i}.data')
os.remove(f'./imgs/{i}_dec.data')
data = ''
reader = easyocr.Reader(['en'])
for j in tqdm(range(472)):
result = reader.readtext(f'./imgs/{j}_.png')
try:
data += result[0][1]
except:
data += f'_{j}_'
print(data)
由于不知道为什么某些数字0和数字7会识别不出来,只能手动替换部分
经过替换之后,得到504b03040a00090000004061a656d31bd66C360000002a00000008001C00666C61672e747874555409000317d3556417d3556475780b000104e803000004e803000065f41ee96387be9dfCb9083dde5b2ad9d9a1757831ef8091d9621d9147dCCed1d3984835b90740bda12Cd9d3d696e0937995a3ad70ed504b0708d31bd66C360000002a000000504b01021e030a00090000004061a656d31bd66C360000002a000000080018000000000001000000ff8100000000666C61672e747874555405000317d3556475780b000104e803000004e8030000504b050600000000010001004e000000880000000000
解hex之后再使用之前得到的密码,即可得到flag
听你心跳里的狂
第一部分很简单,能够发现flaggg大小是正正好好的10mb,且字节随机无意义,尝试xor也不能得到东西,猜测为加密磁盘,这里使用veracrypt,将音频文件作为秘钥文件成功挂载
使用winhex分析发现该磁盘删除了一个文件,但是和现有的文件除了最后有32字节的信息外没有差别,意思是不需要再去分析该部分。直接打开磁盘得到一个加密压缩包,文件尾有32字节字符,根据特征猜测为md5值,因为有特殊符号因此考虑xor和rot47,在rot47之后特殊符号能变成数字,但是其他的某些会变成?,因此猜测是先rot13再rot47,得到9a2126552a9de60d20d95a47f85a16fd
,使用somd5解md5得到Logistic
,得到的600.png发现是经过正常png xor 0x15得到的,经过xor 0x15恢复png
能够发现该图是一张RGBA图,且对图片反色后能够隐约看见flag
根据之前解md5得到的字符串,能够知道是使用了Logistic 置乱。
但是根据我理解的,这里不清楚参数和初始值,给的600猜测是最后的xn的值,根据常见的参数,猜测x0属于0.1~0.9,r属于3.5~4.0
写个脚本进行爆破
from PIL import Image
import numpy as np
def logic_encrypt(im, x0, mu):
xsize, ysize = im.size
im = np.array(im).flatten()
num = len(im)
for i in range(600):
x0 = mu * x0 * (1 - x0)
E = np.zeros(num)
E[0] = x0
for i in range(0, num - 1):
E[i + 1] = mu * E[i] * (1 - E[i])
E = np.round(E * 255).astype(np.uint8)
im = np.bitwise_xor(E, im)
im = im.reshape(ysize, xsize, -1)
im = np.squeeze(im)
im = Image.fromarray(im)
return im
im = Image.open("download.png")
from tqdm import tqdm
for x in tqdm(range(0, 11, 1)):
x0 = round(x / 10, 1)
for y in range(35, 41, 1):
mu = round(y / 10, 1)
im_en = logic_encrypt(im, x0, mu)
im_en.save(f'./out/{x0}_{mu}.png')
最后在n = 600 r = 3.7 x0= 0.5时得到原图
Brain Games
压缩包有密码,发现是aaencode,但是有很多?,而看了一下常见的都是一个゚
,因此替换一下然后解aaencode,得到Peace_And_Love
生成密码后,这里用stegsolve观察能看到貌似有LSB,猜测是加密的LSB
然后根据下面的123和上面子弹射的痕迹,猜测密码是135780的排列组合中的其中一个
import itertools
f = open('passwd.txt','w')
for i in itertools.permutations("135780", 6):
f.write(''.join(i) + "\n")
那就只能爆破cloacked-pixel,在cloacked-pixel文件夹下再创建一个爆破.py脚本文章来源:https://www.toymoban.com/news/detail-462574.html
from lsb import extract
import os
from tqdm import tqdm
hidden_img = 'ATM.png'#image file path
codebook = 'passwd.txt'#password path
passwd = open(codebook,'r').read().splitlines()
os.mkdir(hidden_img[:-4])
for i in tqdm(range(len(passwd))):
out_path = hidden_img[:-4]+'/'+passwd[i]+'.txt'
extract(hidden_img, out_path, passwd[i])
最后在密码为570831时得到有意义字符,为8ae511cd0026edf90ced84dd12f6d1d30fe3e486131c31501300014b2bacb4d202
然后这个地方贼傻逼,答案是From Hex之后再To base85
乐死了,上一次见的时候还是在ctfshow群友挑战的两层被子,当时题目明确表明了是base,你这什么都没有怎么猜的出来
S改成}即可文章来源地址https://www.toymoban.com/news/detail-462574.html
到了这里,关于ISCC2023 擂台misc wp的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!