DubheCTF 2024

咱就是说,上次XCTF得甲流,这次二阳,真会挑时候啊,拢共做了一道半(签到没抢上🤭),属实是废了

Misc

ezPythonCheckin

  • payload,正准备绕呢,学弟就秒了,真是简单粗暴啊,怎么flag名字都不改的
print(open('/flag').read())

cipher

  • Advanced EFS Data Recovery,考验选手搜索能力(,不知道用户密码没关系,导入一个top100字典即可,或者查看powershell历史记录
Users\test\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

cd C:\users\test\Desktop\
.\test2
cd C:\Users\test\Documents
.\test2
ipconfig /all
ipconfig
ping 192.168.17.140
net user
net user john john@123 /add
net user john superman /add
net user mark superman /add
net user ronnie superman /add
net user judd superman /add
net user neil superman /add
net user
net user steve superman /add
  • 正经做法,贴一个,方便后续观摩(偷!
# https://lilachit.notion.site/Lilac-2024DubheCTF-wp-caa603fa40ba4699982a13ddf062906a#1b970b22b5e04cb98a5e02cb2f688a4a
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

with open('private.pem', 'rb') as key_file:
    private_key = serialization.load_pem_private_key(key_file.read(), password=None)
with open('$EFS', 'rb') as EFS_file:
    efs = EFS_file.read()

'''
typedef struct
{
	DWORD		AttributeLength;
	DWORD		State;
	DWORD		Version;
	DWORD		CryptoAPIVersion;
	BYTE		Checksum[16];
	BYTE		ChecksumDDF[16];
	BYTE		ChecksumDRF[16];
	DWORD		OffsetToDDF;
	DWORD		OffsetToDRF;
} MFT_RECORD_ATTRIBUTE_EFS_HEADER, * PMFT_RECORD_ATTRIBUTE_EFS_HEADER;
'''
OffsetToDDF = int.from_bytes(efs[0x40:0x44], byteorder='little')
print(f'OffsetToDDF: {hex(OffsetToDDF)}')

'''
typedef struct {
	DWORD		Count;
} MFT_RECORD_ATTRIBUTE_EFS_ARRAY_HEADER, * PMFT_RECORD_ATTRIBUTE_EFS_ARRAY_HEADER;
'''

Count = int.from_bytes(efs[OffsetToDDF:OffsetToDDF+4], byteorder='little')
print(f'Count: {Count}')
assert Count == 1, 'Count != 1 unsupported for now'

'''
typedef struct {
	DWORD		Length;
	DWORD		CredentialHeaderOffset;
	DWORD		FEKSize;
	DWORD		FEKOffset;
} MFT_RECORD_ATTRIBUTE_EFS_DATA_DECRYPTION_ENTRY_HEADER, * PMFT_RECORD_ATTRIBUTE_EFS_DATA_DECRYPTION_ENTRY_HEADER;
'''
entry_header = efs[OffsetToDDF+4:OffsetToDDF+4+16]
Length = int.from_bytes(entry_header[0:4], byteorder='little')
print(f'Length: {hex(Length)}')
CredentialHeaderOffset = int.from_bytes(entry_header[4:8], byteorder='little')
print(f'CredentialHeaderOffset: {hex(CredentialHeaderOffset)}')
FEKSize = int.from_bytes(entry_header[8:12], byteorder='little')
print(f'FEKSize: {FEKSize}')
FEKOffset = int.from_bytes(entry_header[12:16], byteorder='little') + OffsetToDDF + 4
print(f'FEKOffset: {hex(FEKOffset)}')

encrypted_fek = efs[FEKOffset:FEKOffset+FEKSize][::-1]
decrypted_fek = private_key.decrypt(encrypted_fek, padding=padding.PKCS1v15())
'''
typedef struct {
	DWORD	KeyLength;
	DWORD	Entropy;
	ALG_ID	Algorithm;
	DWORD	Reserved;
	BYTE	Key[1];
} EFS_FEK, * PEFS_FEK;
'''
KeyLength = int.from_bytes(decrypted_fek[0:4], byteorder='little')
print(f'KeyLength: {KeyLength}')
Algorithm = int.from_bytes(decrypted_fek[8:12], byteorder='little')
print(f'Algorithm: {hex(Algorithm)}')
key = decrypted_fek[16:16+KeyLength]
assert 16 + KeyLength == len(decrypted_fek)

def decrypt_block(data_block, fek_key, index, cluster_size):
    iv = bytearray(b'\0' * 16)
    offset = index * cluster_size
    iv[0:8] = (int.from_bytes(iv[0:8], byteorder='big') + offset).to_bytes(8, byteorder='big')
    iv[8:16] = (int.from_bytes(iv[8:16], byteorder='big') + offset).to_bytes(8, byteorder='big')
    cipher = Cipher(algorithms.AES(fek_key), modes.CBC(bytes(iv)))
    decryptor = cipher.decryptor()
    return decryptor.update(data_block) + decryptor.finalize()

def decrypt_file(input_file_path, output_file_path, fek_key, cluster_size=4096):
    with open(input_file_path, 'rb') as input_file, open(output_file_path, 'wb') as output_file:
        index_block = 0
        while True:
            data_block = input_file.read(cluster_size)
            if not data_block:
                break
            decrypted_data = decrypt_block(data_block, fek_key, index_block, cluster_size)
            output_file.write(decrypted_data)
            index_block += 1

decrypt_file('flag.jpg.enc', 'flag.jpg', key)
  • 相关链接
https://tinyapps.org/docs/decrypt-efs-without-cert-backup.html

authenticated mess & unauthenticated less

  • 流量包里得到一些明文信息
{
    "log": {
        "loglevel":"debug"
    },
    "inbounds": [
        {
            "port": 1080, // SOCKS 代理端口,在浏览器中需配置代理并指向这个端口
            "listen": "127.0.0.1",
            "protocol": "socks",
            "settings": {
                "udp": true
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vmess",
            "settings": {
                "vnext": [
                    {
                        "address": "1.95.11.7", // 服务器地址,请修改为你自己的服务器 ip 或域名
                        "port": 40086, // 服务器端口
                        "users": [
                            {
                                "id": "f3a5cae3-6bd2-40d1-b13b-2cc3d87af2c7",
                                "security":"auto"
                            }
                        ]
                    }
                ]
            }
        }
    ]
}
  • 查了个dns:p.sda1.dev,一个图床,猜猜流量是个图
  • 参考22年强网杯谍影重重写一下解流量的脚本:https://wkr.moe/ctf/822.html,要把对于时间的校验删掉proxy/vmess/aead/authid.go
package main

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"github.com/v2fly/v2ray-core/v5/common"
	"github.com/v2fly/v2ray-core/v5/common/protocol"
	"github.com/v2fly/v2ray-core/v5/proxy/vmess"
	. "github.com/v2fly/v2ray-core/v5/proxy/vmess/encoding"
	"io"
)

func toAccount(a *vmess.Account) protocol.Account {
	account, err := a.AsAccount()
	common.Must(err)
	return account
}

func main() {
	user := &protocol.MemoryUser{
		Level: 0,
		Email: "",
	}
	account := &vmess.Account{
		Id:      "f3a5cae3-6bd2-40d1-b13b-2cc3d87af2c7",
		AlterId: 0,
	}
	user.Account = toAccount(account)

	userValidator := vmess.NewTimedUserValidator(protocol.DefaultIDHash)
	userValidator.Add(user)
	defer common.Close(userValidator)

	sessionHistory := NewSessionHistory()
	defer common.Close(sessionHistory)

	server := NewServerSession(userValidator, sessionHistory)

	requestHex := "b6a64e055daca4fd0846544957e32cdabd6fa5213912538bc0a1657b023de2066672b7434aca736e9fd343e61be4707c7d8cecf526b4faba3d2798755a0510cdd84fb395659798fe67827ff578fbe58674f1fb534477c1e249100b7d2742df1456b15c26dd1666805bf25a2e46ef169996a046f8c23856e51ea0cbb17007c26f45c488bd8a02b4c8dc304d887cd939c2caa65dc7394c980f2446f014a29e41fa1729cda99db16454873525f9fc05dbf738dd4f6c0a17164c57146e867ddaf830d4bf4b3eeed61766e1f4b1cd2cbc84838feaaf04c896544a877974b52fd7aceb08feb5cb98454c83636ffd7c0e7e34ef939841ad7ee710c04fc65ad7ab208d26b9026620b8bc0dd77ef21afdb6c5d4cdaec4bb61a9ae5d01785bb887"
	requestBuffer, _ := hex.DecodeString(requestHex)
	requestBufferReader := bytes.NewReader(requestBuffer)

	requestHeader, err := server.DecodeRequestHeader(requestBufferReader)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(requestHeader)
	requestBody, err := server.DecodeRequestBody(requestHeader, requestBufferReader)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(requestBody)
	for {
		requestBodyBuffer, err := requestBody.ReadMultiBuffer()
		if err != nil {
			if err == io.EOF {
				break
			} else {
				fmt.Println(err)
			}
		}
		fmt.Println(requestBodyBuffer.String())
	}
}
// proxy/vmess/aead/authid.go
func (a *AuthIDDecoderHolder) Match(authID [16]byte) (interface{}, error) {
	for _, v := range a.decoders {
		t, z, _, d := v.dec.Decode(authID)
		if z != crc32.ChecksumIEEE(d[:12]) {
			continue
		}

		if t < 0 {
			continue
		}

                // 为 false 即可
		if math.Abs(math.Abs(float64(t))-float64(time.Now().Unix())) < 0 {
			continue
		}

		if !a.filter.Check(authID[:]) {
			return nil, ErrReplay
		}

		return v.ticket, nil
	}
	return nil, ErrNotFound
}
  • 得到图片地址
GET /16/11c111ee40a928d5d751dd5869414093/__p0.png HTTP/1.1
Host: p.sda1.dev
User-Agent: curl/8.5.0
Accept: */*
  • 搜了一下,pixiv上找到原图,图片url后那串数即为附加压缩包的密码:116921220,得到一个项目(通宵了一下,做到这儿脑子已经混了,探服务探了好一阵儿,再加上已经第二天8点多了,就摆烂了),EDtunnel,一个轻量的代理,使用了wrangler,代理两次将其调试端口代理出来即可
  • 再偷wm
{
    "log": {
        "loglevel": "debug"
    },
    "inbounds": [
        {
            "port": 1081,
            "listen": "0.0.0.0",
            "protocol": "socks",
            "settings": {
                "udp": true
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "172.20.0.2",
                        "port": 8787,
                        "users": [
                            {
                                "encryption": "none",
                                "id": "5e5e7b9a-a251-441b-a81b-9d5b8a8f9019"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "ws",
                "tlsSettings": {
                    "disableSystemRoot": false
                },
                "wsSettings": {
                    "headers": {
                        "Host": "172.20.0.2:8787"
                    },
                    "path": "/?ed=2048"
                },
                "xtlsSettings": {
                    "disableSystemRoot": false
                }
            }
        }
    ]
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇