海天一色001 发表于 2020-5-29 20:17

160个Crackme之034学习笔记

第34个CM程序,从160个CM的CHM文件中可以看出采用的是Keyfile验证方式,也就是要有一个验证文件,里面有相应的信息,才能象第32个CM一样正常打开程序。

打开CM程序,标题栏里显示3.0版本,未破解字样。点击File菜单项,只有一个“Exit”退出命令,点击就结束了程序;Help菜单内是“About”命令,没有可以利用的地方。

第一步、查壳:

无壳,ASM汇编程序:
第二步、爆破:
用OD载入Cruehead.3.exe,先中文搜索,很容易看到了各种文本提示内容,和第32个CM一样,看到了CRACKME3.KEY这个keyfile文件名,再向下有一个正确提示和两个错误提示:
和第32个CM一样,先在CM所在目录新建一个CRACKME3.KEY文件,这是一个注册表文件,感觉里面应该要写点什么东西吧。先不管那么多,再打开CM程序,和没有CRACKME3.KEY一样,程序界面及菜单项均无任何改变。双击0040118C这一行进入CPU窗口,上下观察代码,在00401188和0040118A两句应该是关键比较和关键跳,跳过了正确提示 ;

在0040119B处是一个call,跟入查看,这里应该是经计算后得到弹出正确提示框。

返回0040119B处,将0040118A处的跳转命令nop掉试一试,将修改后的可执行文件命名为Cruehead.3.nop.exe,运行一下,主窗口和正确提示框同时出现:

应该是爆破成功了,但主窗口的标题栏中还显示出“Uncracked”的未破解字样,没有完全破解成功。
第三步、追码:
从爆破成功的弹出框中看到内容第一行,应该是说是被某某某破解,所以在“Cracked by:”后面是名字,应该是写在CRACKME3.KEY这个注册表文件中的吧。重载程序,F8单步从头开始向下运行,至00401016到0040102D处要读取“CRACKME3.KEY”的注册表文件,如果不存在,则不弹出注册窗口:
00401016|.6A 00         push 0x0                                        ; /hTemplateFile = NULL模板文件:为空
00401018|.68 80000000   push 0x80                                       ; |Attributes = NORMAL文件标志和属性:为一般文件
0040101D|.6A 03         push 0x3                                        ; |Mode = OPEN_EXISTING创建属性:文件必须存在,如果文件或设备不存在,那么CreateFile调用会失败
0040101F|.6A 00         push 0x0                                        ; |pSecurity = NULL安全属性:为空
00401021|.6A 03         push 0x3                                        ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE共享模式:允许共享读写
00401023|.68 000000C0   push 0xC0000000                                 ; |Access = GENERIC_READ|GENERIC_WRITE读取方式:可读、可写
00401028|.68 D7204000   push Cruehead.004020D7                        ; |CRACKME3.KEY文件设备名:CRACKME3.KEY
0040102D|.E8 76040000   call <jmp.&KERNEL32.CreateFileA>                ; \CreateFileA 返回值:执行成功,则返回文件句柄
到00401032处,因为上一句执行成功,此时eax=0x44,所以00401035处会跳走到读取CRACKME3.KEY这个文件的内容:
00401043|> \A3 F5204000   mov dword ptr ds:,eax               ;D
00401048|.B8 12000000   mov eax,0x12
0040104D|.BB 08204000   mov ebx,Cruehead.00402008
00401052|.6A 00         push 0x0                                        ; /pOverlapped = NULL 参数设为NULL表示不是异步读取操作
00401054|.68 A0214000   push Cruehead.004021A0                        ; |pBytesRead = Cruehead.004021A0从文件中实际读取的字节数
00401059|.50            push eax                                        ; |BytesToRead = 12(18.) 要读入的字符数
0040105A|.53            push ebx                                        ; |Buffer = Cruehead.00402008 用于保存读入数据的缓冲区
0040105B|.FF35 F5204000 push dword ptr ds:                  ; |D
00401061|.E8 30040000   call <jmp.&KERNEL32.ReadFile>                   ; \ReadFile调用成功,返回非0调用不成功,返回为0
00401066|.833D A0214000>cmp dword ptr ds:,0x12                ;文件中不能少于18个字符
0040106D|.^ 75 C8         jnz short Cruehead.00401037                     ;不等跳向失败
00401059 处ReadFile 的BytesToRead参数为0x12,即要读入的字符数为18个,而在00401066处指令是“cmp dword ptr ds:,0x12”,也就是说实际读取出的字数与要读取的字数进行比较要相等,不等则跳走,失败了。所以在00401061处下断,重载CM程序,再切换到CM程序所在目录,打开CRACKME3.KEY文件,随意输入不少于18个字符并保存文件(我输入的是“qwertyuiopasdfghjklasdfghjklzxcvbnm”共26个字母)。打开CM原程序,仍然没有任何改变;关闭后再打开Cruehead.3.nop.exe,运行一下,主窗口和正确提示框同时出现,且提示框内容已经改变了:

可以看出后面一串字符肯定不是正确的名字,所以还要切换回OD,F9运行,继续调试:从00401061开始单步向下,到0040106F处,将CRACKME3.KEY文件中的前18个字符“qwertyuiopasdfghjk”压入堆栈;

运行到00401074处时,先查看了一下ds:=0,F7跟入00401311中:

先将ecx清零,作为下面循环次数的暂存器;再将eax清零,作为serial字符的暂存器;esi存入CRACK3.KEY文件的前18个字符;bl赋值为0x41;al得到第1个字符,再与bl异或,得到的值累加存入ds:中,异或的值转换成的字符再存回原字符的位置(待循环结束,经0040133C子程序验证后作为破解者名字出现在正确提示窗口中);然后字符位置向后1位, bl值加1,循环次数加1,总共循环14次求值,其中如果CRACK3.KEY文件的前14个字符中某1个字符和bl异或后的值为0时就会跳出循环;
运行到00401335处,将ds:中的值与0x12345678异或后重新存入ds:中备用;下一句retn回00401079处,再查看ds:= 0x29E;此时0040106F和00401086处注释变成了“ASCII "05&61?2!&:*?)(ghjk”,00401079处运行后,ds:= 0x123454E6;
继续运行到00401086处,将处理过的字符串压栈作为0040108B处call的参数继续进行处理, F7跟入0040133C中:

可以看出这个call的作用是先得到处理过的字符串,然后esi的地址向后0xE(14)位,即来到0x402008+0xE=0x402016处,从CRACK3.KEY文件中第18、17、16、15个字符的16进制ASC值并连接起来赋予eax,然后retn回00401090处:
00401090|.83C4 04       add esp,0x4
00401093|.3B05 F9204000 cmp eax,dword ptr ds:                ;此处必须相等,否则还是失败!!!!
00401099      0f94c0      sete al                                        ;if eax = ds: then set al=1 else set al =0 endif
0040109C|.50            push eax
0040109D|.84C0          test al,al
0040109F    ^ 74 96         je short Cruehead.00401037                     ;跳至主窗口标题后半部分为uncracked的子程序
004010A1|.68 0E214000   push Cruehead.0040210E                         ;CrackMe v3.0
004010A6|.E8 9B020000   call Cruehead.00401346                         ;al=1时,得出主窗口标题后半部分内容为cracked的子程序
004010AB|.83C4 04       add esp,0x4004010AE|>6A 00         push 0x0                                       ; /Title = NULL
004010B0|.68 28214000   push Cruehead.00402128                         ; |No need to disasm the code!
004010B5|.E8 9A030000   call <jmp.&USER32.FindWindowA>               ; \FindWindowA
004010BA|.0BC0          or eax,eax
004010BC|.74 01         je short Cruehead.004010BF
004010BE|.C3            retn
004010BF|>C705 76204000>mov dword ptr ds:,0x4003
到00401093处将eax与ds:进行比较,结合下面的指令并多次调试后可知此处如果不相等,则运行到0040109F处后跳到00401037处,再call 004012F5子程序,将主窗口标题后半部分变成未注册字样(-Uncracked);eax与ds:相等,则到0040109F处不跳走而向下,到004010A6处调用00401346子程序,主窗口标题后半部分变成了已注册字样(-Cracked),然后向下就会按照标准的win32程序启动过程,先是FindWindowA函数获得顶层窗口的句柄,LoadIconA加载图标、LoadCursorA加载鼠标指针、RegisterClassA注册类,再到CreateWindowExA创建主窗体等,再利用作者修改后的win32过程函数Cruehead.WndProc()来接收消息,从而弹出正确提示框。
所以注册算法主要是在00401311和0040133C这两个call中。
从追码的过程中,可以看到爆破过程还是不完全的,没有将主窗口的标题改成“Cracked”,而追码中明白了作者的思路,所以应该在0040109F和0040118A处将跳转命令nop掉,保存为Cruehead.3.nop.nop.exe,运行一下,成功了,主窗口标题是“cracked”,弹出提示框也是正确的。
0040109F    ^\74 96         je short Cruehead.00401037                     ;跳至主窗口标题后半部分为uncracked的子程序
0040118A   /75 17         jnz short Cruehead.004011A3
注册算法:先读取CRACK3.KEY文件的内容,依次取前14位字符的ASC码与A、B......到N的ASC码分别异或,得到的值再转换成字符,成为破解者名字;异或值累加,再与0x12345678异或后,值的16进制数值形式与第18、17、16、15位字符的16进制ASC值连接起来相同,则破解成功,否则不成功。
注册算法出来了,注册机编写:
Option Explicit
Private Sub Command1_Click()
    Dim Serial, se1, Name, Key As String       'Key文件中的前14个字符、第18至15个字符的16进制数值连接形成的新数值、破解者名字、密钥
    Dim DS004020F9, Bl, i As Integer         'i为循环数,DS004020F9为CM程序中内存地址缓存,Bl依次为A至K的16进制数值
    Dim S() As Integer                         'S()为14个字符分别与A至N异或的值
      Name = Text1.Text                      'Name来自于文本框输入,如果未输入则默认为“www.52pojie.cn”,Serial为写入注册表文件中的前14位字符
      If Name = "" Then
            Name = "www.52pojie.cn"
            Text1.Text = Name
            Text2.Text = "654jpt7'##.b. hS4"
            Exit Sub
      End If
      If Len(Name) > 14 Then Name = Mid(Name, 1, 14)                      '如果超过14个字符则只取前14个
      If Len(Name) < 14 Then Name = Name & String(14 - Len(Name), " ")    '如果不够14个字符则后面补空格到14个
      'Form1.Print Name
      Bl = 65
      ReDim S(1 To 14)
      For i = 1 To 14                                                   '得到前14个字符
            S(i) = Asc(Mid(Name, i, 1)) Xor Bl
            Bl = Bl + 1
            Serial = Serial & Chr(S(i))
            'Form1.Print "Serial(" & i & ") =" & Serial
            DS004020F9 = DS004020F9 + Asc(Mid(Name, i, 1))
            If S(i) = 0 Then Exit For
      Next i
      'Serial = Trim(Serial):习惯性思维去空格,却忘记了空格也是一个字符!
      If Len(Serial) < 14 Then Serial = Serial & String(14 - Len(Serial), "0")
      DS004020F9 = DS004020F9 Xor &H12345678
      'Form1.Print "DS004020F9=" & DS004020F9
      se1 = Hex(DS004020F9)
      'Form1.Print "se1=" & se1
      For i = 4 To 1 Step -1                                              '得出后4位字符
            Key = Key & Chr(Val("&H" & Mid(se1, 2 * i - 1, 2)))
         'Key = Key & Chr(Val("&H" & Mid(se1, i, 2)))
         'Form1.Print "Key=" & Key
      Next i
      Text2.Text = Serial & Key                                           '一个问题,在Key最前面是空格时连接不到一起来,
      Command2.Visible = True
      End Sub
Private Sub Command2_Click()                                                '生成注册文件
    Open "CRACKME3.KEY" For Output As #1
    Print #1, Text2.Text
    Close
End Sub
用VB编写注册机过程中却是错了一遍又一遍,郁闷了很久,自己猜测是不是CM程序自身有问题?毕竟异或0x12345678的结果大部分前4位是1234,转换成字符是和4,而后4位就多了,如E6、8A之类,这些用chr()函数得不出正确的结果。而且在Text2.Text = Serial & Key这句代码中如果Key第1个字符是空格,则无法连接,只显示了前面Serial的字符,盼请各位大神指教!!!
终于完成了!
附件,含CM原程序、爆破后的程序、注册机、OD的调试文件等。百度链接是:http://pan.baidu.com/s/1skMkJY9,密码: 86pm,160个CM、我已练习过的前34个crackme程序(012未能破解)都在里面。

SnowRen 发表于 2020-5-29 21:15

感谢分享,楼主好长时间没发文了

xie7 发表于 2020-5-29 21:19

感谢分享!!

黄河大鲤鱼 发表于 2020-5-29 21:45

有没有打好包的全集啊

天蝎浪花 发表于 2020-5-29 23:33

后面附的网盘链接没有034哦

gaoyuan1234 发表于 2020-5-31 06:39

感谢分享!!学习学习再学习

斩风 发表于 2020-5-31 14:33

学习了,感谢分享

海天一色001 发表于 2020-5-31 14:57

天蝎浪花 发表于 2020-5-29 23:33
后面附的网盘链接没有034哦

不好意思,已上传了

潜水呀zhtty 发表于 2020-6-6 21:09

支持11111
页: [1]
查看完整版本: 160个Crackme之034学习笔记