首页
社区
课程
招聘
[原创]看雪CTF2016-4-JoenChen.rar破解说明
发表于: 2016-11-9 17:38 3443

[原创]看雪CTF2016-4-JoenChen.rar破解说明

2016-11-9 17:38
3443
【文章标题】: 看雪CTF2016-4-JoenChen.rar破解说明
【文章作者】: SilentGamb@pediy
【作者主页】: http://bbs.pediy.com/member.php?u=492631
【软件名称】: 4-JoenChen.rar
【软件大小】: 283 KB (290,304 字节)
【下载地址】: http://ctf.pediy.com/?game-fight-5.htm
【加壳方式】: 无
【保护方式】: WProtect
【使用工具】: OD1.1+IDA6.1
【操作平台】: Win7X64
【软件介绍】: JoenChen为大家制作的cm
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  先说下结果 :
    从文件新加节名看, cm用了WProtect, 单步时,也不是编译器直接编译出来的样子.
    跟进去转了好久,没看出算法。估计作者也是装了这个口袋让攻击者钻。
    单步调试也看出了一些缓冲区操作,但是整体算法没看出,也没搞出算法公式。
    但是通过调试,弄清了注册码和注册成功之间的模糊关系(cm的注册函数地址,入口参数,注册码要求)。
    已经确定自己不能弄清注册算法,结合调试得到的注册码和注册成功之间的模糊关系,写出了穷举程序,
  5秒钟得到了一个注册码。
  
  以下摘自调试记录:
  
  侦查
  注册失败没有提示.
  
  MD5 :: 00000B37 :: 00401737
          The reference is above.
  SHA-512/384 [mixing] :: 00010198 :: 00411998
          The reference is above.
  
  .WProtec
  加了开源虚拟机壳WProtec
  
  https://github.com/xiaoweime/WProtect
  
  口令比对函数
  00401486  |.  FF15 04D14000 call dword ptr ds:[<&USER32.GetDlgItemTe>; \GetDlgItemTextA
  0040148C  |.  83F8 1E       cmp eax,0x1E                             ;  口令位数 = 30个字符
  0040148F  |.  75 25         jnz short CrackMe.004014B6
  00401491  |.  8BD0          mov edx,eax
  00401493  |.  8D8D FCFDFFFF lea ecx,dword ptr ss:[ebp-0x204]
  00401499  |.  E8 62FBFFFF   call CrackMe.00401000
  0040149E  |.  83F8 01       cmp eax,0x1
  004014A1  |.  75 13         jnz short CrackMe.004014B6
  004014A3  |.  6A 00         push 0x0                                 ; /Style = MB_OK|MB_APPLMODAL
  004014A5  |.  68 80374100   push CrackMe.00413780                    ; |Title = "information"
  004014AA  |.  68 8C374100   push CrackMe.0041378C                    ; |Text = "注册成功"
  004014AF  |.  56            push esi                                 ; |hOwner = 00080A2E ('CrackMe by JoenChen',class='#32770')
  004014B0  |.  FF15 00D14000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
  
  口令要求
  30个字符
  采用口令
  111111111111111111111111111111
  
  走到中间记录一下
  0042FCFA                   C3              retn
  栈
  0018F394   0042F3A3  CrackMe.0042F3A3
  0018F398   0018F8C4  返回到 0018F8C4
  0018F39C   00000000
  0018F3A0   00000287
  0018F3A4   0018F8B0
  0018F3A8   0018F770
  0018F3AC   00000000
  0018F3B0   0018F840  ASCII "1111111"
  0018F3B4   0018F4DC
  0018F3B8   0018F8D0  ASCII "111111111111111111111111111111"
  0018F3BC   0001E240
  0018F3C0   0000001E
  0018F3C4   76E47DDD  返回到 usp10.76E47DDD
  
  记录一下
  0042F72C                  /0F87 A7050000   ja CrackMe.0042FCD9
  
  0042F623                   66:F7D3         not bx
  
  
  0042F630                   66:81EB 85E2    sub bx,0xE285
  此时,测试输入还在栈内.
  
  准备对栈内数据下硬件断点了, 看哪用这个数据
  0018F3B0   0018F840  ASCII "1111111"
  
  004015A7     |.  88440E 18     |mov byte ptr ds:[esi+ecx+0x18],al
  
  .text:004015A7                 mov     [esi+ecx+18h], al ; 开始用到测试输入了
  
  004015A4     |> /8A040A        /mov al,byte ptr ds:[edx+ecx]
  004015A7     |. |88440E 18     |mov byte ptr ds:[esi+ecx+0x18],al
  004015AB     |. |41            |inc ecx
  004015AC     |. |3BCB          |cmp ecx,ebx                                     ;  ebx = 7
  004015AE     |.^\72 F4         \jb short CrackMe.004015A4
  
  
  数据被拷贝到新缓冲区
  0018F500  31 31 31 31 31 31 31 00 AC 48 D1 01 02 00 00 00  1111111.琀?...
  
  004015B0     |> \5F            pop edi                                          ;  0018F8D0
  
  
  记录一下
  0042FCFA       C3              retn
  
  edx = 0018F840
  0018F840  31 31 31 31 31 31 31 00 00 00 00 00 00 00 00 00  1111111.........
  
  0042F72C      /0F87 A7050000   ja CrackMe.0042FCD9 // 跳转成立去0042FCFA上面
  0042F732      |8D4F 64         lea ecx,dword ptr ds:[edi+0x64]                  ; 转完圈了会来这
  
  esi = 0018F140是1111111的0x64长度缓冲区,
  拷贝到 edi = 0018F0DC
  ecx = edx = 0x64
  
  0042F749       F3:A4           rep movs byte ptr es:[edi],byte ptr ds:[esi]     ; 拷贝了一次
  0042F74B       2BFA            sub edi,edx
  
  0042FCFA       C3              retn                                             ; 经常会过来
  
  
  0042F749       F3:A4           rep movs byte ptr es:[edi],byte ptr ds:[esi]     ; 拷贝了一次
  0042F74B       2BFA            sub edi,edx
  
  0042F623       66:F7D3         not bx                                           ; 转圈完成后,ret回来
  
  还是在栈内下断
  0018EFC8   0018F840  ASCII "1111111"
  0018EFCC   0018F4DC
  0018EFD0   0018F8D0  ASCII "111111111111111111111111111111"
  
  对0018F840和0018F8D0下满长度的内存访问断点
  
  EIP
  0042F623       66:F7D3         not bx                                           ; 转圈完成后,ret回来
  
  并不再访问用户输入...
  
  开始关键运算
  004012B5   ?  8B8D 08FCFFFF mov ecx,dword ptr ss:[ebp-0x3F8]                      ;  来过 0018f4b8
  004012BB   ?  8D95 90FEFFFF lea edx,dword ptr ss:[ebp-0x170]                      ;  0018f740
  004012C1   ?  8B85 04FCFFFF mov eax,dword ptr ss:[ebp-0x3FC]                      ;  0018f4b4
  004012C7   ?  C1E1 04       shl ecx,0x4
  004012CA   .  03C1          add eax,ecx
  004012CC   .  03D0          add edx,eax
  004012CE   >  8995 04FCFFFF mov dword ptr ss:[ebp-0x3FC],edx
  004012D4   .  8A8C05 90FCFF>mov cl,byte ptr ss:[ebp+eax-0x370]                    ;  0xD4怎么来的?
  
  eax 在 ss:[ebp+eax-0x370] 中指向的字节,如果简单运算后,是只要算出不是30, 24,58就成功.
  
  
  
  
  ss:[0018f540]数据从哪来?
  
  
  0040116E      .  0FB741 1B     movzx eax,word ptr ds:[ecx+0x1B]                 ;  拷贝用户输入, 拷贝了用户输入的31个字符中的前7个字符1111111.
  
  0018F840  31 31 31 31 31 31 31 00 00 00 00 00 00 00 00 00  1111111......... // 中间拷贝的前7个,没用到
  0018F850  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0018F860  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0018F870  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0018F880  31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31  1111111111111111 // 前16个字符
  0018F890  31 31 31 31 31 31 31 76 3A FD 8B 16 FE FF FF FF  1111111v:龐? // 前7个
  
  开始和下面的数据运算
  0018F4C0  04 0B D1 01 44 AD 5C CC 12 90 73 8D 47 81 E3 89  
  ?D璡?恠岹併?
  0018F4D0  84 9C DF F9 47 6A B6 9E 11 30 27 00 D0 F8 18 00  劀啭Gj稙0'.续.
  0018F4E0  3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  <...............
  
  第一个用户输入字符 xor byte[18f4c4]
  00401187      .  32840D 14FCFF>xor al,byte ptr ss:[ebp+ecx-0x3EC]
  
  // 异或的结果放到0018f498
  0018F490                          75 00 00 00 0C 00 00 00          .......
  0018F4A0  00 00 00 00 00 00 02 00 B0 15 E0 76 54 0B D1 01  .......?鄓T
  ?
  0018F4B0  B0 99 D1 01 02 00 00 00 00 00 00 00 C8 0B D1 01  皺?.......??
  
  0040119E      .  C6440D D0 00  mov byte ptr ss:[ebp+ecx-0x30],0x0               ;  清用户输入c1
  004011A3      .  C6840D 14FCFF>mov byte ptr ss:[ebp+ecx-0x3EC],0x0              ;  清数据k1
  
  // 异或0x17(23)个字符
  00401183      > /8A440D D0     mov al,byte ptr ss:[ebp+ecx-0x30]                ;  Cases 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11,12,13,14,15 of switch 00401195
  00401187      . |32840D 14FCFF>xor al,byte ptr ss:[ebp+ecx-0x3EC]
  0040118E      . |88840D E8FBFF>mov byte ptr ss:[ebp+ecx-0x418],al
  00401195      . |83F9 17       cmp ecx,0x17                                     ;  Switch (cases 0..16)
  00401198      . |0F83 68020000 jnb CrackMe.00401406
  0040119E      . |C6440D D0 00  mov byte ptr ss:[ebp+ecx-0x30],0x0               ;  清用户输入c1
  004011A3      . |C6840D 14FCFF>mov byte ptr ss:[ebp+ecx-0x3EC],0x0              ;  清数据k1
  004011AB      . |41            inc ecx
  004011AC      . |83F9 17       cmp ecx,0x17
  004011AF      .^\7C D2         jl short CrackMe.00401183
  
  开始运算了
  00401183      > /8A440D D0     mov al,byte ptr ss:[ebp+ecx-0x30]                ;  Cases 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11,12,13,14,15 of switch 00401195
  00401187      . |32840D 14FCFF>xor al,byte ptr ss:[ebp+ecx-0x3EC]
  0040118E      . |88840D E8FBFF>mov byte ptr ss:[ebp+ecx-0x418],al
  00401195      . |83F9 17       cmp ecx,0x17                                     ;  Switch (cases 0..16)
  00401198      . |0F83 68020000 jnb CrackMe.00401406
  0040119E      . |C6440D D0 00  mov byte ptr ss:[ebp+ecx-0x30],0x0               ;  清用户输入c1
  004011A3      . |C6840D 14FCFF>mov byte ptr ss:[ebp+ecx-0x3EC],0x0              ;  清数据k1
  004011AB      . |41            inc ecx
  004011AC      . |83F9 17       cmp ecx,0x17
  004011AF      .^\7C D2         jl short CrackMe.00401183                        ;  异或运算23个字符
  
  
  23个字符运算完成
  0018F490                          75 9C 6D FD 23 A1 42 BC          渕??
  0018F4A0  76 B0 D2 B8 B5 AD EE C8 76 5B 87 AF 20 01 16     v耙傅葀[嚡 
  
  
  开始运算2 - 也是23个字符
  EIP
  004011C0      > /8A840D 90FDFF>mov al,byte ptr ss:[ebp+ecx-0x270]               ;  Cases 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11,12,13,14,15 of switch 004011D2
  
  
  18f640 与 18f498 异或 送到 0018F880
  
  0018F640  7F A8 28 2A D9 30 47 A4 D6 FE 61 11 C9 3B 30 8A  ?*?Gぶ?0?
  0018F650  7F A8 28 2A D9 30 47                             ?*?G..
  
  
  0018F490                          75 9C 6D FD 23 A1 42 BC          渕??
  0018F4A0  76 B0 D2 B8 B5 AD EE                             v耙傅葀[嚡
  
  
  al=0A (Line Feed)
  堆栈 ss:[0018F880]=00
  
  0018F880在运算前,已经清好了
  0018F880  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0018F890  00 00 00 00 00 00 00                             .......
  
  算完之后
  0018F880  0A 34 45 D7 FA 91 05 18 A0 4E B3 A9 7C 96 DE 42  .4E?燦畅|栟B
  0018F890  09 F3 AF 85 F9 31 51                             .蟑咘1Qv:
  
  继续计算
  004011F1      .  B9 40000000   mov ecx,0x40                                     ;  
  004011F6      .  8DBD 90FCFFFF lea edi,dword ptr ss:[ebp-0x370]                 ;  0018f8d0 用户输入的30个字符
  
  ecx = 00000040
  esi = 00413798
  edi = 0018F540
  
  00413798  6E D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9  n?i_N瑾曵2b?
  004137A8  02 18 74 95 1F C2 4D 33 3C F0 3B EC E9 81 4B 9C  t?翸3<?扉並?
  004137B8  0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D  
  
  0x40 dword拷贝完成后, 总共0x100字节
  
  
  0018F540  6E D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9  n?i_N瑾曵2b?
  0018F550  02 18 74 95 1F C2 4D 33 3C F0 3B EC E9 81 4B 9C  t?翸3<?扉並?
  0018F560  0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D  
  
  继续计算
  
  00401205      .  B9 40000000   mov ecx,0x40
  
  
  0040120A      .  8985 30FCFFFF mov dword ptr ss:[ebp-0x3D0],eax
  
  
  eax=00000000
  堆栈 ss:[0018F4E0]=0000003C
  
  [0018F4E0] = 0 // 清0
  
  开始拷贝数据
  0040121B      .  F3:A5         rep movs dword ptr es:[edi],dword ptr ds:[esi]
  
  esi = 00413898
  edi = 0018F740
  
  拷贝完成后
  0018F740  D8 05 F6 6A E7 A2 0B 9B 54 8C DA 82 BD B6 A8 46  ?鰆纰
  汿屭偨定F
  0018F750  B1 36 2D 55 F7 81 63 FC 3F 0C FE 0B 4B 50 E2 17  ?-U鱽c?.?KP?
  0018F760  F2 E1 27 5B 46 73 1C D0 E5 D7 8D C9 F2 70 94 53  蜥'[Fs绣讔沈p擲
  
  040121F      .  898D 2CFCFFFF mov dword ptr ss:[ebp-0x3D4],ecx                 ;  0x18f4dc用户输入字符串指针清0
  
  00401225      > /8A4C0D D0     mov cl,byte ptr ss:[ebp+ecx-0x30]                ;  [18f880] => cl
  
  0040122C      .  C785 0CFCFFFF>mov dword ptr ss:[ebp-0x3F4],0x6                 ;  dw ss:[18f4bc] = 6
  
  00401236      .  898D 00FCFFFF mov dword ptr ss:[ebp-0x400],ecx                 ;  ss:18f4b0 = a
  
  00401242      .  8985 10FCFFFF mov dword ptr ss:[ebp-0x3F0],eax                 ;  ss:18f4c0 = 0
  
  
  一段查表跳转,往下跳了一句.
  执行eax -=10 or eax += 1, or eax += 10
  00401253      . /FF2495 0C1440>jmp dword ptr ds:[edx*4+0x40140C]                ;  CrackMe.0040125A
  0040125A      > \83E8 10       sub eax,0x10
  0040125D      .  EB 09         jmp short CrackMe.00401268
  0040125F      >  40            inc eax
  00401260      .  EB 06         jmp short CrackMe.00401268
  00401262      >  83C0 10       add eax,0x10
  00401265      .  EB 01         jmp short CrackMe.00401268
  
  00401268      > \8985 30FCFFFF mov dword ptr ss:[ebp-0x3D0],eax
  
  0040128F      > \8985 04FCFFFF mov dword ptr ss:[ebp-0x3FC],eax                 ;  ss:[0018f4b4] = 0
  00401295      .- E9 DBB10300   jmp CrackMe.0043C475
  
  不断的转圈, 如果不转圈了,进下面3个call
  004013E2      .  E8 CF090000   call CrackMe.00401DB6
  004013E7      .  8BE5          mov esp,ebp
  004013E9      .  5D            pop ebp
  004013EA      .  8BE3          mov esp,ebx
  004013EC      .  5B            pop ebx
  004013ED      .  C3            retn
  004013EE      >  8B4D FC       mov ecx,dword ptr ss:[ebp-0x4]
  004013F1      .  B8 01000000   mov eax,0x1
  004013F6      .  5F            pop edi
  004013F7      .  33CD          xor ecx,ebp
  004013F9      .  5E            pop esi                                          ;  CrackMe.00413998
  004013FA      .  E8 B7090000   call CrackMe.00401DB6
  004013FF      .  8BE5          mov esp,ebp
  00401401      .  5D            pop ebp
  00401402      .  8BE3          mov esp,ebx
  00401404      .  5B            pop ebx
  00401405      .  C3            retn
  00401406      >  E8 DF0A0000   call CrackMe.00401EEA                            ;  Default case of switch 004011D2
  
  
  来了
  004013E2      .  E8 CF090000   call CrackMe.00401DB6
  
  
  004013D9 <CrackMe.failed_004013d9>     > \33C0              xor eax,eax                                      ;  失败了来这里
  004013DB                               .  5F                pop edi
  004013DC                               .  5E                pop esi
  004013DD                               .  8B4D FC           mov ecx,dword ptr ss:[ebp-0x4]
  004013E0                               .  33CD              xor ecx,ebp
  004013E2                               .  E8 CF090000       call <CrackMe.fn_anti>                           ;  没有影响eax
  004013E7                               .  8BE5              mov esp,ebp
  004013E9                               .  5D                pop ebp
  004013EA                               .  8BE3              mov esp,ebx
  004013EC                               .  5B                pop ebx
  004013ED                               .  C3                retn
  
  
  004012EE ecx == 0x30                   .  83F9 30           cmp ecx,0x30                                     ;  ecx == 0x30失败
  
  异或之前 ecx = 0x35失败
  
  
  004012E3 (al >> 2) == 0x35             .  C0C8 02           ror al,0x2                                       ;  (al == 0xd4) 失败
  
  0xD4怎么来的?
  004012D4      .  8A8C05 90FCFFFF   mov cl,byte ptr ss:[ebp+eax-0x370]               ;  0xD4怎么来的?
  
  第20次,变成了0xD4
  在第19次时,跟一下.
  
  ss:[ebp+eax-0x370] = ss:[0018f541] = 0xd4时失败
  
  
  如果新打开OD, 运行第4次,就开始算出了错误的ss:[0018f540], 所以第3次,要去看一下.
  
  第4次,就算好了错误值 ss:[0018f540]时,ss:[0018f541]的值已经确定是0xd4. 已经错了.
  
  ss:[0018f541]往下简单移位计算, 只要算出不是30, 24,58就成功.
  
  堆栈 ss:[0018F530]=00
  cl=F0
  
  堆栈 ss:[0018F520]=00
  cl=E0
  
  堆栈 ss:[0018F530]=00
  cl=F0
  
  下面就要算ss:[0018f540], 开始跟一下.
  其实,第一次就已经算成了0xD4, 第一次就要跟.
  
  111111111111111111111111111111
  
  算数据的过程
  这里的数据就是出去后,要比对的ss:[0018f541] 计算出30, 24,58, 只要不算出计算后的30,24,58,就注册成功了.
  
  0040115E   .  8B8D 2CFCFFFF mov ecx,dword ptr ss:[ebp-0x3D4]
  00401164   .  8B41 17       mov eax,dword ptr ds:[ecx+0x17]
  00401167   .  0F1041 07     movups xmm0,dqword ptr ds:[ecx+0x7]
  0040116B   .  8945 E0       mov dword ptr ss:[ebp-0x20],eax
  0040116E   .  0FB741 1B     movzx eax,word ptr ds:[ecx+0x1B]                      ;  拷贝用户输入
  00401172   .  66:8945 E4    mov word ptr ss:[ebp-0x1C],ax
  00401176   .  0FB641 1D     movzx eax,byte ptr ds:[ecx+0x1D]
  0040117A   .  33C9          xor ecx,ecx
  0040117C   .  0F1145 D0     movups dqword ptr ss:[ebp-0x30],xmm0
  00401180   .  8845 E6       mov byte ptr ss:[ebp-0x1A],al
  00401183   >  8A440D D0     mov al,byte ptr ss:[ebp+ecx-0x30]                     ;  Cases 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11,12,13,14,15 of switch 00401195
  00401187   .  32840D 14FCFF>xor al,byte ptr ss:[ebp+ecx-0x3EC]
  0040118E   .  88840D E8FBFF>mov byte ptr ss:[ebp+ecx-0x418],al
  00401195   .  83F9 17       cmp ecx,0x17                                          ;  Switch (cases 0..16)
  00401198   .  0F83 68020000 jnb CrackMe.00401406
  0040119E   .  C6440D D0 00  mov byte ptr ss:[ebp+ecx-0x30],0x0                    ;  清用户输入c1
  004011A3   .  C6840D 14FCFF>mov byte ptr ss:[ebp+ecx-0x3EC],0x0                   ;  清数据k1
  
  
  00413798谁算出来的?
  00413798  6E D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9  n?i_N瑾曵2b?
  004137A8  02 18 74 95 1F C2 4D 33 3C F0 3B EC E9 81 4B 9C  t?翸3<?扉並?
  004137B8  0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D  
  G\.皣S涷?拲
  
  
  004011FC   .  BE 98374100   mov esi,CrackMe.00413798
  00413798决定注册是否成功,[00413799]为d4就失败.
  
  00413798 是内置的数组啊
  
  .data:00413798                 db 6Eh, 0D4h, 1Bh, 69h, 5Fh, 4Eh, 0E8h, 0AAh, 95h, 0F6h, 0AFh, 0CEh, 32h, 1Ah, 62h, 0D9h; 0
  .data:00413798                 db 2, 18h, 74h, 95h, 1Fh, 0C2h, 4Dh, 33h, 3Ch, 0F0h, 3Bh, 0ECh, 0E9h, 81h, 4Bh, 9Ch; 16
  .data:00413798                 db 0Fh, 47h, 5Ch, 0ADh, 0D9h, 9, 0B0h, 87h, 53h, 9Bh, 0F2h, 0E3h, 0Fh, 1, 92h, 8Dh; 32
  .data:00413798                 db 0C2h, 0F5h, 0Ch, 0DDh, 42h, 0CCh, 0AFh, 0B4h, 0D5h, 0E4h, 86h, 0D3h, 9Ah, 0Bh, 62h, 63h; 48
  
  没招了,要穷举了
  再不穷举,就要放弃治疗了...
  
  从前面的调试可以看出, 口令为30个字符, 再没其他限制.
  0042FCFA 时,看栈内数据,有前7个字符
  0040116E开始,可以看到cm拿用户输入的前7个字符做了任务.
  004015AE时,看到前7个字符的拷贝动作
  
  0042F732 时,
  esi = 0018F140是1111111的0x64长度缓冲区,
  拷贝到 edi = 0018F0DC
  ecx = edx = 0x64
  
  0042F623 时,栈内有用户输入的全部注册码,和前7个注册码,而且前7个注册码在前
  
  0040116E时,拷贝了前7个字符
  
  很多操作都进了.WProctect 0x0043xxxx, 对虚拟机不甚了解, 跟进去看了下,无功而返.
  只能看0040xxxx的操作了.
  
  但是咋拿前7个字符计算的,就没看到了,可能在.WProctect 0x0043xxxx.
  
  综合调试记录分析,cm使用前7个字符作为注册码来源的可能性很大.
  先穷举30个字符中的前7个,如果不行,就全部穷举.
  
  将PE作为DLL载入, 穷举前7个字符,后面的23个字符不变,运行5秒钟后,得到一个注册码. 00000bQ11111111111111111111111, 直接运行cm, 输入注册码成功注册^_^
  
  穷举程序片段
  // hw.cpp : Defines the entry point for the console application.
  //
  
  #include "stdafx.h"
  #include <windows.h>
  #include <stdlib.h>
  #include <stdio.h>
  #include <math.h>
  
  #include <windows.h>
  
  DWORD Base;
  DWORD pfn = 0;
  
  // void __declspec(naked) fnCalcRegSn1/*<eax>*/(signed int a1/*<edx>*/, int a2/*<ecx>*/, int a3/*<ebp>*/)
  // {
  //
  // }
  
  typedef void (*PFN_fnCalcRegSn1)/*<eax>*/();
  
  char ucAryPwdCharSet[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
                           };
  
  int main(int argc, char* argv[])
  {
      // v4 和szBuf必须前2个, pfn1要用
      int v4; // ebp@0
      CHAR szBuf[0x200] = {'\0'}; // [sp+4h] [bp-204h]@7
      int iBuf = 0;
      PFN_fnCalcRegSn1 pfn1 = NULL;
      int iRc = -2;
      DWORD dwProt;
      int iLenAryPwdCharSet = sizeof(ucAryPwdCharSet);
      int iLoop1 = 0;
      int iLoop2 = 0;
      int iLoop3 = 0;
      int iLoop4 = 0;
      int iLoop5 = 0;
      int iLoop6 = 0;
      int iLoop7 = 0;
      // 284 KB (290,816 字节) => 290816 => 0x47000
      // CrackMe.exe 默认装载地址为0x0040xxxx
      // 00401000 > $  53            push ebx                                 ;  注册码比对
      // 程序基地址改为 0x200000
      Base = (DWORD)LoadLibraryEx("CrackMe.exe", NULL, DONT_RESOLVE_DLL_REFERENCES);
      VirtualProtect((LPVOID)Base, 0x47000, PAGE_EXECUTE_READWRITE, &dwProt);
      
      if (Base == 0x400000) {
          // 00401000 > $  53            push ebx                                              ;  注册码比对
          pfn = Base + 0x1000;
          pfn1 = (PFN_fnCalcRegSn1)pfn;
         
          // 根据调试记录, 前7个字母是此cm的产生数据的原数据
          // 穷举前7个字符, 规模不大
          for (iLoop1 = 0; iLoop1 < iLenAryPwdCharSet; iLoop1++) {
              for (iLoop2 = 0; iLoop2 < iLenAryPwdCharSet; iLoop2++) {
                  for (iLoop3 = 0; iLoop3 < iLenAryPwdCharSet; iLoop3++) {
                      for (iLoop4 = 0; iLoop4 < iLenAryPwdCharSet; iLoop4++) {
                          for (iLoop5 = 0; iLoop5 < iLenAryPwdCharSet; iLoop5++) {
                              for (iLoop6 = 0; iLoop6 < iLenAryPwdCharSet; iLoop6++) {
                                  for (iLoop7 = 0; iLoop7 < iLenAryPwdCharSet; iLoop7++) {
                                      strcpy(szBuf, "111111111111111111111111111111");
                                      szBuf[0] = ucAryPwdCharSet[iLoop1];
                                      szBuf[1] = ucAryPwdCharSet[iLoop2];
                                      szBuf[2] = ucAryPwdCharSet[iLoop3];
                                      szBuf[3] = ucAryPwdCharSet[iLoop4];
                                      szBuf[4] = ucAryPwdCharSet[iLoop5];
                                      szBuf[5] = ucAryPwdCharSet[iLoop6];
                                      szBuf[6] = ucAryPwdCharSet[iLoop7];
                                      iBuf = (int)szBuf;
                                      __asm {
                                          mov edx, 30
                                          mov ecx, iBuf
                                      };
                                      iRc = 0;
                                      pfn1();
                                      __asm {
                                          mov iRc, eax
                                      };
                                      
                                      if (iRc > 0) {
                                          ::MessageBox(NULL, szBuf, "找到注册码!", MB_OK);
                                          OutputDebugString("找到注册码!\r\n");
                                          OutputDebugString(szBuf);
                                          OutputDebugString("\r\n");
                                      } else {
                                          OutputDebugString(".");
                                      }
                                  }
                              }
                          }
                      }
                  }
              }
          }
      } else {
          // 再FreeLibrary, 再LoadLibraryEx没用的, 必须重新启动一次
          ::MessageBox(NULL, "错误", "载入目标程序失败, 请重新运行一次", MB_OK);
      }
      
      if (0 != Base) {
          FreeLibrary((HMODULE)Base);
          Base = 0;
      }
      
      ::MessageBox(NULL, "END", "穷举结束", MB_OK);
      return 0;
  }
  
  感谢JoenChen制作的cm^_^
  
--------------------------------------------------------------------------------
【经验总结】
  大家都开始上密码学,虚拟机,以后要针对这方面加强练习.
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2016年11月09日 17:31:12

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//