Call: +44 (0)7759 277220 Call
Article

Protect and Secure Your PL/SQL Code with PFCLObfuscate

Do you write secure and protected Oracle database source code?

Do you or your employer sell database applications that you have written?

Do you deploy your applications to customers sites or servers/databases or internally?

If you do write in the PL/SQL language then you should consider the effort and value in your work and think about securing and protecting it your source code. Wouldn’t it be great to be able to secure the intellectual property (IPR) in your code from others prying eyes, in other words stop someone from understanding what you have written in your, your algorithms, secrets and more.

Your source provides the interface to data being held and processed in the Oracle database and is part of the arsenal of layers to provide privacy for your data. That data is what attackers are after. They would like to steal the personal data, health data or card data or indeed any data that is valuable to you. The application is also at the forefront of the attack surface. The attackers trying SQL Injection or other attacks will encounter your code first. If you secure the source and make it harder to run out of context or to understand its secrets then this will help the security landscape and help to protect your data that attackers want to steal.

Would it also be great to apply license restrictions to your software. For instance deploy a trial version of your package to a customer to allow them to test before they license (BUY) or deploy a set of packages and code but only allow the customer to use the programs under your terms. For instance you maybe want to license and secure your IPR to a customer but for a fixed term or to a fixed number of databases. It would be great to have a customer activate your application in their database but under your controls and settings.

These sorts of protections are available in the C programming Win32, Win64, .NET and other worlds. Writers of .NET or C binaries intended to be used on Windows can buy products or even use free facilities in Visual Studio to achieve some of the security and protections against IPR loss and also adding license type protections. i.e. time limit, locked to hardware etc but all of this type of functionallity is not available for PL/SQL until now.

The goal for us with PFCLObfuscate is to provide multi-layered security. We want to:

  1. Protect your applications from being understood – obfuscation, compaction, removal of comments, wrap and wrap protection (if needed)
  2. Protect your source code from being run outside of your controlled licensed conditions. i.e. add technical license protections to control its use, and add those protections automatically.
  3. Protect your IPR from being stolen. We cannot stop someone stealing it (well we can help reduce the risk but thats part of our normal Oracle security audit and PFCLScan business and not directly PFCLObfuscate) but we can stop it working in another database with PFCLObfuscate

To achieve all of this we developed the first version of PFCLObfuscate which allowed code to be obfuscated nicely and also we developed Wrapprotect to stop 9iR2 and earlier unwrappers from working so that where necessary layered security protection can be implemented. The first version of PFCLObfuscate provides good protection but it was obvious we could get better obfuscation and also to achieve some of our goals such as adding license protection or tamperproofing (checking if the source code has been modified by an attacker to avoid protections) we needed a better PFCLObfuscate.

Version 2.0 and above allows you to secure with dynamic obfuscation and licensing

Version 1.0 allowed us to do comprehensive obfuscation but version 2.0 brings “dynamic obfuscation”. This means that as we parse your code to protect it with obfuscation we also run a configurable set of dynamic obfuscations at various “hook” points in your code. These “hooks” are at the start of a declaration block, the end of a declaration block, the start of a block, the end of a block and when any pre-defined marker such as a special comment is found. “Dynamic obfuscation” allows us to programatically (the user can define the rules) modify to achieve much better obfuscation and also to automatically add license protection and tamperproof protection. The core enhancement with version 2.0 is the dynamic obfuscation engine that will allow us to do much more in terms of securing PL/SQL on many levels. The version 2.0 and above technology also allows us to inject statements into your source code to allow the licensing and tamperproofing and more. Adding protections allows us to help reduce security issues in the source code.

Let’s see a simple example of protecting two procedures and adding license protections to them to allow our code to be run by a customer for 30 days.

I have two simple SQL*Plus files, p1.sql and p2.sql; p1.sql is a simple procedure DEMO_RUN that runs another procedure TEST_PROC in p2.sql. The public interface DEMO_RUN is to be retained but the name of the internal procedure TEST_RUN can be obfuscated.

Here is the original source code (p1.sql):

	-- test the interface with TEST_PROC in p2.sql
	create or replace procedure DEMO_RUN(pv_input in varchar2)
	is
		lv_one number:=1;
		lv_two number:=3;
	begin
		dbms_output.put_line('Start of Test');
		dbms_output.new_line();
		test_proc(lv_one,pv_input,lv_two);
		dbms_output.put_line('End of Test');
	end;
	/

p2.sql

	create or replace procedure TEST_PROC( PV_NUM in NUMBER,
	PV_VAR in VARCHAR2, PV_VAR3 in out INTEGER) IS
	L_NUM NUMBER:=3;
	L_VAR NUMBER;
	J NUMBER:=1;
	procedure NESTED( PV_LEN in out NUMBER) is
	X NUMBER;
	begin
	X:= PV_LEN * 5;
	end;
	begin
	case L_NUM
	when 1 then
	L_VAR:=3;
	DBMS_OUTPUT.PUT_LINE('This is a header');
	DBMS_OUTPUT.PUT_LINE('The number is ' ||  L_VAR);
	DBMS_OUTPUT.PUT_LINE('The case var is ' ||  L_NUM);
	when 2 then
	L_VAR:=4;
	DBMS_OUTPUT.PUT_LINE('This is a header');
	DBMS_OUTPUT.PUT_LINE('The number is ' ||  L_VAR);
	DBMS_OUTPUT.PUT_LINE('The case var is ' ||  L_NUM);
	when 3 then
	L_VAR:=6;
	DBMS_OUTPUT.PUT_LINE('This is a header');
	DBMS_OUTPUT.PUT_LINE('The number is ' ||  L_VAR);
	DBMS_OUTPUT.PUT_LINE('The case var is ' ||  L_NUM);
	else
	DBMS_OUTPUT.PUT_LINE('wrong choice');
	end case;
	if ( ( J = 1) and ( J = 3)) then
	DBMS_OUTPUT. PUT_LINE('here is IF');
	elsif ( ( J = 2) or ( J != 3)) then
	DBMS_OUTPUT.PUT_LINE('The elsif clause');
	else
	DBMS_OUTPUT.PUT_LINE('else clause');
	end if;
	J:=4;
	NESTED( J);
	DBMS_OUTPUT.PUT_LINE('nested=:' ||  J);
	for J in reverse 1.. PV_NUM loop
	if MOD( J,2) = 0 then
	DBMS_OUTPUT.PUT_LINE('for loop with reverse');
	end if;
	end loop;
	end;
	/

Now install the code into the database and test that it works:

	Connected to:
	Oracle Database 12c Release 12.1.0.1.0 - 64bit Production

	SQL> @p2.sql

	Procedure created.

	SQL> @p1.sql

	Procedure created.

	SQL> set serveroutput on
	SQL> exec demo_run('Hello');
	Start of Test
	This is a header
	The number is 6
	The case var is 3
	The elsif clause
	nested=:4
	End of Test

	PL/SQL procedure successfully completed.

	SQL>

The code works fine. So now let’s protect the code using version 2.0 of PFCLObfuscate and add license protection automatically to allow the code to run for 30 days. The system date of my database is:

	SQL> select sysdate from dual;

	SYSDATE
	---------
	23-MAR-14

	SQL>

We need to do some simple configuration for PFCLObfuscate before we can run it; let us run through the configuration. If this is the first time that you execute PFCLObfuscate you need to generate the reserved words configuration file using the provided gr.sql script:

running gr.sql

	Connected to:
	Oracle Database 12c Release 12.1.0.1.0 - 64bit Production

	SQL> @gr
	SQL>
	SQL> exit

This created the reserved.txt configuration file for us. Now enable version 2.0 in your configuration file (I am just showing the version 2.0 settings not all of the obfuscation settings available):

Part of ob.conf file

	############################################################################
	# Version 2.0 Settings
	############################################################################
	#
	# The function and string hide file. This file specifies a package to "hide" or
	# strings to hide and then specifies the code to add new PL/SQL processing to
	# deal with this and also PL/SQL substitute for the actual located string. This
	# is detailed in the help
	#
	functionfile=functionfile.txt
	#
	# This parameter is  the file extension used for the intermediate files. This
	# can be changed.
	#
	intermediatefile=.imm
	#

Now add the public interface name DEMO_RUN to the omit.txt configuration file:

omit.txt file

	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>type omit.txt
	DEMO_RUN
	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>

The last thing to do is edit a license.txt file to create the simple settings for your license protection. The current system date for my database is 23-MAR-2014 and I want to license for 30 days so I will set the start date to 22-MAR-2014 and the end date to 22-APR-2014 and the number of days to 30. Note that the lifetime and the expiry date are mutually exclusive and the most restrictive always acts first.

Here is the simple license file for this example:

license.txt

	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>type license.txt
	expire_days=30
	expire_date=22-APR-2014
	start_date=22-MAR-2014
	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>

Now we can obfuscate the code:

execution of PFCLObfuscate

	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>obs -v -c ob.conf -i p1.sql -o p1.opf

	PFCLObfuscate: Release 2.0.122.1937 - Production on Thu Apr 17 15:00:50 2014

	Copyright (c) 2014 PeteFinnigan.com Limited. All rights reserved.

	[2014 Apr 17 14:00:50] obs: Starting PFCLObfuscate...
	[2014 Apr 17 14:00:50] obs: Pre-Load Keywords from [key.txt]
	[2014 Apr 17 14:00:50] obs: Pre-Load Omit words from [omit.txt]
	[2014 Apr 17 14:00:50] obs: Pre-Load StringOmit words from [string.txt]
	[2014 Apr 17 14:00:50] obs: Pre-Load Reserved words from [reserved.txt]
	[2014 Apr 17 14:00:50] obs: Pre-Load force words from [force.txt]
	[2014 Apr 17 14:00:50] obs: Pre-Load function file list from [functionfile.txt]
	[2014 Apr 17 14:00:50] obs: Pre-Load map file list from [map.txt]
	[2014 Apr 17 14:00:50] obs: Version 2.0 Initialisation...
	[2014 Apr 17 14:00:50] obs: Initialise the file list...
	[2014 Apr 17 14:00:50] obs: Initialise the Depth Stack...
	[2014 Apr 17 14:00:50] obs: Initialise the FWD Function list...
	[2014 Apr 17 14:00:50] obs: Initialise the FUNC function list...
	[2014 Apr 17 14:00:50] obs: Initialise the NEW function list...
	[2014 Apr 17 14:00:50] obs: Running PFCLObfuscate PL/SQL Obfuscator
	[2014 Apr 17 14:00:50] obs: Obfuscating PL/SQL Input File [ p1.sql ]
	[2014 Apr 17 14:00:50] obs: Save the transposed variables
	[2014 Apr 17 14:00:50] obs: Process intermediate file...
	[2014 Apr 17 14:00:50] obs: Closing Down PFCLObfuscate

	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>obs -v -c ob.conf -i p2.sql -o p2.opf

	PFCLObfuscate: Release 2.0.122.1937 - Production on Thu Apr 17 15:00:56 2014

	Copyright (c) 2014 PeteFinnigan.com Limited. All rights reserved.

	[2014 Apr 17 14:00:56] obs: Starting PFCLObfuscate...
	[2014 Apr 17 14:00:56] obs: Pre-Load Keywords from [key.txt]
	[2014 Apr 17 14:00:56] obs: Pre-Load Omit words from [omit.txt]
	[2014 Apr 17 14:00:56] obs: Pre-Load StringOmit words from [string.txt]
	[2014 Apr 17 14:00:56] obs: Pre-Load Reserved words from [reserved.txt]
	[2014 Apr 17 14:00:56] obs: Pre-Load force words from [force.txt]
	[2014 Apr 17 14:00:56] obs: Pre-Load function file list from [functionfile.txt]
	[2014 Apr 17 14:00:56] obs: Pre-Load map file list from [map.txt]
	[2014 Apr 17 14:00:56] obs: Version 2.0 Initialisation...
	[2014 Apr 17 14:00:56] obs: Initialise the file list...
	[2014 Apr 17 14:00:56] obs: Initialise the Depth Stack...
	[2014 Apr 17 14:00:56] obs: Initialise the FWD Function list...
	[2014 Apr 17 14:00:56] obs: Initialise the FUNC function list...
	[2014 Apr 17 14:00:56] obs: Initialise the NEW function list...
	[2014 Apr 17 14:00:56] obs: Running PFCLObfuscate PL/SQL Obfuscator
	[2014 Apr 17 14:00:56] obs: Obfuscating PL/SQL Input File [ p2.sql ]
	[2014 Apr 17 14:00:56] obs: Save the transposed variables
	[2014 Apr 17 14:00:56] obs: Process intermediate file...
	[2014 Apr 17 14:00:56] obs: Closing Down PFCLObfuscate

	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>

Note: This is a simple example shown long hand but we can actually obfuscate all PL/SQL files in a directory in one command using provided batch scripts with the PFCLObfuscate software and we can also turn off all output using silent, shortening the output completely. PFCLObfuscate is command line and is easy to integrate into existing build processes.

Now we can install the obfuscated and license protected code into the database and test it:

sql installation

	Connected to:
	Oracle Database 12c Release 12.1.0.1.0 - 64bit Production

	SQL> @p2.opf

	Procedure created.

	SQL> @p2.opf

	Procedure created.

	SQL> set serveroutput on
	SQL> exec demo_run('hello');
	Start of Test
	This is a header
	The number is 6
	The case var is 3
	The elsif clause
	nested=:4
	End of Test

	PL/SQL procedure successfully completed.

	SQL>

So our code is now protected from anyone understanding it and also now has license protection automatically added. The protected code works above as we are in the licensed period for the code but to show that the license protection does work lets change the license so that it has expired already. So I have changed the license to allow this code to be run for 5 days so now the license started on the 12-MAR-2014 and expired on the 19th March. Remember the current database date is 23-Mar-2014 (Don’t ask, its in a VM with the wrong date!):

license.txt

	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>type license.txt
	expire_days=5
	expire_date=17-MAR-2014
	start_date=12-MAR-2014
	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>

Now re-protect the two source code files:

Running PFCLObfuscate, silently this time:

	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>obs -s -c ob.conf -i p1.sql -o p1.opf

	C:\Users\Pete\AppData\Local\PeteFinnigan.com Limited\PFCLObfuscate>obs -s -c ob.conf -i p2.sql -o p2.opf

Now reload the code back into the database and test it:

Loading the files:

	Connected to:
	Oracle Database 12c Release 12.1.0.1.0 - 64bit Production

	SQL> @p2.opf

	Procedure created.

	SQL> @p1.opf

	Procedure created.

	SQL> set serveroutput on
	SQL> exec demo_run('hello');
	BEGIN demo_run('hello'); END;

	*
	ERROR at line 1:
	ORA-20096: invalid license(2)
	ORA-06512: at line 1
	ORA-06512: at "ORABLOG.DEMO_RUN", line 21
	ORA-06512: at "ORABLOG.DEMO_RUN", line 115
	ORA-06512: at line 1
	SQL>

So it works, we automatically licensed our PL/SQL and you can do the same to your PL/SQL.

This was a simple example of license protecting and obfuscating PL/SQL. We will also support licenses locked to the database and deployed licenses. So that a customer can deploy the code and you can then generate a license that is locked to their database allowing your code to be executed in their database. If the code (and even the license) were removed to another database the stolen code would not run as its locked to their database.

Note: In general the configuration for PFCLObfuscate needs to be done only once at the start of a project for a set of packages or procedures that need to be protected and perhaps needs to be updated when changes to the public interfaces are made or new code is added to the protection process.

PFCLObfuscate version 2.0 also provides powerful obfuscation techniques to protect your code. Please contact us for more details by emailing info@petefinnigan.com or by visting the Buy PFCLObfuscate page of this site.