Download this section example (4.29 kB)
(Special Thanks to Compilation Master Dreamtheater made a lot of good optimization for my code! Please visit his home page) The last section we introduced the flower directive, but the flower directive was a very simple thing, basically in the door. Cracker can be dealt with. So, we must make your own software better protection. CRC check is a good method. What is the CRC? In fact, we should not be strange to it, recall it? Have you used compressed software such as RAR and ZIP? Do they often give you an annoying "CRC check error" information? I think you should understand, the CRC is the calculated value of block data, its full name is "cyclic redundancy check", the Chinese name is "cycle redundancy code", "CRC check" is "Cyclic Redundancy Check". (Wow, I really don't want everyone to be Tang Yan, huh, huh. ^ _ ^) CRC What is the use? Its application range is wide, the most common is to conduct information on network transmission. In fact, we can apply it to software protection because it is very very very strict. What exactly is it strict? Your procedure is only changed by a byte (even only the change in case), its value will be different from the original. Hoho, is it very powerful? So just give your "original" program to calculate the CRC value, save it in a place, then randomly in the program, the file is randomly check the file, followed by comparing the first generation and saving the CRC value, if If you are equal, you have not been modified / cracked. If you don't wait, then you are likely that your procedure has been infected by the virus, or it is broken by Cracker. After the words, let's first look at the principle of CRC. (Because the CRC has a certain difficulty, how to use it to protect the file, stay in the next section.) First see two styles: type 1: 9/3 = 3 (remainder = 0) TK: (9 2) / 3 = 3 (Yu = 2) We know in elementary school, the division operation is to repeatedly subtract the division X times, then leave the remainder.
Therefore, the above two forms can be calculated by binary: (what? You don't binary calculation? I poured ~~~) 1: 1001 -> 90011 - -> 3 --------- 0110 -> 60011 - -> 3 --------- 0011 -> 30011 - -> 3 --------- 0000 -> 0, the remainder has been reduced 3 times So the merchant is 3, and the result of the last reduction is 0, so the remainder is 0 types two: 1011 -> 110011 - -> 3 --------- 1000 -> 80011 - > 3 --------- 0101 -> 50011 - -> 3 --------- 0010 -> 2, the remainder has been reduced 3 times, so the merchant is 3, and finally The result of a minus is 2, so the remainder is 2 to understand? Very good, Let's go on! The rules of binary subtraction operations are that if you encounter 0-1, then you have to borrow from the high position, turn it out of (10 0) -1 = 1Crc operation? Let us look at the example: this time I use the child 30/9, but please read the reader to pay attention to the last remainder: 11110 -> 301001 - -> 9 --------- 1100 -> 12 (very Strange? Why isn't it 21?) 1001 - -> 9 -------- 101 -> 3, the remainder -> The CRC! Is the calculation process of this form? Is it very strange? It is not directly reduced, but in the way of xor (programmers should be familiar with xor), and finally get a remainder. Yeah, this is the CRC's operation method, understand? The essence of CRC is a XOR operation. We don't need to manage it because the operation process is meaningless to the last result; we really interested only the remainder of the final result, this remainder is the CRC value. Working with a CRC operation We need to select a division, this divisor we call it "poly", the width W is the highest bit, so the divisor of the example I just raised 9, this Poly 1001 W is 3, not 4 Note that the highest bit is always 1. (Don't ask why, this is the specified) If we want to calculate a bit string CRC code, we want to determine that every bit is handled, so we have to add W 0 bit behind the target bit string.
Now let us rewrite the above example according to the CRC specification: poly = 1001, width w = 3 bit string bitstring = 11110BITSTRING W ZEROES = 11110 000 = 11110000111100001001 |||| ---------- ---- 1100 ||| 1001 ||| - ------------ 1010 || 1001 || - ----------- 0110 | 0000 | -------- 1100 1001 - ---------- 101 -> 3, the remainder -> The CRC! There are two important statements as follows: 1, only when bitstring is the highest 1. We use it to make XOR operations with POLY, otherwise we just move bitstring to one bit. 2, the result of the XOR operation is to perform XOR operations by the low W bit of the active bit string bitString and Poly, because the highest bit is always 0. Oh, is there a little bit of faint feelings? If you don't understand, look at it again from your head, actually very well understood. (Is a XOR operation!) Good, principle introduction here, let me talk about how to program it. Due to the speed of the speed, the implementation of CRC is mainly through the investigation form, for CRC-16 and CRC-32, each has a ready-made table, you can introduce it directly into the program. (Because these two tables are too long, they are not listed here, please read them on the web, it is easy to find.) If we don't have this table? Or, like me, is too lazy to enter yourself? No need to worry, we can "do it yourself, full of food." You may say that it will be too slow to program to generate this table, will it be too slow? In fact, it is not necessary to worry, because we are calculated at the level of assembly code, and this table is only 256 double words in the area, and it will not affect the speed. The C language of this table is described as follows: for (i = 0; i <256; i ) {CRC = I; for (j = 0; j <8; j ) {if (CRC & 1) CRC = (CRC >> 1) ^ 0xedb88320; Else CRC >> = 1;} CRC32TBL [I] = CRC;} After generating a table, it can be calculated. Our algorithms are as follows: 1. Move the register to the right one byte. 2. The one-shifted one byte is performed with the new byte in our string to determine the index of the value table Table [0..255]. 3. Do XOR operations with the table value referred to by the index. 4. If the data is not complete, jump to step 1.
The C language of this algorithm is as follows: Temp = (OldCrc ^ Abyte) & 0x000000FF; CRC = ((OldCrC >> 8) & 0x00ffffff) ^ crc32tbl [Temp]; return crc; ok, all stuff is finished. Finally, a complete Win32ASM example, please read the reader carefully! (The compilation of the CRC-32 data is very small, I personally think that it is very valuable information below.
); ***************************************************************** **********************************************; Program Name : presentation CRC32 principle; author: Luo Cong; date: 2002-8-24; source: http: //laoluoc.yeah.net (Luo colorful world); Note: For reprint, please maintain the integrity of this program And indicate: Reprinted from "Lao Luo" (http://laoluoc.yeah.net) ;; Special Thank Win32ASM Master - Dreamtheater makes quite good optimization for my code! Please go to http://notexpad.yeah.net to download his compact "Cool Notepad" - NOTEXPAD! (100% Win32ASM) ;; *************************************************** *********************************************************** . *** 386.model flat, stdcalloption casemap: noneinclude windows.incinclude kernel32.incinclude user32.incincludelib kernel32.libincludelib user32.libWndProc proto: DWORD,: DWORD,: DWORD,: DWORDinit_crc32table protoarraycrc32 proto.constIDC_BUTTON_OPEN equ 3000IDC_EDIT_INPUT equ 3001.dataszDlgName DB "lc_dialog", 0sztitle DB "CRC DEMO BY LC", 0SzTemplate DB "string"% s "" CRC32 value is:% x ", 0Crc32TBL DD 256 DUP (0); CRC-32 TableSzBuffer DB 255 DUP ? 0) .data szText db 300 dup () codemain:?. invoke GetModuleHandle, NULL invoke DialogBoxParam, eax, offset szDlgName, 0, WndProc, 0 invoke ExitProcess, eaxWndProc proc uses ebx hWnd: HWND, uMsg: UINT, wParam: wPARAM , lParam: lparam .IF uMSG == WM_Close Invoke Enddialog, hwnd, 0 .elseif uMSG == WM_COMMAND MOV EAX, WPARAM MOV EDX, EAX SHR EDX, 16 MOVZX EAX, AX .IF EDX == BN_Clicked .IF EAX == Idcancel Invoke Enddialog, HWnd, Null .elseif EAX =
= IDC_BUTTON_OPEN || EAX == IDOK; ***************************************** *; Key code start: (Dangdang ...); ******************************************** *****; Naked the string of users: Invoke getdlgitemtext, hwnd, idc_edit_input, addr szbuffer, 255; initialization CRC32Table: Invoke init_crc32table; the following assignment to the register EBX for CRC32 conversion:; EBX is a string to be converted First address: Lea EBX, SZBuffer; Invoke ArrayCrC32; Format Output: Invoke WSPrintf, Addr Sztext, Addr Sztemplate, AddR Szbuffer, Eax; Ok, let us display results: Invoke MessageBox, hwnd, addr sztext, Addr sztitle, mb_ok .ndif.ndif .else Mov EAX, FALSE RETWNDPIF MOV EAX, TRUE RETWNDPROC ENDP; *********************************** ***********************; function function: generate CRC-32 table; ******** *********************************************************** Init_CRC32T Able Proc; if used in C language, it should be as follows:;;;; = 0; i <256; i ); {; CRC = i;; for (j = 0; j <8; j ); { IF (CRC & 1); CRC = (CRC >> 1) ^ 0xedb88320 ;; Else; CRC >> = 1;;}; CRC32TBL [I] = CRC;;} ;; huh, let us change the above statement Assembly: MOV ECX, 256;
Repeat for Every DWord in Table Mov Edx, 0edb88320H $ BIGLOOP: Lea Eax, [ECX-1] PUSH ECX MOV ECX, 8 $ SmallLoop: SHR Eax, 1 JNC @f xor eax, edx @@: DEC ECX JNE $ SmallLoop Pop Evx MOV [CRC32TBL ECX * 4-4], EAX DEC ECX JNE $ BIGLOOP RETIT_CRC32TABLE ENDP; ***************************************** ************************; function function: calculate CRC-32; ******** *********************************************************** **** ArrayCrc32 proc; calculates CRC-32, I use the entire string as an array, then assign the first address of this array to EBX, assign the length of the array to ECX, then loop the calculation, return value (Calved CRC-32 value) is stored in EAX:;;; parameter:; ebx = address of first byte; return value:; EAX = CRC-32 of the entire array; ebx =?; ECX = 0; edx = ? Mov EAX, -1; first initialization EAX or EBX, EBX JZ $ DONE; avoid empty pointer @@: Mov DL, [EBX] or DL, D l JE $ done; judgment whether the string scan is completed; here I use the check form method to calculate the CRC-32, so very fast:; because this is the assembly code, so you don't need to pass parameters to this process, just assign the OldCrc Give Eax, and assign the Byte to DL:;;;;;;; ;; ;; Parameter:; eax = OLD CRC-32; DL = a Byte; return value:; eax = new CRC-32; EDX =
X DL, Al Movzx EDX, DL SHR EAX, 8 XOR EAX, [CRC32TBL EDX * 4] Inc EBX JMP @ B $ DONE: NOT EAX RETARRAYC32 Endpend Main; ************* ************* OVER ******************************************** ****; by LC Here's how it .rc file: #include "resource.h" #define IDC_BUTTON_OPEN 3000 # define IDC_EDIT_INPUT 3001 # define IDC_STATIC -1LC_DIALOG DIALOGEX 10, 10, 195, 60STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENUCAPTION "LC's Assembly Framework" Font 9, "Song", 0, 0, 0x0Begin LText "Please enter a string (case sensitive):", IDC_STATIC, 11, 7, 130, 10 EditText IDC_EDit_input, 11, 20, 173, 12, ES_AUTOHSCROLL DEFPUSHBUTTON "CA & LC", IDC_Button_Open, 71, 39, 52, 15nd If you can fully understand this section, please pay attention to my next lecture, I will specifically describe how to use CRC-32 to your files protection. (Oh, good play in the back ...) (Source: http://laoluoc.yeah.net)