Featured image of post uoftctf-2025 misc支线

uoftctf-2025 misc支线

看看misc怎么写

misc 赏玩

隔壁web有一个点卡了7,8个小时怎么也过不去,过来misc逃避一下现实

Surgery

上来直接开盒这么刺激吗😖

第三个小哥年少有为啊

Math-test

小北计算器还在追我tmd😡

这个题为了调试脚本我把他改成5次计算了,因为是第一次写两个进程的交互所以我还是想深入学一下这个写法的

先看一下题目脚本的执行逻辑,弹出

1
2
Question: {计算式}
Answer: {用户输入}

那我就需要写一个脚本可以捕获隔壁输出计算出结果再输出到隔壁。这里需要用到一个叫 Pexpect 的库,他可以使代码完成交互使任务,ai如是说:

  1. 启动程序:它可以运行任何命令行程序,比如 sshftpgit,或者我们这里的 python chall.py
  2. “看到”输出:它可以读取被它启动的程序的输出文本,就像我们用眼睛看屏幕一样。
  3. “等待”提示:这是Pexpect最强大的地方。它可以等待特定的文本模式(比如一个登录提示 login: 或者一个问题 Question:)出现。这使得自动化脚本能够与程序同步,在正确的时间做出正确的反应。
  4. “输入”指令:它可以向被控制的程序发送文本,就像我们用键盘输入命令然后按回车一样。

看一下脚本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import sys
import pexpect

child = pexpect.spawn(f'{sys.executable} chall.py')  # 启动任务程序

child.logfile_read = sys.stdout.buffer  # 让对面的程序的输出也显示在屏幕上

for i in range(5):
    child.expect("Question:")   # 等待 Question

    eqn = child.readline().decode('utf-8').strip()  # 提取表达式

    print(f"Received equation:{eqn}")

    result = eval(eqn)
    print(f"Cal result:{result}")

    child.sendline(str(result)) # 将表达式输出到父进程,我这样说对吗🤔


child.expect(pexpect.EOF)  # 确保退出

Racing-1

第一次知道docker还能连接ssh

连上去看看什么情况

看看C代码

1
2
3
4
5
6
char *fn = "/home/user/permitted";

if (!access(fn, R_OK)) // 判断是否有read /home/user/permitted 的条件,如果有 "access(fn, R_OK)" 返回0,好怪啊
{
  if (strstr(f, "flag") != NULL) // 软链接
}

但是没有这个文件

直接执行文件报错

1
2
user@e73f3cd3fc1f:/challenge$ ./chal 
Cannot read file.

那我手动创建一个不就行了吗🤓☝️

这也没拦着我啊,何eva?

然后去看了一下WP,本质还是创建符号链接,但又利用了代码里的其他逻辑,好像还复杂了

1
2
3
4
5
6
7
8
user@e73f3cd3fc1f:~$ /challenge/chal
Enter file to read: ^Z
[1]+  Stopped                 /challenge/chal
user@e73f3cd3fc1f:~$ ln -sf /flag.txt ~/permitted
user@e73f3cd3fc1f:~$ fg
/challenge/chal
               
uoftctf{r4c3_c0nd1t10n5_4r3_c00l}

所以何eva

Poof

ai率百分百的侦探游戏

这个题我就wireshark还会用一点,其他全不了解,都是ai给我干的

侦查阶段学到一个非常好用的命令

1
tshark -r poof.pcapng --export-objects http,exported_files/  

这个命令可以自动提取流http协议中出现的文件,不需要追踪和去除多余信息

主要得到的是两个文件

  • kcaswqcd.ps1 一个高度混淆的PowerShell脚本
  • 82nvdkandf.bin 加密的二进制恶意文件

ai根据整个流量包分析出这是可能是一个钓鱼攻击,下载到木马的记录。

受害者下载并运行 kcaswqcd.ps1 脚本,这个脚本它立即向服务器发起新的请求,下载,解密并执行最终的恶意文件82nvdkandf.bin。

绕这么一大圈就是一方面通过加密能绕过防御,另一方面有一个触发的trigger,还是很精彩的攻击的,还原也很有意思,像是在玩侦探游戏

然后可以让ai根据 kcaswqcd.ps1 的逻辑写一个解密 82nvdkandf.bin 的脚本,因为我不是学密码的就不研究这个了,只贴出来供读者参考:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import os

def decrypt_file(hex_payload_file, decrypted_file):
    
    key = "sksd89D2G0X9jk2fF1b4S2a7Gh8aVk0L".encode('utf-8')
    iv = "Md33eFa0ZwNx2qY1"[0:16].encode('utf-8')

    if not os.path.exists(hex_payload_file):
        print(f"[!] 错误: 十六进制载荷文件 '{hex_payload_file}' 不存在!")
        return

    print(f"[*] 正在读取十六进制载荷文件: {hex_payload_file}")
    with open(hex_payload_file, 'r') as f:
        hex_payload_raw = f.read()
    
    hex_payload_clean = "".join(hex_payload_raw.split())
    
    encrypted_bytes = bytes.fromhex(hex_payload_clean)
    
    print(f"[*] 正在使用正确的密钥和IV进行解密...")
    try:
        cipher = AES.new(key, AES.MODE_CBC, iv)
        decrypted_data = unpad(cipher.decrypt(encrypted_bytes), AES.block_size)
    except ValueError as e:
        print(f"[!] 解密失败: {e}")
        return
        
    print(f"[*] 正在将解密后的内容写入: {decrypted_file}")
    with open(decrypted_file, 'wb') as f:
        f.write(decrypted_data)
        
    print("\n[+] 解密成功!")
    print(f"    最终的载荷已经被保存为 '{decrypted_file}'。")


if __name__ == "__main__":
    decrypt_file("82nvdkandf.bin", "decrypted_payload.exe")

侦查一下我们解密得到的可执行文件

1
2
file decrypted_payload.exe
decrypted_payload.exe: PE32 executable for MS Windows 4.00 (console), Intel i386 Mono/.Net assembly, 3 sections

是.Net文件,当然我不知道他是干什么的,我去搜了一下,发现完全是另一个世界的东西,跟他有关的编译工具还要下载他家的全家桶,还必须是老版本,更不想知道他是干什么的了,不过我还是搞到了可以反编译这个文件的工具。

1
ilspycmd -p -o decompiled_project decrypted_payload.exe

得到的文件我不贴了,因为看到了那个文件,ai直接给我了最后得到flag的脚本,好像还是一个解密,因为这不是我的方向所以我也不深究了。附带脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
encrypted_shellcode = [
    129, 149, 255, 125, 125, 125, 29, 244, 152, 76,
    189, 25, 246, 45, 77, 246, 47, 113, 246, 47,
    105, 246, 15, 85, 114, 202, 55, 91, 76, 130,
    209, 65, 28, 1, 127, 81, 93, 188, 178, 112,
    124, 186, 159, 143, 47, 42, 246, 47, 109, 246,
    55, 65, 246, 49, 108, 5, 158, 53, 124, 172,
    44, 246, 36, 93, 124, 174, 246, 52, 101, 158,
    71, 52, 246, 73, 246, 124, 171, 76, 130, 209,
    188, 178, 112, 124, 186, 69, 157, 8, 139, 126,
    0, 133, 70, 0, 89, 8, 153, 37, 246, 37,
    89, 124, 174, 27, 246, 113, 54, 246, 37, 97,
    124, 174, 246, 121, 246, 124, 173, 244, 57, 89,
    89, 38, 38, 28, 36, 39, 44, 130, 157, 34,
    34, 39, 246, 111, 150, 240, 32, 23, 124, 240,
    248, 207, 125, 125, 125, 45, 21, 76, 246, 18,
    250, 130, 168, 198, 141, 200, 223, 43, 21, 219,
    232, 192, 224, 130, 168, 65, 123, 1, 119, 253,
    134, 157, 8, 120, 198, 58, 110, 15, 18, 23,
    125, 46, 130, 168, 30, 16, 25, 93, 82, 30,
    93, 19, 24, 9, 93, 8, 14, 24, 15, 93,
    17, 24, 26, 20, 9, 8, 14, 24, 15, 93,
    8, 18, 27, 9, 30, 9, 27, 6, 42, 73,
    14, 34, 76, 41, 34, 47, 78, 28, 17, 17,
    4, 34, 28, 51, 34, 52, 16, 13, 17, 73,
    19, 9, 66, 66, 0, 93, 82, 28, 25, 25,
    93, 82, 4, 125
]

key = 125

decrypted_shellcode = []

for byte in encrypted_shellcode:
    decrypted_byte = byte ^ key
    decrypted_shellcode.append(decrypted_byte)

flag = bytearray(decrypted_shellcode).decode('ascii', 'ignore')

print("--- Decrypted Shellcode ---")
print(flag)

最后最重要的一点,滚快照清除我的新旧.Net全家桶

再见了,所有的.Net工具👋

你好,这是一个随便写写,随便看看的无聊而与我很重要的网站。
使用 Hugo 构建
主题 StackJimmy 设计