Crack: GIF Movie Gear 3.0.1 Type of protection: Time limit (30 day) + Name/#Serial Tools: SoftICE 3.x (I use 3.2 for win98) C compiler (I use Turbo C) Author: --{[CRK]}-- -+< Introduction: Hi ! I'm --{[CRK]}--, I know many of you have never heard from me but I'm here to help you to build a KeyGen today ! I've been written some tutorials along the last 2 years but I'm a lazy guy and didn't translate it (yet). Our target is very simple: GIF Movie Gear 3.0. Before trying to cr.. reverse this one I worked on 2.62 version and then realized that the "protection" scheme is the same ! although we need to change some constants ... I use *many* comments so even if you are not experiencied with ASM you will be able to understand the whole thing :o) -+< Preparing: Ok, let's stop the chat and mess around with this toy ! Fire up you SoftICE (Ctrl+D) and set a break for GetWindowTextA (BPX getwindowtexta). Fill in the fields with bogus data, it would be nice if you use the same name/code i used: name = CRK, code: mg370001234 (I prepared this code ;-) ). If you use a different code you won't take the nice jumps ! The program requires we start our reg code with 'mg37' otherwise it won't even check the entire password ! -+< Starting the fun stuff: Are you ready ? So click ok, SI breaks now, we are reading the name field, so press F5 and let SI break again now here (press F11) : Break due to BPX USER32!GetWindowTextA (ET=77.58 microseconds) USER32!GetWindowTextA :00431977 LEA EAX,[ESP+000000C4] <- EAX = fake code :0043197E LEA ECX,[ESP+60] <- ECX = name :00431982 PUSH EAX <- save name and code on the stack :00431983 PUSH ECX you should trace the next call with F8 ! :00431984 CALL 00431580 <- ** call serial calculation routine ** :00431989 ADD ESP,08 <- pop, pop ... :0043198C TEST EAX,EAX <- if EAX = 0 then: go away cracker :0043198E JZ 00431A41 <- we cannot take this bad jump. ... ... ... :00431A41 PUSH 30 :00431A43 PUSH 00009D15 :00431A48 PUSH 00009D14 :00431A4D PUSH ESI :00431A4E CALL 0040EE90 <- popup a MessageBox telling us we are not nice people :P :00431A53 ADD ESP,10 :bd * At the address 00431984h we have an important call to the offset 00431580. It was actually easy to find this point and now (if you traced with F8 like I warned) we land at the begining of the important piece of the code, breathe now cause we're going to dive a little deeper into this tokens, so trace along with F10: :00431580 PUSH EBX :00431581 PUSH EBP :00431582 MOV EBP,[ESP+10] <- copy code to EBP :00431586 PUSH ESI :00431587 PUSH EDI :00431588 CMP BYTE PTR [EBP+00],6D <- compare 1st letter in EBP with "m" :0043158C JNZ 00431632 :00431592 CMP BYTE PTR [EBP+01],67 <- compare 2nd letter in EBP with "g" :00431596 JNZ 00431632 :0043159C CMP BYTE PTR [EBP+02],33 <- compare 3rd letter in EBP with "3" :004315A0 JNZ 00431632 :004315A6 CMP BYTE PTR [EBP+03],37 <- compare 4th letter in EBP with "7" :004315AA JNZ 00431632 :004315B0 MOV EBX,0044D4C4 <- EBX = points to an interesting thing .... :004315B5 MOV EDX,[EBX] <- EBX now holds a strange code ... type F10 then and then D EBX to see this: :D EBX 016F:0044D4C4 6D 76 67 32 31 39 35 31-37 33 36 00 73 74 61 6D mvg21951736.stam 016F:0044D4D4 70 00 00 00 00 00 00 00-01 00 00 00 00 00 00 00 p............... at first I thought it's a hardcoded serial in the old version (2.6) this string is part of the code in a table with 24 kafe codes just like this ! ... :004315B7 OR ECX,-01 :004315BA MOV EDI,EDX :004315BC XOR EAX,EAX :004315BE REPNZ SCASB <- gets code length :004315C0 NOT ECX :004315C2 DEC ECX <- store code length in ECX :004315C3 MOV EDI,EDX <- EDI = "hardcoded" serial :004315C5 MOV ESI,EBP <- ESI = our fake serial :004315C7 XOR EAX,EAX <- EAX = 0 :P :004315C9 REPZ CMPSB <- compare the codes :004315CB JZ 00431632 <- if they're the same then jump :004315CD ADD EBX,04 <- EBX = 44D4C4 + 4 = 44D4C8 :004315D0 CMP EBX,0044D4C8 <- not important in this version :004315D6 JL 004315B5 <- we won't jump back here :004315D8 CMP BYTE PTR [EBP+04],73 <- compare the 5th char on our fake code and "s" :004315DC JNZ 004315DF <- no problem if you don't have an "s" ;-) :004315DF ADD EBP,07 <- our code now begins in the 8th char :004315E2 PUSH EBP <- save this piece of code if you type D EBP, and you used 'mg370002134' as fake code, you will se this: :D EBP 016F:006BF413 31 32 33 34 00 00 00 70-84 02 00 AA 3C 02 00 BF 1234...p....<... so the main target in the registration checking is the last 4 chars (in case you use 11 char long code like me) ... :004315E3 CALL 0043F3B8 <- check for "+" and "-", ... :004315E8 MOV EDX,[ESP+18] <- copy name to EDX :004315EC ADD ESP,04 :004315EF MOV EDI,EDX <- copy name to EDI :004315F1 XOR ECX,ECX <- ECX = 0 (ECX is used as a counter/index) :004315F3 MOV DL,[EDX] <- DL = stores a char from user name :004315F5 MOV ESI,00000BDF <- ESI = BDFh (=3039) :004315FA TEST DL,DL <- is the name empty ? :004315FC JZ 00431624 <- so jump (well ...) ------------------------------------------------------------------------------------- now we reach the main loop : ------------------------------------------------------------------------------------- :004315FE MOVSX EDX,DL :00431601 INC ECX <- ECX = ECX + 1 :00431602 IMUL EDX,ECX <- EDX = EDX * ECX :00431605 ADD ESI,EDX <- ESI = ESI + EDX :00431607 CMP ESI,000017BE <- is ESI greater than 17BEh ? :0043160D JLE 00431615 <- if so then substract 17BEh from ESI :00431614 SUB ESI,000017BE :00431615 CMP ECX,0A <- ECX is greater than 10 ? :00431618 JLE 0043161C <- if so then ECX = 0; :00431619 XOR ECX,ECX :0043161C MOV DL,[EDI+01] <- get next char from the user name :0043161F INC EDI <- update the name pointer :00431620 TEST DL,DL <- are we thru with this task ? :00431622 JNZ 004315FE <- if not then keep looping ------------------------------------------------------------------------------------- :00431624 CMP ESI,EAX <- compare fake and real codes :00431626 JNZ 00431632 <- jump if they aren't equal ... :00431632 POP EDI :00431633 POP ESI :00431634 POP EBP :00431635 XOR EAX,EAX <- this makes EAX = 0 therefore we are not reg'ed :00431637 POP EBX :00431638 RET -+< Coding the KeyGen: Thats all guys ! I put many comments so you can figure out exactally what's happening inside the program routine. And It's quite a simple check, isn't it ? I know you all are wise enough to build a keygen by yourselves , and I think it would be nice try to do it by yourself as a "challenge". Anyway, as usual, I'll give the code in C: ------------------------------------------------------------------------------------- #include /* header file for printf() / gets()*/ #define N 25 /* define a maximum length for name field */ void main() { char name[N]; int x, i=0, j=1; /* shows a banner */ printf("\n **********************************************"); printf("\n * *"); printf("\n * Gif Movie Gear 3.01 KeyGen by --{[CRK]}-- *"); printf("\n * webSite: www.thereverser.cjb.net *"); printf("\n * e+Mail: infinitecrk@yahoo.com *"); printf("\n * *"); printf("\n **********************************************"); printf("\n\n Type your name (no extended chars): "); gets(name); /* calcs serial */ x = 0xBDF; while (name[i] && i0x17BE) x -= 0x17BE; if (j>10) j=0; ++i; ++j; } /* shows the result */ printf("\n Your code: mg37000%d\n", x); /* shows a stupid message */ printf("\n Go reg it !\tCracking will never stop."); return; } ------------------------------------------------------------------------------------- It could be made in several ways but I did choose the simplest way (I know it would be even simpler just "copying" the ASM code and compile it with TASM). Someone told me when a newbie do a KeyGen he isn't a newbie anymore, he gets some higher "position", it's my 3th KeyGen but I can not agree ... we *always* learn more and more and that is the reason many reversers writes tutorials like this. My message: Share you knowledge ! (Even though your English sux like mine ;-] ) Greetings: +Fravia hp, +ORC tips, Indian_Trail (great paper 'bout Winrar95 scheme !), C4N (everyone had a starting point!), Lazzarus (some PE/unpacking tricks), every good reverser I forgot ;-) webSite: www.thereverser.cjb.net , eMail: infinitecrk@yahoo.com