• 看雪CTF 2016_第四题分析


    结合前辈们的分析,自己再作一个分析,算是当做学习笔记吧!

    OD GetDlgItemTextA 这个断点

    0040148C |. 83F8 1E cmp eax,0x1E 检测注册码长度是否为30

    0040148F |. 75 25 jnz short CrackMe.004014B6

    00401491 |. 8BD0 mov edx,eax

    00401493 |. 8D8D FCFDFFFF lea ecx,[local.129]

    00401499 |. E8 62FBFFFF call CrackMe.00401000 关键算法

    0040149E |. 83F8 01 cmp eax,0x1

    004014A1 |. 75 13 jnz short CrackMe.004014B6

    进入call CrackMe.00401000

    引用别人的话:

    此CrackMe加了开源的 WProtect, 因此有部分是虚拟机。但是虚拟机部分也不是特别重要。因为一般vm是以函数为单位的,当调用子函数时,会退出当前虚拟机(ps:函数要返回时也需要退出虚拟机),还原环境,然后调用。正好此程序只是把外层函数给vm了(只有一个地方是在虚拟机里进行的,后面会讲到)。只需在vm出口等待返回即可。不需要去查看整个虚拟机流程。

    进入call 401000是发现被VM了,我们直接找到vm_Exit 这个handler

    0042F052 8BFC mov edi,esp

    0042F054 BE 0E544300 mov esi,CrackMe.0043540E 字节码表

    0042F059 E9 7B0C0000 jmp CrackMe.0042FCD9

    0042FCD9 F7D3 not ebx

    0042FCDB 4B dec ebx

    0042FCDC 66:F7D3 not bx

    0042FCDF 66:81EB D165 sub bx,0x65D1

    0042FCE4 0FB646 FF movzx eax,byte ptr ds:[esi-0x1] 读取字节码

    0042FCE8 4E dec esi

    0042FCE9 2AC3 sub al,bl

    0042FCEB F6D0 not al

    0042FCED 04 57 add al,0x57

    0042FCEF FEC8 dec al

    0042FCF1 2C 3E sub al,0x3E

    0042FCF3 FF3485 DDF84200 push dword ptr ds:[eax*4+0x42F8DD] 派发表

    0042FCFA C3 retn

    esi处找到最后一个字节码下断点(向上拖动查找)

     
     

    0042F76F 8BE5 mov esp,ebp

    0042F771 5F pop edi

    0042F772 5E pop esi

    0042F773 5D pop ebp

    0042F774 5B pop ebx

    0042F775 5A pop edx

    0042F776 59 pop ecx

    0042F777 58 pop eax

    0042F778 9D popfd

    0042F779 C3 retn

    VM退出handler

    以后直接在VM退出handl下断点跟踪就可以了。

    004014F0 /$ 55 push ebp md5_update

    004014F1 |. 8BEC mov ebp,esp

    004014F3 |. 83EC 0C sub esp,0xC

    004014F6 |. 53 push ebx

    004014F7 |. 8B5D 08 mov ebx,[arg.1]

    004014FA |. 56 push esi

    004014FB |. 57 push edi

    004014FC |. 8BF9 mov edi,ecx

    004014FE |. 8955 FC mov [local.1],edx

    00401501 |. 897D F8 mov [local.2],edi

    00401504 |. 8B47 10 mov eax,dword ptr ds:[edi+0x10]

    00401507 |. 8BC8 mov ecx,eax

    00401509 |. C1E9 03 shr ecx,0x3

    0040150C |. 83E1 3F and ecx,0x3F

    0040150F |. 894D F4 mov [local.3],ecx

    00401512 |. 8D14D8 lea edx,dword ptr ds:[eax+ebx*8]

    00401515 |. 8D04DD 000000>lea eax,dword ptr ds:[ebx*8]

    将注册码前七位进行md5处理

    00401183 8A440D D0 mov al,byte ptr ss:[ebp+ecx-0x30]

    00401187 32840D 14FCFFFF xor al,byte ptr ss:[ebp+ecx-0x3EC]

    0040118E 88840D E8FBFFFF mov byte ptr ss:[ebp+ecx-0x418],al

    00401195 83F9 17 cmp ecx,0x17

    00401198 0F83 68020000 jnb CrackMe.00401406

    0040119E C6440D D0 00 mov byte ptr ss:[ebp+ecx-0x30],0x0

    004011A3 C6840D 14FCFFFF>mov byte ptr ss:[ebp+ecx-0x3EC],0x0

    004011AB 41 inc ecx

    004011AC 83F9 17 cmp ecx,0x17

    004011AF ^ 7C D2 jl short CrackMe.00401183

    异或加密剩余的23个假码

    密钥 44 AD 5C CC 12 90 73 8D 47 81 E3 89 84 9C DF F9 47 6A B6 9E 11 30 27

    进行异或

    得出:

    7C 94 1D 8E 51 D4 36 CB 00 C9 AA C3 CF D0 92 B7 08 3A E7 CC 42 64 72

    004011C0 8A840D 90FDFFFF mov al,byte ptr ss:[ebp+ecx-0x270]

    004011C7 32840D E8FBFFFF xor al,byte ptr ss:[ebp+ecx-0x418]

    004011CE 88440D D0 mov byte ptr ss:[ebp+ecx-0x30],al

    004011D2 83F9 17 cmp ecx,0x17

    004011D5 0F83 2B020000 jnb CrackMe.00401406

    004011DB C6840D E8FBFFFF>mov byte ptr ss:[ebp+ecx-0x418],0x0

    004011E3 C6840D 90FDFFFF>mov byte ptr ss:[ebp+ecx-0x270],0x0

    004011EB 41 inc ecx

    004011EC 83F9 17 cmp ecx,0x17

    004011EF ^ 7C CF jl short CrackMe.004011C0

    继续进行异或

    然后再和前7位的md5值进行异或

    得出:

    80 7E 8F 81 25 C6 83 11 7B 29 65 81 77 19 A5 EE F4 D0 75 C3 36 76 C7

    引用:

    将异或后的结果当作路线开始寻路。

    00401240 8BD1 mov edx,ecx //每次取一个字节

    00401242 8985 10FCFFFF mov dword ptr ss:[ebp-0x3F0],eax

    00401248 8A8D 0CFCFFFF mov cl,byte ptr ss:[ebp-0x3F4]

    0040124E D3EA shr edx,cl //依次取两位

    00401250 83E2 03 and edx,0x3 //最大为3,也就是0,1,2,3

    00401253 FF2495 0C144000 jmp dword ptr ds:[edx*4+0x40140C]

    Case 0:

    0040125A 83E8 10 sub eax,0x10

    0040125D EB 09 jmp short CrackMe。00401268

    case 1:

    0040125F 40 inc eax

    00401260 EB 06 jmp short CrackMe。00401268

    case 2:

    00401262 83C0 10 add eax,0x10

    00401265 EB 01 jmp short CrackMe。00401268

    case 3:

    00401267 48 dec eax

    0即-0x10也即返回一行;

    1则+1,也即前进一列;

    2则+0x10,也即前进一行;

    3则-1,也即返回一列

    引用:

    判断下一步要走的地方

    004012B5 8B8D 08FCFFFF mov ecx,dword ptr ss:[ebp-0x3F8]

    004012BB 8D95 90FEFFFF lea edx,dword ptr ss:[ebp-0x170]

    004012C1 8B85 04FCFFFF mov eax,dword ptr ss:[ebp-0x3FC]

    004012C7 C1E1 04 shl ecx,0x4

    004012CA 03C1 add eax,ecx

    004012CC 03D0 add edx,eax

    004012CE 8995 04FCFFFF mov dword ptr ss:[ebp-0x3FC],edx

    004012D4 8A8C05 90FCFFFF mov cl,byte ptr ss:[ebp+eax-0x370]

    004012DB 8AC1 mov al,cl

    004012DD 888D 37FCFFFF mov byte ptr ss:[ebp-0x3C9],cl

    004012E3 C0C8 02 ror al,0x2

    004012E6 0FB6C8 movzx ecx,al

    004012E9 0FB602 movzx eax,byte ptr ds:[edx]

    004012EC 33C8 xor ecx,eax

    004012EE 83F9 30 cmp ecx,0x30 //是否为墙,如果是则失败

    004012F1 0F84 E2000000 je CrackMe。004013D9

    004012F7 83F9 20 cmp ecx,0x20 //暂时未看到过

    004012FA 0F84 D9000000 je CrackMe。004013D9

    00401300 83F9 58 cmp ecx,0x58 //0x58可以确定为是否到终点了。

    00401303 0F84 E5000000 je CrackMe。004013EE

    00401309 8B8D 10FCFFFF mov ecx,dword ptr ss:[ebp-0x3F0]

    0040130F 8BC1 mov eax,ecx

    00401311 99 cdq

    00401312 83E2 0F and edx,0xF

    00401315 03C2 add eax,edx

    00401317 C1F8 04 sar eax,0x4

    0040131A 8985 08FCFFFF mov dword ptr ss:[ebp-0x3F8],eax

    00401320 81E1 0F000080 and ecx,0x8000000F

    00401326 79 05 jns short CrackMe。0040132D

    00401328 49 dec ecx

    00401329 83C9 F0 or ecx,0xFFFFFFF0

    0040132C 41 inc ecx

    0040132D 898D 10FCFFFF mov dword ptr ss:[ebp-0x3F0],ecx

    这里就是检测操作是否撞墙即是否等于0x30和0x20 如果等于0x58就是通关成功

    004011F1 B9 40000000 mov ecx,0x40

    004011F6 8DBD 90FCFFFF lea edi,dword ptr ss:[ebp-0x370]

    004011FC BE 98374100 mov esi,CrackMe.00413798

    00401201 33C0 xor eax,eax

    00401203 F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi]

    esi的加密表复制到edi里

    6E D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 02 18 74 95 1F C2 4D 33 3C F0 3B EC E9 81

    4B 9C 0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D C2 F5 0C DD 42 CC AF B4 D5 E4 86 D3

    9A 0B 62 63 A7 D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 02 18 74 95 1F C2 4D 33 38 F0

    3B EC ED 81 4B 9C 0B 47 5C AD DD 09 B0 87 57 9B F2 E3 0B 01 92 8D C2 F5 0C DD 42 CC AF B4

    D5 E4 86 D3 9A 0B 62 63 A7 D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 02 18 74 95 1F C2

    4D 33 38 F0 3B EC E9 81 4B 9C 0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D C2 F5 0C DD

    42 CC AF B4 D5 E4 86 D3 9A 0B 62 63 A7 D4 1B 69 5B 4E E8 AA 91 F6 AF CE 36 1A 62 D9 02 18

    74 95 1F C2 4D 33 38 F0 3B EC E9 81 4B 9C 0B 47 5C AD DD 09 B0 87 57 9B F2 E3 0B 01 92 8D

    C6 F5 0C DD 42 CC AF B4 D5 E4 86 D3 9A 0B 62 63

    00401210 BE 98384100 mov esi,CrackMe.00413898

    00401215 8DBD 90FEFFFF lea edi,dword ptr ss:[ebp-0x170]

    0040121B F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi]

    0040121D 33C9 xor ecx,ecx

    0040121F 898D 2CFCFFFF mov dword ptr ss:[ebp-0x3D4],ecx

    同样复制操作

    D8 05 F6 6A E7 A2 0B 9B 54 8C DA 82 BD B6 A8 46 B1 36 2D 55 F7 81 63 FC 3F 0C FE 0B 4B 50

    E2 17 F2 E1 27 5B 46 73 1C D0 E5 D7 8D C9 F2 70 94 53 81 4C 32 46 A0 02 DB 1C 45 09 91 C4

    96 F2 A8 E8 D9 05 F6 6B E7 A2 0A 9B 54 8C DA 82 BD B7 A9 46 B0 36 2D 54 F7 81 63 FC 3E 0C

    FE 0B 4B 50 E3 17 F2 E0 26 5A 47 73 1C D1 E5 D6 8C C8 F2 70 95 53 80 4C 33 47 A0 02 DB 1C

    44 08 91 C4 96 F2 A9 E8 D9 04 F6 6A E7 A2 0A 9B 55 8C DB 83 BC B6 A9 46 B0 37 2D 55 F7 81

    63 FD 3E 0D FE 0B 4A 50 E3 17 F3 E0 27 5B 46 73 1D D0 E4 D7 8C C8 F3 70 95 53 80 4C 33 47

    A0 03 DB 1D 45 08 91 C4 96 F2 A9 E8 D9 04 F6 6A E6 A3 0A 9A 54 8C DB 82 BC B7 A9 46 B0 37

    2C 54 F6 81 62 FD 3E 0D FE 0A 4A 50 E2 17 F2 E1 27 5B 47 72 1C D0 E5 D7 8C C9 F2 70 94 53

    81 4D 33 47 A0 03 DB 1C 44 08 91 C5 97 9A A8 E8

    解密流程:

    lea edx,dword ptr ss:[ebp-0x170]

    add edx, eax

    mov cl,byte ptr ss:[ebp+eax-0x370]

    mov al,cl

    ror al,0x2

    movzx ecx,al

    movzx eax,byte ptr ds:[edx]

    xor ecx,eax

    这里生成一个迷宫地图,就是将上面的两个特定表进行异或生成的

    要求从C开始走到X,0为墙,相当于吃豆子游戏。

    引用别人的源码

    int i = 0;

    int j = 0;

    unsigned char cch = 0; int m = 6;

    ctx xx[] = { { 16, 2 }, { 1, 1 }, { -1, 3}, { -16, 0 } };

    while (t3[i] != 0x58)

    {

    for (int k = 0; k < 4; k++)

    {

    int v = i + xx[k].n;

    if (v < 0 || v > 255)

    continue;

    if (j != v && ((t3[v] == 0x31) || (t3[v] == 0x58)))

    {

    j = i;

    i = v;

    cch |= ((xx[k].bit & 0x03) << m);

    if (m == 0)

    {

    printf("%02X ", cch);

    cch = 0;

    m = 8;

    }

    m -= 2;

    break;

    }

    }

    }

    printf("%02X ", cch);

    输出为:
    x1=
    A9 5A BE AA A5 55 A5 00 00 FA BC 00 00 15 55 AF FE 95 55 AA AA FE A5

    由路线图可以得到序列2221 1122 2332 2222 2211 1111 2211 0000 0000 3322 2330 0000 0000 0111 1111 2233 3332 2111 1111 2222 2222 3332 2211

    16进制

    0xA9,0x5A,0xbe,0xaa, 0xa5,0x55,0xa5,0x00,

    0x00,0xfa,0xbc,0x00, 0x00,0x15,0x55,0xaf,

    0xfe,0x95,0x55,0xaa, 0xaa,0xfe,0xa5,0x00

    上面是手动走出来的数据
    我们知道这个步进的数据是经过两个xor出来的,所以还要xor回去得到正确的注册码
    注册码前7位的md5作为xor列表,只有16个字节,步进数据要23个字节,后面的7个字节用前面的来补齐,然后再
    xor {0x44, 0xAD, 0x5C, 0xCC, 0x12, 0x90, 0x73, 0x8D, 0x47, 0x81,
    0xE3, 0x89, 0x84, 0x9C, 0xDF, 0xF9, 0x47, 0x6A, 0xB6, 0x9E,
    0x11, 0x30, 0x27}

    参考文章:

    http://bbs.pediy.com/showthread.php?t=213796

    http://bbs.pediy.com/showthread.php?t=213802

    http://bbs.pediy.com/showthread.php?t=213805

    等等

     

    文档下载:http://www.vdisk.cn/down/index/19774317

  • 相关阅读:
    [转]C#汉字转拼音的源码
    [转]C# DES 加密/解密类库,支持文件和中文/UNICODE字符,返回BASE64编码字符串
    48瓶子,48种性格
    “识谎”36计
    巧克力有益智商 经常吃可提高大脑计算能力
    调用方未由服务进行身份验证
    揭秘人体24小时使用手册
    [转]C#实现人民币金额小写转大写的代码
    转一篇绝对详细的手工构造PE文件教程
    bat 查找某个进程的ID号
  • 原文地址:https://www.cnblogs.com/Sendige/p/9601040.html
Copyright © 2020-2023  润新知