-
-
[原创]KCTF2022春季赛第3题 石像病毒
-
2022-5-15 11:03 6907
-
SEH 相关题目,我这次主要采取静态分析方法解题,核心是人脑修复 SEH 的控制流跳转,从而让 IDA 可以 F5。
main 函数中的异常处理并没有什么特别的地方,大多是内存的初始化。关键引起我注意的是这么几个地方:
1 2 3 4 5 | ...... strcpy((char * )&v8[ 9 ], "Enj0y_1t_4_fuuuN" ); ...... sub_401109(&v8[ 9 ], 0x10u , ( int )&v8[ 2 ]); sub_401104(&v8[ 2 ], 0x10u , ( int )&v8[ 30 ], ( int )&v8[ 18 ], 32 ); |
使用 IDA findcrypt 插件可以发现,sub_401109
和 sub_401104
分别是 MD5 和 aesEncrypt。首先根据特征找到作者使用的 github 上的开源实现:
但还不能肯定没有魔改。首先人工修复一下 SEH 的异常处理:主要思路是把触发异常的语句 patch 为 jmp 到 except filter,并且把 retn 改成 nop 让执行流顺序执行到 except 块,然后跳转回 try 块中触发异常的下一条指令,最后再跳出来。以 MD5 函数中的这个为例:
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 | .text: 00402D13 ; __try { / / __except at loc_402D34 .text: 00402D13 mov [ebp + ms_exc.registration.TryLevel], 0 .text: 00402D1A xor ebx, ebx .text: 00402D1C jmp short loc_402D27 ; [Keypatch] modified this from : .text: 00402D1C ; } / / starts at 402D13 ; div ebx .text: 00402D1E ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .text: 00402D1E .text: 00402D1E loc_402D1E: ; CODE XREF: sub_402CE0 + 57 ↓j .text: 00402D1E mov [ebp + ms_exc.registration.TryLevel], 0FFFFFFFEh .text: 00402D25 jmp short loc_402D3E .text: 00402D27 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .text: 00402D27 .text: 00402D27 loc_402D27: ; CODE XREF: sub_402CE0 + 3C ↑j .text: 00402D27 ; DATA XREF: .rdata:stru_40A080↓o .text: 00402D27 ; __except filter / / owned by 402D13 .text: 00402D27 mov eax, [ebp + ms_exc.exc_ptr] .text: 00402D2A push eax .text: 00402D2B call sub_4010FA .text: 00402D30 add esp, 4 .text: 00402D33 nop ; [Keypatch] modified this from : .text: 00402D33 ; retn .text: 00402D34 .text: 00402D34 loc_402D34: ; DATA XREF: .rdata:stru_40A080↓o .text: 00402D34 ; __except(loc_402D27) / / owned by 402D13 .text: 00402D34 mov esp, [ebp + ms_exc.old_esp] .text: 00402D37 jmp short loc_402D1E ; [Keypatch] modified this from : .text: 00402D37 ; mov [ebp + ms_exc.registration.TryLevel], 0FFFFFFFEh .text: 00402D37 ; [Keypatch] padded NOP to next boundary: 5 bytes .text: 00402D39 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .text: 00402D39 nop .text: 00402D3A nop .text: 00402D3B nop .text: 00402D3C nop .text: 00402D3D nop .text: 00402D3E .text: 00402D3E loc_402D3E: ; CODE XREF: sub_402CE0 + 45 ↑j .text: 00402D3E mov ecx, 1 |
同样,AES 中的密钥扩展、行移位和列混淆中也有几处。
修复完阅读可以发现,作者在下面几处地方做了魔改:
- shiftRows 改成了 invShiftRows:
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 | int sub_401AE0() { int * v0; / / ebp int v1; / / ecx int v3; / / [esp + 10h ] [ebp - 38h ] int v4; / / [esp + 14h ] [ebp - 34h ] int v5; / / [esp + 18h ] [ebp - 30h ] int v6; / / [esp + 1Ch ] [ebp - 2Ch ] int v7; / / [esp + 20h ] [ebp - 28h ] int v8; / / [esp + 24h ] [ebp - 24h ] int v9; / / [esp + 28h ] [ebp - 20h ] int v10; / / [esp + 2Ch ] [ebp - 1Ch ] int savedregs; / / [esp + 48h ] [ebp + 0h ] BYREF v0 = &savedregs; v4 = - 858993460 ; v9 = - 858993460 ; v10 = - 858993460 ; v5 = 0 ; v6 = 0 ; v7 = 0 ; v8 = 0 ; v3 = 0 ; while ( * (v0 - 14 ) < 4 ) { v0[ * (v0 - 14 ) - 12 ] = _byteswap_ulong( * (_DWORD * )(v0[ 2 ] + 4 * * (v0 - 14 ))); * (v0 - 1 ) = 0 ; v0 = ( int * )((char * )v0 - 1 ); v1 = * (v0 - 14 ); v0[v1 - 12 ] = __ROR4__(v0[v1 - 12 ], 8 * v1); v0[ * (v0 - 14 ) - 12 ] = ((unsigned int )v0[ * (v0 - 14 ) - 12 ] >> ( 32 - 8 * * ((_BYTE * )v0 - 56 ))) | (v0[ * (v0 - 14 ) - 12 ] << v1); * (v0 - 1 ) = - 2 ; * (_BYTE * )(v0[ 2 ] + 4 * * (v0 - 14 )) = HIBYTE(v0[ * (v0 - 14 ) - 12 ]); * (_BYTE * )(v0[ 2 ] + 4 * * (v0 - 14 ) + 1 ) = BYTE2(v0[ * (v0 - 14 ) - 12 ]); * (_BYTE * )(v0[ 2 ] + 4 * * (v0 - 14 ) + 2 ) = BYTE1(v0[ * (v0 - 14 ) - 12 ]); * (_BYTE * )(v0[ 2 ] + 4 * * (v0 - 14 ) + 3 ) = v0[ * (v0 - 14 ) - 12 ]; + + * (v0 - 14 ); } return 0 ; } |
- 密钥扩展处更改了 sbox,即交换 sbox[113] 和 sbox[163]
- 列混淆中的 GMul 函数将密文 cipher[16] 和 cipher[17] 交换顺序
- 还有上文中提到的 MD5 函数代码中把 MD5 常数 k[42] 改成了 0xD4AF3085。
最后去解密就好,拿到 flag{db5c6a8dfec4d0ec5569899640}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2022-5-15 11:09
被trackL编辑
,原因:
赞赏
看原图