hiện … restart lại Crackme lun và suy nghĩ ngay theo hướng khác và đây chính là sai lầm đầu tiên trong việc giải quyết crackme này.. Oki, restart lại Crackme Ctrl + F2 và bắt đầu “ngó ng
Trang 10040106A | 803B 00 |CMP BYTE PTR DS:[EBX],0 ; <== If EBX trỏ tới NULL of szName
0040106D | 75 06 |JNZ SHORT SV_Keyge.00401075; <== Else tăng EDI 0040106F | 8D1D 68344000 |LEA EBX,DWORD PTR DS:[403468] ;<== Then EBX szName
00401075 |> 47 |INC EDI ; <== Tăng ô nhớ lên 1 từ địa chỉ
00403268
00401076 |> \803E 00 CMP BYTE PTR DS:[ESI],0 ; <== If ESI trỏ tới NULL of szCode
00401079 |.^ 75 D1 \JNZ SHORT SV_Keyge.0040104C ; <== Then End Looping
Sau khi kết thúc vòng lặp nhìn xuống cửa sổ dump :
Chúng ta đã có 8 bytes giá trị trong đó : 5F 51 24 1B DD 77 46 35 Hiển nhiên rùi
vì Length(szCode) = 16, mà ta lấy 2 kí tự 1 trong szCode chuyển qua Hex number rồi đem XOR với từng kí tự trong szName Sau khi RETN :
00401265 8D3D 68324000 LEA EDI,DWORD PTR DS:[403268]
0040126B FFD7 CALL EDI ; <== Trace into
Gì vậy ta, thật là đặc biệt Sao đặc biệt ? Chương trình nạp địa chỉ 403268 vào EDI (EDI = 403268) Sau đó nó lại CALL EDI Có nghĩa là CALL 403268, cũng có
nghĩa là nó sẽ “thực thi” những lệnh mà chương trình vừa mới “tạo ra” qua đoạn
code trên Trace into vào hàm CALL EDI :
Những byte vừa được write vào các ô nhớ từ địa chỉ 00403268 giờ trở thành
Opcode thực thi lệnh Hay tuyệt Nếu trace tiếp chắc chắn chúng ta sẽ gặp
Exception Và lần đầu khi trace crackme này, ngay khi gặp exception Merc thực
Trang 2hiện … restart lại Crackme lun và suy nghĩ ngay theo hướng khác (và đây chính là
sai lầm đầu tiên trong việc giải quyết crackme này)
Oki, restart lại Crackme (Ctrl + F2) và bắt đầu “ngó nghiêng” xung quanh :D Coi
xem nào Các bạn có thấy ngay dưới địa chỉ 0040126B là đoạn code :
0040126D 6A 00 PUSH 0 ; /Style =
MB_OK|MB_APPLMODAL
0040126F 68 3B304000 PUSH SV_Keyge.0040303B ; |Title =
"Then ?"
00401274 68 1C304000 PUSH SV_Keyge.0040301C ; |Text = "Try
again"
00401279 6A 00 PUSH 0 ; |hOwner = NULL
0040127B E8 E6000000 CALL <JMP.&user32.MessageBoxA> ;
\MessageBoxA
Ặc ặc, nhìn là biết đây là code gọi NAG đây mà Như vậy sau khi kết thúc lệnh
CALL EDI tại địa chỉ 0040126B chương trình sẽ thực thi ngay đoạn code gọi
NAG :| (và đây là là sai lầm thứ 2 trong suy nghĩ của Merc) Sao kì vậy Vậy đâu là
Goodboy cho ta đây Chúng ta hãy cùng định khối lại vùng code này ha :
Hai khối mầu đỏ là hai khối liên quan tới NAG Khối màu vàng là khối mà tại đây
ta hi vọng là tìm được Goodboy (vì chả còn thấy chỗ nào khả nghi nữa cả :D)
Trang 3Giờ phân tích sai lầm thứ 1 :| Khi nãy bị exception, Merc bye bye nó luôn, nhưng không nghĩ là sau khi Crackme bypass exception thì tự khắc nó sẽ nhảy tới vùng code này :
00401282 8D3D 68324000 LEA EDI,DWORD PTR DS:[403268] ; <== EDI trỏ tới 403268
00401288 83C7 04 ADD EDI,4 ; <== EDI trỏ tới 4 bytes cuối trong 8 bytes
0040128B 8B07 MOV EAX,DWORD PTR DS:[EDI] ; <== EAX = giá trị
4 bytes cuối (theo reverse order)
0040128D 3B05 90364000 CMP EAX,DWORD PTR DS:[403690] ; <== Compare EAX và [403690]
00401293 /75 1C JNZ SHORT SV_Keyge.004012B1 ; <== Jmp to NAG nếu không bằng
Vì vậy lúc đầu khi Merc trace vào hàm CALL EDI tại 00403268, Merc ép sao cho
opcode tại đó thực hiện CALL 00401282 or JMP 00401282 (đại loại tương tự
như vậy để nó tự nhảy tới vùng code này ấy mà) Hmm, nhưng nhảy tới đây thì nó phải thực hiện quá trình check 4 byte cuối, bị so sánh với DWORD tại địa chỉ
403690 Giá trị Init ở ô nhớ tại địa chỉ này là 00FFFFFF :
00401218 C705 90364000 F>MOV DWORD PTR DS:[403690],0FFFFFF
Một cách logic, hiển nhiên Merc sẽ restart lại Crackme, nhập szCode sao cho khi XOR với szName được 4 bytes cuối là FFFFFF00 (chú ý là lúc chuyển vào EAX,
nó sẽ được gán theo qui tắc đảo ngược lại) Chúng ta có mỗi 8 bytes, giờ 4 bytes
cuối đã như thế này thì làm seo mà thực hiện được CALL 00401282 hay JMP
00401282 Phá sản ý tưởng điên rồ ha
Giá mà chiều dài chuỗi szCode nó tăng lên 2 kí tự nữa thì thôi rồi … crackme này
vô nghĩa hết sức :D
Ê, nhớ lại cái NAG ở đầu coi, mình nhập cũng như thế sao trong Olly bị exception
và ngoài này nó vẫn bắn NAG Cũng tại suy nghĩ bị exception là chương trình sẽ bị ngắt lun nên mình mới sai lầm, sai lầm cơ bản Now, restart lại crackme, nhập lại vẫn các thông sô szName, szCode như trên Lần này ta trace trong vùng
exception xem sao :
00403268 5F POP EDI
00403269 51 PUSH ECX
Trang 40040326A 24 1B AND AL,1B
0040326C DD77 46 FSAVE (108-BYTE) PTR DS:[EDI+46] ;
<== Exception
0040326F 35 00000000 XOR EAX,0
7C90EAF0 8B1C24 MOV EBX,DWORD PTR SS:[ESP]
7C90EAF3 51 PUSH ECX
7C90EAF4 53 PUSH EBX
7C90EAF5 E8 C78C0200 CALL ntdll.7C9377C1
7C90EAFA 0AC0 OR AL,AL
7C90EAFC 74 0C JE SHORT ntdll.7C90EB0A
7C90EAFE 5B POP EBX
7C90EAFF 59 POP ECX
7C90EB00 6A 00 PUSH 0
7C90EB02 51 PUSH ECX
7C90EB03 E8 11EBFFFF CALL ntdll.ZwContinue ;
<== Trace into
Tại 7C90EB03 mà nhấn F8 là em nó gọi NAG lun ra à nha Vì vậy nhấn F7
7C90D619 Zw> B8 20000000 MOV EAX,20
7C90D61E BA 0003FE7F MOV EDX,7FFE0300
7C90D623 FF12 CALL DWORD PTR DS:[EDX] ;
<== Trace into
7C90D625 C2 0800 RET 8
7C90EB8B Ki> 8BD4 MOV EDX,ESP
7C90EB8D 0F34 SYSENTER
Nhấn tiếp F8 hai phát nữa - ẹc tới đây luôn mới sợ :| :
00401288 83C7 04 ADD EDI,4
0040128B 8B07 MOV EAX,DWORD PTR DS:[EDI] ; <==
EAX = 354677DD
0040128D 3B05 90364000 CMP EAX,DWORD PTR DS:[403690] ; <==
[403690] = C0000005
00401293 75 1C JNZ SHORT SV_Keyge.004012B1
Các giá trị của EAX và [403690] là đang xét trong trường hợp szName = “Merc”
và szCode = “1234567890123456” nha Hê, tự dưng giờ em [403690] change giá
Trang 5trị gòi kìa Cứ tưởng nó mặc định là 00FFFFFF Tí tìm hiểu nó lấy giá trị đó ở đâu
sau ha Khi đến địa chỉ 00401293 ta change cờ Z thành 1 để không bị nhảy tới
NAG, tiếp tục trace into vào hàm CALL :
00401295 E8 60000000 CALL SV_Keyge.004012FA ;
<== Important
Trace into :
004012FA /$ 33D2 XOR EDX,EDX
004012FC | 33C9 XOR ECX,ECX ; <== ECX = 0
004012FE |> 02D0 /ADD DL,AL ; <== DL = DL + AL
00401300 | 41 |INC ECX ; <== ECX = ECX + 1
00401301 | C1C8 08 |ROR EAX,8
00401304 | 83F9 04 |CMP ECX,4 ; <== If ECX < 4 Then Loop
00401307 |.^ 75 F5 \JNZ SHORT SV_Keyge.004012FE
00401309 | 80FA 54 CMP DL,54 ; <== If DL = 0x54 Then Continue Check
Đoạn code này tính giá trị DL = tổng của 4 byte cuối (thông qua lệnh ROR
EAX,8) If DL = 0x54 thì tiếp tục check típ Tất nhiên là tới địa chỉ 00401307 ta lại
change cờ Z từ 0 thành 1 để đi tiếp xem sao :
0040130E | 8D3D 46304000 LEA EDI,DWORD PTR DS:[403046] ; <== EDI = 403046
00401314 | 33DB XOR EBX,EBX ; <== EBX
= 0
00401316 |> 3107 /XOR DWORD PTR DS:[EDI],EAX ; <==
XOR
00401318 | 83C7 04 |ADD EDI,4 ; <== EDI = EDI + 4
0040131B | 43 |INC EBX
0040131C | 83FB 07 |CMP EBX,7
0040131F |.^ 75 F5 \JNZ SHORT SV_Keyge.00401316 ; <==
LOOPING
Vòng lặp code này đem XOR 1 Table mặc định với giá trị EAX (vẫn là 4 bytes
cuối của Table 8 bytes) Sau khi kết thúc vòng lặp xong :
Trang 600401321 | 8D3D 46304000 LEA EDI,DWORD PTR DS:[403046] ; <== EDI = 403046
00401327 | FFD7 CALL EDI
Chẹp, đoạn này giống đoạn CALL EDI lúc trước quá Trace into vào trong :
Các opcode vẫn đang trong trường hợp của Merc nha Vậy thì đây roài, ta phải làm sao để khi XOR EAX (4 bytes cuối) với Table tại địa chỉ 403046 thì được các opcode dạng thế này :
6A 00
68 ?? ?? 40 00 <== Push Title
68 ?? ?? 40 00 <== Push Text : Phải là GoodBoy
6A 00 <== Push hwnd
E8 0D E3 FF FF <== Call MessageBoxA