首页
社区
课程
招聘
[原创]CTF2016第18题ELyt's CrackMe分析(详细,虚拟指令还原)
发表于: 2016-12-7 15:45 5373

[原创]CTF2016第18题ELyt's CrackMe分析(详细,虚拟指令还原)

2016-12-7 15:45
5373

Elyt作者你好,看着代码简短,忍不住想出手,怎想是VM解码

解题过程:

一、第一天吃了中饭午休,看了题目没有加壳也没有反调试,对于我这样忙于工作的人来说,只要不太费心费力的题目就会感兴趣分析,研究算法很有意思,其他的看到就恶心,因为真的是忙里偷闲,不太可能花费连续几个小时时间去琢磨。如果作品直奔算法去的,应该点赞!

接入正题,消息断点,第一部分注册码算法流程:

00401205    E8 E6300000     CALL Crackme.004042F0                                                 ; 取长度
0040120A    83C4 04         ADD ESP,0x4
0040120D    8945 B4         MOV DWORD PTR SS:[EBP-0x4C],EAX
00401210    837D B4 0D      CMP DWORD PTR SS:[EBP-0x4C],0xD                                       ; 小于13位转移
00401214    0F8C 11010000   JL <Crackme.fail>
0040121A    C745 AC 0000000>MOV DWORD PTR SS:[EBP-0x54],0x0
00401221    C745 B0 0D00000>MOV DWORD PTR SS:[EBP-0x50],0xD
00401228    EB 09           JMP XCrackme.00401233
0040122A    8B55 B0         MOV EDX,DWORD PTR SS:[EBP-0x50]
0040122D    83C2 01         ADD EDX,0x1
00401230    8955 B0         MOV DWORD PTR SS:[EBP-0x50],EDX
00401233    8B45 B0         MOV EAX,DWORD PTR SS:[EBP-0x50]
00401236    3B45 B4         CMP EAX,DWORD PTR SS:[EBP-0x4C]                                       ; 小于等于13位时转移
00401239    7D 27           JGE XCrackme.00401262
0040123B    8B4D 0C         MOV ECX,DWORD PTR SS:[EBP+0xC]
0040123E    034D B0         ADD ECX,DWORD PTR SS:[EBP-0x50]
00401241    0FBE11          MOVSX EDX,BYTE PTR DS:[ECX]
00401244    83FA 30         CMP EDX,0x30
00401247    7C 0E           JL XCrackme.00401257                                                  ; 小于“0”时跳转
00401249    8B45 0C         MOV EAX,DWORD PTR SS:[EBP+0xC]
0040124C    0345 B0         ADD EAX,DWORD PTR SS:[EBP-0x50]
0040124F    0FBE08          MOVSX ECX,BYTE PTR DS:[EAX]
00401252    83F9 39         CMP ECX,0x39                                                          ; 小于等于“9”时跳转
00401255    7E 09           JLE XCrackme.00401260
00401257    C745 AC 0100000>MOV DWORD PTR SS:[EBP-0x54],0x1
0040125E    EB 02           JMP XCrackme.00401262

思考1:注册码必须大于等于13位,并且13位之后的字符必须为0-9的数字

00401278    83C2 01         ADD EDX,0x1                                                           ; 指针+1
0040127B    8955 B0         MOV DWORD PTR SS:[EBP-0x50],EDX
0040127E    837D B0 08      CMP DWORD PTR SS:[EBP-0x50],0x8                                       ; 循环结束9次
00401282    7F 1F           JG XCrackme.004012A3
00401284    8B45 0C         MOV EAX,DWORD PTR SS:[EBP+0xC]                                        ; 读SN
00401287    0345 B0         ADD EAX,DWORD PTR SS:[EBP-0x50]
0040128A    0FBE08          MOVSX ECX,BYTE PTR DS:[EAX]                                           ; 读第1字节
0040128D    8B55 B0         MOV EDX,DWORD PTR SS:[EBP-0x50]
00401290    0FBE4415 9C     MOVSX EAX,BYTE PTR SS:[EBP+EDX-0x64]                                  ; 读密表1字节
00401295    33C8            XOR ECX,EAX                                                           ; 与密表 XOR
00401297    83E9 41         SUB ECX,0x41                                                          ; 异或结果减去0X41
0040129A    8B55 B0         MOV EDX,DWORD PTR SS:[EBP-0x50]
0040129D    894C95 B8       MOV DWORD PTR SS:[EBP+EDX*4-0x48],ECX                                 ; 结果储存
004012A1  ^ EB D2           JMP XCrackme.00401275
004012A3    837D B8 01      CMP DWORD PTR SS:[EBP-0x48],0x1                                       ; 密文第1字节大于1才行
004012A7    7F 07           JG XCrackme.004012B0
004012A9    C745 AC 0100000>MOV DWORD PTR SS:[EBP-0x54],0x1                                       ; 注意可能时标志位为1就死
004012B0    C745 B0 0000000>MOV DWORD PTR SS:[EBP-0x50],0x0
004012B7    EB 09           JMP XCrackme.004012C2

思考2:注册码前9字节与密表“0x33 0x21 0x22 0x21 0x35 0x7c 0x62 0x65 0x6e”分别异或,并减去0x41,得出密文,密文第一位必须大于0x1

004012D2    3B4495 BC       CMP EAX,DWORD PTR SS:[EBP+EDX*4-0x44]                                 ; 比较密文由小到大排列
004012D6    7C 09           JL XCrackme.004012E1

00401302    837D B0 09      CMP DWORD PTR SS:[EBP-0x50],0x9                                       ; 循环计数比较
00401306    7D 10           JGE XCrackme.00401318
00401308    8B55 B0         MOV EDX,DWORD PTR SS:[EBP-0x50]
0040130B    8B45 A8         MOV EAX,DWORD PTR SS:[EBP-0x58]                                       ; 初值1
0040130E    0FAF4495 B8     IMUL EAX,DWORD PTR SS:[EBP+EDX*4-0x48]                                ; 相乘
00401313    8945 A8         MOV DWORD PTR SS:[EBP-0x58],EAX                                       ; 结果替换初值
00401316  ^ EB E1           JMP XCrackme.004012F9
00401318    B9 86204C0D     MOV ECX,0xD4C2086                                                     ; ECX=0xD4C2086
0040131D    2B4D A8         SUB ECX,DWORD PTR SS:[EBP-0x58]                                       ; 相减
00401320    B8 64000000     MOV EAX,0x64                                                          ; EAX=0x64
00401325    99              CDQ
00401326    F7F9            IDIV ECX                                                              ; 0x64 / ECX
00401328    8945 A8         MOV DWORD PTR SS:[EBP-0x58],EAX                                       ; 商放在[EBP-0X58]

思考3:9字节密文相乘,结果必须为 magic key 0xD4C2086,因为显性流程中没有成功分支,显然必须构造除数为0异常,进入SEH才行。对 magic key 分解因子:2、3、5、7、11、13、17、19、23(十进制,都是质数,刚好9字节,如果不是质数或者不为9字节,则可能出现多解)。利用因子倒推注册码前9位:pediy2016

0040112A  |.  68 18454000   PUSH Crackme.00404518                                                 ;  SE 处理程序安装
0040459B  |.  FF548F 08     |CALL DWORD PTR DS:[EDI+ECX*4+0x8]                                    ;  Crackme.0040133E

思考4:跟进SEH处理,进入40133E,再跟进4013B0

004013B0   $  55            PUSH EBP
004013B1   .  8BEC          MOV EBP,ESP
004013B3   .  B8 F4020100   MOV EAX,0x102F4                                                       ;  66292 字节
004013B8   .  E8 63360000   CALL Crackme.00404A20
004013BD   .  53            PUSH EBX
004013BE   .  56            PUSH ESI
004013BF   .  57            PUSH EDI
004013C0   .  8DBD 0CFDFEFF LEA EDI,DWORD PTR SS:[EBP+0xFFFEFD0C]
004013C6   .  B9 BD400000   MOV ECX,0x40BD                                                        ;  0x40BD
004013CB   .  B8 CCCCCCCC   MOV EAX,0xCCCCCCCC
004013D0   .  F3:AB         REP STOS DWORD PTR ES:[EDI]                                           ;  用 0xcc 填充66292字节空间
004013D2   .  C785 68FEFEFF>MOV DWORD PTR SS:[EBP+0xFFFEFE68],0x101
004013DC   .  C685 64FDFEFF>MOV BYTE PTR SS:[EBP+0xFFFEFD64],0x1                                  ;  VM 指令码

004041C4   > \8B45 FC       MOV EAX,DWORD PTR SS:[EBP-0x4]                                        ;  8字节变量地址,用来存放类似寄存器的内容
004041C7   .  66:C740 04 00>MOV WORD PTR DS:[EAX+0x4],0x6000                                      ;  EIP 初值 0x6000
004041CD   .  8B4D 0C       MOV ECX,DWORD PTR SS:[EBP+0xC]                                        ;  读取注册码地址
004041D0   .  51            PUSH ECX                                                              ; /压栈
004041D1   .  8D95 FC1FFFFF LEA EDX,DWORD PTR SS:[EBP+0xFFFF1FFC]                                 ; |地址121960
004041D7   .  52            PUSH EDX                                                              ; |压栈
004041D8   .  E8 53070000   CALL <Crackme.strcpy>                                                 ; \拷贝注册码到地址,比如121960
004041DD   .  83C4 08       ADD ESP,0x8
004041E0   .  8B85 68FEFEFF MOV EAX,DWORD PTR SS:[EBP+0xFFFEFE68]
004041E6   .  50            PUSH EAX                                                              ; /size 0x101
004041E7   .  8D8D 64FDFEFF LEA ECX,DWORD PTR SS:[EBP+0xFFFEFD64]                                 ; |
004041ED   .  51            PUSH ECX                                                              ; |src 比如 11F6C8
004041EE   .  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-0x4]                                        ; |
004041F1   .  33C0          XOR EAX,EAX                                                           ; |
004041F3   .  66:8B42 04    MOV AX,WORD PTR DS:[EDX+0x4]                                          ; |
004041F7   .  8D8C05 FCFFFE>LEA ECX,DWORD PTR SS:[EBP+EAX+0xFFFEFFFC]                             ; |
004041FE   .  51            PUSH ECX                                                              ; |dest 比如 125960
004041FF   .  E8 EC030000   CALL <Crackme.memcpy>                                                 ; \memcpy VM指令码拷贝

思考5:这里作者模拟了汇编指令,自己定义了一套指令规则,相当于一个精简的VM,指令码加操作数一共257字节

00125960  01 00 02 00 03 00 96 00 20 21 0A 00 29 01 2B 01  ...? !..)+
00125970  27 F6 FF 81 14 21 04 00 00 01 2E 12 00 80 01 63  '??!....€c
00125980  02 09 8B 00 20 21 04 00 00 01 6F 2A 01 8B 00 20  .? !..o*?
00125990  21 04 00 00 2A 01 8B 00 20 21 04 00 00 01 6C 2A  !..*? !..l*
001259A0  01 8B 00 20 21 04 00 00 01 2E 03 01 14 00 80 01  ? !....€
001259B0  31 2A 01 8B 00 20 21 04 00 00 0B 00 20 29 D0 08  1*? !... )?
001259C0  45 45 1B 2A 01 0B 00 20 29 D0 08 45 45 1B 2A 01  EE*. )?EE*
001259D0  0B 00 20 29 D0 08 45 45 1D 2D 1D 2D 1B 02 0D 0B  . )?EE--.
001259E0  00 20 29 D0 41 64 2A 01 11 00 20 2B D0 43 0A 2D  . )蠥d*. +蠧.-
001259F0  2A 01 11 00 20 2B D0 2D 1D 85 21 04 00 00 01 2E  *. +??...
00125A00  03 02 14 00 80 2A 01 0B 00 20 29 D0 41 0A 2A 01  .€*. )蠥.*
00125A10  11 00 20 2B D0 2D 1B 2A 01 11 00 20 2B D0 43 0A  . +?*. +蠧.
00125A20  2A 01 0B 00 20 29 D0 30 1E 04 2D 42 04 43 02 2F  *. )?-BC/
00125A30  81 23 26 12 00 82 5E 26 0D 00 01 2E 03 03 14 00  ?&.俕&....
00125A40  80 27 04 00 00 02 00 01 00 03 2E 98 00 80 26 05  €'.....?€&
00125A50  00 29 01 2A 01 82 04 26 F4 FF 81 04 26 04 00 99  .)*?&??&.

代码附近随意浏览,发现成功弹框提示分支,地址4041A3
004041A3   .  8BF4          MOV ESI,ESP
004041A5   .  6A 00         PUSH 0x0                                                              ; /Style = MB_OK|MB_APPLMODAL
004041A7   .  68 CC804000   PUSH Crackme.004080CC                                                 ; |Title = "Success!"
004041AC   .  68 CC804000   PUSH Crackme.004080CC                                                 ; |Text = "Success!"
004041B1   .  8B55 08       MOV EDX,DWORD PTR SS:[EBP+0x8]                                        ; |
004041B4   .  52            PUSH EDX                                                              ; |hOwner
004041B5   .  FF15 9C804000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>]                             ; \MessageBoxA

VM的解码执行:
00404207   .  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-0x4]
0040420A   .  C642 06 FF    MOV BYTE PTR DS:[EDX+0x6],0xFF                                        ;  8字节空间的第6字节赋值0xFF
0040420E   >  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-0x4]
00404211   .  33C9          XOR ECX,ECX
00404213   .  66:8B48 04    MOV CX,WORD PTR DS:[EAX+0x4]                                          ;  取EIP变量(初值0x6000)
00404217   .  33D2          XOR EDX,EDX
00404219   .  8A940D FCFFFE>MOV DL,BYTE PTR SS:[EBP+ECX+0xFFFEFFFC]                               ;  取指令码
00404220   .  8995 60FDFEFF MOV DWORD PTR SS:[EBP+0xFFFEFD60],EDX
00404226   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-0x4]
00404229   .  66:8B48 04    MOV CX,WORD PTR DS:[EAX+0x4]
0040422D   .  66:83C1 01    ADD CX,0x1                                                            ;  EIP指向下一条(初值0x6000)
00404231   .  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-0x4]
00404234   .  66:894A 04    MOV WORD PTR DS:[EDX+0x4],CX                                          ;  更新EIP
00404238   .  8B85 60FDFEFF MOV EAX,DWORD PTR SS:[EBP+0xFFFEFD60]                                 ;  按取出的字节*4+0xFFFEFD60,推算成功时字节为0x99
0040423E   .  FFA485 6CFEFE>JMP DWORD PTR SS:[EBP+EAX*4+0xFFFEFE6C]                               ;  执行

思考6:因为午休时间结束了,今天不太可能继续分析,直接将指令码修改为“0x99”,爆破。

二、第一天下班后要陪伴家人,追剧《锦绣未央》,腹黑女被未央扳倒了,哈哈,没有时间分析作品。第二天,午休时间开始了,接昨天:看来需要分析作者定义的VM指令码和操作数,以及这257字节对应的程序流程(不一定要全部分析完),只好跟踪流程,这里省略中间分析过程,因为太长了,贴出算法相关的所有指令码含义(根据我自己的理解,不一定准确,但不影响算法的分析)

VM指令码:(操作数根据指令码很好理解,此处eip,esp,ebp都是便于理解的虚拟概念,要与实机区别)

00 : ret
01 : mov var1,数据
02 : mov var2,数据
03 : mov var3,数据
04 : mov var1,var2
08 : mov var3,var1
0B : mov var1,[ebp+操作数+var2]
11 : mov var3,[ebp+操作数+var2]
12 : mov [ebp+操作数],var1
14 : mov [ebp+操作数+var3],var1
1B : push var1 (dec esp)
1D : pop var3 (inc esp)
1E : pop var2 (inc esp)
21 : je eip+操作数-1 (jz)
26 : jne eip+操作数-1 (jnz)
27 : jmp eip+操作数-1
29 : add var1,数据
2A : add var2,数据
2B : add var3,数据
2D : add var1,var3
2F : add var2,var3
30 : add var3,var1
41 : imul var1,数据
42 : imul var2,数据
43 : imul var3,数据
45 : imul var1,var3
81 : cmp var1,数据
82 : cmp var2,数据
85 : cmp var1,var3
8B : cmp var1,[ebp+操作数+var2]
96 : cmp [ebp+操作数+var3],0x0
98 : cmp [ebp+操作数+var2],var3
99 : msgbox_success

P-CODE(纯手工) 排版太累,点这里下载





根据上述VM指令码定义和P-CODE流程,很方便可以整理算法流程:

1、81 14 : 定义了注册码长度为0x14字节(20位)
2、01 63 : 定义了注册码第10位为“c"
3、01 6F : 定义了注册码第11位,12位为“o”(两个"o")
4、01 6C : 定义了注册码第13位为“l”
5、01 31 : 定义了注册码第14位为“1”
6、注册码第15-16位,需满足 0x1+(0xD0+Sn15)^3 +(0xD0+Sn16)^3 == 0x64+(0xD0+Sn15)*0xA+(0xD0+Sn16),注意byte运算会有溢出,仅保留byte结果,根据注册码0-9的数字范围,很容易穷举出结果为:"5",“3”
穷举代码:
        unsigned char Sn15,Sn16,Temp1,Temp2;       
        for (Sn15=0x30; Sn15 <= 0x39; Sn15++)
        {
          for (Sn16=0x30; Sn16 <= 0x39; Sn16++)
          {
            Temp1=0x1+pow((0xD0+Sn15),3)+pow((0xD0+Sn16),3);
            Temp2=0x64+(0xD0+Sn15)*0xA+(0xD0+Sn16);
            if (Temp1==Temp2)
            {
              printf ("%c,%c\n",Sn15,Sn16);
            }
          }
        }
7、注册码第17-20位,需满足 (0xD0+Sn17)*0xA+(0xD0+Sn18)+(0xD0+Sn19)*0xA+(0xD0+Sn20) == 0x23,以及 ((0xD0+Sn17)*0xA+(0xD0+Sn18))*4+((0xD0+Sn19)*0xA+(0xD0+Sn20))*2 == 0x5E,注意byte运算会有溢出,仅考虑byte结果,根据注册码0-9的数字范围,也容易穷举出结果为:“1”,“2”,“2”,“3”
穷举代码:
        unsigned char Sn17,Sn18,Sn19,Sn20,Temp1,Temp2;
        for (Sn17=0x30; Sn17 <= 0x39; Sn17++)
        {
          for (Sn18=0x30; Sn18 <= 0x39; Sn18++)
          {
            for (Sn19=0x30; Sn19 <= 0x39; Sn19++)
            {
              for (Sn20=0x30; Sn20 <= 0x39; Sn20++)
              {
                Temp1=(0xD0+Sn17)*0xA+(0xD0+Sn18)+(0xD0+Sn19)*0xA+(0xD0+Sn20);
                Temp2=((0xD0+Sn17)*0xA+(0xD0+Sn18))*4+((0xD0+Sn19)*0xA+(0xD0+Sn20))*2;
                if (Temp1==0x23 && Temp2==0x5E)
                {
                  printf ("%c,%c,%c,%c\n",Sn17,Sn18,Sn19,Sn20);
                }
              }
            }
          }
        }
8、将所有注册码连接就是答案:pediy2016cool1531223

三、将分析过程写下来,同时把CrackMe放在附件,欢迎各位同学研究。总结该作品采用了SEH隐藏算法流程,采用VM防止Cracker轻易理解算法,采用异或,加法,减法、乘法、除法作为算法基本运算规则,在此应感谢Elyt给大家带来了这么一个有意思的作品。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 112
活跃值: (27)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
2
群里打广告,论坛也不放过?!
2016-12-8 20:18
0
游客
登录 | 注册 方可回帖
返回
//