CRACKING FOR NEWBIE Part 1: Introductions Quote: Requirement: Cracking theo Zombie thực chất cũng là một hình thức nghiên cứu Applipcation biến hóa đi nhằm mục đích có được license một cách không chính thức. Do đó các kiến thức lập trình là điều tối thiểu các bạn cần có tuy không quá nhất thiết phải biết nhiều ngôn ngữ hay phải nắm thật quá rõ Assembly như các bạn thường nói. Các chính là một số vốn kiến thức lập trình về một ngôn ngữ nào đó, phần Assembly có thể chỉ cần nắm sơ khái niệm cũng như bảng tra ý nghĩa một số lệnh thông dụng (còn mã máy thì có thể chẳng cần biết vì ta hoàn toàn có công cụ làm việc này) Ngoài ra các toolz Debuger, DeComplier v v. Zombie sẽ lần lượt giới thiệu và đưa link down. Khái niệm về việc Protect License của Softwarez A. Định nghĩa việc protect của softwarez: Quote: - Một Software sau khi được đưa vào mục đích thương mại thì luôn được xử lý nhằm tránh việc ăn cắp bản quyền ( license ) gây thiệt hại cho nhà sản xuất. Thế nhưng việc xử lý này được tiến hành như thế nào ? Nó là 1 module nhỏ trong nhằm xác định tính chủ quyền những ai đã mua Software. Có thể gọi nó là module Protect License. - Module này có rấ t nhiều hình thức biến hóa nhằm ngăn chặn đến mức tối đa việc xâm phạm bản quyền ( bao gồm việc sử dụng softwares ở mức độ không được sự đồng ý của nhà sản xuất, hoặc ăn cắp các giải thuật để code lại một Software khác cạnh tranh, v v) B. Loại Protect bằng Registration Number Registration−Number (Serial−Number) Protection: Đây là hình thức sử dụng phổ biến nhất. Chương trình sự dụng registration−number yêu cầu user nhập registration number để đăng kí. The registration number phụ thuộc vào các tiêu chuẩn riêng biệt theo sự sắp đặt của nhà sản xuất. Và trong chính bản thân loại protect này có nhiều hình thức phân loại như sau (ở đây tạm thời chỉ đưa ra một số dạng cơ bản thườ ng gặp nhất) Quote: + Registration number luôn luôn là một hằng số được lưu trữ sẵn: Cách đơn giản nhất là lưu sẵn trong app một giá trị cố định. Người dùng sau khi đăng kí với nhà sản xuất sẽ có được giá trị này để nhập vào. + Registration number thay đổi phụ thuộc thông tin đăng kí như (company, name, and so on): Cao hơn chút Với cách này ứng với từng user sẽ có thông tin Register khác nhau. + Registration number thay đổi lệ thuộc vào user's computer: Dạng này thì lấy thông tin đăng kí dựa vào thông tin Computer của customer để tạo ra Registration Number. Với dạng này App chỉ có thể được sử dụng như là Registered trên 1 máy duy nhất. + Registration number được check online: Thực chất cũng tương tự các dạng khác, nhưng sử dụng hình thức connect với server nhà sản xuất, từ đó sẽ có thông tin trả về nhằm register chương trình. Còn rất nhiều loại protect khác Nhưng tạm thời ta sẽ xoay quanh các loại chính này. - Oki Như đã nói trên, Softwares khi được phát hành sẽ có những module protect license. Vấn đề ở đây ! Làm sao có thể qua được những protect này, để có thể sử dụng chương trình như là đã registered ? Tuy nhiên muốn làm được như thế ta cần phải hiểu protect loại gì, và sự protect đó diễn ra như thế nào trong chương trình khi nó thực thi. Cách duy nhất là phải “đọc” diễn tiế n quá trình xử lý để rút ra cách chống lại chính nó. - Việc “đọc” quá trình protect, tất nhiên sẽ rất dễ dàng làm nếu như có trong tay source code chương trình >> Thực tế là không khả thi vì đâu ai cung cấp cho ta. Vậy ta phải “đọc” dưới dạng một ngôn ngữ khác Ngôn ngữ assembly. Một ngôn ngữ máy. ( vì một chương trình khi thực thi luôn được đưa về ngôn ngữ máy để tiến hành, ta sẽ “đọc” ở quá trình này). - Khi DeComplie (ASM) ta chỉ có thể đọc được source của nó dưới dạng mã máy hoặ c ngôn ngữ gần mã máy lê assembly. Nhưng cách lêm nêy khá bất lợi vì khi desource ta phải đọc chay source asm Mê điều nêy không phải dễ đề tìm ra module cần thiết (module protect). Với các bạn học về lẪp trình cũng sẽ biết khái niệm debug Nghĩa lê ta vẫn cứ cho ứng dụng chạy bình thường, nhưng trong một chế độ đặc biệt gọi lê Debug nhằm kiểm soát diễn tiến để có thể fix bugs >> Ứng dụng điều nêy vêo vi ệc tìm hiểu diễn tiến của phần mềm để tìm ra cách xỪ lý protect ! Và phục vụ cho các việc này ta có những công cụ như debugger, decomplier v v C. Think to Crack: Phần này sẽ giúp các bạn có cách nhìn cơ bản vào một softwares để định hướng Crack sẽ làm Quote: - Như đã nói qua, module Protect license có nhiều loại biến hóa khác nhau và ứng với mỗi cách ta có những hướng giải quyết khác nhau. Vì thế việc làm đầu tiên là xác định loại protect. - Sau đó là quá trình cách trace đến module protect license này. �*̉ phần này rất rất đa dạng, các bạn cần linh động thay đổi hướng giải quyết nhằm phù hợp với các trường hợp. Tuy nhiên một số cách làm chính như sau: + Tìm cách set Breakpoint từ các APIs thông dụng như GetWindowTextA, GetDlgItemTextA, SendMessages, MessageBoxA: Vì sao ta lại chọn những hàm APIs này? Cũng đơn giản thôi: Trong đa phần trường hợp nhập Registration Infor vào thì luôn có việc chương trình sẽ lấy thông tin ta nhập vào (GetWindowTextA, GetDlgItemTextA, SendMessages). Sau đó là trả về thông báo cho biết việc nhập vào Information trên là valid or not? (MessageBoxA, MeesageBeep). Với cách làm này là tốt nhất vì cho phép ta đến ngay được trước quá trình xử lý thông tin Registration (tức là trước khi module Protect license được gọi) + Hoặc cách khác đơn giản khác là từ String thông báo trả về (Example: “Your Serials No entered is not invalid”). Từ vị trí các string này ta cũng có thể lần được ngược về quá trình xử lý. Tuy nhiên đi ều này đôi lúc khá phức tạp. + Tương tự cách đầu tiên nhưng ta xử lý với các APIs khác như: RegQueryValue, RegOpenKeyExA, ReadFile v v để xứ lý với trường hợp dùng RegKey hoặc KeyFile. - Sau khi tìm ra được module Protect license điều cần quan tâm là ta trace into vào nó để xem đoạn code xử lý của nó và đưa ra cách Crack ( Keygen hoặc Patch ). Part 2: Crack Toolz OllyDBG v1.1 Final PEiD Part 3: About Assembly ?*̉ part này tạm thời Zombie cung cấp giúp các bạn một số lệnh , chỉ thị asm ở mức cơ nhằm tiện cho việc đọc asm sau này để Crack. Quote: MOV DTS, SRC: Chuyển giá trị từ toán hạng nguồn vào toán hạng đích PUSH SRC: Cất giá trị toán hạng nguồn vào đỉnh ngăn xếp PUSHF: Chuyển giá trị cờ vào đỉnh ngăn xếp POP DST: Chuyển giá trị từ đỉnh ngăn xếp vào toán hạng đích POPF: Chuyển giá trị từ đỉnh ngăn xếp vào cờ XCHG DST, SRC: Chuyển đổi giá trị giữa 2 toán hạng LEA REG, mem: Đưa địa chỉ Offset của toán hạng nguồn vào thanh ghi đích ADD DST, SRC: Cộng toán hạng nguồn và đích. Kết quả lưu ở toán hạng đích ADC DST, SRC: Tương tự và cộng thêm cờ CF INC DST: Tăng 1 cho toán hạng đích SUB / SBB / DEC: Tương tự cho phép trừ NEG DST: Bù 2 giá trị toán hạng đích. CMP DST, SRC: So sánh giá trị toán hạng đích và toán hạng nguồn. Tác động vào cờ, giá trị 2 toán hạng không thay đổi. MUL / IMUL DST , SRC: Phép nhân không / có dấu. Kết quả lưu ở toán hạng đích. DIV / IDIV DST , SRC: Tương tự cho phép chia. AX : Số nguyên, DX số dư. NOT DST: Đảo bit. AND DST , SRC: Phép và logic giữa toán hạng đích và nguồn. Kết quả trả về ở toán hạng đích. OR DST, SRC: Phép hoặc logic XOR DST, SRC: Exclusif OR ( Bit của kết quả bằng 1 nếu giá trị 2 bit được XOR khác nhau). TEST DST , SRC: So sánh nội dung 2 toán hạng qua phép toán AND. Kết quả tác động đến các cờ. SHL DST, CL: Dịch trái các bit toán hạng đích Count lần (Count = CL). Ý nghĩa tương đương DST = DST * 2^CL. SHR DST, CL: Tương tự là dịch phải và là phép chia 2^CL * Cách dịch bit bằng cách đưa bit bị dịch vào CF thay bit dồn lên là bit 0. SAL / SAR: tương tự 2 chỉ lệnh trên nhưng dành cho các số có dấu. ROL / ROR: Dịch bit nhưng bit bị dịch được bảo tồn bằng cách chuyển về đầ u bên kia phép dịch. RCL / RCR: Tương tự nhưng giá trị cở CF là giá trị sẽ được dùng để dồn vào đầu bên kia phép dịch. Jump Codition Quote: JA Jump If Above JAE Jump If Above or Equal JB Jump If Below JBE Jump If Below or Equal JC Jump If Carry JCXZ Jump if CX Register Zero JE Jump If Equal JG Jump If Greater JGE Jump If Greater or Equal JL Jump If Less JLE Jump If Less or Equal JMP Jump Unconditionally JNA Jump If Not Above JNAE Jump If Not Above or Equal JNB Jump If Not Below JNBE Jump If Not Below or Equal JNC Jump If No Carry JNE Jump If Not Equal JNG Jump If Not Greater JNGE Jump If Not Greater or Equal JNL Jump If Not Less JNLE Jump If Not Less or Equal JNO Jump If No Overflow JNP Jump If No Parity JNS Jump If No Sign JNZ Jump If Not Zero JO Jump If Overflow JP Jump If Parity JPE Jump If Parity Even JPO Jump If Parity Odd JS Jump If Sign JZ Jump If Zero Part 4: Programming Tất nhiên Zombie không thể viết hết hoàn toàn về programming vì như thế rất lan mang và bản thân Zombie cũng hông biết viết sao. ?*̉ đây chỉ là cách suy luận logic bình thường trong programming thôi. Zombie dùng ngôn ngữ Visual Basic 6 làm ngôn ngữ để hướng dẫn. Giải thuật: Hướng giải quyết một vấn đề hay hiểu theo ý đơn giản là các trình tự chi tiết để xử lý một công việc nào đó. Ví dụ: Lấy một bài toán giải phương trình bậc 2 thời phổ thông. Để giải bài toán này ta qua các bước sau: - Tính Delta (công thức tính Zombie quên gòi :D) - Xử lý 3 trường hợp Delta: + Delta < 0: Vô nghiệm + Delta = 0: Nghiệm kép >> Tính nghiệm kép là hình như là (-b + sqrt(Delta)) / 2*a + Delta > 0: 2 nghiệm phân biệt. >> -b + & -b – sqrt(Delta) / 2*a Khi lập trình cũng vậy Bạn vạch ra cho máy các hướng giải quyết cụ thể, tính toán trước các việc xảy ra nhằm có cách giải quyết Đó là bạn đang tìm giải thuật. Tuy nhiên ở đây nên rõ điều này Giải thuật có được là quá trình chi tiết cách xử lý vấn đề Còn sau đó t ừ giải thuật đó code lại để máy thực thi lại là chuyện khác. Ví dụ. Để xây dựng lại khái quát cách máy xử lý bài toán phương trình bậc 2 kia ta làm sau Nhập các thông số a,b,c cho phương trình. Delta = sqr(b) – 4 * a * c If Delta < 0 Then Msgbox(“Vô nghiệm”) Else ‘ Ngược lại Delta không nhỏ hơn 0 (tức > or =) If Delta = 0 Then Giải tính nghiệm kép Else ‘ Tức Delta không = 0. Giờ chỉ còn trường hợp là > 0 Giải tính 2 nghiệm phân biệt End If End If Cũng đơn giản đúng không ! Chỉ là bạn vi tính hóa các suy luận, các bước giải quyế t vấn đề thơi. Trong lập trình, các lệnh được tạo ra nhằm giải quyết hết mọi việc trong thực tế. Như If Then : Nếu <điều kiện> đúng (Then) thì làm If Then Else: Tương tự Nhưng nếu không đúng (Else) thì làm tiếp việc được chỉ ra cho phần Else Hay các khối lệnh lập For To Do: Lập từ giá trị a đến n Repeat Until: Lập đến khi thỏa điều kiện Tóm lại khi ứng d ụng vào việc Crack thì các khối lập & lệnh điều kiện là thường xuyên gặp như: Nếu Serials = 123456 thì Báo Ok Else (nếu không) Báo Sai API: Một số khái niệm về Windows APIs - APIs ( Applipcation Programming Interface ) với các newbie có thể xem đây như là các hàm được code sẵn, khi sử dụng chỉ việc khai báo và gọi lại ( có rất nhiều hàm vô cùng hữu ích trong các file dll của Windows không thể thiếu trong lập trình hệ thống ). - Các hàm thường được đóng gói vào file .dll cho. Khi sử dụng sẽ gọi hàm cần dùng từ file dll tương ứng chứa nó. - Điểm thuận tiện chính ở đây là khi sử dụng hàm API bạn có thể linh động trong việc upgrade chương trình. Nếu code luôn các hàm cần thiết vào chương trình chính thì khi upgrade và phát tán ra phải complie lại toàn bộ chương trình … Còn rất nhiều rất nhiều điểm mạnh nữa. Tuy nhiên khi sử dụng bạn phải có sẵn thông tin về việc khai báo hàm ( không phải lúc nào cũng sẵn có ). Khai báo APIs Khai báo các hàm APIs Để sử dụng được các hàm APIs cần phải làm: Khai báo hàm, gọi hàm. 1. Khai báo hàm: Cú pháp khai báo tổng quát: Quote: [Public | Private] Declare Sub | Function Name Lib “libname” [Alias “aliasname”] [(args)] [As Type] Quote: - Khai báo Public | Private tương ứng việc khai vùng hoạt động của hàm. Với Public hàm có thể gọi từ ngoài module khai báo nó ( trong cả chương trình ), ngược lại Private chỉ cho phép sử dụng trong module khai báo nó. Mặc định của Visual Basic khi không khai báo Public/Private là Public. Ở đây có thể sử dụng kĩ thuật “wrapper”. Với kĩ thuật này bạn khai báo hàm APIs trong module với Private. Sau đó code một hàm gọi nó rồi khai Public cho hàm này. - Declare Sub | Function: Tương ứng khai báo hàm này là Function or Sub. - Name: Tên của hàm sẽ được dùng để gọi. - Lib “libname”: Tên thư viện DLL chứa hàm cần gọi. - Alias: Tên hàm được export ra trong thư viện DLL. Lưu ý phải đúng chính xác tên hàm được export. - args: Các đối số của hàm. Đây cũng là phần quyết định quan trọng. Phải khai báo tuyệt đối chính xác (ByVal/ByRef, Data type,v v.). Trong trường hợp khai báo sai có khả năng làm crash Windows bằng lỗi GPF ( General Protect Fault ). - As Type: Kiểu giá trị trả về khi sử dụng hàm là Function Examples: ( Code by Visual Basic 6.0 ) 1. Hàm FindWindow: Trả về Handle của một Window khi biết một/cả hai đối số. Khai báo (code trong module mdlAPIs.mdl) Quote: Private Declare Function Lib “user32” Alias “FindWindowA” (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Quote: > Hàm khai báo với tên FindWindow được export từ thư viện user32.dll (với các thư viện dll chuẩn của Windows không cần khai FullName ) với tên FindWindowA. > Các đối số của hàm là lpClassName As String và lpWindowName. Cả hai đều là ByVal. > Trả về giá trị là kiểu Long. > Về việc sử dụng hàm: Có thể thấy ở đây hàm này nhận 2 args truyền vào. Tuy nhiên ở đây bạn có thể truyền vào giá trị 1 trong 2 hàm là đủ (có thể truyền luôn cả 2 nếu muốn). Các đối số ở đ ây là tên Class hoặc Caption của Windows cần lấy Handle Với arg không dùng đến thì đưa giá trị vbNullString hoặc 1 giá trị Null (lưu ý: Giá trị Null hiểu theo ngôn ngữ C, không phải là vbNull). Quote: Public Function wrpFindWindow (Optional ClsName As String = “”, Optional Caption As String = ”” ) As Long wrpFindWindow = FindWindow(ClsName, Caption) End Function Quote: > “Wrapp” lại bằng Function wrpFindWindow *****Có thể sử dụng API Viewer của Visual Basic 6.0 để lấy các Declare sẳn có và paste vào chương trình… Tuy nhiên như vậy bạn sẽ phụ thuộc vào API Viewer, trong khi không ít hàm hoàn toàn không có trong đây. Bạn chí được thông tin trong MSDN. Do đó cần biết cách tự khai báo. Để khai báo cần nắm rõ chút về cách định nghĩa khai báo theo kiểu Hungarian Quote: Sơ lược về định nghĩa Hungarian: ( Sử dụng nguyên văn tài liệu ) API mong đợi một trong hai điều ở các đối số của nó: Một giá trị hoặc địa chỉ của một biến chứa một giá trị. Chìa khóa để biết API mong đợi một giá trị hay một địa chỉ nằm ở định nghĩa Hungarian của tên thông số trong prototype của hàm liệt kê trong SDK. Nếu tên thông số có tiếp đầ u ngữ “lp”, có nghĩa là API mong đợi một địa chỉ. Trong định nghĩa C Hungarian, “lp” viết tắt cho một Long Pointer – Một địa chỉ bộ nhớ. Thường gặp nhất là “lpsz”, tức một con trỏ long đến một chuỗi kết thúc bằng Null ( một khai báo ByVal As String trong Visual Basic ), nhưng bạn cũng có thể đưa một “lp” cho API với tất cả các kiểu ( trừ một string ), dùng ByRef để gửi địa chỉ biến của bạn cho API. Trong thực tế bạn có thể sử dụng các chương trình khai báo sẵn APIs và chỉ việc copy & paste vào ch ương trình. Tuy nhiên nên biết sơ về cách khai báo. Một số APIs các bạn thường gặp trong quá trình Cracking là: Quote: Int GetWindowText(HWND hWnd, LPTSTR lpString, int nMaxCount); Quote: Hàm này nhận 3 đối số là: - Handle Control chứa nội dung cần Get - Biến đệm chứa nội dung sẽ được lấy và trả về - Max Chars sẽ lấy, nếu vượt quá số max này sẽ truncate đi Thường thì hàm này dùng với Alias GetWindowTextA Tương tự GetWindowText là GetDlgItemText (được sử dụng cho việc lấy Text từ control trong Dialog) Quote: UINT GetDlgItemText(HWND hDlg, int nIDDlgItem, LPTSTR lpString, int nMaxCount ); các APIs khác Quote: int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType ); BOOL MessageBeep(UINT uType ); Các khá hữu dụng để lần ra chỗ cần bp và từ đó trace ngược về Module Protect Zoombie (http://www.reaonline.net) . lý của nó và đưa ra cách Crack ( Keygen hoặc Patch ). Part 2: Crack Toolz OllyDBG v1 .1 Final PEiD Part 3: About Assembly ?*̉ part này tạm thời Zombie cung cấp giúp các bạn một số lệnh. CRACKING FOR NEWBIE Part 1: Introductions Quote: Requirement: Cracking theo Zombie thực chất cũng là một hình thức nghiên cứu. trị 1 trong 2 hàm là đủ (có thể truyền luôn cả 2 nếu muốn). Các đối số ở đ ây là tên Class hoặc Caption của Windows cần lấy Handle Với arg không dùng đến thì đưa giá trị vbNullString hoặc 1 giá