这一年又要完了,本想弄个漂亮的GIF图片改改我在看雪上的头像,可是弄了半天也不太称心如意。结果就有个念头搞掉这个老外的东西
软件名称:GIF Movie Gear 4.0.1 (PEncrypt 3.1 Final -> junkcode加的壳)
工具: PEid,OllyDbg,ImportREC
破解过程:
0046D9AC > $ B8 00F04E00 MOV EAX,movgear.004EF000 <========程序加载后停在这里
0046D9B1 . FFD0 CALL EAX <========跟进去就可以了
0046D9B3 . 2C 47 SUB AL,47
0046D9B5 . 0068 B4 ADD BYTE PTR DS:[EAX-4C],CH
0046D9B8 . 1C 47 SBB AL,47
0046D9BA . 0064A1 00 ADD BYTE PTR DS:[ECX],AH
0046D9BE . 0000 ADD BYTE PTR DS:[EAX],AL
0046D9C0 . 0050 64 ADD BYTE PTR DS:[EAX+64],DL
不知道是不是猛壳,一直向下找,一不小心就看到了好东西。^0^
004EF27A E8 5F020000 CALL movgear.004EF4DE
004EF27F 8B56 75 MOV EDX,DWORD PTR DS:[ESI+75]
004EF282 8902 MOV DWORD PTR DS:[EDX],EAX
004EF284 58 POP EAX
004EF285 FF76 1C PUSH DWORD PTR DS:[ESI+1C]
004EF288 E8 B9010000 CALL movgear.004EF446
004EF28D 48 DEC EAX
004EF28E 2D 8D124000 SUB EAX,movgear.0040128D
004EF293 8D90 05104000 LEA EDX,DWORD PTR DS:[EAX+401005]
004EF299 56 PUSH ESI
004EF29A 57 PUSH EDI
004EF29B 51 PUSH ECX
004EF29C 8B7A 1C MOV EDI,DWORD PTR DS:[EDX+1C]
004EF29F 8D72 79 LEA ESI,DWORD PTR DS:[EDX+79]
004EF2A2 B9 08000000 MOV ECX,8
004EF2A7 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
004EF2A9 59 POP ECX
004EF2AA 5F POP EDI
004EF2AB 5E POP ESI
004EF2AC C3 RETN <========返回到46D9AC,也就是程序有壳时候的入口点
004EF2AD E8 94010000 CALL movgear.004EF446 所以,F8一次就可以到OEP了。然后把程序Dump
004EF2B2 C3 RETN 出来,用ImportREC修复一下就可以了。
004EF2B3 E8 8E010000 CALL movgear.004EF446
004EF2B8 48 DEC EAX
004EF2B9 2D B8124000 SUB EAX,movgear.004012B8
004EF2BE 8D80 05104000 LEA EAX,DWORD PTR DS:[EAX+401005]
0045B4EF |. 8D4C24 78 LEA ECX,DWORD PTR SS:[ESP+78] 用户名和注册码就放在这两个寄存器里
0045B4F3 |. 8D5424 14 LEA EDX,DWORD PTR SS:[ESP+14]
0045B4F7 |. 51 PUSH ECX
0045B4F8 |. 52 PUSH EDX
0045B4F9 |. E8 B2FEFFFF CALL new_.0045B3B0 <========所以看到这里就离成功不远了,戴上安全帽,钻进去吧
0045B3B0 /$ 53 PUSH EBX <========进来一看,整个函数很明显就是在验证序列号了。
0045B3B1 |. 55 PUSH EBP ^ ^准备工作
0045B3B2 |. 8B6C24 10 MOV EBP,DWORD PTR SS:[ESP+10]
0045B3B6 |. 56 PUSH ESI
0045B3B7 |. 57 PUSH EDI
0045B3B8 |. 807D 00 6D CMP BYTE PTR SS:[EBP],6D <========比较序列号的第一位是否为m
0045B3BC |. 0F85 A0000000 JNZ new_.0045B462
0045B3C2 |. 807D 01 67 CMP BYTE PTR SS:[EBP+1],67 <========比较序列号的第二位是否为g
0045B3C6 |. 0F85 96000000 JNZ new_.0045B462
0045B3CC |. 807D 02 33 CMP BYTE PTR SS:[EBP+2],33 <========比较序列号的第三位是否为3
0045B3D0 |. 0F85 8C000000 JNZ new_.0045B462
0045B3D6 |. 807D 03 37 CMP BYTE PTR SS:[EBP+3],37 <========比较序列号的第四位是否为7
0045B3DA |. 0F85 82000000 JNZ new_.0045B462
0045B3E0 |. BB E85E4800 MOV EBX,new_.00485EE8
0045B3E5 |> 8B13 /MOV EDX,DWORD PTR DS:[EBX] <========
0045B3E7 |. 83C9 FF |OR ECX,FFFFFFFF |
0045B3EA |. 8BFA |MOV EDI,EDX |
0045B3EC |. 33C0 |XOR EAX,EAX |
0045B3EE |. F2:AE |REPNE SCAS BYTE PTR ES:[EDI] |
0045B3F0 |. F7D1 |NOT ECX |
0045B3F2 |. 49 |DEC ECX |
0045B3F3 |. 8BFA |MOV EDI,EDX |这里比较输入的注册码是否和特定注册码相同
0045B3F5 |. 8BF5 |MOV ESI,EBP |要是相同了就挂了
0045B3F7 |. 33C0 |XOR EAX,EAX |
0045B3F9 |. F3:A6 |REPE CMPS BYTE PTR ES:[EDI],BYTE PTR DS> |
0045B3FB |. 74 65 |JE SHORT new_.0045B462 |
0045B3FD |. 83C3 04 |ADD EBX,4 |
0045B400 |. 81FB 685F4800 |CMP EBX,new_.00485F68 |
0045B406 |.^ 7C DD \JL SHORT new_.0045B3E5 <========
0045B408 |. 807D 04 73 CMP BYTE PTR SS:[EBP+4],73 <========看第5位是否为s,如果是就再验证后4位,不是就验证
0045B40C |. 75 01 JNZ SHORT new_.0045B40F 后5位。
0045B40E |. 45 INC EBP
0045B40F |> 83C5 07 ADD EBP,7
0045B412 |. 55 PUSH EBP
0045B413 |. E8 58230100 CALL new_.0046D770 <========跟进去看个究竟
0045B418 |. 8B5424 18 MOV EDX,DWORD PTR SS:[ESP+18] <========好,回到这里来,接下来就是最最最最……什么什么的地方了^^
0045B41C |. 83C4 04 ADD ESP,4
0045B41F |. 8BFA MOV EDI,EDX
0045B421 |. 33C9 XOR ECX,ECX
0045B423 |. 8A12 MOV DL,BYTE PTR DS:[EDX]
0045B425 |. BE DF0B0000 MOV ESI,0BDF
0045B42A |. 84D2 TEST DL,DL
0045B42C |. 74 26 JE SHORT new_.0045B454
0045B42E |> 0FBED2 /MOVSX EDX,DL <========
0045B431 |. 41 |INC ECX |这里的算法很简单,就是把用户名的每一个字母
0045B432 |. 0FAFD1 |IMUL EDX,ECX |取出来,然后第一个乘于1,第二个乘于2,
0045B435 |. 03F2 |ADD ESI,EDX |以此类推……
0045B437 |. 81FE BE170000 |CMP ESI,17BE |
0045B43D |. 7E 06 |JLE SHORT new_.0045B445 |
0045B43F |. 81EE BE170000 |SUB ESI,17BE |
0045B445 |> 83F9 0A |CMP ECX,0A |
0045B448 |. 7E 02 |JLE SHORT new_.0045B44C |
0045B44A |. 33C9 |XOR ECX,ECX |
0045B44C |> 8A57 01 |MOV DL,BYTE PTR DS:[EDI+1] |
0045B44F |. 47 |INC EDI |
0045B450 |. 84D2 |TEST DL,DL |直到把全部的字母处理完毕
0045B452 |.^ 75 DA \JNZ SHORT new_.0045B42E <========
0045B454 |> 3BF0 CMP ESI,EAX 比较经过处理后的用户名与序列号
0045B456 |. 75 0A JNZ SHORT new_.0045B462 至此以大功告成。
0045B458 |. 5F POP EDI
0045B459 |. 5E POP ESI
0045B45A |. 5D POP EBP
0045B45B |. B8 01000000 MOV EAX,1
0045B460 |. 5B POP EBX
0045B461 |. C3 RETN
0045B462 |> 5F POP EDI
0045B463 |. 5E POP ESI
0045B464 |. 5D POP EBP
0045B465 |. 33C0 XOR EAX,EAX
0045B467 |. 5B POP EBX
0045B468 \. C3 RETN
0046D770 /$ FF7424 04 PUSH DWORD PTR SS:[ESP+4]
0046D774 |. E8 6CFFFFFF CALL new_.0046D6E5 <========Once again
0046D779 |. 59 POP ECX 其实就是把第8位以后的字符串转换为16进制,然后返回
0046D77A \. C3 RETN 麻烦大家把鼠标滚轮向上推,看045B418之后的讲解。
总结一下:
初看这个软件是PEncrypt 3.1 Final -> junkcode加的壳,没见过。不过也不畏惧,用OD脱,原来是个纸老虎。接下来的调试,在注册码
验证的地方担搁了好长时间,后来看了返回值才恍然大悟。到了用户名验证的地方就很简单了,一目了然。最后做了个简单的cmd注册机。
int main()
{
int i=0,lisence=0;
char name[256];
scanf("%s",name);
system("cls");
while(name[i]!=0)
{
lisence+=name[i]*(++i);
}
printf(" ************\n");
printf("User Name: %s\n",name);
printf("lisence : mg37s610%d\n\n",lisence+3039);
printf(" Var:1.0 Mx\n");
getch();
return 0;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课