首页
社区
课程
招聘
[原创]HappyTown的第27个CrackMe分析
发表于: 2006-10-26 11:39 9441

[原创]HappyTown的第27个CrackMe分析

2006-10-26 11:39
9441

【文章标题】: HappyTown的第27个CrackMe分析
【文章作者】: HorstStein
【作者邮箱】: [email]horststein@hotmail.com[/email]
【软件名称】: HappyTown's CrackMe_0027
【下载地址】: http://bbs.pediy.com/showthread.php?s=&threadid=33850
【加壳方式】: 没有
【保护方式】: 序列号
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  RSA签名算法的描述在文章的下面,你可以先浏览一下,然后再来理解程序对签名的验证过程可能会更好。
  
  00401154  |>push    10                                ;  0x10
  00401156  |>push    320                               ;  0x320
  0040115B  |>stos    byte ptr es:[edi]
  0040115C  |>call    00401AC0                          ;  mirsys
  00401161  |>mov     ebp, eax
  00401163  |>mov     ecx, 18
  00401168  |>xor     eax, eax
  0040116A  |>lea     edi, [esp+2D]
  0040116E  |>mov     byte ptr [esp+2C], 0
  00401173  |>mov     byte ptr [esp+90], 0
  0040117B  |>rep     stos dword ptr es:[edi]
  0040117D  |>stos    word ptr es:[edi]
  0040117F  |>stos    byte ptr es:[edi]
  00401180  |>mov     ecx, 18
  00401185  |>xor     eax, eax
  00401187  |>lea     edi, [esp+91]
  0040118E  |>mov     esi, [esp+2C4]
  00401195  |>rep     stos dword ptr es:[edi]
  00401197  |>stos    word ptr es:[edi]
  00401199  |>mov     ebx, [<&USER32.GetDlgItemTextA>]  ;  USER32.GetDlgItemTextA
  0040119F  |>add     esp, 8
  004011A2  |>stos    byte ptr es:[edi]
  004011A3  |>lea     eax, [esp+24]
  004011A7  |>push    65                                ; /Count = 65 (101.)
  004011A9  |>push    eax                               ; |Buffer
  004011AA  |>push    3E8                               ; |ControlID = 3E8 (1000.)
  004011AF  |>push    esi                               ; |hWnd
  004011B0  |>call    ebx                               ; \GetDlgItemTextA
  004011B2  |>lea     edi, [esp+24]                     ;  name
  004011B6  |>or      ecx, FFFFFFFF
  004011B9  |>xor     eax, eax
  004011BB  |>repne   scas byte ptr es:[edi]
  004011BD  |>not     ecx
  004011BF  |>dec     ecx
  004011C0  |>cmp     ecx, 3                            ;  name长度不能小于3
  004011C3  |>jb      004013F5
  004011C9  |>lea     edi, [esp+24]
  004011CD  |>or      ecx, FFFFFFFF
  004011D0  |>repne   scas byte ptr es:[edi]
  004011D2  |>not     ecx
  004011D4  |>dec     ecx
  004011D5  |>cmp     ecx, 23                           ;  name长度不能大于35
  004011D8  |>ja      004013F5
  004011DE  |>lea     ecx, [esp+88]
  004011E5  |>push    65                                ; /Count = 65 (101.)
  004011E7  |>push    ecx                               ; |Buffer
  004011E8  |>push    3E9                               ; |ControlID = 3E9 (1001.)
  004011ED  |>push    esi                               ; |hWnd
  004011EE  |>call    ebx                               ; \GetDlgItemTextA
  004011F0  |>test    eax, eax                          ;  sn长度不能为0
  004011F2  |>je      004013F5
  004011F8  |>mov     al, [esp+88]
  004011FF  |>test    al, al
  00401201  |>je      short 00401249
  00401203  |>lea     esi, [esp+88]
  0040120A  |>/cmp     dword ptr [40DFEC], 1            ;  /sn是否为16进制数
  00401211  |>|jle     short 00401227
  00401213  |>|xor     edx, edx
  00401215  |>|push    80
  0040121A  |>|mov     dl, [esi]
  0040121C  |>|push    edx
  0040121D  |>|call    00407050
  00401222  |>|add     esp, 8
  00401225  |>|jmp     short 00401239
  00401227  |>|mov     ecx, [40DDE0]                    ;  CrackMe_.0040DDEA
  0040122D  |>|xor     eax, eax
  0040122F  |>|mov     al, [esi]
  00401231  |>|mov     al, [ecx+eax*2]
  00401234  |>|and     eax, 80
  00401239  |>|test    eax, eax
  0040123B  |>|je      004013F5
  00401241  |>|mov     al, [esi+1]
  00401244  |>|inc     esi
  00401245  |>|test    al, al
  00401247  |>\jnz     short 0040120A                   ;  \
  00401249  |>push    0
  0040124B  |>mov     dword ptr [ebp+234], 10           ;  mip->IOBASE=16
  00401255  |>call    004018A0                          ;  mirvar
  0040125A  |>push    0
  0040125C  |>mov     esi, eax
  0040125E  |>call    004018A0
  00401263  |>push    0
  00401265  |>mov     ebp, eax
  00401267  |>call    004018A0
  0040126C  |>push    0
  0040126E  |>mov     edi, eax
  00401270  |>call    004018A0
  00401275  |>push    0
  00401277  |>mov     [esp+2C], eax
  0040127B  |>call    004018A0
  00401280  |>push    0
  00401282  |>mov     ebx, eax
  00401284  |>call    004018A0
  00401289  |>push    0
  0040128B  |>mov     [esp+2C], eax
  0040128F  |>call    004018A0
  00401294  |>push    0
  00401296  |>mov     [esp+34], eax
  0040129A  |>call    004018A0
  0040129F  |>mov     edx, [esp+30]
  004012A3  |>push    0040D14C                          ;  ASCII "6012CF41CA8C4406C94D3C1E9CC3A8A7372B29383B5F5761"
  004012A8  |>push    edx                               ;  nA
  004012A9  |>mov     [esp+44], eax
  004012AD  |>call    00403E20
  004012B2  |>push    0040D13C                          ;  ASCII "331F925C548E7"
  004012B7  |>push    ebx                               ;  eA
  004012B8  |>call    00403E20
  004012BD  |>push    0040D108                          ;  ASCII "A41D2F44D7121ADBA723D82F5274B4932103CF7F7B4BCEF1"
  004012C2  |>push    edi                               ;  nB
  004012C3  |>call    00403E20
  004012C8  |>push    0040D0D4                          ;  ASCII "855DD8EBF213704056CC1C0A8BF50154CABC04E00F8ED603"
  004012CD  |>push    ebp                               ;  dB
  004012CE  |>call    00403E20
  004012D3  |>add     esp, 40
  004012D6  |>lea     eax, [esp+88]
  004012DD  |>push    eax                               ;  sn
  004012DE  |>push    esi                               ;  C
  004012DF  |>call    00403E20                          ;  cinstr(C, sn):C=sn
  004012E4  |>push    edi                               ;  nB
  004012E5  |>push    esi                               ;  C
  004012E6  |>call    004027A0                          ;  compare(C, nB):C是否小于nB
  004012EB  |>add     esp, 10
  004012EE  |>cmp     eax, -1
  004012F1  |>jnz     004013F5
  004012F7  |>lea     ecx, [esp+150]
  004012FE  |>push    ecx                               ;  下面是SHA1(name)
  004012FF  |>call    00403AF0                          ;  SHA1_Init,跟进去就可以看见那几个常数
  00401304  |>mov     al, [esp+28]
  00401308  |>add     esp, 4
  0040130B  |>test    al, al
  0040130D  |>je      short 0040133C
  0040130F  |>lea     edx, [esp+24]
  00401313  |>mov     [esp+20], edx
  00401317  |>/and     eax, 0FF
  0040131C  |>|push    eax
  0040131D  |>|lea     eax, [esp+154]
  00401324  |>|push    eax
  00401325  |>|call    00403B30                         ;  SHA1_Update
  0040132A  |>|mov     eax, [esp+28]
  0040132E  |>|add     esp, 8
  00401331  |>|inc     eax
  00401332  |>|mov     [esp+20], eax
  00401336  |>|mov     al, [eax]
  00401338  |>|test    al, al
  0040133A  |>\jnz     short 00401317
  0040133C  |>lea     ecx, [esp+EC]
  00401343  |>lea     edx, [esp+150]
  0040134A  |>push    ecx                               ;  这里保留了最后的hash值
  0040134B  |>push    edx
  0040134C  |>call    00403D80                          ;  SHA1_Final
  00401351  |>mov     eax, [esp+1C]
  00401355  |>lea     ecx, [esp+F4]
  0040135C  |>push    eax                               ;  h
  0040135D  |>push    ecx                               ;  SHA1(name)
  0040135E  |>push    14                                ;  20:SHA1(name)的字节长度
  00401360  |>call    00403970                          ;  bytes_to_big(20, SHA1(name), h)
  00401365  |>mov     edx, [esp+2C]
  00401369  |>push    edx                               ;  S
  0040136A  |>push    edi                               ;  nB
  0040136B  |>push    ebp                               ;  dB
  0040136C  |>push    esi                               ;  C
  0040136D  |>call    00402CE0                          ;  powmod:S=C^dB (mod nB)
  00401372  |>mov     eax, [esp+40]
  00401376  |>mov     ecx, [esp+34]
  0040137A  |>mov     edx, [esp+3C]
  0040137E  |>push    eax                               ;  m
  0040137F  |>push    ecx                               ;  nA
  00401380  |>push    ebx                               ;  eA
  00401381  |>push    edx                               ;  S
  00401382  |>call    00402CE0                          ;  powmod:m=S^eA (mod nA)
  00401387  |>mov     eax, [esp+48]
  0040138B  |>mov     ecx, [esp+50]
  0040138F  |>push    eax                               ;  h
  00401390  |>push    ecx                               ;  m
  00401391  |>call    004027A0                          ;  compare(m,h)是否相等,相等则注册成功
  00401396  |>add     esp, 3C
  00401399  |>test    eax, eax
  0040139B  |>jnz     short 004013F5
  
  我们先来看一下RSA签名算法的过程,然后即可轻松理解上面的验证过程:
  /* A签名的过程(请参考《计算机密码学 第三版》,卢开澄(我的老师:D),清华大学出版社,P162):nA < nB
   * S1. A计算   
   *           S≡h^dA (mod nA)
   * S2. A将S用B的公钥加密得密文
   *           C≡S^eB (mod nB)
   * B收到C后解密如下:
   * S1. 对C用B的密钥dB解密得
   *           C^dB (mod nB)≡S^(eB * dB) (mod nB) ≡S
   * S2. 对S用A的公钥再解密
   *           S^eA (mod nA)≡h^(dA * eA) (mod nA) ≡h
   */
  
  /* 在这个CrackMe中的各个参数(用RSATool可求得):
   * A:
   *  pA = 84E8B65E382CBC80494D438B;
   *  qA = B90CC96501089AF27EC13E43;
   *  nA = 6012CF41CA8C4406C94D3C1E9CC3A8A7372B29383B5F5761;        //在原程序中有
   *  dA = 59445332D2C4A00497EFCC34D2C34C1EB72B572566EFE263;
   *  eA = 331F925C548E7;                                                //在原程序中有
   *
   * B:
   *  pB = DA974C254AB581D22550A323;
   *  qB = C0333135920DF051F992C0DB;
   *  nB = A41D2F44D7121ADBA723D82F5274B4932103CF7F7B4BCEF1;        //在原程序中有
   *  dB = 855DD8EBF213704056CC1C0A8BF50154CABC04E00F8ED603;        //在原程序中有
   *  eB = 23B9294352183;
   * 192 bit
   */
  
  好了,我们来写这个CrackMe的注册机,这里是关键代码:
  #include <miracl.h>
  void GenSn(unsigned char *name, unsigned char *sn)
  {
          int i;
          sha sh;
          char szSHAHash[20]={0};  //存放SHA1(Name)
  
          big dA,nA,eB,nB,S,C,h;
          miracl *mip=mirsys(0x320,0x10);
  
  
  
          //initialization
          mip->IOBASE = 16;        // 设定16进制模式
          dA = mirvar(0);
          nA = mirvar(0);               
          eB = mirvar(0);
          nB = mirvar(0);
          S = mirvar(0);
          C = mirvar(0);
          h = mirvar(0);
         
          cinstr(nA, "6012CF41CA8C4406C94D3C1E9CC3A8A7372B29383B5F5761");
          cinstr(dA, "59445332D2C4A00497EFCC34D2C34C1EB72B572566EFE263");
          cinstr(nB, "A41D2F44D7121ADBA723D82F5274B4932103CF7F7B4BCEF1");
          cinstr(eB, "23B9294352183");
  
          //计算h = SHA1(name)
          shs_init(&sh);
          for (i=0; name[i]!=0; i++)
          {
                  shs_process(&sh,name[i]);
          }
          shs_hash(&sh, szSHAHash);       
          bytes_to_big(20, szSHAHash, h);
  
          //
          powmod(h,dA,nA,S);        //S≡h^dA (mod nA)
          powmod(S,eB,nB,C);        //C≡S^eB (mod nB)
  
          //输出
          cotstr(C,sn);
  
          mirkill(dA);
          mirkill(nA);
          mirkill(eB);
          mirkill(nB);
          mirkill(S);
          mirkill(C);
          mirkill(h);
          mirexit();
  }
  
  给出两组可用的注册码:
  name:HorstStein
  sn:93B1735114E67B2492DA403EC8F18DFADCA356A482A6B794

  name:pediy
  sn:5A79793A010344A53ADBD73933B1E2A1255D105020DAE6A2

  附件中有我写的注册机。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年10月26日 11:01:26


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (11)
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
2
兄弟,你出手太快了,论坛还有那么多XDJM还没看到这个CrackMe呢。
2006-10-26 11:51
0
雪    币: 35
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
3
我一看到你的CrackMe手就发痒。哈哈
2006-10-26 11:52
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习..HOHO
2006-10-26 12:18
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
5
慢慢学习中~~~~~~

HappyTown找到克星了,嘻嘻.。

看来要换新花样了
2006-10-26 12:37
0
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
6
最初由 binbinbin 发布
...

HappyTown找到克星了,嘻嘻.。

看来要换新花样了


是啊!
HorstStein,算你厉害。
2006-10-26 12:41
0
雪    币: 313
活跃值: (250)
能力值: ( LV9,RANK:650 )
在线值:
发帖
回帖
粉丝
7
《计算机密码学 第三版》,卢开澄这本书找了N久也没有找到此书的电子版。谁有请提供一个。
2006-10-26 15:33
0
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
8
请参考《计算机密码学 第三版》,卢开澄(我的老师:D),清华大学出版社,P162

太牛了!!
2006-10-26 21:31
0
雪    币: 441
活跃值: (149)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
9
看上面算法分析        happytown的几个crackme关于RSA和ECC用的都是MIRACL库,

转帖一下MIRACL库函数的识别方法(首先载入程序,查找串MIRACL,如果找到基本用下面分析函数),我保存到本地了,原链接没找到:

=============================================================

快速地识别MIRACL库函数

MIARCL是当前使用比较广泛的基于公钥加密算法保护实现的大数库之一,特别在各种算法Crackme中。
目前为止还没有发现使用该库的商业软件,因为MIRACL用于商业目的的话需要交纳一笔昂贵的授权费――1000$。
所以这里介绍的这个技巧只能对你破解各种算法Crackme起到一点帮助。

这个技巧是怎么来的呢?

我们知道,MIRACL有一个十分有用的特性:它可以让你十分方便的定位程序运行过程中出错的函数,MIRACL的文档是这样说的:

”初始化函数mirsys运行的同时也会初始化集成在MIRACL库中的错误跟踪系统。这样,
无论何时只要函数调用序列中的任何一个函数发生错误都会被检测到,包括错误本身。一个典型的错误信息如下:

    MIRACL error from routine powltr
    called from isprime
    called from your program
    Raising integer to a negative power
   
这些错误报告在开发过程中对我们调试有很大的帮助。与之相关的一个常量是TRACER,默认是OFF,
如果将它改为ON,程序运行过程中将会把错误信息打印到电脑屏幕上。”

上面这些信息对我们有什么帮助呢?

MIRACL能确切知道哪个函数出错是因为它对每个函数定义了一个特定的常量作为标识符,
这些信息是从MIRACL源代码里发现的。下面是MrArth3.c里的一段代码:

void power(_MIPD_ big x,long n,big z,big w)
{ /* raise big number to int power  w=x^n *
    * (mod z if z and w distinct)          */
     mr_small norm;
#ifdef MR_OS_THREADS
     miracl *mr_mip=get_mip();
#endif
     copy(x,mr_mip->w5);
     zero(w);
     if(mr_mip->ERNUM || size(mr_mip->w5)==0) return;
     convert(_MIPP_ 1,w);
     if (n==0L) return;

     MR_IN(17)

     if (n<0L)
     {
         mr_berror(_MIPP_ MR_ERR_NEG_POWER);
         MR_OUT
         return;
     }   
     //rest of the code from file
}

注意粗体字显示的那段代码。我们可以看到,这条代码不在任何一个条件编译代码段内,
这就意味着无论你用何种选项编译MIRACL,MR_IN(17)都会在最终生成库文件里面。

将这段代码反汇编的结果是:

mov dword ptr [esi+eax*4+20h], 11h

11h的十进制正是17。

现在你明白如何去识别MIRACL库的函数了吧:调试时跟进有疑问的CALL,搜索下面形式的指令:

mov dword ptr [esi+eax*4+20h], XXh

在你自己的函数特征值表中查找XX,或者直接对照我在后面列出的那个表。

有了这个所有函数特征值对应表后我们就可以十分轻松的识别MIRACL里的所有函数。这个方法的优点就是每个函数对应的特征值一般不会由于库版本的升级而发生变化,因此可以比较放心的使用。缺点呢就是你必须自己动手去一个一个函数地去识别。对于这点一个好的解决办法就是编写一个IDA的脚本,自动搜索那些的指令并根据特征值修改函数名。

附表:

MIRACL MAGIC NUMBERS TABLE:
     by bLaCk-eye
     from an original ideea by bF!^k23

NUMBER OF FUNCTIONS: 08Eh

Innum                          equ 01h

Otnum                         equ 02h

Jack                             equ 03h

normalise                      equ 04h

multiply                        equ 05h

divide                           equ 06h

incr                              equ 07h

decr                             equ 08h

premult                        equ 09h

subdiv                          equ 0Ah

fdsize                           equ 0Bh

egcd                             equ 0Ch

cbase                           equ 0Dh

cinnum                         equ 0Eh

cotnum                        equ 0Fh

nroot                            equ 10h

power                          equ 11h

powmod                       equ 12h

bigdig                           equ 13h

bigrand                         equ 14h

nxprime                        equ 15h

isprime                         equ 16h

mirvar                          equ 17h

mad                             equ 18h  

multi_inverse                equ 19h

putdig                          equ 1Ah

add                              equ 1Bh

subtract                        equ 1Ch

mirsys                          equ 1Dh

xgcd                            equ 1Eh

fpack                           equ 1Fh

dconv                          equ 20h

mr_shift                       equ 21h

mround                        equ 22h

fmul                             equ 23h

fdiv                              equ 24h

fadd                             equ 25h

fsub                             equ 26h

fcomp                          equ 27h

fconv                           equ 28h

frecip                           equ 29h

fpmul                           equ 2Ah

fincr                             equ 2Bh

;null entry

ftrunc                          equ 2Dh

frand                            equ 2Eh

sftbit                            equ 2Fh

build                            equ 30h

logb2                           equ 31h

expint                           equ 32h

fpower                         equ 33h

froot                             equ 34h

fpi                               equ 35h

fexp                             equ 36h

flog                              equ 37h

fpowf                          equ 38h

ftan                              equ 39h

fatan                            equ 3Ah

fsin                              equ 3Bh

fasin                            equ 3Ch

fcos                             equ 3Dh

facos                           equ 3Eh

ftanh                            equ 3Fh

fatanh                          equ 40h

fsinh                            equ 41h

fasinh                           equ 42h

fcosh                           equ 43h

facosh                          equ 44h

flop                              equ 45h

gprime                         equ 46h

powltr                          equ 47h

fft_mult                        equ 48h

crt_init                         equ 49h

crt                               equ 4Ah

otstr                             equ 4Bh

instr                             equ 4Ch

cotstr                           equ 4Dh

cinstr                           equ 4Eh

powmod2                     equ 4Fh

prepare_monty              equ 50h

nres                             equ 51h

redc                             equ 52h

nres_modmult               equ 53h

nres_powmod               equ 54h

nres_moddiv                 equ 55h

nres_powltr                  equ 56h

divisible                        equ 57h

remain                          equ 58h

fmodulo                       equ 59h

nres_modadd                equ 5Ah

nres_modsub                equ 5Bh

nres_negate                  equ 5Ch

ecurve_init                    equ 5Dh

ecurve_add                   equ 5Eh

ecurve_mult                  equ 5Fh

epoint_init                     equ 60h

epoint_set                     equ 61h

epoint_get                     equ 62h

nres_powmod2             equ 63h

nres_sqroot                  equ 64h

sqroot                          equ 65h

nres_premult                 equ 66h

ecurve_mult2                equ 67h

ecurve_sub                   equ 68h

trial_division                 equ 69h

nxsafeprime                  equ 6Ah

nres_lucas                    equ 6Bh

lucas                            equ 6Ch

brick_init                      equ 6Dh

pow_brick                    equ 6Eh

set_user_function          equ 6Fh

nres_powmodn             equ 70h

powmodn                     equ 71h

ecurve_multn                equ 72h

ebrick_init                    equ 73h

mul_brick                     equ 74h

epoint_norm                 equ 75h

nres_multi_inverse         equ 76h

;null entry

nres_dotprod                equ 78h

epoint_negate                equ 79h

ecurve_multi_add          equ 7Ah

ecurve2_init                  equ 7Bh

epoint2_init                   equ 7Ch

epoint2_set                   equ 7Dh

epoint2_norm                equ 7Eh

epoint2_get                   equ 7Fh

epoint2_comp               equ 80h

ecurve2_add                 equ 81h

epoint2_negate              equ 82h

ecurve2_sub                 equ 83h

ecurve2_multi_add        equ 84h

ecurve2_mult                equ 85h

ecurve2_multn              equ 86h

ecurve2_mult2              equ 87h

ebrick2_init                   equ 88h

mul2_brick                   equ 89h

prepare_basis                equ 8Ah

strong_bigrand              equ 8Bh

bytes_to_big                 equ 8Ch

big_to_bytes                 equ 8Dh

set_io_buffer_size         equ 8Eh
2006-10-27 09:21
0
雪    币: 441
活跃值: (149)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
10
有上面的表用MIRACL的算法很容易在IDA中分析出来。。。
2006-10-27 09:26
0
雪    币: 309
活跃值: (15)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
11
兄弟好牛啊~~
偶要学习去~~
2006-10-27 11:53
0
雪    币: 390
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
真的很厉害,佩服!
2007-3-22 15:39
0
游客
登录 | 注册 方可回帖
返回
//