飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3209|回复: 5

一个crackme的算法分析(适合初学者)

[复制链接]

该用户从未签到

发表于 2006-3-5 18:43:23 | 显示全部楼层 |阅读模式
【破文标题】一个crackme的算法分析
【破文作者】windycandy
破解工具】OD,Peid0.94
【破解平台】Windows xp
【软件名称】crackme
【软件大小】12K
【保护方式】name & SN
【破解声明】我是一只小菜鸟,偶得一点心得,愿与大家分享
------------------------------------------------------------------------
1.前言

最近学习CCDebuger前辈的<OllyDBG 入门系列>,使我等菜鸟受益匪浅,今有所成,又巧遇一crackme,可用前辈的
<消息断点及 RUN 跟踪>方法破之,遂将过程写出来,与跟我一样的菜鸟共勉,同时激励前辈在有时间情况下写出
更多的教程,以供我们观摩学习.

2.破解过程

先运行程序看看情况,点HELP随便输入name:windycandy,serial:87654321.按OK,出现错误提示框.好了,现在拿
工具开始行动.

Peid 查壳无壳,为MASM32 / TASM32 [Overlay]编写的程序.

OD载入,停在入口:

00401000 C>/$  6A 00         push 0                              ; /(初始化 cpu 选择状态)
00401002   |.  E8 FF040000   call <jmp.&KERNEL32.GetModuleHandle>; \GetModuleHandleA
00401007   |.  A3 CA204000   mov dword ptr ds:[4020CA],eax
0040100C   |.  6A 00         push 0                              ; /Title = NULL
0040100E   |.  68 F4204000   push CRACKME.004020F4               ; |no need to disasm the code!
00401013   |.  E8 A6040000   call <jmp.&USER32.FindWindowA>      ; \FindWindowA
00401018   |.  0BC0          or eax,eax
0040101A   |.  74 01         je short CRACKME.0040101D

用字符串插件能找到有效字符"great work, mate!\nnow try the next crackme!"及"no luck there, mate!"分别
双击都能来到反汇编窗口,但是向上找都没有找到能跳过错误提示框的关键跳,这下好象有点意思了.这样找关键算法
的call好象也比较困难,改用<消息断点及 RUN 跟踪>方法则轻松破之.

OD重新载入,F9运行,到注册界面输入"windycandy"及"8765432100",不按"OK"
在OD菜单找"查看"下的"窗口"或直接按"M"(有时按"窗口"或"M"看不到内容,这时可以轮换按"M"或"窗口")
出现以下窗口

句柄           标题                 父级       WinProc    ID      ? 样式       ExtStyle   线程       ClsProc    Class
00020684                            Topmost                          0CC00000   00000100   主          10005F60   ATL:10055250
00040682       Register             Topmost                          14C800C4   00010101   主          77D1C6C4   #32770
K0002064E      Serial               00040682              0000FFFF   50020000   00000004   主          77D1CC6C   Static
K00020652      Name                 00040682              0000FFFF   50020000   00000004   主          77D1CC6C   Static
K00020654      Cancel               00040682              000003EB   50010000   00000004   主          77D30515   Button
K00020664      OK                   00040682              000003EA   50010000   00000004   主          77D30515   Button
K00020666                           00040682              000003E9   50010080   00000204   主          77D28530   Edit
K00030668                           00040682              000003E8   50010080   00000204   主          77D28530   Edit
E00090650      Default IME          00040682                         8C000000              主          77D63CE2   IME
NE0008066C     M                    00090650                         8C000000              主          FFFF037D   MSCTFIME UI
00060644       Hammer of Thor       Topmost                          8C000000              主          77D15C55   Mjolnir
E00040642      THOR MAIN WINDOW     00060644                         8C400000   00000188   主          10037BCB   CiceroUIWndFrame
NK0002063E     CiceroUIWndFrame     00040642                         8C000000   00080008   主          10037BCB   CiceroUIWndFrame
NIK0002062E    PadListView          0002063E                         56000000   00000200   主          10028210   PadListView
NIIE000206A2                        0002062E              00000020   50000002              主          FFFF02C1   SysHeader32
NIE0002063C    CiceroUIWndFrame     0002063E                         8C800000   00000008   主          10037BCB   CiceroUIWndFrame
NK00020640     CiceroUIWndFrame     00040642                         8C800000   00000008   主          10037BCB   CiceroUIWndFrame
NE00020698     PadListView          00040642                         56000000   00000200   主          10028210   PadListView
NNE00020658                         00020698              00000020   40000002              主          FFFF02C1   SysHeader32
00090648       CrackMe v1.0         Topmost               00070781   1CCF0000   00000100   主          00401128   No need to disasm the code!

找到按钮"OK"
单击右键------->  "在Classproc上设消息断点"---------> 选"202 WM_LBUTTONUP"--------> 点"确定"

再在"调试"菜单下"打开或清除RUN跟踪",开始RUN跟踪
确保在反汇编窗口下
单击右键---------> RUN跟踪------------->  添加全部函数例程的入口
返回到crackme窗口,按"OK"
条件中断在
77D30515 [>  55              push ebp--------中断在这里
77D30516     8BEC            mov ebp,esp
77D30518     8B4D 08         mov ecx,dword ptr ss:[ebp+8]
77D3051B     56              push esi
77D3051C     E8 0335FEFF     call USER32.77D13A24
77D30521     8BF0            mov esi,eax
77D30523     85F6            test esi,esi
77D30525     74 38           je short USER32.77D3055F
77D30527     8B55 0C         mov edx,dword ptr ss:[ebp+C]
77D3052A     3B15 C8C0D677   cmp edx,dword ptr ds:[77D6C0C8]
77D30530     77 1E           ja short USER32.77D30550
77D30532     33C0            xor eax,eax

按Alt+M

内存映射,项目 23
地址=00401000
大小=00001000 (4096.)
宿主=CRACKME  00400000
区段=CODE
包含=code
类型=Imag 01001002
访问=R
初始访问=RWE

在crackme, code 段下F2断点,F9运行,中断在00401253

00401253   /.  C8 000000     enter 0,0-------断在这里
00401257   |.  53            push ebx
00401258   |.  56            push esi
00401259   |.  57            push edi
0040125A   |.  817D 0C 10010>cmp dword ptr ss:[ebp+C],110
00401261   |.  74 34         je short CRACKME.00401297
00401263   |.  817D 0C 11010>cmp dword ptr ss:[ebp+C],111
0040126A   |.  74 35         je short CRACKME.004012A1
0040126C   |.  837D 0C 10    cmp dword ptr ss:[ebp+C],10
00401270   |.  0F84 81000000 je CRACKME.004012F7
00401276   |.  817D 0C 01020>cmp dword ptr ss:[ebp+C],201
0040127D   |.  74 0C         je short CRACKME.0040128B
0040127F   |.  B8 00000000   mov eax,0
00401284   |>  5F            pop edi
00401285   |.  5E            pop esi

向下翻,看到

004012B5   |.  6A 0B         |push 0B                            ; /Count = B (11.)
004012B7   |.  68 8E214000   |push CRACKME.0040218E              ; |Buffer = CRACKME.0040218E
004012BC   |.  68 E8030000   |push 3E8                           ; |ControlID = 3E8 (1000.)
004012C1   |.  FF75 08       |push dword ptr ss:[ebp+8]          ; |hWnd
004012C4   |.  E8 07020000   |call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA--------------这个,我们喜欢
004012C9   |.  83F8 01       |cmp eax,1
004012CC   |.  C745 10 EB030>|mov dword ptr ss:[ebp+10],3EB
004012D3   |.^ 72 CC         \jb short CRACKME.004012A1
004012D5   |.  6A 0B         push 0B                             ; /Count = B (11.)
004012D7   |.  68 7E214000   push CRACKME.0040217E               ; |Buffer = CRACKME.0040217E
004012DC   |.  68 E9030000   push 3E9                            ; |ControlID = 3E9 (1001.)
004012E1   |.  FF75 08       push dword ptr ss:[ebp+8]           ; |hWnd
004012E4   |.  E8 E7010000   call <jmp.&USER32.GetDlgItemTextA>  ; \GetDlgItemTextA--------------这个,我们喜欢
004012E9   |.  B8 01000000   mov eax,1
004012EE   |.  EB 07         jmp short CRACKME.004012F7

于是在4012B5,F2下断,删除其他断点, Ctrl+F2重新载入,F9运行,输入name和serail,点确定中断在4012B5
F8一路来到
00401223    .  83F8 00       cmp eax,0
00401226    .^ 74 BE         je short CRACKME.004011E6
00401228    .  68 8E214000   push CRACKME.0040218E               ;  ASCII "windycandy"姓名入栈
0040122D    .  E8 4C010000   call CRACKME.0040137E -----------------对name进行算法运算,F7跟进
00401232    .  50            push eax
00401233    .  68 7E214000   push CRACKME.0040217E               ;  ASCII "8765432100"
00401238    .  E8 9B010000   call CRACKME.004013D8
0040123D    .  83C4 04       add esp,4
00401240    .  58            pop eax
00401241    .  3BC3          cmp eax,ebx
00401243    .  74 07         je short CRACKME.0040124C
00401245    .  E8 18010000   call CRACKME.00401362
0040124A    .^ EB 9A         jmp short CRACKME.004011E6
0040124C    >  E8 FC000000   call CRACKME.0040134D
00401251    .^ EB 93         jmp short CRACKME.004011E6

进入40122D来到
0040137E   /$  8B7424 04     mov esi,dword ptr ss:[esp+4]------------输入的name放入esi
00401382   |.  56            push esi
00401383   |>  8A06          /mov al,byte ptr ds:[esi]---------------取name的字符进行逐个判断
00401385   |.  84C0          |test al,al
00401387   |.  74 13         |je short CRACKME.0040139C---------------所有字符判断结束则跳走
00401389   |.  3C 41         |cmp al,41               ----------------是否是字母"A"以上的字符
0040138B   |.  72 1F         |jb short CRACKME.004013AC---------------不是,over
0040138D   |.  3C 5A         |cmp al,5A
0040138F   |.  73 03         |jnb short CRACKME.00401394---------------与字母"Z"比较,不小于则进行处理
00401391   |.  46            |inc esi                  ------------------下一个字符
00401392   |.^ EB EF         |jmp short CRACKME.00401383
00401394   |>  E8 39000000   |call CRACKME.004013D2------------------------字符转换,关键call,F7跟进
00401399   |.  46            |inc esi                            ;  CRACKME.0040218E
0040139A   |.^ EB E7         \jmp short CRACKME.00401383

F7进入401394
004013D2   /$  2C 20         sub al,20---------------------------------------将name中的小写字母换成大写字母
004013D4   |.  8806          mov byte ptr ds:[esi],al
004013D6   \.  C3            retn-----------------------------------------------返回

字符转换完后,返回到这里继续以下处理

0040139C   |> \5E            pop esi             ---------------------------换算结果入esi
0040139D   |.  E8 20000000   call CRACKME.004013C2--------------------------算法call,F7跟进
004013A2   |.  81F7 78560000 xor edi,5678
004013A8   |.  8BC7          mov eax,edi

F7进入40139D

004013C2   /$  33FF          xor edi,edi-----------------清零,准备运算
004013C4   |.  33DB          xor ebx,ebx-----------------清零,准备运算
004013C6   |>  8A1E          /mov bl,byte ptr ds:[esi]---逐一取esi的字符
004013C8   |.  84DB          |test bl,bl            
004013CA   |.  74 05         |je short CRACKME.004013D1--esi内的字符处理完则跳走
004013CC   |.  03FB          |add edi,ebx------------------累加,结果放入edi
004013CE   |.  46            |inc esi  -------------------下一位字符
004013CF   |.^ EB F5         \jmp short CRACKME.004013C6
004013D1   \>  C3            retn----------------------------返回

返回到这里
004013A2   |.  81F7 78560000 xor edi,5678---------------运算结果与"5678"异域运算
004013A8   |.  8BC7          mov eax,edi-----------------运算结果送入eax
004013AA   |.  EB 15         jmp short CRACKME.004013C1---跳到4013C1,返回

返回这里
00401232    .  50            push eax--------------------返回这里
00401233    .  68 7E214000   push CRACKME.0040217E               ;  ASCII "8765432100"假码入栈
00401238    .  E8 9B010000   call CRACKME.004013D8------------------算法call,F7跟进
0040123D    .  83C4 04       add esp,4
00401240    .  58            pop eax
00401241    .  3BC3          cmp eax,ebx
00401243    .  74 07         je short CRACKME.0040124C
00401245    .  E8 18010000   call CRACKME.00401362
0040124A    .^ EB 9A         jmp short CRACKME.004011E6
0040124C    >  E8 FC000000   call CRACKME.0040134D
00401251    .^ EB 93         jmp short CRACKME.004011E6

F7进入
004013D8   /$  33C0          xor eax,eax-----------------清零,准备运算
004013DA   |.  33FF          xor edi,edi-----------------清零,准备运算
004013DC   |.  33DB          xor ebx,ebx-----------------清零,准备运算
004013DE   |.  8B7424 04     mov esi,dword ptr ss:[esp+4]----假码送入esi
004013E2   |>  B0 0A         /mov al,0A
004013E4   |.  8A1E          |mov bl,byte ptr ds:[esi]----逐一取假码进行运算
004013E6   |.  84DB          |test bl,bl
004013E8   |.  74 0B         |je short CRACKME.004013F5---处理完则跳走
004013EA   |.  80EB 30       |sub bl,30-------------------减30
004013ED   |.  0FAFF8        |imul edi,eax-----------------edi=edi*eax
004013F0   |.  03FB          |add edi,ebx------------------edi=eid+ebx
004013F2   |.  46            |inc esi----------------------下一位
004013F3   |.^ EB ED         \jmp short CRACKME.004013E2
004013F5   |>  81F7 34120000 xor edi,1234--------------------运算结果与1234异域
004013FB   |.  8BDF          mov ebx,edi----------------------运算结果送入edx
004013FD   \.  C3            retn-----------------------------返回

返回这里
0040123D    .  83C4 04       add esp,4------返回这里
00401240    .  58            pop eax
00401241    .  3BC3          cmp eax,ebx-----------------------name的算法运算结果与serial的算法运算结果比较
00401243    .  74 07         je short CRACKME.0040124C---------------关键跳,爆破点
00401245    .  E8 18010000   call CRACKME.00401362--------------------不等则OVER
0040124A    .^ EB 9A         jmp short CRACKME.004011E6
0040124C    >  E8 FC000000   call CRACKME.0040134D--------------------相等"congraduatin!"
00401251    .^ EB 93         jmp short CRACKME.004011E6


破解总结:
这个crackme的注册属于F'(name)=F'(serial)的类型,其算法为:
①输入的name必须全部是字母,在name的字母中如果有小写字母则需要将该小写字母换成大写
字母,本身是大写字母的不用转换,然后将name(都是大写字母)的各字符串的ARSII值累加,累
加结果与"5678"进行异域运算,得出F'(name);
②取输入假码的每位ARSCII值(B),作如下运算(A为常数):
y<=B-30
Z<=Z*A
Z<=Z+Y
算完一位再取下一位.
最后将累加结果(Z)与"1234"作异域运算,得出F'(serial)

如果F'(name)=F'(serial)则注册成功.

注册机,我不会写,只能算出自己的注册码,有时间再学写写注册机.

name=windycandy
serial=B102或serial=18102

推算过程:
windycany

│转换为大写

WINDYCANDY

│name的算法、累加处理

2FA

│xor 5678

5482----F'(name)

│xor 1234

46B6

│除以常数“A”------------余数“2”,2+30=32-----ARSII表中为字符“2”------注册码倒数第一位

712

│除以常数“A”------------余数“0”,0+30=30-----ARSII表中为字符“0”------注册码倒数第二位

B5

│除以常数“A”------------余数“1”,1+30=31-----ARSII表中为字符“1”------注册码倒数第三位

12---------(如果只算到这里余数“12”,12+30=42---ARSII表中为字符“B”------注册码倒数第四位)----得出serial=B102

│除以常数“A”------------余数“8”,8+30=38-----ARSII表中为字符“8”------注册码倒数第四位

1--------------------------余数“1”,1+30=31-----ARSII表中为字符“1”------注册码倒数第五位----得出serial=18102


最后,如果使用字符串插件找到"no luck there, mate!",双击来到反汇编窗口
00401362   /$  6A 00         push 0                              ; /BeepType = MB_OK
00401364   |.  E8 AD000000   call <jmp.&USER32.MessageBeep>      ; \MessageBeep
00401369   |.  6A 30         push 30                             ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
0040136B   |.  68 60214000   push CRACKME.00402160               ; |no luck!
00401370   |.  68 69214000   push CRACKME.00402169               ; |no luck there, mate!--------------到这里
00401375   |.  FF75 08       push dword ptr ss:[ebp+8]           ; |hOwner
00401378   |.  E8 BD000000   call <jmp.&USER32.MessageBoxA>      ; \MessageBoxA
0040137D   \.  C3            retn

到这里后,注意401362及40137D,可以猜测这是某个CALL调用的子程序,于是使用Ctrl+F查找"call 401362"也能找到关键点
00401241    .  3BC3          cmp eax,ebx
00401243    .  74 07         je short CRACKME.0040124C
00401245    .  E8 18010000   call CRACKME.00401362------------找到这里
0040124A    .^ EB 9A         jmp short CRACKME.004011E6
0040124C    >  E8 FC000000   call CRACKME.0040134D
00401251    .^ EB 93         jmp short CRACKME.004011E6
以下分析相同.


------------------------------------------------------------------------
【版权声明】本文仅属于技术交流,如有转载请注明出处.

[ 本帖最后由 windycandy 于 2006-3-19 01:30 编辑 ]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入我们

x
PYG19周年生日快乐!
  • TA的每日心情
    难过
    2024-4-22 14:49
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    发表于 2006-3-5 18:49:11 | 显示全部楼层
    建议将CrackMe贴出来,给大家学习!

    写注册机时,对算法求逆就可以了,呵呵!
    PYG19周年生日快乐!
  • TA的每日心情
    无聊
    2020-4-10 17:02
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2006-3-5 20:19:04 | 显示全部楼层
    其实只要在这里下断就OK:

    00401223    .  83F8 00       cmp eax,0

    往下的两个CALL 就是算法CALL了!很容易看出来!

    对于这个练习,好像有点麻烦了!呵呵!

    不过对于学习,我是非常支持的!!

    先计算出用户名的算法,再计算注册码,是非常容易的!呵呵!

    NAME: lengxue
    CODE: 18004
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2006-3-6 09:03:36 | 显示全部楼层
    强啊,适合我等新手
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2006-3-6 09:43:31 | 显示全部楼层
    好文章哪!! 顶起来!!!
    PYG19周年生日快乐!
  • TA的每日心情
    奋斗
    2019-1-26 00:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2006-3-6 18:04:09 | 显示全部楼层
    辛苦了,支持一下
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表