最近在看加密解密,看到了第五章序列号保护方式的crackme,分析了一下。

在输入用户名和序列号的地方随便输入,弹出错误对话框。

用lordPE查看输入表发现user32模块中有GetDlgItemTextA,直接OD加载对其下断,运行回到程序领空:

004012B5  |.  6A 0B         |push    0B                              ; /Count = B (11.)
004012B7  |.  68 8E214000   |push    0040218E                        ; |Buffer = serial.0040218E
004012BC  |.  68 E8030000   |push    3E8                             ; |ControlID = 3E8 (1000.)
004012C1  |.  FF75 08       |push    dword ptr [ebp+8]               ; |hWnd
004012C4  |.  E8 07020000   |call    <jmp.&USER32.GetDlgItemTextA>   ; \GetDlgItemTextA    得到用户名


004012C9  |.  83F8 01       |cmp     eax, 1                          ;  判断得到用户名是否为空
004012CC  |.  C745 10 EB030>|mov     dword ptr [ebp+10], 3EB
004012D3  |.^ 72 CC         \jb      short 004012A1
004012D5  |.  6A 0B         push    0B                               ; /Count = B (11.)
004012D7  |.  68 7E214000   push    0040217E                         ; |Buffer = serial.0040217E
004012DC  |.  68 E9030000   push    3E9                              ; |ControlID = 3E9 (1001.)
004012E1  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
004012E4  |.  E8 E7010000   call    <jmp.&USER32.GetDlgItemTextA>    ; \GetDlgItemTextA    得到序列号
004012E9  |.  B8 01000000   mov     eax, 1
004012EE  |.  EB 07         jmp     short 004012F7
004012F0  |>  B8 00000000   mov     eax, 0
004012F5  |.^ EB 8D         jmp     short 00401284
004012F7  |>  50            push    eax                              ; /Result
004012F8  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
004012FB  |.  E8 B2010000   call    <jmp.&USER32.EndDialog>          ; \EndDialog    关闭输入对话框
00401300  |.  B8 01000000   mov     eax, 1
00401305  \.^ E9 7AFFFFFF   jmp     00401284

继续跟来到这里

00401228   .  68 8E214000   push    0040218E                         ;  ASCII “lingdux”
0040122D   .  E8 4C010000   call    0040137E                         ;  用户名算法call
00401232   .  50            push    eax                              ;  保存用户名加密后的值
00401233   .  68 7E214000   push    0040217E                         ;  ASCII “123456″
00401238   .  E8 9B010000   call    004013D8                         ;  序列号的算法call
0040123D   .  83C4 04       add     esp, 4
00401240   .  58            pop     eax                              ;  从堆栈中取出之前保存的用户名加密后的结果
00401241   .  3BC3          cmp     eax, ebx                         ;  序列号算完保存在ebx中,与用户名比较
00401243   .  74 07         je      short 0040124C

nop掉这处je就可以爆破了,然后分析两个算法call

第一个call    0040137E是加密用户名的,跟进去分析。。

0040137E  /$  8B7424 04     mov     esi, dword ptr [esp+4]
00401382  |.  56            push    esi
00401383  |>  8A06          /mov     al, byte ptr [esi]
00401385  |.  84C0          |test    al, al                 ;  检测是不是到了字符串结尾
00401387  |.  74 13         |je      short 0040139C
00401389  |.  3C 41         |cmp     al, 41                 ;  小于字符A跳
0040138B  |.  72 1F         |jb      short 004013AC
0040138D  |.  3C 5A         |cmp     al, 5A                 ;  大于字符Z跳
0040138F  |.  73 03         |jnb     short 00401394
00401391  |.  46            |inc     esi
00401392  |.^ EB EF         |jmp     short 00401383
00401394  |>  E8 39000000   |call    004013D2               ;  小写字母转换成大写字母call
00401399  |.  46            |inc     esi                    ;  serial.0040218E
0040139A  |.^ EB E7         \jmp     short 00401383         ;  如果字符串中有小写字母转换为大写,如果有数字则直接跳出
0040139C  |>  5E            pop     esi
0040139D  |.  E8 20000000   call    004013C2                ;  求字母asc码值的和call
004013A2  |.  81F7 78560000 xor     edi, 5678               ;  结果和5678异或
004013A8  |.  8BC7          mov     eax, edi                ;  结果保存在eax中作为返回值
004013AA  |.  EB 15         jmp     short 004013C1
004013AC  |>  5E            pop     esi
004013AD  |.  6A 30         push    30                      ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013AF  |.  68 60214000   push    00402160                ; |Title = “Error!  ”
004013B4  |.  68 69214000   push    00402169                ; |Text = “Incorrect!,Try Again”
004013B9  |.  FF75 08       push    dword ptr [ebp+8]       ; |hOwner
004013BC  |.  E8 79000000   call    <jmp.&USER32.MessageBox>; \MessageBoxA
004013C1  \>  C3            retn

004013C2  /$  33FF          xor     edi, edi
004013C4  |.  33DB          xor     ebx, ebx
004013C6  |>  8A1E          /mov     bl, byte ptr [esi]
004013C8  |.  84DB          |test    bl, bl                 ;  检测是否到字符串尾
004013CA  |.  74 05         |je      short 004013D1
004013CC  |.  03FB          |add     edi, ebx               ;  循环加和到edi中
004013CE  |.  46            |inc     esi
004013CF  |.^ EB F5         \jmp     short 004013C6
004013D1  \>  C3            retn

004013D2  /$  2C 20         sub     al, 20                  ;  小写字母asc值加0×20就是对应的大写
004013D4  |.  8806          mov     byte ptr [esi], al
004013D6  \.  C3            retn

用户名中不能有数字,小写字母均转换成大写并所有字母的数值加和与0×5678异或得出的值用来做比较

下面分析序列号加密。。

004013D8  /$  33C0          xor     eax, eax
004013DA  |.  33FF          xor     edi, edi
004013DC  |.  33DB          xor     ebx, ebx
004013DE  |.  8B7424 04     mov     esi, dword ptr [esp+4]
004013E2  |>  B0 0A         /mov     al, 0A
004013E4  |.  8A1E          |mov     bl, byte ptr [esi]
004013E6  |.  84DB          |test    bl, bl                 ;  判断是否到字符串结尾
004013E8  |.  74 0B         |je      short 004013F5
004013EA  |.  80EB 30       |sub     bl, 30                 ;  数字的asc减0×30相当于把字符转换成值
004013ED  |.  0FAFF8        |imul    edi, eax               ;  edi用于保存结果,每次相加前edi乘以0×0A,相当于进位
004013F0  |.  03FB          |add     edi, ebx               ;  和数值相加
004013F2  |.  46            |inc     esi
004013F3  |.^ EB ED         \jmp     short 004013E2
004013F5  |>  81F7 34120000 xor     edi, 1234               ;  执行循环后结果和0×1234异或
004013FB  |.  8BDF          mov     ebx, edi                ;  最终结果保存在ebx中
004013FD  \.  C3            retn

 序列号的加密方法就是:把输入的字符串转换成一个数然后和0×1324异或

由于异或是可逆的,非常容易写出算法注册机。

char name[256];
 cin>>name;
 CharUpper(name);
 int s=0;
 int i=0;
 while(name[i])
 {
  s+=name[i];
  i++;
 }
 s^=0×5678;
 s^=0×1234;
 cout<<s<<endl;

上面代码编译执行,输入用户名就输出序列号了~!~

Trackback

本文到目前为止有 7 个回复

  1. 前段时间我也在看诶~

    [回复]

    零度x 回复:

    呵呵,等有不会的向你请教!

    [回复]

    一击屠夫 回复:

    - -||我不行的

    [回复]

    零度x 回复:

    屠夫兄谦虚!呵呵。对了,屠夫兄知道什么时候google更新PR吗?

  2. PR更新这个事。不好说,完全无规律可循。
    最近一次就是元旦。
    零度兄这个blog pr值不达到预期的原因我想跟外链建设力度还不够有关~

    [回复]

    零度x 回复:

    受教了!
    上次是从2降到1的

    [回复]

    一击屠夫 回复:

    恩,链条是这样的
    内容-流量-链接-更多流量-再绕回内容

    我们这些blog都很难做的成功的另一个原因是受众不关注互联网产品,衡量一个博客成功与否的最好方法其实是看订阅数- -可是很多人都不使用订阅- =||

    [回复]

添加回复