PFCLObfuscate – Protect Your PL/SQL

Do you write code in PL/SQL?

Do you or your employer sell your applications written in PL/SQL?

Do you deploy your applications written in PL/SQL to customers sites or servers/databases or internally?

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

And wouldn’t it also be great to apply license restrictions to your PL/SQL. For instance deploy a trial version of your PL/SQL package to a customer to allow them to test before they license (BUY) or deploy a set of PL/SQL packages and code but only allow the customer to use the PL/SQL code under your terms. For instance you maybe want to license your PL/SQL (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 PL/SQL code 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 acheive some of the protections of 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 for your PL/SQL. We want to:

  1. Protect your PL/SQL from being understood – obfuscation, compaction, removal of comments, wrap and wrap protection (if needed)
  2. Protect your PL/SQL code from being run outside of your controlled licensed conditions. i.e. add technical license protections to your PL/SQL to control its use, and add those protections automatically.
  3. Protect your PL/SQL 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 PL/SQL to be obfuscated nicely and also we developed Wrapprotect to stop 9iR2 and earlier unwrappers from working so that where necessary layerded protection of your PL/SQL 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 PL/SQL has been modified by an attacker to avoid protections) we needed a better PFCLObfuscate.

!!Yesterday!! we released the brand new version 2.0 of PFCLObfuscate. All current customers should have now received an email to download their new build of version 2.0.

Version 1.0 allowed us to do comprehensive obfuscation but version 2.0 brings “dynamic obfuscation”. This means that as we parse your PL/SQL to protect it with obfuscation we also run a configurable set of dynamic obfuscations at various “hook” points in your PL/SQL 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 PL/SQL is found. “Dynamic obfuscation” allows us to programatically (the user can define the rules) modify the PL/SQL 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.

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

I have two simple PL/SQL files, p1.sql and p2.sql; p1.sql is a simple PL/SQL 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 PL/SQL code that needs 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.

This entry was posted in PFCLObfuscate, PL/SQL, Protect PL/SQL, Uncategorized. Bookmark the permalink.