首页
社区
课程
招聘
[原创] 看雪.TSRC 2017CTF秋季赛第三题crackMe破解过程
2017-10-28 23:55 3098

[原创] 看雪.TSRC 2017CTF秋季赛第三题crackMe破解过程

2017-10-28 23:55
3098
本题反调试比较多,算法有BUG,分析得可能不算到位,请见谅。
下载地址:https://ctf.pediy.com/attach-download-80.htm

一、侦查
    无壳,粗略分析有Base64等算法,有成功提示信息,定位"ok"找到注册算法流程:
00435061   .  68 01040000   PUSH 0x401                               ; /Count = 401 (1025.)
00435066   .  8D85 D8F7FFFF LEA EAX,DWORD PTR SS:[EBP-0x828]         ; |
0043506C   .  50            PUSH EAX                                 ; |Buffer
0043506D   .  68 E9030000   PUSH 0x3E9                               ; |ControlID = 3E9 (1001.)
00435072   .  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+0x8]           ; |
00435075   .  51            PUSH ECX                                 ; |hWnd
00435076   .  FF15 70F54900 CALL DWORD PTR DS:[<&USER32.GetDlgItemTe>; \GetDlgItemTextA
0043507C   .  3BF4          CMP ESI,ESP
0043507E   .  E8 CE8DFFFF   CALL crackMe3.0042DE51
00435083   .  8985 E0FBFFFF MOV DWORD PTR SS:[EBP-0x420],EAX
00435089   .  C685 C8EFFFFF>MOV BYTE PTR SS:[EBP-0x1038],0x0
00435090   .  68 FF030000   PUSH 0x3FF
00435095   .  6A 00         PUSH 0x0
00435097   .  8D85 C9EFFFFF LEA EAX,DWORD PTR SS:[EBP-0x1037]
0043509D   .  50            PUSH EAX
0043509E   .  E8 4385FFFF   CALL crackMe3.0042D5E6
004350A3   .  83C4 0C       ADD ESP,0xC
004350A6   .  8D85 D0F3FFFF LEA EAX,DWORD PTR SS:[EBP-0xC30]
004350AC   .  50            PUSH EAX
004350AD   .  68 00040000   PUSH 0x400
004350B2   .  8D8D D8F7FFFF LEA ECX,DWORD PTR SS:[EBP-0x828]
004350B8   .  51            PUSH ECX
004350B9   .  E8 A981FFFF   CALL crackMe3.0042D267                   ;  Base64解码
004350BE   .  83C4 0C       ADD ESP,0xC
004350C1   .  C685 C0EBFFFF>MOV BYTE PTR SS:[EBP-0x1440],0x0
004350C8   .  68 FF030000   PUSH 0x3FF
004350CD   .  6A 00         PUSH 0x0
004350CF   .  8D85 C1EBFFFF LEA EAX,DWORD PTR SS:[EBP-0x143F]
004350D5   .  50            PUSH EAX
004350D6   .  E8 0B85FFFF   CALL crackMe3.0042D5E6
004350DB   .  83C4 0C       ADD ESP,0xC
004350DE   .  8D85 C8EFFFFF LEA EAX,DWORD PTR SS:[EBP-0x1038]
004350E4   .  50            PUSH EAX
004350E5   .  68 00040000   PUSH 0x400
004350EA   .  8D8D D0F3FFFF LEA ECX,DWORD PTR SS:[EBP-0xC30]
004350F0   .  51            PUSH ECX
004350F1   .  E8 7181FFFF   CALL crackMe3.0042D267                   ;  Base64解码
004350F6   .  83C4 0C       ADD ESP,0xC
004350F9   .  68 00040000   PUSH 0x400
004350FE   .  8D85 C0EBFFFF LEA EAX,DWORD PTR SS:[EBP-0x1440]
00435104   .  50            PUSH EAX
00435105   .  8D8D C8EFFFFF LEA ECX,DWORD PTR SS:[EBP-0x1038]
0043510B   .  51            PUSH ECX
0043510C   .  E8 5988FFFF   CALL crackMe3.0042D96A                   ;  0x20 set
00435111   .  83C4 0C       ADD ESP,0xC
00435114   .  C785 B4EBFFFF>MOV DWORD PTR SS:[EBP-0x144C],0x3
0043511E   .  8D85 8CEBFFFF LEA EAX,DWORD PTR SS:[EBP-0x1474]
00435124   .  50            PUSH EAX
00435125   .  8B8D B4EBFFFF MOV ECX,DWORD PTR SS:[EBP-0x144C]
0043512B   .  51            PUSH ECX
0043512C   .  8D95 C8EFFFFF LEA EDX,DWORD PTR SS:[EBP-0x1038]
00435132   .  52            PUSH EDX
00435133   .  E8 4089FFFF   CALL crackMe3.0042DA78                   ;  国密SM3(前3字节)
00435138   .  83C4 0C       ADD ESP,0xC
0043513B   .  C785 78E7FFFF>MOV DWORD PTR SS:[EBP-0x1888],0x0
00435145   .  EB 0F         JMP XcrackMe3.00435156
00435147   >  8B85 78E7FFFF MOV EAX,DWORD PTR SS:[EBP-0x1888]
0043514D   .  83C0 01       ADD EAX,0x1
00435150   .  8985 78E7FFFF MOV DWORD PTR SS:[EBP-0x1888],EAX
00435156   >  83BD 78E7FFFF>CMP DWORD PTR SS:[EBP-0x1888],0x20
0043515D   .  7D 2C         JGE XcrackMe3.0043518B
0043515F   .  8B85 78E7FFFF MOV EAX,DWORD PTR SS:[EBP-0x1888]
00435165   .  0FB68C05 8CEB>MOVZX ECX,BYTE PTR SS:[EBP+EAX-0x1474]
0043516D   .  51            PUSH ECX
0043516E   .  68 A4B14800   PUSH crackMe3.0048B1A4                   ;  ASCII "%02x"
00435173   .  8B95 78E7FFFF MOV EDX,DWORD PTR SS:[EBP-0x1888]
00435179   .  8D8455 84E7FF>LEA EAX,DWORD PTR SS:[EBP+EDX*2-0x187C]
00435180   .  50            PUSH EAX
00435181   .  E8 7F8DFFFF   CALL crackMe3.0042DF05                   ;  十六进制转ASCII
00435186   .  83C4 0C       ADD ESP,0xC
00435189   .^ EB BC         JMP XcrackMe3.00435147
0043518B   >  8D85 84E7FFFF LEA EAX,DWORD PTR SS:[EBP-0x187C]
00435191   .  50            PUSH EAX
00435192   .  E8 FD85FFFF   CALL crackMe3.0042D794                   ;  len
00435197   .  83C4 04       ADD ESP,0x4
0043519A   .  50            PUSH EAX
0043519B   .  8D8D D8F7FFFF LEA ECX,DWORD PTR SS:[EBP-0x828]
004351A1   .  51            PUSH ECX
004351A2   .  E8 ED85FFFF   CALL crackMe3.0042D794                   ;  len
004351A7   .  83C4 04       ADD ESP,0x4
004351AA   .  8DB405 D8F7FF>LEA ESI,DWORD PTR SS:[EBP+EAX-0x828]
004351B1   .  8D95 84E7FFFF LEA EDX,DWORD PTR SS:[EBP-0x187C]
004351B7   .  52            PUSH EDX
004351B8   .  E8 D785FFFF   CALL crackMe3.0042D794                   ;  len
004351BD   .  83C4 04       ADD ESP,0x4
004351C0   .  2BF0          SUB ESI,EAX
004351C2   .  56            PUSH ESI
004351C3   .  8D85 84E7FFFF LEA EAX,DWORD PTR SS:[EBP-0x187C]
004351C9   .  50            PUSH EAX
004351CA   .  E8 5889FFFF   CALL crackMe3.0042DB27                   ;  cmp Hash 64字节对比和输入的右侧64字节(不足留0x0)
004351CF   .  83C4 0C       ADD ESP,0xC
004351D2   .  85C0          TEST EAX,EAX
004351D4   .  75 3E         JNZ XcrackMe3.00435214                   ;  关键跳1
004351D6   .  E8 D97EFFFF   CALL crackMe3.0042D0B4
004351DB   .  8D85 C0EBFFFF LEA EAX,DWORD PTR SS:[EBP-0x1440]
004351E1   .  50            PUSH EAX
004351E2   .  68 00B04900   PUSH crackMe3.0049B000
004351E7   .  E8 BF87FFFF   CALL crackMe3.0042D9AB                   ;  0x20 check
004351EC   .  83C4 08       ADD ESP,0x8
004351EF   .  0FB6C8        MOVZX ECX,AL
004351F2   .  83F9 01       CMP ECX,0x1
004351F5   .  75 1D         JNZ XcrackMe3.00435214                   ;  关键跳2
004351F7   .  8BF4          MOV ESI,ESP
004351F9   .  6A 00         PUSH 0x0                                 ; /Style = MB_OK|MB_APPLMODAL
004351FB   .  68 98B14800   PUSH crackMe3.0048B198                   ; |Title = "CrackMe"
00435200   .  68 94B14800   PUSH crackMe3.0048B194                   ; |Text = "ok"
00435205   .  6A 00         PUSH 0x0                                 ; |hOwner = NULL
00435207   .  FF15 88F54900 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
v20 = GetDlgItemTextA(hDlg, 1001, &String, 1025);
    v14 = 0;
    j__memset(&v15, 0, 0x3FFu);
    sub_42D267((int)&String, 1024, (int)&v16);  // BASE64解码,里头有反调试
    v13[0] = 0;
    j__memset(&v13[1], 0, 0x3FFu);
    sub_42D267((int)&v16, 1024, (int)&v14);     // BASE64解码,里头有反调试
    sub_42D96A(&v14, (int)v13, 1024);           // 0x20 set,里头有反调试
    v12 = 3;
    sub_42DA78(&v14, 3u, (int)v11);             // 国密SM3,仅加密前3字节,里头有反调试
    for ( i = 0; i < 32; ++i )
      j__sprintf(&hash[2 * i], "%02x", v11[i]);
    v4 = j__strlen(hash);
    v5 = &String + j__strlen(&String);
    v6 = j__strlen(hash);
    if ( !j__memcmp(hash, &v5[-v6], v4) )       // hash64字节对比和输入的右侧64字节(不足留0x0)
    {
      sub_42D0B4();
      if ( sub_42D9AB((int)&unk_49B000, (int)v13) == 1 )// 0x20 check,里头有反调试
        MessageBoxA(0, "ok", "CrackMe", 0);
    }
二、反调试
    该作品反调试种类繁多,常见的都有了,估计很多人会罗列出来详细阐述,太占篇幅我就不必要复制粘贴了,只要把CALL反调试子程序修改RET返回即可绕过。
    这里仅罗列我实际为了调试所patch掉的地址和代码:(不保证齐全)
三、算法

    ⑴: 对输入的注册码(≥64位)进行2次Base64解码,解码错误可能使输出结果为空;

    ⑵: 根据 Base64 解码结果设置标志0x20(2次Base64解码后包含0x2f);

    ⑶: 使用国密SM3对2次Base64解码后的前3字节进行加密,并转为64位字符串;

    ⑷: SM3加密结果64位字符与输入的注册码右边64位字符比较(关键跳1);

    ⑸: 对标志0x20 (2次Base64解码后包含0x2f)比较,含BUG(关键跳2)。

四、破解:   

    ①:如果不是算法包含BUG,正常的解题思路是:

        ⑴ : 穷举中间过程的前3字节密文(即2次Base64解码后,)计算SM3转字符串64位;
        ⑵:  对64位SM3进行2次 Base64解码 ,要求解码后的前3字节与穷举的3字节吻合,并且解码结果包含“0x2f”即可将64位作为正确答案。
        但本题算法包含BUG,首先Base64对64位SM3结果进行2次解码后,很有可能输出空白结果,前3字节容易构造“0x00”或“0x2f”;
        其次“0x20”标志不一定可靠,即算法第 ⑵ 步解码结果未包含0x2f,未设置0x20标志位,最后第 ⑸ 步也有很大概率验证通过(具体BUG原因未继续细查,估计是检测地址范围过大,内存状态每次运行都会有所变化,也有其他原因可能导致该BUG)。
    ② :综上所述,我们可以随意选择一种方法进行破解
        ⑴ :比如构造 Base64的2次解码输出3字节“0x00,0x00,0x00”,得到SM3:“183920f00e15a0433ee3a8fc90dd9ac164c4142ccf63ca189a8f645ec96ff8de”,输入该64位字符有很大可能通过验证,因2次Base64解码未包含“0x2f”没有设置“0x20”标志位,所以通过验证靠运气,有时不行,但按比赛规则有一次通过就算题目被破解。
        ⑵: 再比如,我们还可以构造2次Base64解码输出“0x2f”结果的 -->1次Base64加密 “Lw==”  --> 2次Base64加密“THc9PQo”,把 “THc9PQo”输入Crackme观察SM3加密结果为“2f725aaf8d9fa538554e9f3589ddc785364d52ab1a6760c12caa2ec01ae4ba9e”,也就是“0x2f,0x00,0x00”这3个字节的SM3加密结果(可以自己写代码或者利用算法工具验证), “2f725aaf8d9fa538554e9f3589ddc785364d52ab1a6760c12caa2ec01ae4ba9e” 在本题中的2次Base64解码为空,因此在其前面连接 “THc9PQo” 即可:         
        THc9PQo2f725aaf8d9fa538554e9f3589ddc785364d52ab1a6760c12caa2ec01ae4ba9e
        类似的构造方法太多了,答案数不胜数。
五、总结:
    本题利用大量反调试手段抵抗破解,采用密码学算法增加强度,但结果也是戏剧化的。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回