missviola 发表于 2009-5-2 14:53:58

救市KGme算法分析

【破文标题】KGme 算法分析
【破文作者】missviola
【作者邮箱】
【作者主页】
【破解工具】DEDE OD PEID
【破解平台】Windows XP
【软件名称】
【软件大小】
【原版下载】
【保护方式】
【软件简介】
【破解声明】只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
------------------------------------------------------------------------
【破解过程】这几天逛论坛发现as3852711大牛发的一个KGme,自己下载分析了一下,于是就有了这篇破文。首先用PEID查壳,显示Borland Delphi 6.0 - 7.0。用DEDE分析下,发
现“Register”按钮click事件对应的地址为467C30。打开OD在467C30处下断点,F9运行,输入假码123456,点击按钮,crackme断下,F8单步往下走。
00467C30 <K>55            push ebp                                 ; <-TForm1@Button1Click
00467C31      8BEC            mov ebp,esp
00467C33      83C4 C0         add esp,-40
00467C36      53            push ebx
00467C37      56            push esi
00467C38      33C9            xor ecx,ecx
00467C3A      894D DC         mov dword ptr ss:,ecx
00467C3D      894D D8         mov dword ptr ss:,ecx
00467C40      894D CC         mov dword ptr ss:,ecx
00467C43      894D E0         mov dword ptr ss:,ecx
00467C46      894D FC         mov dword ptr ss:,ecx
00467C49      8BF2            mov esi,edx
00467C4B      8BD8            mov ebx,eax
00467C4D      33C0            xor eax,eax
00467C4F      55            push ebp
00467C50      68 917D4600   push <KGMe.->System.@HandleFinally;>
00467C55      64:FF30         push dword ptr fs:
00467C58      64:8920         mov dword ptr fs:,esp
00467C5B      8D55 FC         lea edx,dword ptr ss:
00467C5E <K>8B83 04030000   mov eax,dword ptr ds:             ; *Edit2:TEdit
00467C64 <K>E8 D7B0FCFF   call KGMe.00432D40                         ; ->Controls.TControl.GetText(TControl):TCaption;取注册码长度
00467C69      8D55 E4         lea edx,dword ptr ss:
00467C6C      8B45 FC         mov eax,dword ptr ss:
00467C6F <K>E8 6CB3F9FF   call KGMe.00402FE0                         ; ->System.@ValExt;
00467C74      DD5D F0         fstp qword ptr ss:
00467C77      9B            wait
00467C78      837D E4 00      cmp dword ptr ss:,0                ; 检验是否输入了注册码
00467C7C      0F85 D0000000   jnz KGMe.00467D52
00467C82      8D55 E0         lea edx,dword ptr ss:
00467C85 <K>8B83 00030000   mov eax,dword ptr ds:             ; *Edit1:TEdit
00467C8B <K>E8 B0B0FCFF   call KGMe.00432D40                         ; ->Controls.TControl.GetText(TControl):TCaption;取机器码长度
00467C90      8B45 E0         mov eax,dword ptr ss:
00467C93 <K>E8 F81AFAFF   call KGMe.00409790                         ; ->SysUtils.StrToFloat(AnsiString):Extended;overload;
00467C98      83C4 F8         add esp,-8
00467C9B      DD1C24          fstp qword ptr ss:
00467C9E      9B            wait
00467C9F      E8 D0FCFFFF   call KGMe.00467974                         ; 这个CALL跟进
00467974      55            push ebp
00467975      8BEC            mov ebp,esp
00467977      83C4 DC         add esp,-24
0046797A      33C0            xor eax,eax
0046797C      8945 EC         mov dword ptr ss:,eax
0046797F      8945 E8         mov dword ptr ss:,eax
00467982      8945 DC         mov dword ptr ss:,eax
00467985      33C0            xor eax,eax
00467987      55            push ebp
00467988      68 2E7A4600   push KGMe.00467A2E
0046798D      64:FF30         push dword ptr fs:
00467990      64:8920         mov dword ptr fs:,esp
00467993      DD45 08         fld qword ptr ss:
00467996      D825 407A4600   fsub dword ptr ds:               ; 机器码减去9527,记为M1
0046799C      DD5D 08         fstp qword ptr ss:
0046799F      9B            wait
004679A0      DD45 08         fld qword ptr ss:
004679A3      D835 447A4600   fdiv dword ptr ds:               ; M1再除以139,记为M2
004679A9      DD5D F0         fstp qword ptr ss:
004679AC      9B            wait
004679AD      8D45 E8         lea eax,dword ptr ss:
004679B0      50            push eax
004679B1      0FB705 20BC4600 movzx eax,word ptr ds:
004679B8      8945 E0         mov dword ptr ss:,eax
004679BB      C645 E4 00      mov byte ptr ss:,0
004679BF      8D55 E0         lea edx,dword ptr ss:
004679C2      33C9            xor ecx,ecx
004679C4      A1 08BC4600   mov eax,dword ptr ds:
004679C9      E8 2E16FAFF   call KGMe.00408FFC
004679CE      FF75 E8         push dword ptr ss:
004679D1      FF35 04BC4600   push dword ptr ds:
004679D7      DD05 FCBB4600   fld qword ptr ds:
004679DD      83C4 F4         add esp,-0C
004679E0      DB3C24          fstp tbyte ptr ss:
004679E3      9B            wait
004679E4      8D45 DC         lea eax,dword ptr ss:
004679E7      E8 441DFAFF   call KGMe.00409730
004679EC      FF75 DC         push dword ptr ss:
004679EF      8D45 EC         lea eax,dword ptr ss:
004679F2      BA 03000000   mov edx,3
004679F7      E8 A4CCF9FF   call KGMe.004046A0                         ; 获取昨天的系统日期
004679FC      8B45 EC         mov eax,dword ptr ss:
004679FF      E8 8C1DFAFF   call KGMe.00409790
00467A04      DC45 F0         fadd qword ptr ss:               ; 昨天的系统日期同M2相加,记为M3
00467A07      DD5D F8         fstp qword ptr ss:
00467A0A      9B            wait
00467A0B      33C0            xor eax,eax
00467A0D      5A            pop edx
00467A0E      59            pop ecx
00467A0F      59            pop ecx
00467A10      64:8910         mov dword ptr fs:,edx
00467A13      68 357A4600   push KGMe.00467A35
00467A18      8D45 DC         lea eax,dword ptr ss:
00467A1B      E8 00C9F9FF   call KGMe.00404320
00467A20      8D45 E8         lea eax,dword ptr ss:
00467A23      BA 02000000   mov edx,2
00467A28      E8 17C9F9FF   call KGMe.00404344
00467A2D      C3            retn
00467CA4      DD5D E8         fstp qword ptr ss:
00467CA7      9B            wait
00467CA8      8D45 D8         lea eax,dword ptr ss:
00467CAB      50            push eax
00467CAC      0FB705 20BC4600 movzx eax,word ptr ds:
00467CB3      8945 D0         mov dword ptr ss:,eax
00467CB6      C645 D4 00      mov byte ptr ss:,0
00467CBA      8D55 D0         lea edx,dword ptr ss:
00467CBD      33C9            xor ecx,ecx
00467CBF      A1 08BC4600   mov eax,dword ptr ds:
00467CC4      E8 3313FAFF   call KGMe.00408FFC                         ; 获取当前的系统日期
00467CC9      FF75 D8         push dword ptr ss:
00467CCC      FF35 04BC4600   push dword ptr ds:
00467CD2      8D45 CC         lea eax,dword ptr ss:
00467CD5      50            push eax
00467CD6      0FB705 26BC4600 movzx eax,word ptr ds:
00467CDD      8945 D0         mov dword ptr ss:,eax
00467CE0      C645 D4 00      mov byte ptr ss:,0
00467CE4      8D55 D0         lea edx,dword ptr ss:
00467CE7      33C9            xor ecx,ecx
00467CE9      A1 08BC4600   mov eax,dword ptr ds:
00467CEE      E8 0913FAFF   call KGMe.00408FFC
00467CF3      FF75 CC         push dword ptr ss:
00467CF6      8D45 DC         lea eax,dword ptr ss:
00467CF9      BA 03000000   mov edx,3
00467CFE <K>E8 9DC9F9FF   call KGMe.004046A0                         ; ->System.@LStrCatN;
00467D03      8B45 DC         mov eax,dword ptr ss:
00467D06 <K>E8 851AFAFF   call KGMe.00409790                         ; ->SysUtils.StrToFloat(AnsiString):Extended;overload;转换为浮点数
00467D0B      DC6D F0         fsubr qword ptr ss:                ; 注册码减去当前的系统日期,记为M4
00467D0E      DB7D C0         fstp tbyte ptr ss:
00467D11      9B            wait
00467D12      DD45 E8         fld qword ptr ss:
00467D15 <K>E8 92AFF9FF   call KGMe.00402CAC                         ; ->System.@TRUNC;
00467D1A      8945 D0         mov dword ptr ss:,eax
00467D1D      8955 D4         mov dword ptr ss:,edx
00467D20      DF6D D0         fild qword ptr ss:
00467D23      DB6D C0         fld tbyte ptr ss:
00467D26      DED9            fcompp                                     ; M3和M4比较,两者要相等
00467D28      DFE0            fstsw ax
00467D2A      9E            sahf
00467D2B      74 0E         je short KGMe.00467D3B
至此我们已经分析出了这个crackme的算法,我们来总结一下如何得出注册码,首先机器码减去9527,然后除以139,同昨天的系统日期相加,最后还要加上今天的系统日期,这个
就是最终的注册码了。不过到现在我们还有一点不清楚,就是这个crackme的机器码是如何得来的呢?我们在它的FORMCREATE事件这里设置断点来看一下。从DEDE的分析可知,断点
应该下在467DA0。断下以后我们F8单步走,走到467E90这里的CALL,我们F7跟进去看一下。
00468094      53            push ebx
00468095      81C4 F4FDFFFF   add esp,-20C
0046809B      8BD8            mov ebx,eax
0046809D      68 00010000   push 100
004680A2      8D8424 10010000 lea eax,dword ptr ss:
004680A9      50            push eax
004680AA      8D4424 10       lea eax,dword ptr ss:
004680AE      50            push eax
004680AF      8D4424 10       lea eax,dword ptr ss:
004680B3      50            push eax
004680B4      8D4424 10       lea eax,dword ptr ss:
004680B8      50            push eax
004680B9      68 00010000   push 100
004680BE      8D4424 24       lea eax,dword ptr ss:
004680C2      50            push eax
004680C3      A1 1CBC4600   mov eax,dword ptr ds:
004680C8      50            push eax
004680C9      E8 06E4F9FF   call <jmp.&kernel32.GetVolumeInformationA>
此时堆栈的内容是这样的:
0012FB94   00972700      |RootPathName = "c:\"
0012FB98   0012FBC0      |VolumeNameBuffer = 0012FBC0
0012FB9C   00000100      |MaxVolumeNameSize = 100 (256.)
0012FBA0   0012FBB4      |pVolumeSerialNumber = 0012FBB4
0012FBA4   0012FBB8      |pMaxFilenameLength = 0012FBB8
0012FBA8   0012FBBC      |pFileSystemFlags = 0012FBBC
0012FBAC   0012FCC0      |pFileSystemNameBuffer = 0012FCC0
0012FBB0   00000100      \pFileSystemNameSize = 00000100

这里我们可以看到crackme调用了GetVolumeInoformation这个API函数,返回了c盘的卷序列号,这个序列号转为十进制就是机器码了。我们可以在cmd中切换到c盘,然后输入label
命令就可以看到了。分析到这里,我想这个crackme的算法流程我们已经搞清楚了,最后我用python写了一个注册机(第一次用python写东西,写的不好,希望大侠们见谅),源代
码如下:
# -*- coding: cp936 -*-
import time
import os
import win32api
d=win32api.GetVolumeInformation('C:')
machinecode=d
print ("您的机器码为:%d" % machinecode)
a=time.localtime()
if a<10:
    b=int(str(a)+ str(a).zfill(2) + str(a))
else:
    b=int(str(a) + str(a) + str(a))

regcode=(((machinecode-9527) / 139) + (b-1)) + b
print ("您的注册码是:%d" % regcode)
os.system("pause")

lgjxj 发表于 2009-5-2 17:56:48

哦,原来 python 和 C/C++ 很像(别笑,我真的不懂)

MOV 发表于 2009-5-3 00:29:30

见到了顶你一个
学习

HDd1145 发表于 2009-5-3 06:47:57

老海 发表于 2009-5-3 11:00:07

写得不错,支持一下。
页: [1]
查看完整版本: 救市KGme算法分析