首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
CTF对抗
发新帖
0
1
[原创][推荐][原创]CodeGateCTF 2026 - Silicon Dream WP
发表于: 2026-3-31 20:56
3286
[原创][推荐][原创]CodeGateCTF 2026 - Silicon Dream WP
SleepAlone
3
2026-3-31 20:56
3286
# CodeGateCTF 2026 - Silicon Dream WP # 写在前面 赛后反思,在比赛期间没有解出这道80+多解题目,十分惭愧。是我过度依赖AI,也是我能力的退步。 # 题目描述 作者实现了一个基于**魔改**过的 openMSP430 硬件处理器,看似合理的扩展指令实际会触发基于Fistel网络的加密。 # 解题 ## 0x01 基本逆向 这一步通过AI基本都能逆明白,加载字节码,然后解执行。 执行的字节码反汇编后(部分): ```python ; Segment starting at 0x0000c000: 0xc000: 4255 0120 mov.b &0x0120, R5 ; ca. 3 cycles 0xc004: d035 5a08 bis #0x5a08, R5 ; ca. 2 cycles 0xc008: 4582 02d2 mov R5, &0x02d2 ; ca. 4 cycles 0xc00c: 4031 0400 mov #0x0400, SP ; ca. 2 cycles 0xc010: 403f 0000 mov #0x0000, R15 ; ca. 2 cycles 0xc014: 930f tst R15 ; ca. 1 cycle 0xc016: 2408 jz .L0001 ; ca. 2 cycles +16 --> 0xc028 0xc018: 4292 02d2 0120 .L0002: mov &0x02d2, &0x0120 ; ca. 6 cycles 0xc01e: 832f decd R15 ; ca. 1 cycle 0xc020: 4f9f c740 0200 mov 0xc740(R15), 512(R15) ; ca. 6 cycles 0xc026: 23f8 jnz .L0002 ; ca. 2 cycles -16 --> 0xc018 0xc028: 403f 006a .L0001: mov #0x006a, R15 ; ca. 2 cycles 0xc02c: 930f tst R15 ; ca. 1 cycle 0xc02e: 2407 jz .L0003 ; ca. 2 cycles +14 --> 0xc03e 0xc030: 4292 02d2 0120 .L0004: mov &0x02d2, &0x0120 ; ca. 6 cycles 0xc036: 831f dec R15 ; ca. 1 cycle 0xc038: 43cf 0200 clr.b 512(R15) ; ca. 4 cycles 0xc03c: 23f9 jnz .L0004 ; ca. 2 cycles -14 --> 0xc030 0xc03e: 5031 ffdc .L0003: add #0xffdc, SP ; ca. 2 cycles 0xc042: 40b2 5a80 0120 mov #0x5a80, &0x0120 ; ca. 5 cycles 0xc048: 4381 0020 clr 32(SP) ; ca. 4 cycles 0xc04c: 43c1 0022 clr.b 34(SP) ; ca. 4 cycles 0xc050: 40b1 c64a 0010 mov #0xc64a, 16(SP) ; ca. 5 cycles 0xc056: 40b1 026a 0012 mov #0x026a, 18(SP) ; ca. 5 cycles 0xc05c: 40b1 0200 0014 mov #0x0200, 20(SP) ; ca. 5 cycles 0xc062: 4381 0016 clr 22(SP) ; ca. 4 cycles 0xc066: 4381 0018 clr 24(SP) ; ca. 4 cycles 0xc06a: 40b1 000d 001a mov #0x000d, 26(SP) ; ca. 5 cycles 0xc070: 411f 0020 .L0006: mov 0x0020(SP), R15 ; ca. 3 cycles 0xc074: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc078: 531f inc R15 ; ca. 1 cycle 0xc07a: 537e add.b #0xff, R14 ; ca. 1 cycle 0xc07c: 907e 0015 cmp.b #0x15, R14 ; ca. 2 cycles 0xc080: 2802 jnc .L0005 ; ca. 2 cycles +4 --> 0xc086 0xc082: 4030 c446 br #0xc446 ; ca. 3 cycles 0xc086: 4e4e .L0005: mov.b R14, R14 ; ca. 1 cycle 0xc088: 5e0e rla R14 ; ca. 1 cycle 0xc08a: 4e10 c620 br 0xc620(R14) ; ca. 3 cycles 0xc08e: 4f5d c6b3 mov.b 0xc6b3(R15), R13 ; ca. 3 cycles 0xc092: 531f inc R15 ; ca. 1 cycle 0xc094: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc098: 4d0e mov R13, R14 ; ca. 1 cycle 0xc09a: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc09e: 5e0e rla R14 ; ca. 1 cycle 0xc0a0: 510e add SP, R14 ; ca. 1 cycle 0xc0a2: 4e2e mov @R14, R14 ; ca. 1 cycle 0xc0a4: 4d4f mov.b R13, R15 ; ca. 1 cycle 0xc0a6: c312 clrc ; ca. 1 cycle 0xc0a8: 104f rrc.b R15 ; ca. 1 cycle 0xc0aa: c312 clrc ; ca. 1 cycle 0xc0ac: 104f rrc.b R15 ; ca. 1 cycle 0xc0ae: c312 clrc ; ca. 1 cycle 0xc0b0: 104f rrc.b R15 ; ca. 1 cycle 0xc0b2: c312 clrc ; ca. 1 cycle 0xc0b4: 104f rrc.b R15 ; ca. 1 cycle 0xc0b6: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc0ba: 5f0f rla R15 ; ca. 1 cycle 0xc0bc: 510f add SP, R15 ; ca. 1 cycle 0xc0be: 4eaf 0000 mov @R14, 0(R15) ; ca. 4 cycles 0xc0c2: 3fd6 jmp .L0006 ; ca. 2 cycles -84 --> 0xc070 0xc0c4: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc0c8: 531f inc R15 ; ca. 1 cycle 0xc0ca: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc0ce: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc0d0: c312 clrc ; ca. 1 cycle 0xc0d2: 104f rrc.b R15 ; ca. 1 cycle 0xc0d4: c312 clrc ; ca. 1 cycle 0xc0d6: 104f rrc.b R15 ; ca. 1 cycle 0xc0d8: c312 clrc ; ca. 1 cycle 0xc0da: 104f rrc.b R15 ; ca. 1 cycle 0xc0dc: c312 clrc ; ca. 1 cycle 0xc0de: 104f rrc.b R15 ; ca. 1 cycle 0xc0e0: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc0e4: 5f0f rla R15 ; ca. 1 cycle 0xc0e6: 510f add SP, R15 ; ca. 1 cycle 0xc0e8: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc0ec: 5e0e rla R14 ; ca. 1 cycle 0xc0ee: 510e add SP, R14 ; ca. 1 cycle 0xc0f0: 4e2e mov @R14, R14 ; ca. 1 cycle 0xc0f2: 4fae 0000 mov @R15, 0(R14) ; ca. 4 cycles 0xc0f6: 3fbc jmp .L0006 ; ca. 2 cycles -136 --> 0xc070 0xc0f8: 4f0d mov R15, R13 ; ca. 1 cycle 0xc0fa: 503d c6b3 add #0xc6b3, R13 ; ca. 2 cycles 0xc0fe: 4d6e mov.b @R13, R14 ; ca. 1 cycle 0xc100: c312 clrc ; ca. 1 cycle 0xc102: 104e rrc.b R14 ; ca. 1 cycle 0xc104: c312 clrc ; ca. 1 cycle 0xc106: 104e rrc.b R14 ; ca. 1 cycle 0xc108: c312 clrc ; ca. 1 cycle 0xc10a: 104e rrc.b R14 ; ca. 1 cycle 0xc10c: c312 clrc ; ca. 1 cycle 0xc10e: 104e rrc.b R14 ; ca. 1 cycle 0xc110: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc114: 5e0e rla R14 ; ca. 1 cycle 0xc116: 510e add SP, R14 ; ca. 1 cycle 0xc118: 4d5c 0002 mov.b 0x0002(R13), R12 ; ca. 3 cycles 0xc11c: 108c swpb R12 ; ca. 1 cycle 0xc11e: 4d5d 0001 mov.b 0x0001(R13), R13 ; ca. 3 cycles 0xc122: dd0c bis R13, R12 ; ca. 1 cycle 0xc124: 4c8e 0000 mov R12, 0(R14) ; ca. 4 cycles 0xc128: 503f 0003 add #0x0003, R15 ; ca. 2 cycles 0xc12c: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc130: 3f9f jmp .L0006 ; ca. 2 cycles -194 --> 0xc070 0xc132: 4f5d c6b3 mov.b 0xc6b3(R15), R13 ; ca. 3 cycles 0xc136: 531f inc R15 ; ca. 1 cycle 0xc138: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc13c: 4d0e mov R13, R14 ; ca. 1 cycle 0xc13e: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc142: 5e0e rla R14 ; ca. 1 cycle 0xc144: 510e add SP, R14 ; ca. 1 cycle 0xc146: 4d4f mov.b R13, R15 ; ca. 1 cycle 0xc148: c312 clrc ; ca. 1 cycle 0xc14a: 104f rrc.b R15 ; ca. 1 cycle 0xc14c: c312 clrc ; ca. 1 cycle 0xc14e: 104f rrc.b R15 ; ca. 1 cycle 0xc150: c312 clrc ; ca. 1 cycle 0xc152: 104f rrc.b R15 ; ca. 1 cycle 0xc154: c312 clrc ; ca. 1 cycle 0xc156: 104f rrc.b R15 ; ca. 1 cycle 0xc158: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc15c: 5f0f rla R15 ; ca. 1 cycle 0xc15e: 510f add SP, R15 ; ca. 1 cycle 0xc160: 4eaf 0000 mov @R14, 0(R15) ; ca. 4 cycles 0xc164: 3f85 jmp .L0006 ; ca. 2 cycles -246 --> 0xc070 0xc166: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc16a: 531f inc R15 ; ca. 1 cycle 0xc16c: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc170: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc172: c312 clrc ; ca. 1 cycle 0xc174: 104f rrc.b R15 ; ca. 1 cycle 0xc176: c312 clrc ; ca. 1 cycle 0xc178: 104f rrc.b R15 ; ca. 1 cycle 0xc17a: c312 clrc ; ca. 1 cycle 0xc17c: 104f rrc.b R15 ; ca. 1 cycle 0xc17e: c312 clrc ; ca. 1 cycle 0xc180: 104f rrc.b R15 ; ca. 1 cycle 0xc182: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc186: 5f0f rla R15 ; ca. 1 cycle 0xc188: 510f add SP, R15 ; ca. 1 cycle 0xc18a: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc18e: 5e0e rla R14 ; ca. 1 cycle 0xc190: 510e add SP, R14 ; ca. 1 cycle 0xc192: eeaf 0000 xor @R14, 0(R15) ; ca. 4 cycles 0xc196: 3f6c jmp .L0006 ; ca. 2 cycles -296 --> 0xc070 0xc198: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc19c: 531f inc R15 ; ca. 1 cycle 0xc19e: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc1a2: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc1a4: c312 clrc ; ca. 1 cycle 0xc1a6: 104f rrc.b R15 ; ca. 1 cycle 0xc1a8: c312 clrc ; ca. 1 cycle 0xc1aa: 104f rrc.b R15 ; ca. 1 cycle 0xc1ac: c312 clrc ; ca. 1 cycle 0xc1ae: 104f rrc.b R15 ; ca. 1 cycle 0xc1b0: c312 clrc ; ca. 1 cycle 0xc1b2: 104f rrc.b R15 ; ca. 1 cycle 0xc1b4: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc1b8: 5f0f rla R15 ; ca. 1 cycle 0xc1ba: 510f add SP, R15 ; ca. 1 cycle 0xc1bc: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc1c0: 5e0e rla R14 ; ca. 1 cycle 0xc1c2: 510e add SP, R14 ; ca. 1 cycle 0xc1c4: 5eaf 0000 add @R14, 0(R15) ; ca. 4 cycles 0xc1c8: 3f53 jmp .L0006 ; ca. 2 cycles -346 --> 0xc070 0xc1ca: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc1ce: 531f inc R15 ; ca. 1 cycle 0xc1d0: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc1d4: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc1d6: c312 clrc ; ca. 1 cycle 0xc1d8: 104f rrc.b R15 ; ca. 1 cycle 0xc1da: c312 clrc ; ca. 1 cycle 0xc1dc: 104f rrc.b R15 ; ca. 1 cycle 0xc1de: c312 clrc ; ca. 1 cycle 0xc1e0: 104f rrc.b R15 ; ca. 1 cycle 0xc1e2: c312 clrc ; ca. 1 cycle 0xc1e4: 104f rrc.b R15 ; ca. 1 cycle 0xc1e6: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc1ea: 5f0f rla R15 ; ca. 1 cycle 0xc1ec: 510f add SP, R15 ; ca. 1 cycle 0xc1ee: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc1f2: 5e0e rla R14 ; ca. 1 cycle 0xc1f4: 510e add SP, R14 ; ca. 1 cycle 0xc1f6: 8eaf 0000 sub @R14, 0(R15) ; ca. 4 cycles 0xc1fa: 3f3a jmp .L0006 ; ca. 2 cycles -396 --> 0xc070 0xc1fc: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc200: 531f inc R15 ; ca. 1 cycle 0xc202: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc206: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc208: c312 clrc ; ca. 1 cycle 0xc20a: 104f rrc.b R15 ; ca. 1 cycle 0xc20c: c312 clrc ; ca. 1 cycle 0xc20e: 104f rrc.b R15 ; ca. 1 cycle 0xc210: c312 clrc ; ca. 1 cycle 0xc212: 104f rrc.b R15 ; ca. 1 cycle 0xc214: c312 clrc ; ca. 1 cycle 0xc216: 104f rrc.b R15 ; ca. 1 cycle 0xc218: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc21c: 5f0f rla R15 ; ca. 1 cycle 0xc21e: 510f add SP, R15 ; ca. 1 cycle 0xc220: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc224: 5e0e rla R14 ; ca. 1 cycle 0xc226: 510e add SP, R14 ; ca. 1 cycle 0xc228: 435d mov.b #1, R13 ; ca. 1 cycle 0xc22a: 9eaf 0000 cmp @R14, 0(R15) ; ca. 4 cycles 0xc22e: 2401 jz .L0007 ; ca. 2 cycles +2 --> 0xc232 0xc230: 434d clr.b R13 ; ca. 1 cycle 0xc232: 4dc1 0022 .L0007: mov.b R13, 34(SP) ; ca. 4 cycles 0xc236: 3f1c jmp .L0006 ; ca. 2 cycles -456 --> 0xc070 0xc238: 4f0e mov R15, R14 ; ca. 1 cycle 0xc23a: 531e inc R14 ; ca. 1 cycle 0xc23c: 4f5f c6b3 mov.b 0xc6b3(R15), R15 ; ca. 3 cycles 0xc240: 118f sxt R15 ; ca. 1 cycle 0xc242: 5f0e add R15, R14 ; ca. 1 cycle 0xc244: 4e81 0020 mov R14, 32(SP) ; ca. 4 cycles 0xc248: 3f13 jmp .L0006 ; ca. 2 cycles -474 --> 0xc070 0xc24a: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc24e: 531f inc R15 ; ca. 1 cycle 0xc250: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc254: 93c1 0022 tst.b 34(SP) ; ca. 4 cycles 0xc258: 270b jz .L0006 ; ca. 2 cycles -490 --> 0xc070 0xc25a: 118e sxt R14 ; ca. 1 cycle 0xc25c: 5f0e add R15, R14 ; ca. 1 cycle 0xc25e: 4e81 0020 mov R14, 32(SP) ; ca. 4 cycles 0xc262: 3f06 jmp .L0006 ; ca. 2 cycles -500 --> 0xc070 0xc264: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc268: 531f inc R15 ; ca. 1 cycle 0xc26a: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc26e: 93c1 0022 tst.b 34(SP) ; ca. 4 cycles 0xc272: 2402 jz .L0008 ; ca. 2 cycles +4 --> 0xc278 0xc274: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc278: 118e .L0008: sxt R14 ; ca. 1 cycle 0xc27a: 5f0e add R15, R14 ; ca. 1 cycle 0xc27c: 4e81 0020 mov R14, 32(SP) ; ca. 4 cycles 0xc280: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc284: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc288: 531f inc R15 ; ca. 1 cycle 0xc28a: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc28e: 410f mov SP, R15 ; ca. 1 cycle 0xc290: 12b0 c452 call .L0009 ; ca. 5 cycles --> 0xc452 0xc294: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc298: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc29c: 531f inc R15 ; ca. 1 cycle 0xc29e: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc2a2: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc2a4: c312 clrc ; ca. 1 cycle 0xc2a6: 104f rrc.b R15 ; ca. 1 cycle 0xc2a8: c312 clrc ; ca. 1 cycle 0xc2aa: 104f rrc.b R15 ; ca. 1 cycle 0xc2ac: c312 clrc ; ca. 1 cycle 0xc2ae: 104f rrc.b R15 ; ca. 1 cycle 0xc2b0: c312 clrc ; ca. 1 cycle 0xc2b2: 104f rrc.b R15 ; ca. 1 cycle 0xc2b4: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc2b8: 5f0f rla R15 ; ca. 1 cycle 0xc2ba: 510f add SP, R15 ; ca. 1 cycle 0xc2bc: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc2c0: 5e0e rla R14 ; ca. 1 cycle 0xc2c2: 510e add SP, R14 ; ca. 1 cycle 0xc2c4: 4e2e mov @R14, R14 ; ca. 1 cycle 0xc2c6: 4eef 0000 mov.b @R14, 0(R15) ; ca. 4 cycles 0xc2ca: 43cf 0001 clr.b 1(R15) ; ca. 4 cycles 0xc2ce: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc2d2: 4f5d c6b3 mov.b 0xc6b3(R15), R13 ; ca. 3 cycles 0xc2d6: 531f inc R15 ; ca. 1 cycle 0xc2d8: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc2dc: 4d0e mov R13, R14 ; ca. 1 cycle 0xc2de: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc2e2: 5e0e rla R14 ; ca. 1 cycle 0xc2e4: 510e add SP, R14 ; ca. 1 cycle 0xc2e6: 4e2e mov @R14, R14 ; ca. 1 cycle 0xc2e8: 4d4f mov.b R13, R15 ; ca. 1 cycle 0xc2ea: c312 clrc ; ca. 1 cycle 0xc2ec: 104f rrc.b R15 ; ca. 1 cycle 0xc2ee: c312 clrc ; ca. 1 cycle 0xc2f0: 104f rrc.b R15 ; ca. 1 cycle 0xc2f2: c312 clrc ; ca. 1 cycle 0xc2f4: 104f rrc.b R15 ; ca. 1 cycle 0xc2f6: c312 clrc ; ca. 1 cycle 0xc2f8: 104f rrc.b R15 ; ca. 1 cycle 0xc2fa: f03f 000f .L0025: and #0x000f, R15 ; ca. 2 cycles 0xc2fe: 5f0f rla R15 ; ca. 1 cycle 0xc300: 510f add SP, R15 ; ca. 1 cycle 0xc302: 4fee 0000 mov.b @R15, 0(R14) ; ca. 4 cycles 0xc306: 4030 c070 .L0030: br #0xc070 ; ca. 3 cycles 0xc30a: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc30e: 531f inc R15 ; ca. 1 cycle 0xc310: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc314: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc316: c312 clrc ; ca. 1 cycle 0xc318: 104f rrc.b R15 ; ca. 1 cycle 0xc31a: c312 clrc ; ca. 1 cycle 0xc31c: 104f rrc.b R15 ; ca. 1 cycle 0xc31e: c312 clrc ; ca. 1 cycle 0xc320: 104f rrc.b R15 ; ca. 1 cycle 0xc322: c312 clrc ; ca. 1 cycle 0xc324: 104f rrc.b R15 ; ca. 1 cycle 0xc326: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc32a: 5f0f rla R15 ; ca. 1 cycle 0xc32c: 510f add SP, R15 ; ca. 1 cycle 0xc32e: 4f2e mov @R15, R14 ; ca. 1 cycle 0xc330: 531e inc R14 ; ca. 1 cycle 0xc332: 4e8f 0000 mov R14, 0(R15) ; ca. 4 cycles 0xc336: 435f mov.b #1, R15 ; ca. 1 cycle 0xc338: 2401 jz .L0010 ; ca. 2 cycles +2 --> 0xc33c 0xc33a: 434f clr.b R15 ; ca. 1 cycle 0xc33c: 4fc1 0022 .L0010: mov.b R15, 34(SP) ; ca. 4 cycles 0xc340: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc344: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc348: 531f inc R15 ; ca. 1 cycle 0xc34a: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc34e: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc350: c312 clrc ; ca. 1 cycle 0xc352: 104f rrc.b R15 ; ca. 1 cycle 0xc354: c312 clrc ; ca. 1 cycle 0xc356: 104f rrc.b R15 ; ca. 1 cycle 0xc358: c312 clrc ; ca. 1 cycle 0xc35a: 104f rrc.b R15 ; ca. 1 cycle 0xc35c: c312 clrc ; ca. 1 cycle 0xc35e: 104f rrc.b R15 ; ca. 1 cycle 0xc360: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc364: 5f0f rla R15 ; ca. 1 cycle 0xc366: 510f add SP, R15 ; ca. 1 cycle 0xc368: 4f2e mov @R15, R14 ; ca. 1 cycle 0xc36a: 533e add #0xffff, R14 ; ca. 1 cycle 0xc36c: 4e8f 0000 mov R14, 0(R15) ; ca. 4 cycles 0xc370: 435f mov.b #1, R15 ; ca. 1 cycle 0xc372: 2401 jz .L0011 ; ca. 2 cycles +2 --> 0xc376 0xc374: 434f clr.b R15 ; ca. 1 cycle 0xc376: 4fc1 0022 .L0011: mov.b R15, 34(SP) ; ca. 4 cycles 0xc37a: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc37e: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc382: 531f inc R15 ; ca. 1 cycle 0xc384: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc388: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc38a: c312 clrc ; ca. 1 cycle 0xc38c: 104f rrc.b R15 ; ca. 1 cycle 0xc38e: c312 clrc ; ca. 1 cycle 0xc390: 104f rrc.b R15 ; ca. 1 cycle 0xc392: c312 clrc ; ca. 1 cycle 0xc394: 104f rrc.b R15 ; ca. 1 cycle 0xc396: c312 clrc ; ca. 1 cycle 0xc398: 104f rrc.b R15 ; ca. 1 cycle 0xc39a: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc39e: 5f0f rla R15 ; ca. 1 cycle 0xc3a0: 510f add SP, R15 ; ca. 1 cycle 0xc3a2: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc3a6: 5e0e rla R14 ; ca. 1 cycle 0xc3a8: 510e add SP, R14 ; ca. 1 cycle 0xc3aa: feaf 0000 and @R14, 0(R15) ; ca. 4 cycles 0xc3ae: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc3b2: 4f5e c6b3 mov.b 0xc6b3(R15), R14 ; ca. 3 cycles 0xc3b6: 531f inc R15 ; ca. 1 cycle 0xc3b8: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc3bc: 4e4f mov.b R14, R15 ; ca. 1 cycle 0xc3be: c312 clrc ; ca. 1 cycle 0xc3c0: 104f rrc.b R15 ; ca. 1 cycle 0xc3c2: c312 clrc ; ca. 1 cycle 0xc3c4: 104f rrc.b R15 ; ca. 1 cycle 0xc3c6: c312 clrc ; ca. 1 cycle 0xc3c8: 104f rrc.b R15 ; ca. 1 cycle 0xc3ca: c312 clrc ; ca. 1 cycle 0xc3cc: 104f rrc.b R15 ; ca. 1 cycle 0xc3ce: f03f 000f and #0x000f, R15 ; ca. 2 cycles 0xc3d2: 5f0f rla R15 ; ca. 1 cycle 0xc3d4: 510f add SP, R15 ; ca. 1 cycle 0xc3d6: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc3da: 5e0e rla R14 ; ca. 1 cycle 0xc3dc: 510e add SP, R14 ; ca. 1 cycle 0xc3de: deaf 0000 bis @R14, 0(R15) ; ca. 4 cycles 0xc3e2: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc3e6: 4f0d mov R15, R13 ; ca. 1 cycle 0xc3e8: 503d c6b3 add #0xc6b3, R13 ; ca. 2 cycles 0xc3ec: 4d7e mov.b @R13+, R14 ; ca. 1 cycle 0xc3ee: c312 clrc ; ca. 1 cycle 0xc3f0: 104e rrc.b R14 ; ca. 1 cycle 0xc3f2: c312 clrc ; ca. 1 cycle 0xc3f4: 104e rrc.b R14 ; ca. 1 cycle 0xc3f6: c312 clrc ; ca. 1 cycle 0xc3f8: 104e rrc.b R14 ; ca. 1 cycle 0xc3fa: c312 clrc ; ca. 1 cycle 0xc3fc: 104e rrc.b R14 ; ca. 1 cycle 0xc3fe: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc402: 5e0e rla R14 ; ca. 1 cycle 0xc404: 510e add SP, R14 ; ca. 1 cycle 0xc406: 4d6d mov.b @R13, R13 ; ca. 1 cycle 0xc408: 5d8e 0000 add R13, 0(R14) ; ca. 4 cycles 0xc40c: 532f incd R15 ; ca. 1 cycle 0xc40e: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc412: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc416: 4f0d mov R15, R13 ; ca. 1 cycle 0xc418: 503d c6b3 add #0xc6b3, R13 ; ca. 2 cycles 0xc41c: 4d7e mov.b @R13+, R14 ; ca. 1 cycle 0xc41e: c312 clrc ; ca. 1 cycle 0xc420: 104e rrc.b R14 ; ca. 1 cycle 0xc422: c312 clrc ; ca. 1 cycle 0xc424: 104e rrc.b R14 ; ca. 1 cycle 0xc426: c312 clrc ; ca. 1 cycle 0xc428: 104e rrc.b R14 ; ca. 1 cycle 0xc42a: c312 clrc ; ca. 1 cycle 0xc42c: 104e rrc.b R14 ; ca. 1 cycle 0xc42e: f03e 000f and #0x000f, R14 ; ca. 2 cycles 0xc432: 5e0e rla R14 ; ca. 1 cycle 0xc434: 510e add SP, R14 ; ca. 1 cycle 0xc436: 4d6d mov.b @R13, R13 ; ca. 1 cycle 0xc438: 8d8e 0000 sub R13, 0(R14) ; ca. 4 cycles 0xc43c: 532f incd R15 ; ca. 1 cycle 0xc43e: 4f81 0020 mov R15, 32(SP) ; ca. 4 cycles 0xc442: 4030 c070 br #0xc070 ; ca. 3 cycles 0xc446: 3fff .L0012: jmp .L0012 ; ca. 2 cycles -2 --> 0xc446 ``` 经过分析,可以发现该汇编实现一个VM,接着提取内层的汇编: ```python ; inner bytecode @ ROM 0xC6B3 ; preinitialized virtual registers: ; const_ptr = 0xC64A ; input_ptr = 0x026A ; work_ptr = 0x0200 ; loop_bound = 0x000D loc_0000: 0000 04 E8 mov tmp_ptr, const_ptr 0002 01 0E ldw v0, [tmp_ptr] 0004 14 E0 02 addi tmp_ptr, 2 0007 01 1E ldw v1, [tmp_ptr] 0009 14 E0 02 addi tmp_ptr, 2 000C 01 2E ldw v2, [tmp_ptr] 000E 14 E0 02 addi tmp_ptr, 2 0011 01 3E ldw v3, [tmp_ptr] 0013 04 E9 mov tmp_ptr, input_ptr 0015 01 5E ldw v5, [tmp_ptr] 0017 14 E0 02 addi tmp_ptr, 2 001A 01 4E ldw v4, [tmp_ptr] 001C 14 E0 02 addi tmp_ptr, 2 001F 01 7E ldw v7, [tmp_ptr] 0021 14 E0 02 addi tmp_ptr, 2 0024 01 6E ldw v6, [tmp_ptr] 0026 0C 00 helper helper_rrcm1 0028 0C 01 helper helper_rram1 002A 0C 02 helper helper_rlam1 002C 0C 03 helper helper_rrum1 002E 09 0C jmp loc_003C ; signed rel8 +12 loc_003C: 003C 04 EA mov tmp_ptr, work_ptr 003E 02 0E stw [tmp_ptr], v0 0040 14 E0 02 addi tmp_ptr, 2 0043 02 1E stw [tmp_ptr], v1 0045 14 E0 02 addi tmp_ptr, 2 0048 02 2E stw [tmp_ptr], v2 004A 14 E0 02 addi tmp_ptr, 2 004D 02 3E stw [tmp_ptr], v3 004F 04 E8 mov tmp_ptr, const_ptr 0051 04 FA mov tmp_work, work_ptr 0053 03 00 04 00 movi v0, 0x0004 loc_0057: 0057 01 1E ldw v1, [tmp_ptr] 0059 01 2F ldw v2, [tmp_work] 005B 08 12 cmpeq v1, v2 ; sets the VM flag byte to 1 iff equal 005D 0B 0C jfalse loc_006B ; branch if VM flag byte == 0, rel8 +12 loc_005F: 005F 14 E0 02 addi tmp_ptr, 2 0062 14 F0 02 addi tmp_work, 2 0065 11 00 dec v0 ; updates the VM flag byte with zero(result) 0067 0B EE jfalse loc_0057 ; branch if VM flag byte == 0, rel8 -18 loc_0069: 0069 10 B0 inc vB ; updates the VM flag byte with zero(result) loc_006B: 006B 14 80 08 addi const_ptr, 8 006E 14 90 08 addi input_ptr, 8 0071 14 A0 08 addi work_ptr, 8 0074 10 C0 inc vC ; updates the VM flag byte with zero(result) 0076 08 CD cmpeq vC, loop_bound ; sets the VM flag byte to 1 iff equal 0078 0B 86 jfalse loc_0000 ; branch if VM flag byte == 0, rel8 -122 loc_007A: 007A 08 BD cmpeq vB, loop_bound ; sets the VM flag byte to 1 iff equal 007C 0B 06 jfalse loc_0084 ; branch if VM flag byte == 0, rel8 +6 loc_007E: 007E 03 00 37 13 movi v0, 0x1337 0082 09 02 jmp loc_0086 ; signed rel8 +2 loc_0084: 0084 04 0B mov v0, vB loc_0086: 0086 03 E0 68 02 movi tmp_ptr, 0x0268 008A 02 0E stw [tmp_ptr], v0 008C 00 halt ; interpreter would fall into the invalid-op trap ``` 这里可以看到很简单的运算后然后比较,但是稍微发现就会发现运算的古怪之处,如果扩展指令合法的话,压根就没有使用到全部的输入这非常不合理。 并且rrcm这种指令是在msp40X(20位)上支持,本题的msp40(16位)是不支持的。 题目肯定存在处理这些扩展指令的逻辑 ## eavl函数分析 vatbale[3]就是eavl函数,总体有2000多行,丢给AI,可以分析出其有Fistel、sbox、列混合等操作。 但是我的AI分析的轮数错误了,导致我调试纠错花费了很多时间。 而且也不要直接调试eval函数,这个函数会一直跑,如果下断点会有很多噪声(经验之谈) ## gdb脚本探测内存 可以看内存汇编,一开始操作栈帧:sp-0x24,后面mov #imm, imm(sp),这里可以看到这是对内存虚拟寄存器开辟空间,0x24=36正好是18个16位寄存器的大小。 但是在宿主机上调试实际上的地址是 sp - 0x24 * 2 , 并且16位寄存器实际占用4个字节,这个差异化实现还是挺坑的,不过写脚本验证可以纠正。 ```python set pagination off set confirm off set debuginfod enabled off file /mnt/h/CTF/CODEGATE2026/Silicon\ Dream/hand/challenge set args 6161616162616161636161616461616165616161666161616761616168616161696161616a6161616b6161616c6161616d6161616e6161616f616161706161617161616172616161736161617461616175616161766161617761616178616161796161617a616162 b *0x40A4B8 run set $vm = $rsp + 0x80 set $ram = *(void**)($vm+0x468) set $stack = $ram+0x3b8 set $slot = $ram+0x3c4 set $slot_hits = 0 printf "vmctx=%p ram=%p stack=%p slot=%p\n", $vm, $ram, $stack, $slot watch *(unsigned int*)$slot commands silent set $slot_hits = $slot_hits + 1 printf "[slot-hit #%u] rip=%p\n", $slot_hits, $pc printf "[before-patch]\n" x/8wx $stack set *(unsigned int*)($stack+0x0) = 0x00003939 set *(unsigned int*)($stack+0x4) = 0x00006c20 set *(unsigned int*)($stack+0x8) = 0x00007469 set *(unsigned int*)($stack+0xc) = 0x00006c74 printf "[after-patch]\n" x/8wx $stack continue end continue ``` 查看 R0-3, R4-7的内容真相大白 ## 加密分析 题目使用的经典fistel网络,只不过F是由sbox + mixColumns实现  这道题目很巧的是最后密文,在加密一开始就参与了加密,实际上就是要计算: 现在的未知量恰恰是 `U_L/U_R` 本身,所以你面对的是: - 一个**带未知轮注入量的固定点方程** 当前 4 轮模型是: - `B1 = A0 ^ F(B0 ^ U_L ^ k1)` - `B2 = B0 ^ F(B1 ^ U_R ^ k2)` - `B3 = B1 ^ F(B2 ^ U_L ^ k3)` - `B4 = B2 ^ F(B3 ^ U_R ^ k4)` 固定点条件是: - `B3 = A0` - `B4 = B0` 将条件带入可得 ```python b1 = a0 ^ k2 ^ k4 b2 = b0 ^ k1 ^ k3 ``` 题目用的sbox正好是自反置换,也就是说INV_SBOX == SBOX 那么只要实现F_INV(),就能反推出U_L, U_R最终拿到flag ## 求解 AI直接写出求解脚本 ```python from __future__ import annotations import argparse import re import subprocess from dataclasses import dataclass from pathlib import Path HAND = Path(r"H:\CTF\CODEGATE2026\Silicon Dream\hand") TMP_GDB = HAND / "_tmp_exp_forward_verify.gdb" CHALLENGE_WSL = "/mnt/h/CTF/CODEGATE2026/Silicon Dream/hand/challenge" GDB_WSL = "/mnt/h/CTF/CODEGATE2026/Silicon Dream/hand/_tmp_exp_forward_verify.gdb" ROUND_KEYS = [ 0xE4AFC9DF, 0xAF10C5B5, 0x4361F2A6, 0xDB948BBC, ] TARGET_HEX = ( "3939206c6974746c65206275677320696e2074686520636f64652c203939206c69" "74746c6520627567732e2054616b65206f6e6520646f776e2c2070617463682069" "742061726f756e642c20313237206c6974746c65206275677320696e2074686520" "636f64652e" ) TARGET_DATA = bytes.fromhex(TARGET_HEX) DEFAULT_PAYLOAD_HEX = 'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaab'.encode().hex() CUSTOM_SBOX = [ 0x00, 0x10, 0xB1, 0xD1, 0x91, 0xE1, 0x60, 0x70, 0xC7, 0x57, 0x86, 0x36, 0xF6, 0x26, 0x47, 0xA7, 0x01, 0x11, 0xCC, 0xAA, 0xFF, 0x88, 0x61, 0x71, 0x40, 0xDA, 0x20, 0x9F, 0x30, 0xE8, 0xBC, 0x50, 0x1A, 0xA2, 0x7E, 0xEC, 0x83, 0x68, 0x0D, 0xDE, 0xF9, 0x97, 0x3C, 0x2B, 0x59, 0x4F, 0xCA, 0xB7, 0x1C, 0xC3, 0x9A, 0x79, 0x6F, 0xF2, 0x0B, 0xB9, 0xD7, 0xAC, 0x4E, 0x58, 0x2A, 0x3D, 0xE7, 0x8E, 0x18, 0x84, 0x7C, 0xC5, 0x6B, 0xBF, 0xEB, 0x0E, 0x5F, 0x49, 0x96, 0xF8, 0xAD, 0xD6, 0x3A, 0x2D, 0x1F, 0xF5, 0xA4, 0x7A, 0xD8, 0x6D, 0x9D, 0x09, 0x3B, 0x2C, 0xCB, 0xB6, 0xE6, 0x8F, 0x5E, 0x48, 0x06, 0x16, 0xFE, 0x89, 0xD0, 0xB0, 0x66, 0x76, 0x25, 0xC0, 0x99, 0x44, 0xEE, 0x55, 0xA0, 0x34, 0x07, 0x17, 0x90, 0xE0, 0xAB, 0xCD, 0x67, 0x77, 0xDD, 0x33, 0x53, 0x80, 0x42, 0xF0, 0x22, 0xBB, 0x7B, 0xA5, 0xC1, 0x24, 0x41, 0xDB, 0x0A, 0xB8, 0x15, 0x63, 0xE2, 0xFD, 0x8C, 0x94, 0x3F, 0x5D, 0x72, 0x04, 0xE3, 0xFC, 0x8D, 0x95, 0x4A, 0x29, 0xBE, 0x6A, 0x32, 0xDC, 0xC6, 0x56, 0xA3, 0x1B, 0x6E, 0xF3, 0x21, 0x9E, 0x52, 0x81, 0xEA, 0x0F, 0xA8, 0xB2, 0x13, 0x74, 0x39, 0x4C, 0xC9, 0xD5, 0x65, 0x02, 0xA9, 0xB3, 0xC8, 0xD4, 0x5B, 0x2F, 0x87, 0x37, 0xED, 0x7F, 0x1E, 0xF4, 0x98, 0x45, 0x69, 0x82, 0xE9, 0x31, 0xF1, 0x43, 0x9C, 0x08, 0xB4, 0xAE, 0x2E, 0x5A, 0x12, 0x75, 0xD3, 0xCF, 0x64, 0x03, 0xD2, 0xCE, 0xB5, 0xAF, 0x4D, 0x38, 0x54, 0xEF, 0x19, 0x85, 0x9B, 0x78, 0x27, 0xF7, 0x73, 0x05, 0x8A, 0x92, 0xE4, 0xFB, 0x5C, 0x3E, 0x1D, 0xC2, 0xA6, 0x46, 0x23, 0xBA, 0x6C, 0xD9, 0x7D, 0xC4, 0x35, 0xA1, 0xBD, 0x51, 0x0C, 0xDF, 0x4B, 0x28, 0xFA, 0xE5, 0x93, 0x8B, 0x62, 0x14, ] assert len(CUSTOM_SBOX) == 256 and len(set(CUSTOM_SBOX)) == 256 INV_SBOX = [0] * 256 for _idx, _value in enumerate(CUSTOM_SBOX): INV_SBOX[_value] = _idx assert INV_SBOX == CUSTOM_SBOX @dataclass(frozen=True) class RoundTrace: block_idx: int round_idx: int round_key: int user_half: int acc_l_in: int acc_r_in: int x: int fx: int acc_l_out: int acc_r_out: int def xtime(value: int) -> int: value &= 0xFF if value & 0x80: return ((value << 1) ^ 0x1B) & 0xFF return (value << 1) & 0xFF def gf_mul(a: int, b: int) -> int: a &= 0xFF b &= 0xFF out = 0 cur = a mask = b while mask: if mask & 1: out ^= cur cur = xtime(cur) mask >>= 1 return out & 0xFF def f_function(word32: int) -> int: b0 = CUSTOM_SBOX[(word32 >> 0) & 0xFF] b1 = CUSTOM_SBOX[(word32 >> 8) & 0xFF] b2 = CUSTOM_SBOX[(word32 >> 16) & 0xFF] b3 = CUSTOM_SBOX[(word32 >> 24) & 0xFF] t = b0 ^ b1 ^ b2 ^ b3 o0 = b0 ^ t ^ xtime(b0 ^ b1) o1 = b1 ^ t ^ xtime(b1 ^ b2) o2 = b2 ^ t ^ xtime(b2 ^ b3) o3 = b3 ^ t ^ xtime(b3 ^ b0) # Dynamic tracing shows the hardware rotates the 4-byte MixColumns output by one byte # before packing it back into a 32-bit word. return o1 | (o2 << 8) | (o3 << 16) | (o0 << 24) def f_inv(word32: int) -> int: p0 = (word32 >> 0) & 0xFF p1 = (word32 >> 8) & 0xFF p2 = (word32 >> 16) & 0xFF p3 = (word32 >> 24) & 0xFF # Undo the one-byte rotate used when packing the MixColumns result. o0, o1, o2, o3 = p3, p0, p1, p2 s0 = gf_mul(o0, 0x0E) ^ gf_mul(o1, 0x0B) ^ gf_mul(o2, 0x0D) ^ gf_mul(o3, 0x09) s1 = gf_mul(o0, 0x09) ^ gf_mul(o1, 0x0E) ^ gf_mul(o2, 0x0B) ^ gf_mul(o3, 0x0D) s2 = gf_mul(o0, 0x0D) ^ gf_mul(o1, 0x09) ^ gf_mul(o2, 0x0E) ^ gf_mul(o3, 0x0B) s3 = gf_mul(o0, 0x0B) ^ gf_mul(o1, 0x0D) ^ gf_mul(o2, 0x09) ^ gf_mul(o3, 0x0E) x0 = INV_SBOX[s0] x1 = INV_SBOX[s1] x2 = INV_SBOX[s2] x3 = INV_SBOX[s3] return x0 | (x1 << 8) | (x2 << 16) | (x3 << 24) def solve_block_via_midstate(target_block: bytes) -> bytes: if len(target_block) != 8: raise ValueError("target_block must be exactly 8 bytes") k1, k2, k3, k4 = ROUND_KEYS a0 = int.from_bytes(target_block[:4], "little") b0 = int.from_bytes(target_block[4:], "little") # Fixed-point equations after 4 rounds: # B3 = A0 # B4 = B0 # with # B1 = A0 ^ k2 ^ k4 # B2 = B0 ^ k1 ^ k3 b1 = a0 ^ k2 ^ k4 b2 = b0 ^ k1 ^ k3 # Recover the two user halves directly through F^{-1}. u_l = f_inv(a0 ^ b1) ^ b0 ^ k1 u_r = f_inv(b0 ^ b2) ^ a0 ^ k4 return u_l.to_bytes(4, "little") + u_r.to_bytes(4, "little") def solve_payload_via_midstate(target_data: bytes) -> bytes: if len(target_data) % 8 != 0: raise ValueError("target_data length must be a multiple of 8 bytes") out = bytearray() for off in range(0, len(target_data), 8): out.extend(solve_block_via_midstate(target_data[off : off + 8])) return bytes(out) def encrypt_block_from_exp( block0: bytes, target_block: bytes, *, block_idx: int = 0 ) -> tuple[bytes, list[RoundTrace]]: if len(block0) != 8: raise ValueError("block0 must be exactly 8 bytes") if len(target_block) != 8: raise ValueError("target_block must be exactly 8 bytes") user_l, user_r = int.from_bytes(block0[:4], "little"), int.from_bytes(block0[4:], "little") acc_l = int.from_bytes(target_block[:4], "little") acc_r = int.from_bytes(target_block[4:], "little") traces: list[RoundTrace] = [] for round_idx, round_key in enumerate(ROUND_KEYS): acc_l_in, acc_r_in = acc_l, acc_r user_half = user_l if (round_idx % 2 == 0) else user_r x = (acc_r ^ user_half ^ round_key) & 0xFFFFFFFF fx = f_function(x) next_acc = (acc_l ^ fx) & 0xFFFFFFFF acc_l, acc_r = acc_r, next_acc traces.append( RoundTrace( block_idx=block_idx, round_idx=round_idx + 1, round_key=round_key, user_half=user_half, acc_l_in=acc_l_in, acc_r_in=acc_r_in, x=x, fx=fx, acc_l_out=acc_l, acc_r_out=acc_r, ) ) return acc_l.to_bytes(4, "little") + acc_r.to_bytes(4, "little"), traces def encrypt_payload_from_exp(payload: bytes, target_data: bytes) -> tuple[bytes, list[RoundTrace]]: if len(payload) != len(target_data): raise ValueError("payload and target_data must have the same length") if len(payload) % 8 != 0: raise ValueError("payload length must be a multiple of 8 bytes") out = bytearray() traces: list[RoundTrace] = [] for block_idx, off in enumerate(range(0, len(payload), 8)): block = payload[off : off + 8] target_block = target_data[off : off + 8] enc_block, block_traces = encrypt_block_from_exp(block, target_block, block_idx=block_idx) out.extend(enc_block) traces.extend(block_traces) return bytes(out), traces def words_from_block(block8: bytes) -> tuple[int, int, int, int]: return tuple(int.from_bytes(block8[i : i + 2], "little") for i in range(0, 8, 2)) def fmt_words(words: tuple[int, int, int, int]) -> str: return "[" + ", ".join(f"0x{word:04X}" for word in words) + "]" def fmt_block64(block8: bytes) -> str: words = words_from_block(block8) return "0x" + "".join(f"{word:04x}" for word in reversed(words)) def fmt_u32(value: int) -> str: return f"0x{value:08X}" def normalize_hex(text: str) -> str: return "".join(ch for ch in text if ch not in " \t\r\n").lower() def make_gdb_script(payload_hex: str) -> str: return "\n".join( [ "set pagination off", "set confirm off", "set debuginfod enabled off", f'file "{CHALLENGE_WSL}"', f"set args {payload_hex}", "b *0x40A4B8", "run", "set $vm = $rsp + 0x80", "set $ram = *(void**)($vm+0x468)", "watch *(unsigned int*)$ram", "continue", "x/8wx $ram+0x3b8", "quit", "", ] ) def parse_gdb_words(stdout: str) -> tuple[int, int, int, int]: for line in stdout.splitlines(): m = re.match( r"^0x[0-9a-fA-F]+:\s+0x([0-9a-fA-F]+)\s+0x([0-9a-fA-F]+)\s+0x([0-9a-fA-F]+)\s+0x([0-9a-fA-F]+)$", line.strip(), ) if not m: continue return tuple(int(m.group(i), 16) & 0xFFFF for i in range(1, 5)) raise RuntimeError("failed to parse first-store words from gdb output") def run_gdb_probe(block0: bytes) -> tuple[int, int, int, int]: payload = bytearray(104) payload[:8] = block0 payload_hex = payload.hex() TMP_GDB.write_text(make_gdb_script(payload_hex), encoding="utf-8", newline="\n") proc = subprocess.run( ["wsl", "bash", "-lc", f"gdb -nx -q -batch -x '{GDB_WSL}'"], capture_output=True, text=True, encoding="utf-8", errors="ignore", check=True, ) return parse_gdb_words(proc.stdout) def verify_payload(payload_hex: str, *, do_gdb: bool) -> None: payload_hex = normalize_hex(payload_hex) if len(payload_hex) != 208: raise ValueError("payload must be exactly 104 bytes / 208 hex chars") payload = bytes.fromhex(payload_hex) block0 = payload[:8] target_block = TARGET_DATA[:8] predicted_data, traces = encrypt_payload_from_exp(payload, TARGET_DATA) predicted_block = predicted_data[:8] predicted_words = words_from_block(predicted_block) print("[payload]") print(f"input payload : {payload_hex}") print(f"input block0 : {block0.hex()}") print(f"target block0 : {target_block.hex()} {fmt_words(words_from_block(target_block))}") print(f"model block0 : {fmt_block64(predicted_block)} {fmt_words(predicted_words)}") print(f"model full hex : {predicted_data.hex()}") print("") print("[round-trace]") for trace in traces: print( f"b{trace.block_idx:02d}.r{trace.round_idx:02d} " f"key={fmt_u32(trace.round_key)} " f"user={fmt_u32(trace.user_half)} " f"A_in={fmt_u32(trace.acc_l_in)} " f"B_in={fmt_u32(trace.acc_r_in)} " f"X={fmt_u32(trace.x)} " f"F={fmt_u32(trace.fx)} " f"A_out={fmt_u32(trace.acc_l_out)} " f"B_out={fmt_u32(trace.acc_r_out)}" ) if do_gdb: print("") gdb_words = run_gdb_probe(block0) print(f"gdb first-store: {fmt_words(gdb_words)}") print(f"match-gdb : {predicted_words == gdb_words}") print("") def main() -> None: parser = argparse.ArgumentParser( description="Forward encryption model derived directly from hand/exp.py, with optional GDB verification." ) parser.add_argument( "payload_hex", nargs="?", default=DEFAULT_PAYLOAD_HEX, help="full 104-byte payload as 208 hex chars; default is all 'aa'", ) parser.add_argument( "--no-gdb", action="store_true", help="skip live GDB verification", ) args = parser.parse_args() verify_payload(args.payload_hex, do_gdb=not args.no_gdb) if __name__ == "__main__": main() ``` ```python from z3 import * import struct import time from exp_forward import ( CUSTOM_SBOX, INV_SBOX, ROUND_KEYS, TARGET_DATA, encrypt_block_from_exp, solve_block_via_midstate, ) print("[+] 正在加载硬件密码协处理器的硅片模型...") # ⚠️ 神级优化:用 O(logN) 的二分树替换低效的 Z3 Array def sbox_lookup_z3(x): def build_tree(l, r): if l == r: return BitVecVal(CUSTOM_SBOX[l], 8) mid = (l + r) // 2 # ULT: Unsigned Less Than (无符号小于) return If(ULT(x, mid + 1), build_tree(l, mid), build_tree(mid + 1, r)) return build_tree(0, 255) # 4. Z3 下的 MixColumns def xtime_z3(a): return If(a & 0x80 != 0, (a << 1) ^ 0x1B, a << 1) & 0xFF def mix_single_column_z3(s0, s1, s2, s3): t = s0 ^ s1 ^ s2 ^ s3 u = s0 out0 = s0 ^ t ^ xtime_z3(s0 ^ s1) out1 = s1 ^ t ^ xtime_z3(s1 ^ s2) out2 = s2 ^ t ^ xtime_z3(s2 ^ s3) out3 = s3 ^ t ^ xtime_z3(s3 ^ u) return out0, out1, out2, out3 def F_function_z3(X_32bit): # 用优化后的二分树进行查表 b0 = sbox_lookup_z3(Extract(7, 0, X_32bit)) b1 = sbox_lookup_z3(Extract(15, 8, X_32bit)) b2 = sbox_lookup_z3(Extract(23, 16, X_32bit)) b3 = sbox_lookup_z3(Extract(31, 24, X_32bit)) m0, m1, m2, m3 = mix_single_column_z3(b0, b1, b2, b3) return Concat(m0, m3, m2, m1) def encrypt_block_z3(U_L, U_R, T_L, T_R): """ Mirror hand/exp_forward.py exactly: - one 8-byte block at a time - 4 rounds - user_half alternates U_L/U_R - A_out = B_in - B_out = A_in ^ F(B_in ^ user_half ^ round_key) """ A = BitVecVal(T_L, 32) B = BitVecVal(T_R, 32) for round_idx, r_key in enumerate(ROUND_KEYS): user_half = U_L if (round_idx % 2 == 0) else U_R X = B ^ user_half ^ BitVecVal(r_key, 32) A_next = A ^ F_function_z3(X) A = B B = A_next return A, B def add_printable_ascii_constraints(solver, word32): for shift in (0, 8, 16, 24): byte = Extract(shift + 7, shift, word32) solver.add(UGE(byte, BitVecVal(0x20, 8))) solver.add(ULE(byte, BitVecVal(0x7E, 8))) # ============================================================== # 分组求解循环 # 先使用 4 轮固定点方程的中间态化简直接恢复 U_L/U_R, # 再用 forward 模型复核结果。 # ============================================================== flag_bytes = b"" flag_hex_parts = [] print("[+] 使用中间态化简恢复每组输入,并用 forward 模型复核...\n") for i in range(0, len(TARGET_DATA), 8): block = TARGET_DATA[i:i+8] T_L, T_R = struct.unpack('<II', block) print(f"[*] 正在撕裂 Block {i//8 + 1}/13 ...") start_time = time.time() chunk = solve_block_via_midstate(block) ul_val, ur_val = struct.unpack("<II", chunk) out_block, _ = encrypt_block_from_exp(chunk, block, block_idx=i // 8) if out_block != block: print(f" [-] forward 复核失败: got={out_block.hex()} expected={block.hex()}") break flag_bytes += chunk flag_hex_parts.append(chunk.hex()) print( f" [+] 解出: {chunk} " f"(U_L=0x{ul_val:08X}, U_R=0x{ur_val:08X}; 仅耗时: {time.time() - start_time:.3f} 秒)" ) print("\n=======================================================") print("[] 硅之梦核心已被彻底击穿!终极 FLAG: ") print(flag_bytes.decode('ascii', errors='ignore')) print("".join(flag_hex_parts)) print("=======================================================") ``` # 反思 让ai辅助得时候,自己也要主动思考,不能完全让ai带着走。
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
#Reverse
上传的附件:
challenge
(1.35MB,5次下载)
收藏
・
0
点赞
・
1
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
wx_晨梦
期待更多优质内容的分享,论坛有你更精彩!
2026-7-16 08:41
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
SleepAlone
3
17
发帖
50
回帖
230
RANK
关注
私信
他的文章
[原创][推荐][原创]CodeGateCTF 2026 - Silicon Dream WP
3286
[原创] 强网杯2025-PolyEncryption之Vibe Reing的胜利
11449
[原创] JustCTF 6pack wp
5108
[原创]从Google CTF Fluffy 看Dart逆向
4986
[原创]DEFCON33-Quals nfuncs angr➕unicorn 快速自动化逆向
4720
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
谁下载
×
huangyalei
ONewTach
npc0vo
mb_kujsrqqv
mb_lthgjpwj
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部