| 关键词: nbsp eax ptr ecx 004060 dword 注册码 edx mov 004061 |
使用工具: Fi、AspackDie、W32dasm、Filemon、WinHex、OllyDbg 破解过程: 在序列号框中随意输入,点 注册 后弹出对话框“无效的注册编码!”。用 Fi 侦测,发现其用 ASPack 加壳,用 AspackDie 脱掉,在用 W32dasm 反汇编,在串式参考中找到“无效的注册编码!”,来到如下代码。* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:|:00406B2F(C), :00406B42(C)|:00406B62 6A00 push 00000000:00406B64 6A00 push 00000000* Possible StringData Ref from Data Obj ->"无效的注册编码!" |:00406B66 68A8F34100 push 0041F3A8:00406B6B 8BCE mov ecx, esi它由两个地方跳转来,分别查看。:00406B17 E806D30000 Call 00413E22:00406B1C 8B7E64 mov edi, dword ptr [esi+64]:00406B1F 8D5E64 lea ebx, dword ptr [esi+64]:00406B22 83C9FF or ecx, FFFFFFFF:00406B25 33C0 xor eax, eax:00406B27 F2 repnz:00406B28 AE scasb:00406B29 F7D1 not ecx:00406B2B 49 dec ecx:00406B2C 83F906 cmp ecx, 00000006:00406B2F 7531 jne 00406B62 ---------------> 与 6 比较,不等就跳 "无效的注册编码!":00406B31 8B7E68 mov edi, dword ptr [esi+68]:00406B34 8D5668 lea edx, dword ptr [esi+68]:00406B37 83C9FF or ecx, FFFFFFFF:00406B3A F2 repnz:00406B3B AE scasb:00406B3C F7D1 not ecx:00406B3E 49 dec ecx:00406B3F 83F909 cmp ecx, 00000009:00406B42 751E jne 00406B62 ---------------> 与 9 比较,不等就跳 "无效的注册编码!":00406B44 6A0A push 0000000A:00406B46 8BCA mov ecx, edx因为注册码由两部分组成,猜想可能是判断两部分各自的长度,再在第一部分随便输入 6 个字符,第二部分输入 9 个字符,点 注册 ,果然不在弹出对话框了!(居然蒙对了 :) )可再看看软件,还是未注册,接着用 Filemon 监视,在点下 注册 后,发现其对C:\WINDOWS\system32\stpk.obj 进行操作,看来是将输入的注册码保存到 stpk.obj 中了,用 WinHex 打开这个文件,里面果然有刚才输入的注册码。接着请出OllyDbg,装载程序,进行动态跟踪,在其字符参考中搜索 stpk.obj ,发现两处,均下断。按 F9 运行程序,在 0040643B 处中断。现对其代码分析如下:00406410 /$ 81EC DC030000 SUB ESP,3DC00406416 |. 55 PUSH EBP00406417 |. 56 PUSH ESI00406418 |. 57 PUSH EDI00406419 |. 8D4424 58 LEA EAX,DWORD PTR SS:[ESP+58]0040641D |. 8BF9 MOV EDI,ECX0040641F |. 68 90010000 PUSH 190 ; /BufSize = 190 (400.)00406424 |. 50 PUSH EAX ; |Buffer00406425 |. 897C24 18 MOV DWORD PTR SS:[ESP+18],EDI ; |00406429 |. FF15 60904100 CALL DWORD PTR DS:[; \GetSystemDirectoryA0040642F |. 8D4C24 58 LEA ECX,DWORD PTR SS:[ESP+58]00406433 |. 8D9424 E801000>LEA EDX,DWORD PTR SS:[ESP+1E8]0040643A |. 51 PUSH ECX ; /0040643B |. 68 74F34100 PUSH unpacked.0041F374 ; |format = "%s\stpk.obj"00406440 |. 52 PUSH EDX ; |s00406441 |. FF15 88964100 CALL DWORD PTR DS:[] ; \sprintf00406447 |. 8B35 94964100 MOV ESI,DWORD PTR DS:[] ; msvcrt.fopen0040644D |. 8D8424 F401000>LEA EAX,DWORD PTR SS:[ESP+1F4]………… ; [ 省略若干行 ]00406506 |. 6A 0A PUSH 0A ; [ 0A 入栈,后面计算注册码会用到 ]………… ; [ 省略若干行 ]0040651A |. 50 PUSH EAX0040651B |. 894F 08 MOV DWORD PTR DS:[EDI+8],ECX0040651E |. E8 7DFBFFFF CALL unpacked.004060A0 ; [ 计算注册码的关键 Call ]00406523 |. 8B4424 24 MOV EAX,DWORD PTR SS:[ESP+24]00406527 |. 83C4 0C ADD ESP,0C0040652A |. 83C0 04 ADD EAX,40040652D |. 8BCF MOV ECX,EDI0040652F |. 6A 32 PUSH 3200406531 |. 50 PUSH EAX00406532 |. C747 04 010000>MOV DWORD PTR DS:[EDI+4],100406539 |. E8 D2020000 CALL unpacked.00406810 ; [ 关键 Call ,判断注册码的第一部分是否全为数字 ]0040653E |. 8B47 04 MOV EAX,DWORD PTR DS:[EDI+4] ; [ EAX = DS:[EDI+4] ] [ 此处的 EAX 至与 00406539 的 Call 有关 ]00406541 |. 85C0 TEST EAX,EAX00406543 |. 74 54 JE SHORT unpacked.00406599 ; [ 若 EAX = 00000000 , 则跳至 00406599 ] [ 即跳过注册码第二部分的判断,直接以未注册版运行 ]00406545 |. 8B4C24 18 MOV ECX,DWORD PTR SS:[ESP+18]00406549 |. 6A 09 PUSH 9 ; /maxlen = 90040654B |. 83C1 0B ADD ECX,0B ; |0040654E |. 8D5424 47 LEA EDX,DWORD PTR SS:[ESP+47] ; |00406552 |. 51 PUSH ECX ; |s2 [ 读入假码的第二部分 ]00406553 |. 52 PUSH EDX ; |s1 [ 读入真码的第二部分 ]00406554 |. FF15 84964100 CALL DWORD PTR DS:[] ; \strncmp [ 进行比较 ]………… ; [ 以下省略 ]**************计算注册码的关键 Call*******************************************************004060A0 /$ 53 PUSH EBX004060A1 |. 55 PUSH EBP004060A2 |. 8B6C24 10 MOV EBP,DWORD PTR SS:[ESP+10]004060A6 |. 56 PUSH ESI004060A7 |. 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+10]004060AB |. 57 PUSH EDI004060AC |. 8BCE MOV ECX,ESI004060AE |. 8D5D 07 LEA EBX,DWORD PTR SS:[EBP+7]004060B1 |. C646 06 00 MOV BYTE PTR DS:[ESI+6],0004060B5 |. 8BC5 MOV EAX,EBP004060B7 |. 2BCD SUB ECX,EBP004060B9 |. BF 06000000 MOV EDI,6004060BE |> 8A1401 /MOV DL,BYTE PTR DS:[ECX+EAX] ; / 004060BE~004060C5这一段的功能是:004060C1 |. 8810 |MOV BYTE PTR DS:[EAX],DL ; | 将注册码的第一部分复制 0012F8A0004060C3 |. 40 |INC EAX ; | 0012F8A0 就是真码出现的地方004060C4 |. 4F |DEC EDI ; |004060C5 |.^75 F7 \JNZ SHORT unpacked.004060BE ; \004060C7 |. 8B7C24 1C MOV EDI,DWORD PTR SS:[ESP+1C] ; [ 将 SS:[ESP+1C] 的值给 EDI ] ; [ EDI = 0000000A ,即前面入栈的 0A ]004060CB |. C645 06 2D MOV BYTE PTR SS:[EBP+6],2D ; [ 0012F8A0 中注册码第一部分的后面加上 - ]--------------- 计算第二部分的前三个字母开始 ------------004060CF |. 0FBE4E 03 MOVSX ECX,BYTE PTR DS:[ESI+3] ; [ 将第一部分的第四个数字的 ASCII 码给 ECX ]004060D3 |. 0FBE06 MOVSX EAX,BYTE PTR DS:[ESI] ; [ 将第一部分的第一个数字的 ASCII 码给 EAX ]004060D6 |. 8BD7 MOV EDX,EDI ; [ EDX = EDI = 0000000A ]004060D8 |. 6A 03 PUSH 3 004060DA |. 03D1 ADD EDX,ECX ; [ EDX = EDX +ECX ] 004060DC |. B9 19000000 MOV ECX,19 ; [ ECX = 19h ]004060E1 |. 03C2 ADD EAX,EDX ; [ EAX = EAX + EDX ]004060E3 |. C64424 1B 00 MOV BYTE PTR SS:[ESP+1B],0 004060E8 |. 99 CDQ ; [ EAX 符号扩展为 64 位 EDX:EAX ] [ 此处 CDQ 的作用实际就是将 EDX 清零 ] ( 不知道我的理解对不对,望高手指点。)004060E9 |. F7F9 IDIV ECX ; [ EAX 除以 ECX 商存入 EAX ,余数存入 EDX ]004060EB |. 0FBE46 01 MOVSX EAX,BYTE PTR DS:[ESI+1] ; [ 将第一部分的第二个数字的 ASCII 码给 EAX ]004060EF |. 8BCF MOV ECX,EDI ; [ ECX = EDI ]004060F1 |. 80C2 41 ADD DL,41 ; [ DL = DL +41h ]004060F4 |. 885424 18 MOV BYTE PTR SS:[ESP+18],DL ; [ 将 DL 值存入 SS:[ESP+18] ] [ 这就是注册码第二部分的第一位 ] [ 接下来是计算注册码第二部分的第二、三位] [ 算法与此相同,不再赘述 ]004060F8 |. 0FBE56 04 MOVSX EDX,BYTE PTR DS:[ESI+4] 004060FC |. 03CA ADD ECX,EDX 004060FE |. 03C1 ADD EAX,ECX 00406100 |. B9 19000000 MOV ECX,19 00406105 |. 99 CDQ 00406106 |. F7F9 IDIV ECX 00406108 |. 0FBE46 02 MOVSX EAX,BYTE PTR DS:[ESI+2] 0040610C |. 8BCF MOV ECX,EDI 0040610E |. 80C2 41 ADD DL,41 00406111 |. 885424 19 MOV BYTE PTR SS:[ESP+19],DL 00406115 |. 0FBE56 05 MOVSX EDX,BYTE PTR DS:[ESI+5] 00406119 |. 03CA ADD ECX,EDX 0040611B |. 03C1 ADD EAX,ECX 0040611D |. B9 19000000 MOV ECX,19 00406122 |. 99 CDQ 00406123 |. F7F9 IDIV ECX 00406125 |. 80C2 41 ADD DL,41 00406128 |. 885424 1A MOV BYTE PTR SS:[ESP+1A],DL--------------- 计算第二部分的前三个字母结束 -------------0040612C |. 8D5424 18 LEA EDX,DWORD PTR SS:[ESP+18] 00406130 |. 52 PUSH EDX 00406131 |. 53 PUSH EBX 00406132 |. 8B1D 8C964100 MOV EBX,DWORD PTR DS:[] 00406138 |. FFD3 CALL EBX ; [ 将这三个字母接在 0012F8A0 中部分注册码的后面 ]--------------- 计算第二部分的中间三个字母开始 --------------0040613A |. 0FBE46 03 MOVSX EAX,BYTE PTR DS:[ESI+3] ; [ 将第一部分的第四个数字的 ASCII 码给 EAX ]0040613E |. 0FBE0E MOVSX ECX,BYTE PTR DS:[ESI] ; [ 将第一部分的第一个数字的 ASCII 码给 ECX ]00406141 |. 2BC8 SUB ECX,EAX ; [ ECX = ECX - EAX ]00406143 |. 6A 03 PUSH 300406145 |. 8D4439 20 LEA EAX,DWORD PTR DS:[ECX+EDI+20] ; [ EAX = ECX + EDI + 20h ]00406149 |. B9 19000000 MOV ECX,19 ; [ ECX = 19h ]0040614E |. 99 CDQ ; [ 将 EDX 清零 ]0040614F |. F7F9 IDIV ECX ; [ EAX 除以 ECX 商存入 EAX ,余数存入 EDX ]00406151 |. 0FBE46 04 MOVSX EAX,BYTE PTR DS:[ESI+4] ; [ 将第一部分的第五个数字的 ASCII 码给 EAX ]00406155 |. 80C2 41 ADD DL,41 ; [ DL = DL + 41h ]00406158 |. 885424 24 MOV BYTE PTR SS:[ESP+24],DL ; [ 将 DL 值存入 DS:[ESI+24] ] [ 这就是注册码第二部分的第四位 ] [ 接下来是计算注册码第二部分的第五、六位] [ 算法与此相同,不再赘述 ]0040615C |. 0FBE56 01 MOVSX EDX,BYTE PTR DS:[ESI+1]00406160 |. 2BD0 SUB EDX,EAX00406162 |. 8D443A 20 LEA EAX,DWORD PTR DS:[EDX+EDI+20]00406166 |. 99 CDQ00406167 |. F7F9 IDIV ECX00406169 |. 0FBE46 05 MOVSX EAX,BYTE PTR DS:[ESI+5]0040616D |. 80C2 41 ADD DL,4100406170 |. 885424 25 MOV BYTE PTR SS:[ESP+25],DL00406174 |. 0FBE56 02 MOVSX EDX,BYTE PTR DS:[ESI+2]00406178 |. 2BD0 SUB EDX,EAX0040617A |. 8D443A 20 LEA EAX,DWORD PTR DS:[EDX+EDI+20]0040617E |. 99 CDQ0040617F |. F7F9 IDIV ECX00406181 |. 8D45 0A LEA EAX,DWORD PTR SS:[EBP+A]00406184 |. 80C2 41 ADD DL,4100406187 |. 885424 26 MOV BYTE PTR SS:[ESP+26],DL--------------- 计算第二部分的中间三个字母结束 -----------------0040618B |. 8D5424 24 LEA EDX,DWORD PTR SS:[ESP+24]0040618F |. 52 PUSH EDX00406190 |. 50 PUSH EAX00406191 |. FFD3 CALL EBX ; [ 将这三个字母接在 0012F8A0 中部分注册码的后面 ]--------------- 计算第二部分的后三个字母开始 -------------------00406193 |. 0FBE46 03 MOVSX EAX,BYTE PTR DS:[ESI+3] ; [ 将第一部分的第四个数字的 ASCII 码给 EAX ]00406197 |. 0FBE0E MOVSX ECX,BYTE PTR DS:[ESI] ; [ 将第一部分的第一个数字的 ASCII 码给 ECX ]0040619A |. 03C7 ADD EAX,EDI ; [ EAX = EAX + EDI ]0040619C |. 33C1 XOR EAX,ECX ; [ EAX = EAX XOR ECX ]0040619E |. B9 19000000 MOV ECX,19 ; [ ECX = 19h ]004061A3 |. 99 CDQ ; [ 将 EDX 清零 ]004061A4 |. F7F9 IDIV ECX ; [ EAX 除以 ECX 商存入 EAX ,余数存入 EDX ]004061A6 |. 0FBE46 04 MOVSX EAX,BYTE PTR DS:[ESI+4] ; [ 将第一部分的第五个数字的 ASCII 码给 EAX ]004061AA |. 80C2 41 ADD DL,41 ; [ DL = DL + 41h ]004061AD |. 03C7 ADD EAX,EDI ; [ EAX = EAX + EDI ]004061AF |. 885424 2C MOV BYTE PTR SS:[ESP+2C],DL ; [ DL 存入 SS:[ESP+2C] ] [ 这就是注册码第二部分的第七位 ] [ 接下来是计算注册码第二部分的第八、九位] [ 算法与此相同,不再赘述 ]004061B3 |. 0FBE56 01 MOVSX EDX,BYTE PTR DS:[ESI+1]004061B7 |. 33C2 XOR EAX,EDX004061B9 |. 6A 03 PUSH 3004061BB |. 99 CDQ004061BC |. F7F9 IDIV ECX004061BE |. 0FBE46 05 MOVSX EAX,BYTE PTR DS:[ESI+5]004061C2 |. 03C7 ADD EAX,EDI004061C4 |. 80C2 41 ADD DL,41004061C7 |. 885424 31 MOV BYTE PTR SS:[ESP+31],DL004061CB |. 0FBE56 02 MOVSX EDX,BYTE PTR DS:[ESI+2]004061CF |. 33C2 XOR EAX,EDX004061D1 |. 99 CDQ004061D2 |. F7F9 IDIV ECX004061D4 |. 8D45 0D LEA EAX,DWORD PTR SS:[EBP+D]004061D7 |. 80C2 41 ADD DL,41004061DA |. 885424 32 MOV BYTE PTR SS:[ESP+32],DL--------------- 计算第二部分的后三个字母结束 -------------------004061DE |. 8D5424 30 LEA EDX,DWORD PTR SS:[ESP+30]004061E2 |. 52 PUSH EDX004061E3 |. 50 PUSH EAX004061E4 |. FFD3 CALL EBX ; [ 将这三个字母接在 0012F8A0 中部分注册码的后面 ] [ 至此,从 0012F8A0 开始为完整的正确注册码 ]004061E6 |. 83C4 24 ADD ESP,24004061E9 |. C645 10 00 MOV BYTE PTR SS:[EBP+10],0004061ED |. B8 01000000 MOV EAX,1004061F2 |. 5F POP EDI004061F3 |. 5E POP ESI004061F4 |. 5D POP EBP004061F5 |. 5B POP EBX004061F6 \. C3 RETN**********判断注册码的第一部分是否全为数字关键 Call *******************************00406810 /$ 8B51 04 MOV EDX,DWORD PTR DS:[ECX+4]00406813 |. 85D2 TEST EDX,EDX00406815 |. 74 30 JE SHORT unpacked.0040684700406817 |. 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]0040681B |> 85C0 /TEST EAX,EAX0040681D |. 7E 08 |JLE SHORT unpacked.004068270040681F |. 48 |DEC EAX00406820 |. 85D2 |TEST EDX,EDX00406822 |.^75 F7 \JNZ SHORT unpacked.0040681B00406824 |. C2 0800 RETN 800406827 |> 56 PUSH ESI00406828 |. 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+8]0040682C |. 33D2 XOR EDX,EDX0040682E |> 8A0432 /MOV AL,BYTE PTR DS:[EDX+ESI]00406831 |. 3C 30 |CMP AL,3000406833 |. 7C 04 |JL SHORT unpacked.00406839 ; [ 比 30 小就令 DS:[ECX+4]=0 ]00406835 |. 3C 39 |CMP AL,3900406837 |. 7E 07 |JLE SHORT unpacked.00406840 ; [ 比 39 大就令 DS:[ECX+4]=0 ]00406839 |> C741 04 000000>|MOV DWORD PTR DS:[ECX+4],000406840 |> 42 |INC EDX00406841 |. 83FA 06 |CMP EDX,600406844 |.^7C E8 \JL SHORT unpacked.0040682E00406846 |. 5E POP ESI00406847 \> C2 0800 RETN 8***********算法总结***************************************************************注册码由两段组成:第一段必须为数字,有六位;第二段有九位,由第一部分算得。第二部分九位的算法:( !注意:以下均指 ASCII码 )前三个字母: 1) ( 第一段第一个 + 第一段第四个 + 0Ah ) 除以 19h 的余数 + 41h 的和即为第二段第1个字母 2) ( 第一段第二个 + 第一段第五个 + 0Ah ) 除以 19h 的余数 + 41h 的和即为第二段第2个字母 3) ( 第一段第三个 + 第一段第六个 + 0Ah ) 除以 19h 的余数 + 41h 的和即为第二段第3个字母 中间三个字母: 4) ( 第一段第一个 - 第一段第四个 + 0Ah + 20h ) 除以 19h 的余数 + 41h 即为第二段第4个字母 5) ( 第一段第二个 - 第一段第五个 + 0Ah + 20h ) 除以 19h 的余数 + 41h 即为第二段第5个字母 6) ( 第一段第三个 - 第一段第六个 + 0Ah + 20h ) 除以 19h 的余数 + 41h 即为第二段第6个字母后三个字母: 7) ( 第一段第四个 + 0Ah 的和与第一段第一个异或 ) 除以 19h 的余数 + 41h 即为第二段第7个字母 8) ( 第一段第五个 + 0Ah 的和与第一段第二个异或 ) 除以 19h 的余数 + 41h 即为第二段第8个字母 9) ( 第一段第六个 + 0Ah 的和与第一段第三个异或 ) 除以 19h 的余数 + 41h 即为第二段第9个字母 |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|