00351244 |> \8ACA |MOV CL, DL ; CL = DL (DL =
MagicString.IndexOf(fSerials.Char))
00351246 |.^ EB DE |JMP SHORT scrabb_1.00351226
Quote:
* Trong trường hợp bằng thì nhảy đến đây gán DL (Index kí tự trong
MagicString bên trên) vào CL.
Code:
00351228 |. 8A06 |MOV AL, BYTE PTR DS:[ESI] ; MOV AL,
TableString(Index).Char
0035122A |. 50 |PUSH EAX
0035122B |. E8 10FEFFFF |CALL scrabb_1.00351040 ; UCase
Quote:
* AL gán là Char đầu tiên trong TableString đang xử lý (Lưu ý TableString là
1 mảng gồm nhiều String. Nhưng trong Function này lần lượt xử lý trên từng
phần tử, hay cách khác là từng String trong mảng TableString). Sau đó
UCase Không có gì đáng nói
Code:
00351230 |. 0FBEC0 |MOVSX EAX, AL ; EAX,
TableString(Index).Char
00351233 |. 99 |CDQ
00351234 |. F7FD |IDIV EBP ; EAX = EAX \
MagicString.Length (20h)
* Nhớ EBP là gì không nhỉ. Nó là MagicString.Length. Ở đây sẽ lấy Char vừa
lấy trong MagicString chia EBP.
Code:
00351236 |. 0FBEC9 |MOVSX ECX, CL ; ECX = CL
MagicString.IndexOf(fSerials.Char)
00351239 |. 83C4 04 |ADD ESP, 4
0035123C |. 3BD1 |CMP EDX, ECX ; CMP EDX (EDX =
TableString(Index).Char MOD MagicString.Length), ECX (ECX = Index)
0035123E |. /75 1C |JNZ SHORT scrabb_1.0035125C ; DIE IF NOT
EQUAL
Quote:
* Khúc này để ý kĩ nha. EDX là phần dư phép chia trên. ECX là Index Char trong
MagicString. Nếu 2 số này không bằng nhau thì DIE.
End Function
Vậy là sao nhỉ
Function này tính toán và yêu cầu:
- Tính vị trí kí tự fSerials trong MagicString và trả về Index của nó trong
MagicString.
- Tính kí tự trong TableString(Index) MOD cho MagicString.Length.
- Số dư phép chia trên = Index else DIE.
Khá là khó chịu với cách xử lý này ! Tạm để đó hén .! Nếu bình thường mà gặp
kiểu này ta dễ nghĩ tới ý tưởng BruteForce lém.
Để có cách nhìn dễ hơn. Tạm để Game này đó đi.
Ta quay sang em Combo Chaos!
Lưu ý. Dạo này check lại một số Games trên GameHouse thấy nó có vẻ như đang
Updated lại các Games cũ sang một kiểu Encrypted Protect (Sẽ nói về em này sau
khi solved UnCrypted Protec). Nên Zom up lên Target Combo Chaos! để mọi
người dễ tham khảo.
Code:
2.74 MB
OK. Ta vô thẳng ngay quá trình xử lý bỏ qua các thứ "mở bài" cho được việc hén.
Code:
10001A60 |> /81F9 FF000000 /CMP ECX, 0FF
10001A66 |. |7D 36 |JGE SHORT COREGRAP.10001A9E
10001A68 |. |3C 61 |CMP AL, 61
10001A6A |. |7C 13 |JL SHORT COREGRAP.10001A7F
10001A6C |. |3C 7A |CMP AL, 7A
10001A6E |. |7F 0F |JG SHORT COREGRAP.10001A7F
10001A70 |. |0FBEF0 |MOVSX ESI, AL
10001A73 |. |8BF9 |MOV EDI, ECX
10001A75 |. |03FE |ADD EDI, ESI
10001A77 |. |8D6CAF E0 |LEA EBP, DWORD PTR DS:[EDI+EBP*4-20]
10001A7B |. |2C 20 |SUB AL, 20
10001A7D |. |EB 12 |JMP SHORT COREGRAP.10001A91
10001A7F |> |3C 41 |CMP AL, 41
10001A81 |. |7C 13 |JL SHORT COREGRAP.10001A96
10001A83 |. |3C 5A |CMP AL, 5A
10001A85 |. |7F 0F |JG SHORT COREGRAP.10001A96
10001A87 |. |0FBEF0 |MOVSX ESI, AL
10001A8A |. |8BF9 |MOV EDI, ECX
10001A8C |. |03FE |ADD EDI, ESI
10001A8E |. |8D2CAF |LEA EBP, DWORD PTR DS:[EDI+EBP*4]
10001A91 |> |88440C 18 |MOV BYTE PTR SS:[ESP+ECX+18], AL
10001A95 |. |41 |INC ECX
10001A96 |> |8A42 01 |MOV AL, BYTE PTR DS:[EDX+1]
10001A99 |. |42 |INC EDX
10001A9A |. |84C0 |TEST AL, AL
10001A9C |.^\75 C2 \JNZ SHORT COREGRAP.10001A60
10001A9E |> 81E5 FFFFFF7F AND EBP, 7FFFFFFF
10001AA4 |. 75 0F JNZ SHORT COREGRAP.10001AB5
Đoạn code này mọi người có nhớ nó không ! Chính là NameCalc2Number. Do
đó ta không cần code lại khúc này mà tận dụng lại Function cũ (Đặc điểm của
Bundled là tận dụng tối đa các điểm giống nhau giữa Protection các sản phẩm nhà
sx).
Zom lấy Name = True Evil Never Die
Khi này EBP = ED9B4E40 AND 7FFFFFFF = 6D9B4E40
Code:
10001AB5 |> \8B35 50B00010 MOV ESI, DWORD PTR DS:[1000B050] ;
ComboCha.0043E4F4
10001ABB |. C6440C 18 00 MOV BYTE PTR SS:[ESP+ECX+18], 0
10001AC0 |. 803E 00 CMP BYTE PTR DS:[ESI], 0
10001AC3 |. 74 2B JE SHORT COREGRAP.10001AF0
10001AC5 |. 8B3D 5C900010 MOV EDI, DWORD PTR
DS:[<&KERNEL32.lstrcm>; kernel32.lstrcmpiA
10001ACB |. EB 03 JMP SHORT COREGRAP.10001AD0
10001ACD | 8D49 00 LEA ECX, DWORD PTR DS:[ECX]
10001AD0 |> 56 /PUSH ESI
10001AD1 |. 8D4C24 1C |LEA ECX, DWORD PTR SS:[ESP+1C]
10001AD5 |. 51 |PUSH ECX
10001AD6 |. FFD7 |CALL NEAR EDI
10001AD8 |. 85C0 |TEST EAX, EAX
10001ADA |. 0F84 41010000 |JE COREGRAP.10001C21
10001AE0 |. 56 |PUSH ESI ; /String
10001AE1 |. FF15 58900010 |CALL NEAR DWORD PTR
DS:[<&KERNEL32.lstr>; \lstrlenA
10001AE7 |. 8D7406 01 |LEA ESI, DWORD PTR DS:[ESI+EAX+1]
10001AEB |. 803E 00 |CMP BYTE PTR DS:[ESI], 0
10001AEE |.^ 75 E0 \JNZ SHORT COREGRAP.10001AD0
Khúc code này đơn giản chỉ là kiểm tra Name với Black List. Nếu = thì xem như
teo (tương tự khi Check Online. Do đó các Games sau này / Games cũ được
Updated phần này loại bỏ đi vì không cần thiết một khi đã có Check Online,
Rite?).
Code:
10001AFD |. E8 9E140000 CALL COREGRAP.10002FA0
10001B02 |. 85C0 TEST EAX, EAX
10001B04 |. 0F84 2F010000 JE COREGRAP.10001C39
Gọi API check xem ta đang có tín hiệu Online không Nếu có thì sẽ
CheckOnline
Code:
0012E164 0012E250 ASCII
"://store.gamehouse.com/checkban.jsp?name=TRUEEVILNEVERDIE"
(uhm Version này bản thân đã bị Update lên Version mới rồi. Trước đây Zom
Crack thì link nó theo Format khác)
Mà thôi mấy khúc linh tinh này cho qua đi
Code:
10001C39 |> \8BC5 MOV EAX, EBP
10001C3B |. 99 CDQ
10001C3C |. F73D 40B00010 IDIV DWORD PTR DS:[1000B040]
Gán EBP vào EAX. Vì vậy EAX lúc này sẽ là kết quả trả về của Function
NameCalc2Number.
DS:[1000B040]: Giá trị này chính là số phần tử của Table (có ai nhớ tới em này
không hay wên gòi á :D).
OK. Vậy là chia NameCalc2Number \ TableString.Count
Code:
10001C42 |. 8B35 60B90010 MOV ESI, DWORD PTR DS:[1000B960] ;
ComboCha.0043E0A7
10001C48 |. 85D2 TEST EDX, EDX
10001C4A |. 7E 12 JLE SHORT COREGRAP.10001C5E
Gán vào ESI giá trị chuổi đầu tiên trong TableString.
EDX lúc này là số dư kết quả phép chia trên.
JLE xảy ra khi EDX <= 0. Để xem nào. Ở phép chia số dư không bao giờ là số âm
rite ? Như vậy chỉ còn trường hợp = 0.
Trường hợp Name của Zom không xảy ra Jump nên ta tiếp tục.
Code:
10001C4C |. 8BFA MOV EDI, EDX
Gán số dư vào EDI. (Trong trường hợp Zom thì như vậy EDI = 38h)
Code:
10001C50 |> /56 /PUSH ESI ; /String =
"ZVYSNKMHMY"