数据分析
server_logs
Challenge
某服务器在2023-06-15 02:00-04:00期间被入侵,请分析日志并回答:
- 攻击者使用的SSH用户名和IP
- 植入的恶意服务名称
- 泄露机密文件时使用的DNS域名
提交形式:flag{SSH用户名_IP_恶意服务名称(不包括后缀)_DNS域名(固定部分)}
Solution
/var/log/auth.log的第201行找到攻击者使用的SSH用户名和IP分别是attacker和192.168.42.77
Jun 15 02:30:15 server sshd[5678]: Accepted password for attacker from 192.168.42.77 port 1337/var/log/syslog的第501-502行找到植入的恶意服务名称是hidden_backdoor
Jun 15 02:35:15 server systemd[1]: Started hidden_backdoor.serviceJun 15 02:35:15 server hidden_backdoor: listening on [any] 31337 .../var/log/dnsmasq.log的第601-604行找到泄露机密文件时使用的DNS域名为data.leak.ev
Jun 15 02:40:15 dnsmasq[123]: query[A] CiAgICByb290Oio6MTk0Nzk6MDo5OTk5OTo3Ojo6.data.leak.ev from 192.168.42.77Jun 15 02:40:17 dnsmasq[123]: query[A] CmRhZW1vbjoqOjE5NDc5OjA6OTk5OTk6Nzo6Ogph.data.leak.ev from 192.168.42.77Jun 15 02:40:19 dnsmasq[123]: query[A] dHRhY2tlcjokNiRzZWNyZXQkZW5jcnlwdGVkcGFz.data.leak.ev from 192.168.42.77Jun 15 02:40:21 dnsmasq[123]: query[A] c3dvcmQ6MTk0Nzk6MDo5OTk5OTo3Ojo6CiAgICA.data.leak.ev from 192.168.42.77拼起来得到flag
flag{attacker_192.168.42.77_hidden_backdoor_data.leak.ev}flowzip2[复现]
Challenge
There are many encrypted zip files.
Solution
从流量包导出200个加密方式为AES的.zip压缩包
在压缩包的备注发现提示\d{3},推测密码是三位数的数字,用ARCHPR爆一下发现还真是
写脚本尝试从000到999的三位数字密码来暴力破解并解压指定目录下名为 000.zip 至 199.zip 的加密压缩包
# -*- coding: utf-8 -*- import osimport pyzipperfrom tqdm import tqdmimport time # --- 配置区 ---# 使用原始字符串 (r"...") 来避免路径中的反斜杠问题ZIP_DIRECTORY = r"E:\Desktop\flowzip2_fe9d6d2cf5a6fe83f1d7f0fe3c60fa25"# --- 配置区结束 --- def generate_passwords(): """ 生成所有可能的密码 (000, 001, ..., 999) """ # 使用 f-string 和 {:03d} 格式化来生成三位数的字符串,不足的前面补0 return [f"{i:03d}" for i in range(1000)] def crack_zips(): """ 爆破和解压ZIP文件 """ if not os.path.isdir(ZIP_DIRECTORY): print(f"错误:目录'{ZIP_DIRECTORY}'不存在。请检查路径是否正确。") return # 在主函数开始时生成密码列表并打印提示 print("正在生成密码列表 (000-999)...") passwords = generate_passwords() print(f"密码列表生成完毕,共 {len(passwords)} 个。") print(f"开始处理目录'{ZIP_DIRECTORY}'中的ZIP文件...\n") # 使用 with 语句管理 tqdm 实例,确保进度条在结束或异常时能被正确关闭 # bar_format 自定义了进度条的显示格式,{l_bar} 是左边的描述文本 with tqdm(range(200), desc="[+] 准备开始...", bar_format="{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}]") as pbar: for i in pbar: file_number_str = f"{i:03d}" zip_filename = f"{file_number_str}.zip" zip_filepath = os.path.join(ZIP_DIRECTORY, zip_filename) if not os.path.exists(zip_filepath): # 更新描述信息,提示文件不存在 pbar.set_description(f"[-] {zip_filename}不存在,已跳过") continue found_password = False # 遍历所有可能的密码 for password in passwords: try: # 尝试用当前密码打开和解压ZIP文件 # 密码需要被编码成bytes with pyzipper.AESZipFile(zip_filepath, 'r') as zf: zf.extractall(path=ZIP_DIRECTORY, pwd=password.encode('utf-8')) # 密码正确,更新tqdm的描述信息 # 这会覆盖上一条信息,实现动态更新的效果 pbar.set_description(f"[+] {zip_filename}已解压,密码是'{password}'") found_password = True break # 密码已找到,跳出内部的密码循环 except RuntimeError as e: # pyzipper在密码错误时会抛出RuntimeError if 'Bad password' in str(e): continue # 密码不对,继续尝试下一个密码 else: # 其他运行时错误,更新描述并跳出密码循环 pbar.set_description(f"[!] 处理{zip_filename}时发生运行时错误") break except Exception: # 捕获其他可能的异常 pbar.set_description(f"[!] 处理{zip_filename}时发生意外错误") break if not found_password: # 如果遍历完所有密码都未成功,更新描述信息 pbar.set_description(f"[-] 未找到{zip_filename}的密码") # 在所有文件处理完毕后,光标移到新的一行,并打印最终的完成信息 print("\n--- 所有文件处理完毕 ---") if __name__ == "__main__": crack_zips()最后在138.zip(解压密码是853)中的dcsxr.txt找到flag
flag{5f5491b6-fddf-4be8-ab44-5a18831cc45b}密码破解
xxtea
Challenge
It’s getting hard to even copy the data this time.
Solution
没啥好说的,照猫画虎就是了From Hexdump, XXTEA Decrypt - CyberChef
00000000 9e 45 02 82 ea 25 d2 62 0d 06 e7 b4 5f dc 62 bd |.E...%.b...._.b.|00000010 39 68 47 26 54 50 9e 26 4c 86 06 2e 2b af 3b 8b |9hG&TP.&L...+.;.|00000020 7c e4 99 0d ad 12 e2 7e 46 c9 00 29 a6 ea 1f b0 ||......~F..)....|00000030 ae c1 da 30 f3 98 94 82 33 fd 99 d3 d3 b9 a0 12 |...0....3.......|00000040 d9 de a5 d2 0e 95 f3 a5 bb f2 f9 91 b2 a3 c2 94 |................|00000050 b1 1c b7 eb 87 65 d7 0e 0c 6b d5 65 4d e1 43 1e |.....e...k.eM.C.|00000060 be b4 34 71 b5 53 d4 ea 62 4e b9 80 f3 6f f0 5c |..4q.S..bN...o.\|00000070 59 75 58 52 9e a4 ec e2 35 b7 d8 68 27 ee c0 94 |YuXR....5..h'...|flag{4eb88a16-be48-4de2-ab2a-ed09a09ed386}fastcoll
Challenge
这是一个MD5碰撞挑战:你能找到两个不同文件,但却拥有相同的MD5值吗?
Solution
题目要求有相同前缀 gamelab,因此先在当前目录下新建内容为 gamelab 的文件 prefix.txt
然后运行得到两个文件
fastcoll_v1.0.0.5.exe -p prefix -o msg1.bin msg2.bin用厨子分别编码一下然后交上去就行
Z2FtZWxhYgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgJW38EhH3hRbFIaBQ1pJrGjBHm7YrS5TlmOI0uqIkmIeLjwF5kFHpLMMBS9qHZu8CskXE6WmVGDv5KV/BJywYUt9xfoI2x/8k8ldPje4Yyx6N3WzwZgr8tsyDXKmCoxtcr9AOvCI4e+v6BkkqwGwu2OQlPh8TpgdH0Mq0Cic8mZ2FtZWxhYgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgJW38EhH3hRbFIaBQ1pJrGjBFm7YrS5TlmOI0uqIkmIeLjwF5kFHpLMMBS9iHau8CskXE6WmVGDv5K1/BJywYUt9xfoI2x/8k8ldPje4Yyx6N32zwZgr8tsyDXKmCoxtcr9AOvCI4e+v6BkkowGwu2OQlPh8TpgdH0Mi0Cic8m逆向分析
encodefile[复现]
Challenge
分析一个用于加密明文的可执行程序,通过识别其加密逻辑成功解密生成的密文文件,恢复出原始数据内容。
Solution
这个程序的核心功能是读取 flag.txt,使用RC4加密算法对其内容进行加密,然后将加密后的结果写入一个名为 enc.dat 的文件
加密所使用的密钥是硬编码在程序中的字符串 key2025lqb
找到主函数 sub_40487D 并分析
__int64 sub_40487D(){ _QWORD *v1; // rax unsigned int v2; // ebx __int64 v3; // rbx __int64 v4; // rax _QWORD *v5; // rax __int64 result; // rax char v7; // [rsp+Fh] [rbp-481h] BYREF __int64 v8[2]; // [rsp+10h] [rbp-480h] BYREF __int64 v9[2]; // [rsp+20h] [rbp-470h] BYREF _QWORD v10[4]; // [rsp+30h] [rbp-460h] BYREF _QWORD v11[4]; // [rsp+50h] [rbp-440h] BYREF _QWORD v12[31]; // [rsp+70h] [rbp-420h] BYREF __int64 v13; // [rsp+168h] [rbp-328h] BYREF _QWORD v14[32]; // [rsp+270h] [rbp-220h] BYREF __int64 v15; // [rsp+370h] [rbp-120h] BYREF unsigned __int64 ______Stack_Canary_; // [rsp+478h] [rbp-18h] ______Stack_Canary_ = __readfsqword(0x28u); ifstream((__int64)v14, (__int64)"flag.txt", 4);// 读取 "flag.txt" ofstream((__int64)v12, (__int64)"enc.dat", 4);// 写入 "enc.dat" if ( sub_44FB80((__int64)&v15) || sub_44FB80((__int64)&v13) )// 检查文件是否成功打开 { v1 = sub_46F140(qword_5DD320, (__int64)&unk_578019); sub_46DC30((__int64)v1, (__int64 (*)(void))sub_46EA20);// 如果文件打开失败,打印错误信息并退出 v2 = 1; } else // 如果文件打开成功,执行核心加密逻辑 { sub_407080(); sub_404E42((__int64)v9); sub_404DF8((__int64)v8, v14); // 从文件流 v14 ("flag.txt")读取数据到 v8 sub_404E6C((__int64)v10, v8[0], v8[1], v9[0], v9[1], (__int64)&v7);// 再将数据从 v8 转移到 v10 sub_4070A0(); sub_407080(); sub_404F50((__int64)v11, (__int64)"key2025lqb", (__int64)v9);// v11 是密钥结构,使用 "key2025lqb" 进行初始化 sub_404605((__int64)v10, (__int64)v11); // 使用密钥 v11 对数据 v10 进行 RC4 加密 sub_475510(v11); sub_4070A0(); v3 = sub_404DB4(v10); v4 = sub_405014(v10); sub_46E890(v12, v4, v3); // 将数据 (v4, v3) 写入文件流 v12 ("enc.dat") v5 = sub_46F140(qword_5DD440, (__int64)&unk_578040); sub_46DC30((__int64)v5, (__int64 (*)(void))sub_46EA20); v2 = 0; sub_404F08(v10); } sub_44C300(v12); sub_44C440(v14); result = v2; if ( ______Stack_Canary_ != __readfsqword(0x28u) ) sub_52FBA0(); return result;}分析加密函数 sub_404605
unsigned __int64 __fastcall sub_404605(_QWORD *a1, __int64 a2){ int v2; // r12d unsigned __int64 v3; // rax __int64 v4; // kr00_8 _BYTE *v5; // rax unsigned __int64 result; // rax char v7; // [rsp+17h] [rbp-139h] int i; // [rsp+18h] [rbp-138h] int v9; // [rsp+1Ch] [rbp-134h] int v10; // [rsp+1Ch] [rbp-134h] int j; // [rsp+20h] [rbp-130h] int v12; // [rsp+24h] [rbp-12Ch] unsigned __int64 k; // [rsp+28h] [rbp-128h] _BYTE v14[264]; // [rsp+30h] [rbp-120h] BYREF unsigned __int64 v15; // [rsp+138h] [rbp-18h] v15 = __readfsqword(0x28u); for ( i = 0; i <= 255; ++i ) // 初始化S盒 v14[i] = i; v9 = 0; for ( j = 0; j <= 255; ++j ) // 打乱S盒 { v2 = (unsigned __int8)v14[j] + v9; v3 = sub_475730(a2); v9 = (v2 + *(char *)sub_475A40(a2, j % v3)) % 256; sub_404D3D(&v14[j], &v14[v9]); // swap(S[i], S[j]) } v12 = 0; // i v10 = 0; // j for ( k = 0LL; k < sub_404DB4(a1); ++k ) { v12 = (v12 + 1) % 256; // i = (i + 1) % 256 v4 = (unsigned __int8)v14[v12] + v10; v10 = (unsigned __int8)(HIBYTE(v4) + v14[v12] + v10) - HIBYTE(HIDWORD(v4));// j = (j + S[i]) % 256 sub_404D3D(&v14[v12], &v14[v10]); // swap(S[i], S[j]) v7 = v14[(unsigned __int8)(v14[v12] + v14[v10])];// 生成密钥流中的一个字节 v5 = (_BYTE *)sub_404DD8(a1, k); // 获取第 k 个明文字节的地址 *v5 ^= v7; // XOR } result = v15 - __readfsqword(0x28u); if ( result ) sub_52FBA0(); return result;}发现这是标准的RC4,密钥是硬编码在主函数中的key2025lqb,用厨子解就行RC4 - CyberChef
flag{db6007d2-9b1e-2f98-cef3-6595b63763dd}rand_pyc
Challenge
对由Python打包生成的exe文件进行逆向处理,提取并还原出其核心源码,以便进一步分析程序逻辑并获得正确的输入。
Solution
解包反编译拿到代码
# Source Generated with Decompyle++# File: rand_pyc_obf.pyc (Python 3.8) import sysimport randomimport base64Ii = input('Please input the flag: ').strip()if not Ii.startswith('flag{') and Ii.endswith('}') or len(Ii) == 42: print('Length incorrect') sys.exit(-999)oo0O000ooO = base64.b64encode(Ii.encode()).decode() + '_easyctf'ii = []for iiI in oo0O000ooO: random.seed(ord(iiI)) ii.append(random.randint(1000000, 9999999))iii111 = [ 4417023, 5690625, 9639225, 1327718, 4417023, 5085550, 5752075, 9556690, 5240080, 6431679, 3428007, 3189766, 3438336, 5757818, 3189766, 5690625, 4148389, 2254831, 6292433, 2122126, 5240080, 6431679, 9488271, 2464675, 7216908, 5757818, 3189766, 5690625, 3438336, 6431679, 2360475, 6002055, 5240080, 9040261, 8655414, 9347278, 3438336, 2254831, 2122126, 5135281, 2360475, 9347278, 4417023, 1327718, 3438336, 3448715, 9488271, 5501611, 5240080, 5757818, 9488271, 5501611, 5240080, 9347278, 4148389, 1714134, 9923116, 4267438, 4263793, 5752075, 2464675, 7777627, 6002055, 3485900]Iio0 = []for iiI in oo0O000ooO: random.seed(ord(iiI)) Iio0.append(random.randint(1000000, 9999999))if Iio0 != iii111: print('Wrong flag') sys.exit(-1)print('Correct!')程序将输入的内容base64编码在尾部添加字符串_easyctf,然后分别将这些字符作为伪随机数的种子后生成一个数
由于种子是知道的因此这些随机数也是知道的,用base64的表制作一个对应的伪随机数的表,然后查表还原出密文,最后解码base64即可
import randomimport base64 iii111 = [ 4417023, 5690625, 9639225, 1327718, 4417023, 5085550, 5752075, 9556690, 5240080, 6431679, 3428007, 3189766, 3438336, 5757818, 3189766, 5690625, 4148389, 2254831, 6292433, 2122126, 5240080, 6431679, 9488271, 2464675, 7216908, 5757818, 3189766, 5690625, 3438336, 6431679, 2360475, 6002055, 5240080, 9040261, 8655414, 9347278, 3438336, 2254831, 2122126, 5135281, 2360475, 9347278, 4417023, 1327718, 3438336, 3448715, 9488271, 5501611, 5240080, 5757818, 9488271, 5501611, 5240080, 9347278, 4148389, 1714134, 9923116, 4267438, 4263793, 5752075, 2464675, 7777627, 6002055, 3485900] list1 = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890+/=_") list2 = []for guess_flag in list1: random.seed(ord(guess_flag)) list2.append(random.randint(1000000, 9999999))print(list2) flag_list = []for i in iii111: if i in list2: flag_list.append(list1[list2.index(i)]) else: print(i)flag = "".join(flag_list[:-8])print(base64.b64decode(flag))flag{30de99f4-50d2-9f8f-2868-dcfa9d81483c}