PolarloTS个人挑战赛第一季 个人WP

张开发
2026/4/20 21:13:42 15 分钟阅读

分享文章

PolarloTS个人挑战赛第一季 个人WP
简单locke-treasure逆向狂喜void __fastcall decrypt_flag_to_buf( const unsigned __int8 *enc, int enc_len, const char *key, char *out_buf, int out_buf_len) { int key_len; // [rsp24h] [rbp4h] int i; // [rsp44h] [rbp24h] j___CheckForDebuggerJustMyCode(_68090DB3_calc_hide_c); key_len j_strlen_0(key); if ( out_buf_len enc_len 1 ) { for ( i 0; i enc_len; i ) out_buf[i] key[i % key_len] ^ enc[i]; out_buf[enc_len] 0; } else if ( out_buf_len 0 ) { *out_buf 0; } }这是关键函数key和enc均给了这道题好像只能静态分析密码是abc123但是却让输入纯数字expenc[0x7, 0xe, 0x2, 0x56, 0x49, 0x44, 0x8, 0xc, 0x3c, 0x59, 0x53, 0x40, 0x9, 0x3d, 0x1, 0x48, 0x42, 0x52, 0x12, 0x11, 0x1e] flag keyabc123 for i in range(len(enc)): flagchr(ord(key[i%6])^enc[i]) print(flag)智能门锁里的秘钥信息打开二进制程序看到敏感函数char *get_encryption_key() { _BYTE c4t_[11]; // [rsp4h] [rbp-1Ch] BYREF char _15_cut3_[17]; // [rspFh] [rbp-11h] BYREF *(_QWORD *)_15_cut3_[9] __readfsqword(0x28u); strcpy(c4t_[5], d0g3_); strcpy(c4t_, c4t_); strcpy(_15_cut3_, 15_cut3!); strcpy(final_key_0, c4t_[5]); strcat(final_key_0, c4t_); strcat(final_key_0, _15_cut3_); byte_4030 0; return final_key_0; }提取出密钥d0g3_c4t_15_cut3!一般取前16字节脚本如下from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import os def decrypt_file(input_file, output_file): raw_key_string d0g3_c4t_15_cut3! key raw_key_string.encode(utf-8)[:16] iv b\x00 * 16 try: with open(input_file, rb) as f: ciphertext f.read() cipher AES.new(key, AES.MODE_CBC, iv) decrypted_data unpad(cipher.decrypt(ciphertext), AES.block_size) with open(output_file, wb) as f: f.write(decrypted_data) print(f[*] 解密成功解密后的文件已保存为: {output_file}) except Exception as e: print(f[-] 发生错误: {e}) if __name__ __main__: ENCRYPTED_FILE log_encrypted.bin DECRYPTED_FILE decrypted_data.txt if os.path.exists(ENCRYPTED_FILE): decrypt_file(ENCRYPTED_FILE, DECRYPTED_FILE) else: print(f[-] 找不到加密文件: {ENCRYPTED_FILE}请检查路径。)提取flag在010都异或0x9A紧跟着payload后面出来flagWiFi抓包搜索flag字符找到以下数据包经过URL解码是flag{asfhwoefiajsfhowea}咖啡店的虚假WiFi登录页面需要找到受害者MAC地址的前6位十六进制字符去掉冒号钓鱼页面域名不含http://攻击者窃取到的密码攻击时间戳密码数据包的最后4位数字UNIX时间戳第一个根据前三个数据包就能看出来了第一个数据包是路由器周期性对外广播自己的 WiFi 信息第二个是Authentication 认证帧设备向路由器发送身份检验因此我的设备MAC前六位十六进制字符就是112233第二个需要找钓鱼页面域名攻击者窃取的密码在下图找到了时间戳就是上图的数据包的时间戳在左侧分组详情查看即可最终答案flag{112233_starbucks-wifi-auth.com_MySecurePass123!_8000}EasyRouter某校园物联网实验室部署了一批入门级教学路由器型号EasyRouter-100用于学生实践嵌入式设备配置与安全测试。为方便教师验证学生的固件分析能力实验室技术人员通过 Flashrom 工具 读取了路由器 NOR Flash 芯片型号 W25Q16JV2MB 容量的完整镜像将通关验证 Flag 隐藏在固件文件系统中。该路由器为简化教学未启用复杂加密机制仅对 Flag 做基础编码处理。现需你通过分析 Flash 镜像、提取文件系统找到隐藏的 Flag完成设备安全验证任务。题目给了一个附件binwalk提取固件得到flag.txt,内容如下Q1RG{ZWFzeV9mbGFzaF8yMDI0}BASE64解码即可结果是flag{easy_flash_2024}WiFi协议题目只给了一个流量包一个个找在这里发现了关键信息疑似是flag结果是flag{2025_1123_wifi_polar}透明的无线电题目给了一个txt文本和一个C程序源码C源码如下// Device: Smart_Meter_V3 #include lorawan.h // Device Address 0x26013300 uint8_t DEV_ADDR[4] { 0x00, 0x33, 0x01, 0x26 }; // Network Session Key (NwkSKey) - Used for MIC check uint8_t NWK_S_KEY[16] { 0x00 }; // Redacted // Application Session Key (AppSKey) - Used for Payload Encryption // LEAKED! uint8_t APP_S_KEY[16] { 0x2B, 0x7E, 0x15, 0x16,0x28, 0xAE, 0xD2, 0xA6,0xAB, 0xF7, 0x15, 0x88,0x09, 0xCF, 0x4F, 0x3C };题目给的txt文件经过base解码和16进制应该是协议报文40 00 33 01 26 00 05 00 01 d7 6b 07 06 5d 45 c9 bc d0 66 06 ca 11 40 4f 44 4b 9a 3b 93 31 aa bb cc dd按 LoRaWAN 拆字段后40MHDR表示这是一个 uplink 数据帧00 33 01 26DevAddr小端表示正好是0x26013300(在C源码表示地址)00FCtrl05 00FCnt 501FPort 1后面一段是FRMPayload最后aa bb cc dd看起来是 MIC刚开始题目附件上错了flag计算的是错误的但是到这里的思路是对的接下来就是解密FRMPayloadLoRaWAN 的FRMPayload不是直接 AES-CBC 那种解法而是AES-128 的流式异或解法。核心是先构造一组Ai块然后Si aes128_encrypt(AppSKey, Ai)最后明文 密文 XOR SFRMPayload d76b07065d45c6bbd30d0edf7f4d182c409e78c67e29d4d99fc960a60f27919a1a04eec98263因为是 uplink所以Dir 0。对应的Ai和SiA1 01000000000000330126050000000001 S1 b10766612623a5ddb7396fb94e29211b A2 01000000000000330126050000000002 S2 23ff49f64c11b0b8aafd04c73e15a8af A3 01000000000000330126050000000003 S3 2232d6aab51edf927e8cd833a210c730把FRMPayload和S1|S2|S3按长度逐字节异或得到明文666c61677b66636664346166316439376361313032386461353464613132393538363863377d转 ASCII 就是flag{fcfd4af1d97ca1028da54da1295868c7}expimport base64 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes appskey bytes.fromhex(2B7E151628AED2A6ABF7158809CF4F3C) pkt base64.b64decode(QAAzASYABQAB12sHBl1FxrvTDQ7ff00YLECeeMZKdTZn8lgpg8nkZoaBO7JgmPerb7v) devaddr pkt[1:5] fcnt int.from_bytes(pkt[6:8], little) frmpayload pkt[9:-4] direction 0 # uplink cipher Cipher(algorithms.AES(appskey), modes.ECB()) enc cipher.encryptor() keystream b for i in range(1, (len(frmpayload) 15) // 16 1): Ai ( b\x01\x00\x00\x00\x00 bytes([direction]) devaddr fcnt.to_bytes(4, little) b\x00 bytes([i]) ) Si enc.update(Ai) print(fA{i} {Ai.hex()}) print(fS{i} {Si.hex()}) keystream Si plaintext bytes(a ^ b for a, b in zip(frmpayload, keystream)) print(plaintext.decode())中等你会伪造吗附件是一个gpx文件看来是要篡改gpx文件伪造运动轨迹基准对齐Base Alignment按原顺序包含base.gpx的 101 个原始点未修改任何原始坐标。点数要求在原有点中插入了 2 个 CP 打卡点并在末尾插入了 3 个占位点总计正好 106 个点。速度要求时间戳从09:00:00开始以严格的6秒/点均匀递增直到09:10:30结束完美满足最高速度要求。这个真的不太了解用gemini跑的智能盆栽固件分析binwalk提取找到隐藏的脚本#!/bin/bash # PlantPal Secret Access Script # This script is triggered by the diagnostic backdoor echo echo ╔══════════════════════════════════════════╗ echo ║ SECRET GARDEN ACCESS ║ echo ║ AUTHENTICATED ║ echo ╚══════════════════════════════════════════╝ echo echo [] Backdoor authentication: OK echo [] Privilege escalation: OK echo [] Accessing secure partition... echo sleep 1 # Read the secret key if [ -f /etc/plantpal_secret ]; then SECRET_KEY$(cat /etc/plantpal_secret) echo [✓] Secret key loaded: (hidden) else SECRET_KEYDEFAULT_KEY_BACKDOOR_123 echo [⚠] Using default secret key fi # Generate flag DEVICE_IDPP-2024- MD5_HASH$(echo -n $SECRET_KEY | md5sum | awk {print $1}) MD5_PREFIX$(echo $MD5_HASH | cut -c1-8) FLAGflag{${DEVICE_ID}${MD5_PREFIX}} echo echo ════════════════════════════════════════════ echo FLAG: $FLAG echo ════════════════════════════════════════════ echo echo [] Debug Information: echo Device ID: $DEVICE_ID echo Secret Key MD5: $MD5_HASH echo MD5 Prefix (8 chars): $MD5_PREFIX echo echo [⚠️] Security Notice: echo This backdoor will be removed in v1.1.0 echo Please secure your devices in production echo 以及一个秘密钥匙MY_SECRET_BACKDOOR_KEY_1337加密算法就是md5密钥取前八位再加上DEVICE-ID我的flash提示说厂商为了防止被直接扫描采用了“多段分散 简单混淆”的方式存储敏感信息。010打开里面有大量的0XFF那也就是说不是0XFF的很有可能是加密数据甚至是密钥都是简单一字节加密方式是异或猜测有了接下来就是开始答题由于0XFF太多让AI提取出不同位置的信息如下第一段0x2000处按0x4B异或后FLAG{flashro第二段0x3F00处按0xFF异或后_zlib_not}第三段0x9000处是 zlib解压后om_segmented_xor答案FLAG{flashroom_segmented_xor_zlib_not}智能门锁协议分析固件里面可以直接看到keyAES加密模式也给了。但是在这个固件之中counter值是从1开始下面是AI生成的expfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes # # 1. 题目里从固件提取出的 AES 密钥 # key bLOCK_KEY_2024_!! # # 2. 三条日志 # nonce 是 8 字节 # 密文是十六进制字符串 # records [ { desc: 管理员开锁记录, nonce: 72c4e915062c70d3, ciphertext: 336b1e563c51bfa1b965307190596c76b406a86dd6ac38022450f4b248f65382d9c6a67a002f164aa6222d1b11ddd050462fe827139cf7365425a56c33eaab7e2504d2e5c567eff95687bed9f198dbbc }, { desc: 用户开锁记录, nonce: a624068b03d3effb, ciphertext: 3f5f193d2aa20ece3bd76457245ede0851db9925684be457b4ef62563350ee9b6efee2a31f10992c5a64796fd611227591cee2f27362b6c6c8f33451576cf1d9a2385ac463b38ace677741ad5ad01268 }, { desc: 失败尝试记录, nonce: 634e44a002b69715, ciphertext: 847d0c34d459eb05d062ff78901cf48fa2208459fe6ca4d6d4bc3452ff1e333bd8b66d209c84360634ac01df01aa981b919006eb87c1e95a2cb4206229f871b6a32ac26c2ecdc922fc3064119c3b1591 } ] # # 3. 去 PKCS7 填充 # 如果最后几个字节是合法填充就去掉 # def remove_pkcs7_padding(data: bytes) - bytes: if len(data) 0: return data pad_len data[-1] # pad_len 必须在 1~16 之间 if pad_len 1 or pad_len 16: return data # 最后 pad_len 个字节都要等于 pad_len if data[-pad_len:] ! bytes([pad_len]) * pad_len: return data return data[:-pad_len] # # 4. AES-CTR 解密 # 这题的 IV nonce(8字节) counter(8字节) # 注意counter 初始值要从 1 开始 # def aes_ctr_decrypt(key: bytes, nonce_hex: str, ciphertext_hex: str) - bytes: nonce bytes.fromhex(nonce_hex) ciphertext bytes.fromhex(ciphertext_hex) # 计数器从 1 开始占 8 字节大端 counter_start (1).to_bytes(8, big) # CTR 模式需要 16 字节初始块 iv nonce counter_start cipher Cipher(algorithms.AES(key), modes.CTR(iv)) decryptor cipher.decryptor() plaintext decryptor.update(ciphertext) decryptor.finalize() return plaintext # # 5. 解密全部日志 # admin_plaintext None for i, record in enumerate(records, 1): plaintext aes_ctr_decrypt(key, record[nonce], record[ciphertext]) plaintext remove_pkcs7_padding(plaintext) text plaintext.decode(utf-8, errorsreplace) print(f记录{i} - {record[desc]}) print(text) print(- * 60) if record[desc] 管理员开锁记录: admin_plaintext text # # 6. 从管理员记录里提取 door 和 time # 例如 # DOOR:B208 CARD:ADMIN TIME:20240115_143022 ACTION:UNLOCK RESULT:SUCCESS # if admin_plaintext: parts admin_plaintext.split() door None time_str None for part in parts: if part.startswith(DOOR:): door part.split(:, 1)[1] elif part.startswith(TIME:): time_str part.split(:, 1)[1] if door and time_str: flag fflag{{{door}_{time_str}}} print(最终 flag , flag) else: print(管理员记录解出来了但没有成功提取 DOOR 或 TIME) else: print(没有找到管理员记录)私钥解密提取一下文件系统找到一个提示文本说密码在2025年中秋节6一个文件夹内有10个脚本应该有一个对应6执行了以下命令openssl enc -des3 -nosalt -salt -in data.txt -out data.enc -k pass123但是这个执行完报错不是密码密码经过尝试应该是123456才对然后用RSA私钥解密expfrom pathlib import Path from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import padding pem Path(private_key_encrypted.pem).read_bytes() enc Path(flag.enc).read_bytes() private_key serialization.load_pem_private_key( pem, passwordb123456 ) plaintext private_key.decrypt(enc, padding.PKCS1v15()) print(plaintext.decode())easy壳壳逻辑在FileUtils.splitPayLoadFromDex里读取 APK 的 classes.dex整体 xor 0xff末尾 4 字节是原始 dex 长度然后从尾部切出真实 dex。找到真逻辑如下package com.example.iot2; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; /* loaded from: f:\Desktop\新建文件夹\yongye.dex */ public class MainActivity extends AppCompatActivity { private final String CORRECT_PWD adsbu32cais; private final String FLAG flag{sadbuy12368gdsabhu}; private EditText et_pwd; Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity protected void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.activity_main); this.et_pwd (EditText) findViewById(R.id.et_password); } public void checkPassword(View view) { if (this.et_pwd.getText().toString().trim().equals(adsbu32cais)) { Toast.makeText(this, flag{sadbuy12368gdsabhu}, 1).show(); } else { Toast.makeText(this, 密码错误请重试, 0).show(); } } }明文flag已经给出固件锁匠先说一个解法010打开内部出现明文flag按照题目要求我们应该找到这个代码的后门在哪里也就是说只要传入指定参数就可以绕过保护命令如下所示LoRaWAN网络安全审计这是一个py打包的exe实际上解包反编译就出来了困难有些题目看描述说是需要ESP32板子就作罢了。只写了一些简单的ApK47突突突直接手撕so文件通过JNI_ONload函数发现关键代码这是密文说白了反向逻辑就是((byte_36B9C[i 1] - mod5 - n2)expbyte_36B9C [ 0x76, 0x65, 0x82, 0x76, 0x6B, 0x7D, 0x77, 0x66, 0x83, 0x77, 0x80, 0x74, 0x82, 0x76, 0x84, 0x73, 0x81, 0x75, 0x83, 0x24, 0x23, 0x21, 0x26, 0x23, 0x28, 0x73, 0x81, 0x22, 0x27 ] flag flag{a for i in range(28): n2 -1 if (i % 2 0) else 2 mod5 (i 1) % 5 char_val ((byte_36B9C[i 1] - mod5 - n2) 0xFF) ^ 0x15 flag chr(char_val) flag } print(flag)appreverse检验逻辑应该在so层厨子解决最终答案flag{wdiu23087fsebu4387fds}

更多文章