摸了个第三?也顺便加了好多师傅的 QQ。隔壁同时进行的 SICTF 比 VNCTF 卷多了,在 SICTF 我还不如新生🤣
# Reverse
# TBXO
用 eax 和栈实现的控制流,汇编层面动态调试起来,不难找到主要逻辑在 sub_9610F4 处,写出解密程序。
#include <stdio.h> | |
int main() { | |
unsigned char cipher[] = | |
{ | |
0x10, 0x30, 0x36, 0x31, 0x23, 0x86, 0x93, 0xAD, 0xC5, 0xD4, | |
0x92, 0x84, 0x66, 0xE3, 0x67, 0x75, 0x6B, 0x69, 0x86, 0xC7, | |
0x31, 0x2E, 0x09, 0xA0, 0x33, 0x57, 0x69, 0xDB, 0x93, 0xA8, | |
0x13, 0xDD, 0x3E, 0xA5, 0xD8, 0x88, 0x37, 0x54, 0x84, 0x7E}; | |
for(int i=0; i<5; i++) { | |
unsigned int d = 0; | |
for (int i = 0; i < 32; i++) | |
d -= 0x61c88647; | |
unsigned int r = ((unsigned int*)cipher)[2*i+1]; | |
unsigned int l = ((unsigned int*)cipher)[2*i]; | |
for(int j=0; j<32; j++) { | |
r -= ((l + d) ^ ((l << 4) + 0x79645f65) ^ ((l >> 5) + 0x6b696c69) ^ 0x33); | |
l -= ((r + d) ^ ((r << 4) + 0x67626463) ^ ((r >> 5) + 0x696d616e) ^ 0x33); | |
d += 0x61c88647; | |
} | |
((unsigned int*)cipher)[2*i] = l; | |
((unsigned int*)cipher)[2*i+1] = r; | |
} | |
printf("%s\n", cipher); | |
return 0; | |
} |
🚩 VNCTF{Box_obfuscation_and_you_ar_socool}
# baby_c2
流量中只关注 192.168.218.1 与 192.168.218.129 的 TCP 流量即可,第 84 条记录有 D 盘的文件列表(flag.txt 为 43 字节),第 121 条记录有 flag.txt 的加密数据(长度 43),从流量包本身信息可以知道当天是 2 月 7 日。
ps1 脚本,解 base64 的部分可以去掉 iex 然后丢进 powershell 跑,最后一层是写一个 PE 文件到 %temp%\169sdaf1c56a4s5da4.bin
。
NOP 掉 40131F 处的 call 和 ret、创建函数即可反编译。在 405178 和 405088 处会传入文件名,对文件进行加密,然后再传输。
长度不变的加密方式,猜一个异或,猜一个 RC4
但我没找到 RC4 的实现在哪里,对 405178 和 405088 处逐字节异或日期 207 后,只得到了无意义递减字节。等一个 WP。
后记:
一方面是要异或 217,另一方面是我 IDAPython 脚本写错了,get_db_byte 写成 byte_value 了(捂脸)
def my_patch(frm, sz, byt): for i in range(frm, frm+sz): idc.patch_byte(i, idc.get_db_byte(i) ^ byt) my_patch(0x405088, 234, 217) my_patch(0x405178, 206, 217)然后转换为未定义(U),转换为代码(C),创建函数(P),反编译(F5)。
🚩 vnctf{84976be3-9809-4a3b-9711-51621e388286}
# Crypto
# SignAhead
套路题,哈希长度扩展攻击
直接用 https://github.com/JoyChou93/md5-extension-attack ,md5pad.py 修改成用 pwntools 自动交互,Python2 运行。
import md5py | |
import hashlib | |
import struct | |
from pwn import * | |
def payload(length, str_append): | |
pad = '' | |
n0 = ((56 - (length + 1) % 64) % 64) | |
pad += '\x80' | |
pad += '\x00'*n0 + struct.pack('Q', length*8) | |
return pad + str_append | |
def hashmd5(str): | |
return hashlib.md5(str).hexdigest() | |
context.log_level = 'debug' | |
c = remote('manqiu.top', 21926) | |
for _ in range(100): | |
c.recvuntil('msg: ') | |
msg = c.recvline().strip() | |
c.recvuntil('sign: ') | |
hash_origin = c.recvline().strip() | |
str_append = "LilRan :)" | |
lenth = 96 | |
m = md5py.md5() | |
str_payload = payload(lenth, str_append) | |
c.recvuntil('msg: ') | |
c.send(msg) | |
for i in str_payload: | |
c.send(hex(ord(i))[2:].zfill(2)) | |
c.sendline() | |
c.recvuntil('sign: ') | |
c.sendline(m.extension_attack(hash_origin, str_append, lenth)) | |
print c.recvall() |
🚩 VNCTF{append_key_instead_of_message#6603db4e}
# Misc
# ez_msb
GNU Radio,启动!
原 wav 数据按位与 11111001,flag 平铺到 00000??0。在 wav 刚开始零点几秒还没有音乐,直接把 flag 那条路逆过来走就行,可以得到纯净的 flag。后面有音乐的位置就是乱码了,并且不懂各种数据类型是怎么转换的,等一个 WP。
🚩 VNCTF{gnuradio_best_radio_3de8b}
# LearnOpenGL
这个好好玩,做得很精致😆
透过墙上缺的一个洞可以看见白色的线条,而背景图素材上没有,所以 flag 图层在背景图和砖块之间。想办法把砖块隐藏。
翻文件夹,多次尝试,发现这样 patch 一下就行。
🚩 VNCTF{T3xtur3_M45t3r_0r_r3v_g405h0u_8703d0ccfef0}
# sqlshark
上次做盲注流量还是在上次我第一次参加 CTF 的时候,那时我还手动写了一页 A4 纸,好怀念啊。这次用 b 神的轮子了。
from FlowAnalyzer import FlowAnalyzer | |
pth = FlowAnalyzer.get_json_data('Misc/sqlshark/sqlshark.pcap', 'http') | |
for count, dic in enumerate(FlowAnalyzer(pth).generate_http_dict_pairs()): | |
response_num, response_data = dic['response'] | |
request = dic.get("request") | |
if not request: | |
continue | |
request_num, request_data = request | |
if b'success!' in response_data and b'leAst' not in request_data: | |
dat = int(request_data.decode().split(r'%29%29%29%29in%28')[1].split(r'%29%29%29')[0]) | |
print(chr(dat), end='') | |
# admin_p@ssw0rd |
🚩 VNCTF{admin_p@ssw0rd}
# 问卷调查
🚩 VNCTF{wen_juan_diao_cha}
# Web
# Checkin
出题人电脑的 F12 按键坏了,你能帮他按一按吗
🚩 VNCTF{W31c0m3_t0_VNCTF_2024_g@od_J0B!!!!}