Posted by: moonbaby Dec 9 2003, 02:43 PM Homepage : http://crackme.de CrackMe : crackme2.zip ( crackme2.exe ) Coder : BadSector ( MASM32 / TASM32 ) Type : Enable button / Name / Serial Packed : N / A Crack Tool : OllyDbg 1.09d, ResHacker (or PE Explorer 1.93 ) Unpack Tool : N / A Request : Enable button / Correct Serial Rule : N/A Note : N/A >>>> Để enable nút “test” ta có thể dùng ResHacker (hay PE Explorer 1.93), bằng cách : >>>> Bước I : Dùng ResHacker mở file, trong mục Dialog chọn mục 100. Ta sẽ thấy xuất hiện : 100 DIALOG 0, 0, 243, 85 STYLE DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "CrackMe #2 by BadSector" LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL FONT 8, "MS Sans Serif" { CONTROL "", 200, EDIT, ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 20, 20, 150, 12 CONTROL "", 201, EDIT, ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 20, 49, 150, 12 CONTROL "Put your name here:", 0, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 20, 10, 71, 10 CONTROL "Serial:", 0, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 20, 39, 32, 10 CONTROL "Test", 300, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 185, 20, 40, 12 CONTROL "Info", 301, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 185, 35, 40, 12 CONTROL "Exit", 302, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 185, 50, 40, 12 } ta xoá dòng | WS_DISABLED đi, và lưu lại một file mới. Bây giờ nút “ Test “ đã được kích hoạt. Đối với chương trình này ta thấy có đặc biệt là hai điểu để Set BreakPoint lại nằm dưới thông báo. >>>> Bước II : Đặt BreakPoint ở hai điểm sau : 00401191 . E8 02010000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA 004011B7 . E8 DC000000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA >>>> Bước III : Đoạn chương trình kiểm tra chiều dài chuỗi U nhập vào 00401196 . 8BF0 MOV ESI,EAX 00401198 . 8975 FC MOV DWORD PTR SS:[EBP-4],ESI 0040119B . E8 48000000 CALL enable_c.004011E8 >> Trace vào trong lệnh CALL (hay di chuyển đến địa chỉ 004011E8) ta thấy : 004011E8 /$ 33C9 XOR ECX,ECX 004011EA |. 33D2 XOR EDX,EDX 004011EC |. 83F8 05 CMP EAX,5 < === so sánh chiều dài U nhập với 5 004011EF |. /72 2C JB SHORT enable_c.0040121D >> như vậy, U nhập vào phải có trên 5 ký tự. >> Kiểm tra chiều dài chuỗi S nhập vào 004011B7 . E8 DC000000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA 004011BC . 83F8 00 CMP EAX,0 < === Nếu không nhập sẽ xuất hiện thông báo sai 004011BF .^ 0F84 FDFEFFFF JE enable_c.004010C2 >>>> Bước IV : Quá trình kiểm tra S nhập vào. 004011CA . E8 4F000000 CALL enable_c.0040121E < === gọi đến một tập lệnh xử lý chuỗi. 004011CF . 81FE E00E0000 CMP ESI,0EE0 004011D5 .^ 0F85 E7FEFFFF JNZ enable_c.004010C2 >> Ta truy theo địa chỉ 0040121E thì thấy tập lệnh sau : 0040121E /$ 8B75 F4 MOV ESI,DWORD PTR SS:[EBP-C] 00401221 |. 03F6 ADD ESI,ESI 00401223 |. 6BF6 08 IMUL ESI,ESI,8 00401226 |. 83C6 0E ADD ESI,0E 00401229 |. C1E6 02 SHL ESI,2 0040122C |. 6BF6 04 IMUL ESI,ESI,4 >> Chiều dài của S được chứa ở ESI 0040121E /$ 8B75 F4 MOV ESI,DWORD PTR SS:[EBP-C] >> Tăng gấp đôi ESI lên, kết quả đựơc lưu ở ESI 00401221 |. 03F6 ADD ESI,ESI >> Nhấn ESI lên 8 lần và lưu kết quả ở ESI 00401223 |. 6BF6 08 IMUL ESI,ESI,8 >> Cộng ESI với Eh. 00401226 |. 83C6 0E ADD ESI,0E >> Shift Logical Left ESI 2 lần ( di chuyển logic ESI sang trái 2 lần ) 00401229 |. C1E6 02 SHL ESI,2 >> Nhân ESI lên 4 lần và lưu kết quả ở ESI 0040122C |. 6BF6 04 IMUL ESI,ESI,4 >> Kết quả sau khi trả về được so sánh với EE0h, 004011CF . 81FE E00E0000 CMP ESI,0EE0 004011D5 .^ 0F85 E7FEFFFF JNZ enable_c.004010C2 >> Như vậy ở đây ta sẽ truy ngược lại để tính xem chiều dài thật sự của chuỗi yêu cầu là bao nhiêu. Và ta tính ra được là Eh = 14. Vậy, chiều dài của chuỗi S phải đúng bằng 14 ký tự. >>>> Bước V : Sau đó lại đến một lệnh gọi xử lý khác, 004011DB . E8 50000000 CALL enable_c.00401230 >> trace vào trong lệnh này ta thấy : 00401230 /$ 33C9 XOR ECX,ECX 00401232 |. BA 0E000000 MOV EDX,0E 00401237 |> 0FBE81 BB2140>MOVSX EAX,BYTE PTR DS:[ECX+4021BB] 0040123E |. 83C0 0C ADD EAX,0C 00401241 |. 83F0 15 XOR EAX,15 00401244 |. 83E8 20 SUB EAX,20 00401247 |. 83F0 0C XOR EAX,0C 0040124A |. 8981 F3204000 MOV DWORD PTR DS:[ECX+4020F3],EAX 00401250 |. 41 INC ECX 00401251 |. 3BCA CMP ECX,EDX 00401253 |.^ 75 E2 JNZ SHORT enable_c.00401237 >> Gán cho EDX = 0Eh = 14 00401230 /$ 33C9 XOR ECX,ECX < ==== ECX = 0 00401232 |. BA 0E000000 MOV EDX,0E >> Do ECX = 0 nên từng ký tự của chuỗi lưu ở địa chỉ 4021BB sẽ được chuyển vào EAX, mà tại địa chỉ này lưu giá trị của S nhập vào. 00401237 |> /0FBE81 BB2140>MOVSX EAX,BYTE PTR DS:[ECX+4021BB] >> Cộng EAX với Ch = 12 0040123E |. 83C0 0C ADD EAX,0C >> XOR EAX với 15, lưu giá trị vào EAX 00401241 |. 83F0 15 XOR EAX,15 >> Trừ EAX cho 20 và lưu giá trị và EAX 00401244 |. 83E8 20 SUB EAX,20 >> XOR EAX với Ch = 12 một lần nữa, giá trị được cất vào EAX. 00401247 |. 83F0 0C XOR EAX,0C >> Chuyển giá trị của EAX vào địa chỉ 4020F3 ( do ECX = 0 ) 0040124A |. 8981 F3204000 MOV DWORD PTR DS:[ECX+4020F3],EAX >> Tăng ECX lên 1 hay ECX + 1, đây là biến đếm. 00401250 |. 41 INC ECX >> Quá trình trên cứ tiếp diễn cho đến hết chuỗi S nhập vào. >>>> Bước VI : Trace tiếp ta gặp lệnh. 004011E2 . E8 71000000 CALL enable_c.00401258 >> trace vào trong ta đi đến tập lệnh 00401258 $ 0FBE81 E82240>MOVSX EAX,BYTE PTR DS:[ECX+4022E8] 0040125F . 0FBE99 F32040>MOVSX EBX,BYTE PTR DS:[ECX+4020F3] 00401266 . 3BC3 CMP EAX,EBX 00401268 .^ 0F85 54FEFFFF JNZ enable_c.004010C2 >> Gọi từng ký tự của chuỗi S được lưu trong chương trình, lưu vào EAX 00401258 $ 0FBE81 E82240>MOVSX EAX,BYTE PTR DS:[ECX+4022E8] >> Gọi từ ký tự của chuỗi S nhập vào đã được mã hoá, lưu vào EBX 0040125F . 0FBE99 F32040>MOVSX EBX,BYTE PTR DS:[ECX+4020F3] >> So sánh hai ký tự đầu, nếu không bằng thì nhảy luôn ra thông báo sai. 00401266 . 3BC3 CMP EAX,EBX 00401268 .^ 0F85 54FEFFFF JNZ enable_c.004010C2 >>>> Ở đây ta nhận thấy, không có lệnh lặp, điều này có nghĩa là quá trình kiểm tra chỉ diễn ra đối với ký tự đầu tiên, còn các ký tự sau giống hay không, không quan trọng. >>>> Chính vì thế để tìm chính xác ký tự đầu tiên này là gì ta truy đến địa chỉ 4022E8, ở đây ta tìm thấy mã hex là 2F. Làm ngược lại Bước V ta tìm được ký tự đó là J. >>>> Vậy chương trình này có ba yêu cầu cần phải thoả : 1- U phải từ 5 ký tự trở lên 2- S phải có 14 ký tự 3- S phải bắt đầu bằng J Vậy : User : Moonbaby Serial : J2345678901234 . nhập vào. 00 4 01 1 CA . E8 4F 000 000 CALL enable_c .00 4 01 2 1E < === gọi đến một tập lệnh xử lý chuỗi. 00 4 01 1 CF . 81FE E00E 000 0 CMP ESI,0EE0 00 4 01 1 D5 .^ 0F85 E7FEFFFF JNZ enable_c .00 4 01 0 C2 >>. : 00 4 01 2 30 /$ 33C9 XOR ECX,ECX 00 4 01 2 32 |. BA 0E 000 000 MOV EDX,0E 00 4 01 2 37 |> 0FBE 81 BB 214 0& gt;MOVSX EAX,BYTE PTR DS:[ECX+ 402 1BB] 00 4 01 2 3E |. 83C0 0C ADD EAX,0C 00 4 01 2 41 |. 83F0 15 XOR. EAX ,15 00 4 01 2 44 |. 83E8 20 SUB EAX, 20 00 4 01 2 47 |. 83F0 0C XOR EAX,0C 00 4 01 2 4A |. 89 81 F3 204 000 MOV DWORD PTR DS:[ECX+ 402 0F3],EAX 00 4 01 2 50 |. 41 INC ECX 00 4 01 2 51 |. 3BCA CMP ECX,EDX 00 4 01 2 53