Dear CARCK knows whether the intensity of a software registration code algorithm is high, but if it is just a simple comparison of the input registration code after encryption, it is determined whether the user registers if the correct registration code is equal. Software is very easy to be blasting. No matter how software writers use the high-intensity algorithm, CARCKER does not need to care. The short modification of several bytes skip verification (called blasting) Let this judgment invalid. Therefore, it is necessary to solve this problem fundamentally, it is necessary to perform dynamic decryption of functional core code according to the input registration code to completely prevent blasting.
Because of the code written in the program language, after compiling into an executable file, it is ultimately a memory data in the machine, so we need to encrypt the memory data in the execution key core function, when the user enters the correct At the time of the registration code, this memory data is naturally correct. It can run correctly, and if it is wrong, this memory data will naturally be unforgettable, generally report error by the operating system and prohibit operation, even occasionally It is natural to operate nature, it is naturally not the original function. Therefore, we do not need to verify the registration code, just if the verification program is wrong, you know if the registration code is correct.
In the sample code below, the core function execution code is a string array, which is encrypted in advance, then compiled into the EXE, when it is necessary, dynamically decrypt it according to the input password, this code Can fundamentally prevent blasting.
Note: Because only examples, encryption algorithms are certainly defined, the value of each byte is 1, of course, if it is applied in actual application, it can be used to replace the high-intensity encryption algorithm in the like. Encryption The key code length does not have to be the same as the encrypted length.
As for the key code to convert into a machine code, you can refer to some SHELLCODE writing articles, which is more detailed for the introduction of the function addresses, because I mainly explain a way of thinking, the specific technical details are not more.
Sample code:
// by: Good people (QQ: 46163851)
#include "stdafx.h" #include
Using namespace std;
INT g_nnumber;
Void KernelProc (FarProc Flbaddr);
INT Main (int Argc, char * argv []) {
Cout << "Please enter your password:"; cin >> g_nnumber;
/ / A address to get the address of the loadLibrarya and getProcadDress, for the core code call // Because it is in your own process, the address is more convenient. If the external process is inserted with shellcode //, you have to get the address of kernel32.dll loaded by other methods. then get the addresses of these functions, there is not introduce too much HMODULE hHandle = LoadLibrary ( "Kernel32.dll"); FARPROC fLbAddr = GetProcAddress (hHandle, "LoadLibraryA"); FARPROC fGtAddr = GetProcAddress (hHandle, "GetProcAddress");
// Perform the core code KernelProc (FLBADDR, FGTADDR);
Return 0;}
Void KernelProc (FarProc Flbaddr, FarProc FGTADDR) {
Try {// Core Core Code After Encrypted Machine Code Char Szbuffer [200] = "/ X8E / X96 / XED / X00 / X00 / X00 / XC7 / X03 / X56 / XC7 / X43 / X02 / X74 / XC7 / X43 / X03 / X04 "" / x73 / xc7 / xc7 / x43 / x06 / x33 / xc7 / x43 / x07 / x2f / xc7 / x43 / x08 / x65 / xc7 / x43 / x09 "" / x6d / xc7 / x43 / x0a / x6d / xc7 / x43 / x0b / x01 / x53 / x00 / x56 / x09 / x8e / x96 / xc7 "" / x00 / x00 / xc7 "" / x03 / X4E / XC7 / X43 / X02 / X03 / X74 / XC7 / X43 / X04 / X74 / XC7 / X43 / X05 / X62 / XC7 / X43 "" / x06 / x68 / xc7 / x43 / x07 / X66 / XC7 / X43 / X08 / X09 / X70 / XC7 / X43 / X0A / X79 / XC7 / X43 "" / x0b / x42 / xc7 / x43 / x0c / x01 / x53 / x51 / x00 / x56 / x0d / x6b / x01 / x6b / x01 / x6b / x01 / x6b / x01 / x00 "" / xd1 / xc4 "; // core code decryption is reduced to the original machine code (encryption algorithm for each byte value 1, decrypt to each byte value -1) for (int i = 0; i <200; i ) {szbuffer [i] - = g_nnumber;
// Perform a core code __asm {lea edx, szbuffer call edx}
Cout << "Password is correct!" << endl; system ("pause");
/ * Core code function is roughly c code:
TypedEf int (* msgbox) (HWND, UINT); typedef hHandle (* loadLib) (LPCTSTR); typedef farproc (* getaddr) (HMODULE, LPCSTR);
FARPROC fLoadLibrary = (LoadLib) fLbAddr; FARPROC fGetProcAddress = (GetAddr) fGtAddr; HMODULE hHandle = fLoadLibrary ( "User32.dll"); FARPROC fMsgBox = (MsgBox) fGetProcAddress (hHandle, "MessageBoxA"); fMsgBox (NULL, NULL, NULL , NULL); // Note: There is no direct use of loadLibrary and getProcAddress functions, because the core code does not know this function address, // This address is different under various machines and system platforms, it is inconvenient to encode / / Then indirectly uses the incoming FLBADDR address and FGTADDR address call.
// Core Code Embrading Code: __ASM {Push Offset String "User32.dll" Call Flbaddr Push Offset String "MessageBoxa" Push Eax Call FGTADDR PUSH 0 Push 0 Push 0 Push 0 Call Eax}
* /}