Posted by: moonbaby Jan 4 2004, 07:11 AM QUOTE Homepage : http://crackme.de CrackMe : vcrkme02.zip (vcrkme02.exe ) Coder : [v0!d] ( Microsoft Visual C++ 6.0 ) Type : Serial Packed : N / A Crack Tool : OllyDbg 1.09d Unpack Tool : N / A Request : Correct Serial Rule : N/A Note : N/A >>>>>>>> Đặt BreakPoint tại hai điểm sau : QUOTE 00401169 . FF15 A4404000 CALL DWORD PTR DS:[<&USER32.GetDlgItemTe>; \GetDlgItemTextA >>>>>>>> Trace tiếp ta đến đây : QUOTE Sau khi trace qua lệnh CALL trên thì chuỗi này sẽ được thay bằng chính chuỗi S nhập. 0040116F . 68 30504000 PUSH vcrkme02.00405030 ; ASCII "Enter your code here" 0040116F . 68 30504000 PUSH vcrkme02.00405030 ; ASCII "1234567890123456" Qua đoạn lệnh này ta nhận thấy đoạn mã này không bao gồm quá trình kiểm tra và xử lý là chỉ có quá trình so sánh giá trị trả về cho EAX, như vậy lệnh CALL sẽ bao hàm một qúa trình so sánh vào xử lý. Nếu đúng thì giá trị trả về sẽ là khác 0 và chuyển đến thông báo đúng. 00401174 . E8 87FEFFFF CALL vcrkme02.00401000 00401179 . 83C4 04 ADD ESP,4 0040117C . A3 A0564000 MOV DWORD PTR DS:[4056A0],EAX 00401181 . 85C0 TEST EAX,EAX < === So sánh EAX với 00h 00401183 . 74 37 JE SHORT vcrkme02.004011BC < === Nếu bằng 00h thì nhảy đến Nag sai >>>>>>>> Trace thẳng vào trong để xem xét quá trình mã hoá QUOTE 00401174 . E8 87FEFFFF CA LL vcrkme02.00401000 >>>>>>>> Sau khi trace vào trong lệnh CALL trên ta đến đây : QUOTE 00401000 /$ 53 PUSH EBX < === Ta đến đây. 00401001 |. 55 PUSH EBP 00401002 |. 8B6C24 0C MOV EBP,DWORD PTR SS:[ESP+C] < === S nhập lưu vào EBP 00401006 |. 56 PUSH ESI 00401007 |. 57 PUSH EDI 00401008 |. 8BFD MOV EDI,EBP 0040100A |. 83C9 FF OR ECX,FFFFFFFF 0040100D |. 33C0 XOR EAX,EAX 0040100F |. F2:AE REPNE SCAS BYTE PTR ES:[EDI] 00401011 |. F7D1 NOT ECX 00401013 |. 49 DEC ECX < === ECX sau lệnh này đúng là chiều dài chuỗi nhập 00401014 |. 83F9 10 CMP ECX,10 < === Kiểm tra chiều dài chuỗi nhập với 010h = 16 ký tự 00401017 |. 0F85 93000000 JNZ vcrkme02.004010B0 < === Nếu không bằng thì nhảy thoát. Sai 0040101D |. 8A5D 00 MOV BL,BYTE PTR SS:[EBP] < === BL lưu từng ký tự S nhập 00401020 |. 33F6 XOR ESI,ESI < === ESI = 00h 00401022 |. B2 30 MOV DL,30 < === DL = 030h 00401024 |> 84DB /TEST BL,BL < === so sánh BL với 00h. Kiểm tra xem đã hết chuỗi S chưa 00401026 |. 74 16 |JE SHORT vcrkme02.0040103E < === Nếu hết rồi thì nhảy 00401028 |. 8AC3 |MOV AL,BL < === AL = BL 0040102A |. 8BCD |MOV ECX,EBP < === ECX = EBP : lưu địa chỉ của chuỗi S nhập 0040102C |> 3AD0 |/CMP DL,AL < === Kiểm tra xem hai ký tự lưu ở đây giống nhau không 0040102E |. 75 01 ||JNZ SHORT vcrkme02.00401031 < === nếu bằng nhày đến so sánh. 00401030 |. 46 ||INC ESI < === Tăng biến ESI lên 1 00401031 |> 83FE 06 ||CMP ESI,6 < === So sánh với 06h 00401034 |. 7D 7A ||JGE SHORT vcrkme02.004010B0 < === Nếu lớn hơn thì nhảy NAG SAI. 00401036 |. 8A41 01 ||MOV AL,BYTE PTR DS:[ECX+1] < === AL chứ ký tự kế của S nhập 00401039 |. 41 ||INC ECX < == Biến đếm chuỗi tăng 1 0040103A |. 84C0 ||TEST AL,AL < === So sánh với 00h 0040103C |.^ 75 EE |\JNZ SHORT vcrkme02.0040102C < === Nếu chưa hết thì lập lại. 0040103E |> 33F6 |XOR ESI,ESI < === ESI = 00h 00401040 |. FEC2 |INC DL < === ký tự kế tiếp sẽ là 030h + 01h * n ( n là số lần lặp ) 00401042 |. 80FA 39 |CMP DL,39 < === So sánh với 039h 00401045 |.^ 7E DD \JLE SHORT vcrkme02.00401024 < === Nếu chưa bằng thì tiếp tục lặp. >>>> Thực chất của quá trình này có thể nói như sau : chuỗi S nhập nếu là toàn số thì không có gì xảy ra ( vì ESI sẽ không bao giờ đạt đến 06h ). Nếu bên trong chuỗi có những ký tự khác số thì giá trị của ESI sẽ tăng lên, nhưng ở đây CODER cho ta đến 6 ký tự khác số (CMP ESI,6 ). >>>>>>>> Giai đoạn kiểm tra chuỗi thứ nhất : QUOTE 00401047 |. 0FBE45 03 MOVSX EAX,BYTE PTR SS:[EBP+3] < === EAX lưu ký tự thứ 4 : T04 0040104B |. 0FBE4D 02 MOVSX ECX,BYTE PTR SS:[EBP+2] < === ECX lưu ký tự thứ 3 : T03 0040104F |. 0FBE55 01 MOVSX EDX,BYTE PTR SS:[EBP+1] < === EDX lưu ký tự thứ 2 : T02 00401053 |. 03C1 ADD EAX,ECX < === EAX = EAX + ECX 00401055 |. 0FBECB MOVSX ECX,BL < === ECX lưu ký tự thứ 1 : T01 00401058 |. 03C2 ADD EAX,EDX < === EAX = EAX + EDX >>>> EDX = EAX + ECX – 0Ch 0040105A |. 8D9408 40FFFF>LEA EDX,DWORD PTR DS:[EAX+ECX-C0] < ========= 00401061 |. 83FA 16 CMP EDX,16 < ==== So sánh giá trị này với 016h 00401064 |. 75 4A JNZ SHORT vcrkme02.004010B0 < === Nếu không bằng thì NAG SAI. >>>>>>>> Ở giai đoạn này ta nhận thấy có 4 ký tự được kiểm tra ( 4 ký tự đầu tiên ). Và giá trị của chúng phải là 016h. Từ đây ta suy ngược quá trình : EDX = EAX + ECX – 0C0h = 016h ==== >EAX + ECX = 016h + 0C0h = 0D6h EAX ( EAX + EDX ) + ECX ( lưu giá trị ký tự thứ nhất ) = 0D6h < == > EAX + T02 + T01 = 0D6h EAX ( EAX + ECX ) + T02 + T01 = T01 + T02 + T03 + T04 = 0D6h Giả sử T01 = T02 = T03 = T04 = T00 === > T00 = 0D6h / 4 = 035h Nhưng 035h * 4 = 0D4h === > phép chia trên có dư ( 02h ) ===== > Rất quan trọng để tính chuỗi. >>>> Vậy ta có rất nhiều giá trị thoả mãn được điều này. Giả sử ta có : 3838 >>>>>>>> Giai đoạn kiểm tra chuỗi thứ hai : QUOTE 00401066 |. 0FBE45 0D MOVSX EAX,BYTE PTR SS:[EBP+D] < = EAX lưu ký tự thứ 14 : T14 0040106A |. 0FBE4D 0A MOVSX ECX,BYTE PTR SS:[EBP+A] < = ECX lưu ký tự thứ 11 : T11 0040106E |. 0FBE55 07 MOVSX EDX,BYTE PTR SS:[EBP+7] < === EDX lưu ký tự thứ 8 : T08 00401072 |. 03C1 ADD EAX,ECX < === EAX = EAX + ECX 00401074 |. 0FBE4D 04 MOVSX ECX,BYTE PTR SS:[EBP+4] < === ECX lưu ký tự thứ 5 : T05 00401078 |. 03C2 ADD EAX,EDX < === EAX = EAX + EDX >>>> EDX = EAX+ECX-0C0h 0040107A |. 8D9408 40FFFF>LEA EDX,DWORD PTR DS:[EAX+ECX-C0] < ========= 00401081 |. 83FA 1E CMP EDX,1E < === So sánh EDX với 01Eh 00401084 |. 75 2A JNZ SHORT vcrkme02.004010B0 < === Nếu không bằng nhày đến SAI >>>> Tương tự như trên ta tính được : T05 + T08 + T11 + T14 = 0DEh === > Và giá trị trung bình là 037h, có dư cũng là 02h >>>> Vậy ta có rất nhiều giá trị thoả mãn được điều này. Giả sử ta có : 7878 >>>>>>>> Giai đoạn kiểm tra chuỗi thứ ba : QUOTE 00401086 |. 0FBE45 0F MOVSX EAX,BYTE PTR SS:[EBP+F] < = EAX lưu ký tự thứ 16 : T16 0040108A |. 0FBE4D 0C MOVSX ECX,BYTE PTR SS:[EBP+C] < = ECX lưu ký tự thứ 13 : T13 0040108E |. 0FBE55 09 MOVSX EDX,BYTE PTR SS:[EBP+9] < == EDX lưu ký tự thứ 10 : T10 00401092 |. 03C1 ADD EAX,ECX < ==== EAX = EAX + ECX 00401094 |. 0FBE4D 06 MOVSX ECX,BYTE PTR SS:[EBP+6] < == ECX lưu ký tự thứ 7 : T07 00401098 |. 03C2 ADD EAX,EDX >>>> EDX = EAX+ECX-0C0h 0040109A |. 8D9408 40FFFF>LEA EDX,DWORD PTR DS:[EAX+ECX-C0] < ====== 004010A1 |. 83FA 09 CMP EDX,9 < ==== So sánh EDX với 09h 004010A4 |. 75 0A JNZ SHORT vcrkme02.004010B0 < === Nếu không bằng nhảy đến SAI. >>>> Tương tự như trên ta tính được : T07 + T10 + T13 + T16 = 0C9h === > Và giá trị trung bình là 032h, có dư là 01h >>>> Vậy ta có rất nhiều giá trị thoả mãn được điều này. Giả sử ta có : 2223 >>>>>>>> Như vậy ta chỉ mới có được 4 * 3 = 12 ký tự, còn lại 4 ký tự. Đây là 4 ký tự tuỳ ý, ta có thể thêm bất kỳ số nào mà ta thích. >>>>>>>>>>>> Kết luận : QUOTE 1- Chuỗi S nhập phải có chiều dài 16 ký tự. 2- Chuỗi nhập được phép có 6 ký tự không phải là số. 3- Quá trình mã hoá chỉ diễn ra đối với 12 ký tự, còn 4 ký tự thì tuỳ ta nhập. Có thể là số hay chữ hay bất ký thứ gì. >>>>>>>>>>>> Vậy : QUOTE Serial : 38387A28B27C28D3 Serial : 3838722822722832 . khác 0 và chuyển đến thông báo đúng. 00 4 01 1 74 . E8 87FEFFFF CALL vcrkme02 .00 4 01 0 00 00 4 01 1 79 . 83C4 04 ADD ESP,4 00 4 01 1 7C . A3 A056 400 0 MOV DWORD PTR DS:[ 405 6A0],EAX 00 4 01 1 81 . 85C0 TEST. 00 4 01 0 14 |. 83F9 10 CMP ECX , 10 < === Kiểm tra chiều dài chuỗi nhập với 01 0 h = 16 ký tự 00 4 01 0 17 |. 0F85 9 300 000 0 JNZ vcrkme02 .00 4 01 0 B0 < === Nếu không bằng thì nhảy thoát. Sai 00 4 01 0 1D. 00 4 01 0 01 |. 55 PUSH EBP 00 4 01 0 02 |. 8B6C24 0C MOV EBP,DWORD PTR SS:[ESP+C] < === S nhập lưu vào EBP 00 4 01 0 06 |. 56 PUSH ESI 00 4 01 0 07 |. 57 PUSH EDI 00 4 01 0 08 |. 8BFD MOV EDI,EBP 00 4 01 0 0A