找回密码
 注册
搜索
热搜: 回贴

Happytown的第35个crackme分析 注册机 ,CrackMe,happytown,加密算法

2010-1-22 18:38| 发布者: admin| 查看: 92| 评论: 0|原作者: 九天玄女


Happytown的第35个crackme分析 注册机 ,CrackMe,happytown,加密算法
2008年06月22日 星期日 下午 11:51
【文章标题】: 【原创】Happytown的第35个crackme分析 注册机

【文章作者】: ylp1332

【作者邮箱】: ylp1332@yahoo.com.cn

【作者主页】: n/a

【作者QQ号】: n/a

【软件名称】: CrackMe_0035.exe

【软件大小】: 220k

【下载地址】: 自己搜索下载

【加壳方式】: none

【保护方式】: md5,大数运算

【编写语言】: visual c 6

【使用工具】: peid,ida,ollydbg,vc6

【操作平台】: win32

【软件介绍】: 非商业软件

【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

--------------------------------------------------------------------------------

【详细过程】



『分析过程』

1、首先用PEiD 0.94检查,用visual c 6编译,没有加壳。



2、用PEiD的插件Krypto ANAlyzer检查,发现有MD5算法和大数运算。



3、用IDA载入,进行初步的静态分析。



分析结论:

使用了Miracl大数运算库;

使用了标准的MD5算法;

使用Windows API GetDlgItemTextA从控件中取得用户名、组织和注册码,

用户名和组织名至少要2个字符长,注册码必须都是16进制字符,且不能为空。

验证过程的反汇编代码如下:



.text:00401110

.text:00401110 ; =============== S U B R O U T I N E =======================================

.text:00401110

.text:00401110

.text:00401110 ; int __cdecl OnCheck(HWND hDlg)

.text:00401110 OnCheck proc near ; CODE XREF: DialogFunc 55 p

.text:00401110

.text:00401110 var_2C4 = dword ptr -2C4h

.text:00401110 md5_str_out = dword ptr -2C0h

.text:00401110 var_2BB = dword ptr -2BBh

.text:00401110 var_2B7 = dword ptr -2B7h

.text:00401110 var_2B3 = word ptr -2B3h

.text:00401110 var_2B1 = byte ptr -2B1h

.text:00401110 md5_ctx = dword ptr -2B0h

.text:00401110 Serial = dword ptr -258h

.text:00401110 UserName = byte ptr -190h

.text:00401110 Group = byte ptr -0C8h

.text:00401110 hDlg = dword ptr 4

.text:00401110

.text:00401110 sub esp, 2C4h

.text:00401116 push ebx

.text:00401117 push esi

.text:00401118 push edi

.text:00401119 mov ecx, 49

.text:0040111E xor eax, eax

.text:00401120 lea edi, [esp 141h]

.text:00401127 mov [esp 2D0h UserName], 0

.text:0040112F mov [esp 2D0h Group], 0

.text:00401137 rep stosd

.text:00401139 stosw

.text:0040113B stosb

.text:0040113C mov ecx, 49

.text:00401141 xor eax, eax

.text:00401143 lea edi, [esp 209h]

.text:0040114A mov byte ptr [esp 2D0h Serial], 0

.text:0040114F rep stosd

.text:00401151 stosw

.text:00401153 stosb

.text:00401154 mov ecx, 49

.text:00401159 xor eax, eax

.text:0040115B lea edi, [esp 2D0h Serial 1]

.text:0040115F mov byte ptr [esp 2D0h md5_str_out], 0

.text:00401164 rep stosd

.text:00401166 stosw

.text:00401168 stosb

.text:00401169 xor eax, eax ; 使 eax = 0

.text:0040116B mov [esp 2D0h md5_str_out 1], eax

.text:0040116F mov [esp 2D0h var_2BB], eax

.text:00401173 mov [esp 2D0h var_2B7], eax

.text:00401177 mov [esp 2D0h var_2B3], ax

.text:0040117C push eax

.text:0040117D push 300h

.text:00401182 mov [esp 2D8h var_2B1], al

.text:00401186 call _mirsys ; mirsys(300h,0h)

.text:0040118B mov esi, [esp 2D8h hDlg]

.text:00401192 mov edi, ds:GetDlgItemTextA

.text:00401198 add esp, 8

.text:0040119B lea ecx, [esp 2D0h UserName]

.text:004011A2 mov ebx, eax

.text:004011A4 push 0C9h ; nMaxCount

.text:004011A9 push ecx ; lpString

.text:004011AA push 3EDh ; nIDDlgItem

.text:004011AF push esi ; hDlg

.text:004011B0 call edi ; GetDlgItemTextA

.text:004011B2 cmp eax, 2 ; 用户名不少于2个字符

.text:004011B5 jnb short loc_4011C3

.text:004011B7

.text:004011B7 loc_4011B7: ; CODE XREF: OnCheck 135 j

.text:004011B7 pop edi

.text:004011B8 pop esi

.text:004011B9 xor eax, eax

.text:004011BB pop ebx

.text:004011BC add esp, 2C4h

.text:004011C2 retn

.text:004011C3 ; ---------------------------------------------------------------------------

.text:004011C3

.text:004011C3 loc_4011C3: ; CODE XREF: OnCheck A5 j

.text:004011C3 lea edx, [esp 2D0h Group]

.text:004011CA push 0C9h ; nMaxCount

.text:004011CF push edx ; lpString

.text:004011D0 push 3EEh ; nIDDlgItem

.text:004011D5 push esi ; hDlg

.text:004011D6 call edi ; GetDlgItemTextA

.text:004011D8 cmp eax, 2 ; 组织名不少于2个字符

.text:004011DB jnb short loc_4011E9

.text:004011DD pop edi

.text:004011DE pop esi

.text:004011DF xor eax, eax

.text:004011E1 pop ebx

.text:004011E2 add esp, 2C4h

.text:004011E8 retn

.text:004011E9 ; ---------------------------------------------------------------------------

.text:004011E9

.text:004011E9 loc_4011E9: ; CODE XREF: OnCheck CB j

.text:004011E9 lea eax, [esp 2D0h Serial]

.text:004011ED push 0C9h ; nMaxCount

.text:004011F2 push eax ; lpString

.text:004011F3 push 3EFh ; nIDDlgItem

.text:004011F8 push esi ; hDlg

.text:004011F9 call edi ; GetDlgItemTextA

.text:004011FB test eax, eax ; 注册码不能为空

.text:004011FD jnz short loc_401209

.text:004011FF pop edi

.text:00401200 pop esi

.text:00401201 pop ebx

.text:00401202 add esp, 2C4h

.text:00401208 retn

.text:00401209 ; ---------------------------------------------------------------------------

.text:00401209

.text:00401209 loc_401209: ; CODE XREF: OnCheck ED j

.text:00401209 mov al, byte ptr [esp 2D0h Serial] ; 取注册码的第一个字符

.text:0040120D test al, al

.text:0040120F jz short loc_401253

.text:00401211 lea esi, [esp 2D0h Serial] ; 取注册码

.text:00401215

.text:00401215 loc_401215: ; CODE XREF: OnCheck 141 j

.text:00401215 cmp dword_414FDC, 1 ; 循环检查注册码的每一个字符看是否是16进制字符,否则退出

.text:0040121C jle short loc_401232

.text:0040121E xor ecx, ecx

.text:00401220 push 80h ; int

.text:00401225 mov cl, [esi]

.text:00401227 push ecx ; int

.text:00401228 call __isctype

.text:0040122D add esp, 8

.text:00401230 jmp short loc_401243

.text:00401232 ; ---------------------------------------------------------------------------

.text:00401232

.text:00401232 loc_401232: ; CODE XREF: OnCheck 10C j

.text:00401232 mov eax, off_414DD0

.text:00401237 xor edx, edx

.text:00401239 mov dl, [esi]

.text:0040123B mov al, [eax edx*2]

.text:0040123E and eax, 80h

.text:00401243

.text:00401243 loc_401243: ; CODE XREF: OnCheck 120 j

.text:00401243 test eax, eax

.text:00401245 jz loc_4011B7

.text:0040124B mov al, [esi 1]

.text:0040124E inc esi

.text:0040124F test al, al

.text:00401251 jnz short loc_401215

.text:00401253

.text:00401253 loc_401253: ; CODE XREF: OnCheck FF j

.text:00401253 lea ecx, [esp 2D0h Group] ; 取组织名

.text:0040125A push ebp

.text:0040125B push ecx ; char *

.text:0040125C call __strrev ; 将组织名字符串逆转

.text:00401261 mov edi, eax

.text:00401263 or ecx, 0FFFFFFFFh

.text:00401266 xor eax, eax

.text:00401268 lea edx, [esp 2D8h UserName] ; 取用户名

.text:0040126F repne scasb

.text:00401271 not ecx

.text:00401273 sub edi, ecx

.text:00401275 mov esi, edi

.text:00401277 mov ebp, ecx

.text:00401279 mov edi, edx

.text:0040127B or ecx, 0FFFFFFFFh

.text:0040127E repne scasb

.text:00401280 mov ecx, ebp

.text:00401282 dec edi

.text:00401283 shr ecx, 2

.text:00401286 rep movsd

.text:00401288 mov ecx, ebp

.text:0040128A lea eax, [esp 2D8h md5_ctx]

.text:0040128E and ecx, 3

.text:00401291 push eax

.text:00401292 rep movsb ; 用户名和组织名的逆连接起来

.text:00401294 call _MD5_Init

.text:00401299 lea edi, [esp 2DCh UserName]

.text:004012A0 or ecx, 0FFFFFFFFh

.text:004012A3 xor eax, eax

.text:004012A5 lea edx, [esp 2DCh md5_ctx]

.text:004012A9 repne scasb

.text:004012AB not ecx

.text:004012AD dec ecx

.text:004012AE push ecx

.text:004012AF lea ecx, [esp 2E0h UserName]

.text:004012B6 push ecx

.text:004012B7 push edx

.text:004012B8 call _MD5_Update

.text:004012BD lea eax, [esp 2E8h md5_ctx]

.text:004012C1 lea ecx, [esp 2E8h md5_str_out]

.text:004012C5 push eax

.text:004012C6 push ecx

.text:004012C7 call _MD5_Final

.text:004012CC push 0

.text:004012CE mov dword ptr [ebx 234h], 10h ; mip->IOBASE = 16;

.text:004012D8 call _mirvar

.text:004012DD push 0

.text:004012DF mov esi, eax

.text:004012E1 call _mirvar

.text:004012E6 push 0

.text:004012E8 mov edi, eax

.text:004012EA call _mirvar

.text:004012EF push 0

.text:004012F1 mov ebp, eax

.text:004012F3 call _mirvar

.text:004012F8 push offset a97944b587e4991 ; "97944B587E49910C2DFDD84BA062BC8917B3085"...

.text:004012FD push ebp

.text:004012FE mov ebx, eax

.text:00401300 call _cinstr

.text:00401305 push offset a10001 ; "10001"

.text:0040130A push edi

.text:0040130B call _cinstr

.text:00401310 lea edx, [esp 310h md5_str_out]

.text:00401314 push ebx

.text:00401315 push edx

.text:00401316 push 16

.text:00401318 call _bytes_to_big

.text:0040131D add esp, 48h

.text:00401320 lea eax, [esp 2D4h Serial] ; 取用户输入的注册码,然后转化为大数,与计算出来的注册码比较

.text:00401324 push eax

.text:00401325 push esi

.text:00401326 call _cinstr

.text:0040132B push esi

.text:0040132C push ebp

.text:0040132D push edi

.text:0040132E push esi

.text:0040132F call _powmod

.text:00401334 push ebx

.text:00401335 push esi

.text:00401336 call _compare ; 大数比较。相等则注册成功,否则失败

.text:0040133B mov [esp 2F4h var_2C4], eax

.text:0040133F push esi

.text:00401340 call _mirkill

.text:00401345 push edi

.text:00401346 call _mirkill

.text:0040134B push ebp

.text:0040134C call _mirkill

.text:00401351 push ebx

.text:00401352 call _mirkill

.text:00401357 add esp, 30h

.text:0040135A call _mirexit

.text:0040135F mov ecx, [esp 2D4h var_2C4]

.text:00401363 xor eax, eax

.text:00401365 pop ebp

.text:00401366 pop edi

.text:00401367 test ecx, ecx

.text:00401369 pop esi

.text:0040136A pop ebx

.text:0040136B setz al

.text:0040136E add esp, 2C4h

.text:00401374 retn

.text:00401374 OnCheck endp

.text:00401374





注册码验证过程:

1、将用户名字符串和组织名字符串的逆串连接起来,用标准MD5算法计算该字符串hash值,将该hash串转化为大数H。

2、将注册码转化为大数S,进行模幂运算S^e mod p = C

3、如果H = C,则注册成功。

其中 e=10001h,p=97944B587E49910C2DFDD84BA062BC8917B3085FFAB61ABF930A8396CDE8B9E3h



可以看出整个验证过程很简单。

生成注册码的过程:

1、将用户名字符串和组织名字符串的逆串连接起来,用标准MD5算法计算该字符串hash值,将该hash串转化为大数H。

2、令 e*d mod p-1 = 1,则 d = e^-1 mod p-1。用扩展Euclid算法求得e关于模p-1的乘法逆元d,则有

S = C^e mod p = H^e mod p

3、将大数S转化为字符串,即为所求的注册码。





以下是一组正确的注册码:

name: ylp1332

group: hahik

serial: 52575D6C6D8A32B11FF6F8215B93DBC9AE89ACCFFECFCF89B6D442A484F54278





以下是keygen的主要代码,不含md5算法实现。

在visual c 6 with sp6 下编译通过。



#include

#include

#include "miracl.h"

#include "md5.h"



#pragma comment ( lib, "miracl.lib" )



#define MAXLEN 50



int main(int argc, char **argv)

{

char usr_name[ MAXLEN ] = {0};

char grp_name[ MAXLEN ] = {0};

char ser_code[ MAXLEN ] = {0};

char hash_out[ MAXLEN ] = {0};



struct MD5Context md5_ctx;

miracl *mip;

big x,y,z,w;

char buf[ MAXLEN ];



// Your Name here, at least 2 chars !

strcpy( usr_name, "ylp1332" );

// Your Group here, at least 2 chars !

strcpy( grp_name, "hahik" );



printf(" name: %s\n", usr_name );

printf(" group: %s\n", grp_name );



memset( buf, 0, MAXLEN );

strcpy( buf, usr_name );

strcat( buf, _strrev(grp_name) );



MD5Init( &md5_ctx );

MD5Update( &md5_ctx, buf, strlen(buf) );

MD5Final( hash_out, &md5_ctx );



mip = mirsys( 0x300, 0 );

mip->IOBASE = 0x10;



x = mirvar( 0 );

y = mirvar( 0 );

z = mirvar( 0 );

w = mirvar( 0 );



bytes_to_big( 16, hash_out, x );

cinstr( y, "648A7A87920C9DE7244271CB87F0B5F980FCC19B58229E0F602AE3298E1EC5DD" );

cinstr( z, "97944B587E49910C2DFDD84BA062BC8917B3085FFAB61ABF930A8396CDE8B9E3" );

powmod( x, y, z, w );

cotstr( w, ser_code );



printf(" serial: %s\n", ser_code );



mirkill( x );

mirkill( y );

mirkill( z );

mirkill( w );



mirexit();

return 0;

}





--------------------------------------------------------------------------------

【经验总结】

静态分析和动态调试相结合。

大数运算要熟悉正逆向推导过程。




最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-30 03:23 , Processed in 0.285120 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部