The
company developed a relatively dedicated web system based on a customer, and later talked about how the system prevents copying and building on top of it. Looking for a long time on the internet, most of them are talking code confusing, There are few places to go to prevent copying. Combined with the online common practice, add something to yourself, it becomes a relatively simple way to prevent copying. The
method applies only to simple small systems where security requirements are high. And the code obfuscation part is not taken into account, which prevents non-technical operation of the system by non technical personnel. (only to prevent ordinary users)
1, database
now basically puts the username and password in the configuration file, so it's not practical to put the connection data in the program. So consider in the code for the data connection, The actual data is obtained by another operation (decryption) of the read data. The following illustration shows: XML code <driver-properties> <property name= "Decrypt" value= "true" /> <property name= "user" value= "root" /> <property name= "Password value=" 4akslkslksiwx3fr24sef /> </driver-properties>
<driver-properties>
<property name= "Decrypt" value= "true"/> <property name=
"user" value= Root "/>
<property name=" Password value= "4akslkslksiwx3fr24sef"/>
</driver-properties>
For simplicity, only the password is processed. The actual password is 123456, and the generated password is based on the
The password in the configuration file, that is, the password after the encryption, the original password is (123456).
The decrypt in the configuration file, that is, whether the decrypted configuration, when the value is true, is expressed as requiring decryption. When false, it is represented as not decrypted.
At the time of development, the decrypt is set to false and developed in plaintext password, and the corresponding configuration file is overwritten after the password is encrypted for actual deployment. To achieve the purpose of database connection encryption.
The reference code is as follows: Java code String x = Properties.getproperty ("Decrypt");if(x!=NULL&& x.equals ("true")) {String password = properties.getproperty ("password");if(Password!=NULL&& password.length () > 0) {String passwordtemp =NewString (Singlecipher.getdefaultcipher (). Decrypt (Singlecipher.hex2byte (password)); Properties.remove ("Decrypt"); Properties.setproperty ("password", passwordtemp); }
String x = Properties.getproperty ("Decrypt");
if (x!= null && x.equals ("true")) {
String password = properties.getproperty ("password");
if (password!= null && password.length () > 0) {
String passwordtemp = new String (SINGLECIPHER.GETDEFAULTCI Pher (). Decrypt (Singlecipher.hex2byte (password));
Properties.remove ("Decrypt");
Properties.setproperty ("password", passwordtemp);
}
2, program
Here the main discussion is in the system running, when loading the class file to decrypt the file to reload the situation.
Since we are using Tomcat, we consider the classloader of Tomcat, which is divided into two parts according to the needs of the system. For the advanced line decryption (forced decryption) that needs to be decrypted and loaded without the need for direct parsing. The specific methods are as follows:
Files that need to be encrypted are placed in a list in a configurable configuration file, such as the Encrypt.properties file.
Encrypt the files that need to be encrypted and deploy them to the user system.
Tomcat runs the system, runs load class binaries, reads configuration files, decrypts files that need to be decrypted, and then loads files.
The reference code is as follows:
Encrypt.properties content:
Java code COM. Xx.action.a. class com. xx.service.b. class
Com. Xx.action.a.class
com. Xx.service.b.class
To parse the restore data
Java Code if(encryptfilelist.contains (name)) {//binarycontent is a file binary data read by the tomcat loader binarycontent = Single Cipher.getdefaultcipher (). Decrypt (binarycontent); }
if (encryptfilelist.contains (name)) {
//binarycontent is a file binary data read by the tomcat loader
binarycontent = Singlecipher.getdefaultcipher (). Decrypt (binarycontent);
In this way, the system will need to be modified by Tomcat to run, so when the user just copies the system, because the new tomcat can not directly resolve the encrypted class file, and can not start running. To prevent copying.
3, machine binding
The main method is to read the machine's internal signature (currently mainly considering the MAC address), to perform a series of operations, compared to the expected value. If it does, it means that the destination machine is compliant, or else an exception is thrown, indicating that validation is not possible. The main steps are as follows:
When the program is deployed, the relevant commands generate a specified file x (file name C:/windows/sys.key, confused with the system file), the file contains information about the machine.
The source program carries out a static method, and the program starts to validate the method while the program is loading and running.
method to read the specified file X.
method to read the corresponding data from the file.
method to read the MAC address of the running machine and generate the corresponding verification information according to the fixed algorithm.
The new validation information is compared to the validation information in file X, and if it succeeds, the validation passes.
The reference code is as follows:
Read out MAC address (applicable to jdk1.6): Java code enumeration<networkinterface> networkinterfaces = Networkinterface.getnetworkinterfaces (); List<string> stringlist =NewArraylist<string> (); while(Networkinterfaces.hasmoreelements ()) {NetworkInterface networkinterface = networkinterfaces.nextelement ();byte[] x = networkinterface.gethardwareaddress ();if(x!=NULL) {Stringlist.add (Singlecipher.byte2hex (x)); } } returnStringlist.toarray (NewString[stringlist.size ()]);
enumeration<networkinterface> networkinterfaces = Networkinterface.getnetworkinterfaces ();
list<string> stringlist = new arraylist<string> ();
while (Networkinterfaces.hasmoreelements ()) {
NetworkInterface networkinterface = networkinterfaces.nextelement ();
byte[] x = networkinterface.gethardwareaddress ();
if (x!= null) {
Stringlist.add (Singlecipher.byte2hex (x));
}
}
Return Stringlist.toarray (New String[stringlist.size ());
Static Validation: Java code PublicStaticvoidVaditate () {String fileName = file_name; File File =NewFile (FileName);Try{String random = getObject (file, 1); String message = GetObject (file, 2); String[] mac = Getmac ();if(Mac.length = = 0) invalidate ("No Mac."); for(String M:mac) {String mtemp = Byte2hex (Singlecipher.getdefaultcipher (). Encrypt ((M + random). GetBytes ()));if(mtemp.equals (message)) return; }ThrowNewException ("LS"); }Catch(Exception e) {Invalidate ("verify error"); } }
public static void Vaditate () {
String fileName = file_name;
File File = new file (fileName);
try {
String random = getObject (file, 1);
String message = GetObject (file, 2);
String[] mac = Getmac ();
if (Mac.length = = 0)
invalidate ("No Mac.");
for (string M:mac) {
string mtemp = Byte2hex (Singlecipher.getdefaultcipher (). Encrypt ((M + random). GetBytes ()); C10/>if (mtemp.equals) return
;
throw new Exception ("LS");
} catch (Exception e) {
invalidate ("Verify error");
}
The above 3 methods protect the code from different parts. For some industry-specific systems, there is a certain protective effect.
If you have a new method, please let me know.