Obfuscating PL/SQL Code
Semantic Designs can construct custom obfuscators for virtually any source language as a part of the corresponding Source Formatter. This page contains PL/SQL sample code, its obfuscated version, and the generated obfuscation map.
PL/SQL Sample Code before Obfuscation
(This is the same formatted code shown on the PL/SQL Formatter example page)
DECLARE part_no NUMBER(4); in_stock BOOLEAN; my_sal REAL(7, 2); credit_limit CONSTANT NUMBER := 5000.00; my_title books.title%TYPE; dept_rec dept%ROWTYPE; -- declare record variableCURSOR c1 IS emp_rec c1%ROWTYPE; -- declare record variable that represents -- a row fetched from the emp table acct_balance NUMBER(11, 2); acct CONSTANT NUMBER(4) := 3; debit_amt CONSTANT NUMBER(5, 2) := 500.00; BEGIN tax := price * tax_rate; valid_id := FALSE; bonus := current_salary * 0.10; wages := gross_pay(emp_id, st_hrs, ot_hrs) - deductions; SELECT ename, sal, hiredate, job FROM emp; SELECT salary * 0.10 INTO bonus FROM employees WHERE employee_id = emp_id; SELECT AVG(sal) INTO my_sal FROM emp; adjust_salary(7788, my_sal); -- assigns a new value to my_sal FOR someone IN (SELECT * FROM employees) LOOP DBMS_OUTPUT.PUT_LINE('First name = ' || someone.first_name); DBMS_OUTPUT.PUT_LINE('Last name = ' || someone.last_name); END LOOP; my_deptno := dept_rec.deptno; FETCH c1 INTO emp_rec; SELECT bal INTO acct_balance FROM accounts WHERE account_id = acct FOR UPDATE OF bal; IF acct_balance >= debit_amt THEN UPDATE accounts SET bal = bal - debit_amt WHERE account_id = acct; ELSE INSERT INTO temp VALUES (acct, acct_balance, 'Insufficient funds'); -- insert account, current balance, and message END IF; COMMIT; -- This CASE statement performs different actions based -- on a set of conditional tests. CASE WHEN shape = 'square' THEN area := side * side; WHEN shape = 'circle' THEN BEGIN area := pi * (radius * radius); DBMS_OUTPUT.PUT_LINE('Value is not exact because pi is irrational.'); END; WHEN shape = 'rectangle' THEN area := LENGTH * width; ELSE BEGIN DBMS_OUTPUT.PUT_LINE('No formula to calculate area of a' || shape); RAISE PROGRAM_ERROR; END; END CASE; FOR num IN 1 .. 500 LOOP INSERT INTO roots VALUES (num, SQRT(num)); END LOOP; END; DECLARE salary emp.sal%TYPE := 0; mgr_num emp.mgr%TYPE; last_name emp.ename%TYPE; starting_empno emp.empno%TYPE := 7499; BEGIN SELECT mgr INTO mgr_num FROM emp WHERE empno = starting_empno; WHILE salary <= 2500 LOOP SELECT sal, mgr, ename INTO salary, mgr_num, last_name FROM emp WHERE empno = mgr_num; END LOOP; INSERT INTO temp VALUES (NULL, salary, last_name); COMMIT; EXCEPTION WHEN NO_DATA_FOUND THEN INSERT INTO temp VALUES (NULL, NULL, 'Not found'); COMMIT; END; DECLARE PROCEDURE award_bonus(emp_id NUMBER) IS bonus REAL; comm_missing EXCEPTION; BEGIN -- executable part starts here SELECT comm * 0.15 INTO bonus FROM emp WHERE empno = emp_id; IF bonus IS NULL THEN RAISE comm_missing; ELSE UPDATE payroll SET pay = pay + bonus WHERE empno = emp_id; END IF; EXCEPTION -- exception-handling part starts here WHEN comm_missing THEN COMMIT; END award_bonus; BEGIN bonus := 1.0; END; CREATE PACKAGE emp_actions AS -- package specification PROCEDURE hire_employee(empno NUMBER, ename CHAR); PROCEDURE fire_employee(emp_id NUMBER); END emp_actions; CREATE PACKAGE BODY emp_actions AS -- package body PROCEDURE hire_employee(empno NUMBER, ename CHAR) IS BEGIN INSERT INTO emp VALUES (empno, ename); END hire_employee; PROCEDURE fire_employee(emp_id NUMBER) IS BEGIN DELETE FROM emp WHERE empno = emp_id; END fire_employee; END emp_actions; DECLARE TYPE Staff IS TABLE OF Employee; staffer Employee; FUNCTION new_hires(hiredate DATE) RETURN Staff IS BEGIN NULL; END; BEGIN staffer := new_hires('10-NOV-98') (5); END; DECLARE TYPE TimeRec IS RECORD (hours SMALLINT, minutes SMALLINT); TYPE MeetingTyp IS RECORD (date_held DATE, duration TimeRec, -- nested record location VARCHAR2(20), purpose VARCHAR2(50)); BEGIN NULL; END; CREATE TYPE Bank_Account AS OBJECT (acct_number INTEGER(5), balance REAL, status VARCHAR2(10), MEMBER PROCEDURE OPEN (amount IN REAL), MEMBER PROCEDURE verify_acct(num IN INTEGER), MEMBER PROCEDURE CLOSE (num IN INTEGER, amount OUT REAL), MEMBER PROCEDURE deposit(num IN INTEGER, amount IN REAL), MEMBER PROCEDURE withdraw(num IN INTEGER, amount IN REAL), MEMBER FUNCTION curr_bal(num IN INTEGER) RETURN REAL); DECLARE comm_missing EXCEPTION; -- declare exception BEGIN IF commission IS NULL THEN RAISE comm_missing; -- raise exception END IF; bonus := (salary * 0.10) + (commission * 0.15); EXCEPTION WHEN comm_missing THEN NULL; END; DECLARE n NUMBER; BEGIN n := 10E127; -- causes a 'numeric overflow or underflow' error END; DECLARE x BINARY_FLOAT := sqrt(2.0); -- Single-precision floating-point number y BINARY_DOUBLE := sqrt(2.0); -- Double-precision floating-point number BEGIN NULL; END; BEGIN str := 'Hello, world!'; str := 'XYZ Corporation'; str := '10-NOV-91'; str := 'He said "Life is like licking honey from a thorn."'; str := '$1,000,000'; str := q'{I'm a string, you're a string.}'; -- q'!...!' notation lets us use single quotes inside the literal. string_var := q'{I'm a string, you're a string.}'; -- To use delimiters [, {, <, and (, pair them with ], }, >, and ). -- Here we pass a string literal representing a SQL statement -- to a subprogram, without doubling the quotation marks around -- 'INVALID'. func_call(q'{select index_name from user_indexes where status = 'INVALID'}'); -- For NCHAR and NVARCHAR2 literals, use the prefix nq instead of q. where_clause := q'{where col_value like '%e'}'; END; DECLARE d1 DATE := DATE '1998-12-25'; t1 TIMESTAMP := TIMESTAMP '1997-10-22 13:01:01'; t2 TIMESTAMP WITH TIME ZONE := TIMESTAMP '1997-01-31 09:26:56.66 +02:00'; -- Three years and two months -- (For greater precision, we would use the day-to-second interval) i1 INTERVAL YEAR TO MONTH := INTERVAL '3-2' YEAR TO MONTH; -- Five days, four hours, three minutes, two and 1/100 seconds i2 INTERVAL DAY TO SECOND := INTERVAL '5 04:03:02.01' DAY TO SECOND; BEGIN NULL; END; DECLARE some_condition BOOLEAN; pi NUMBER := 3.1415926; radius NUMBER := 15; area NUMBER; BEGIN /* Perform some simple tests and assignments */ IF 2 + 2 = 4 THEN some_condition := TRUE; /* We expect this THEN to always be done */ END IF; /* The following line computes the area of a circle using pi, which is the ratio between the circumference and diameter. */ area := pi * radius ** 2; END; DECLARE credit_limit CONSTANT REAL := 5000.00; max_days_in_year CONSTANT INTEGER := 366; urban_legend CONSTANT BOOLEAN := FALSE; hours_worked INTEGER DEFAULT 40; employee_count INTEGER := 0; acct_id INTEGER(4) NOT NULL := 9999; credit NUMBER(7, 2); debit credit%TYPE; NAME VARCHAR2(20) := 'JoHn SmItH'; -- If we increase the length of NAME, the other variables -- become longer too. upper_name NAME%TYPE := UPPER(NAME); lower_name NAME%TYPE := LOWER(NAME); init_name NAME%TYPE := INITCAP(NAME); the_trigger user_triggers.trigger_name%TYPE; my_empno employees.employee_id%TYPE; -- %ROWTYPE can include all the columns in a table... emp_rec employees%ROWTYPE; -- ...or a subset of the columns, based on a cursor. CURSOR c1 IS SELECT department_id, department_name FROM departments; dept_rec c1%ROWTYPE; -- Could even make a %ROWTYPE with columns from multiple tables. CURSOR c2 IS SELECT employee_id, email, employees.manager_id, location_id FROM employees, departments WHERE employees.department_id = departments.department_id; join_rec c2%ROWTYPE; BEGIN -- We know EMP_REC can hold a row from the EMPLOYEES table. SELECT * INTO emp_rec FROM employees WHERE ROWNUM < 2; -- We can refer to the fields of EMP_REC using column names -- from the EMPLOYEES table. IF emp_rec.department_id = 20 AND emp_rec.last_name = 'JOHNSON' THEN emp_rec.salary := emp_rec.salary * 1.15; END IF; END; DECLARE dept_rec1 departments%ROWTYPE; dept_rec2 departments%ROWTYPE; CURSOR c1 IS SELECT department_id, location_id FROM departments; dept_rec3 c1%ROWTYPE; BEGIN dept_rec1 := dept_rec2; -- allowed -- dept_rec2 refers to a table, dept_rec3 refers to a cursor -- dept_rec2 := dept_rec3; -- not allowed END; DECLARE dept_rec departments%ROWTYPE; BEGIN SELECT * INTO dept_rec FROM departments WHERE department_id = 30 AND ROWNUM < 2; END; BEGIN -- We assign an alias (COMPLETE_NAME) to the expression value, because -- it has no column name. FOR item IN (SELECT first_name || ' ' || last_name complete_name FROM employees WHERE ROWNUM < 11) LOOP -- Now we can refer to the field in the record using this alias. dbms_output.put_line('Employee name: ' || item.complete_name); END LOOP; END; -- CREATE TABLE employees2 AS SELECT last_name FROM employees; << MAIN >> DECLARE last_name VARCHAR2(10) := 'King'; my_last_name VARCHAR2(10) := 'King'; BEGIN -- Deletes everyone, because both LAST_NAMEs refer to the column DELETE FROM employees2 WHERE last_name = last_name; dbms_output.put_line('Deleted ' || SQL%ROWCOUNT || ' rows.'); ROLLBACK; -- OK, column and variable have different names DELETE FROM employees2 WHERE last_name = my_last_name; dbms_output.put_line('Deleted ' || SQL%ROWCOUNT || ' rows.'); ROLLBACK; -- OK, block name specifies that 2nd LAST_NAME is a variable DELETE FROM employees2 WHERE last_name = main.last_name; dbms_output.put_line('Deleted ' || SQL%ROWCOUNT || ' rows.'); ROLLBACK; END; -- DROP TABLE employees2; DECLARE FUNCTION dept_name(department_id IN NUMBER) RETURN departments.department_name%TYPE IS department_name departments.department_name%TYPE; BEGIN -- DEPT_NAME.DEPARTMENT_NAME specifies the local variable -- instead of the table column SELECT department_name INTO dept_name.department_name FROM departments WHERE department_id = dept_name.department_id; RETURN department_name; END; BEGIN FOR item IN (SELECT department_id FROM departments) LOOP dbms_output.put_line('Department: ' || dept_name(item.department_id)); END LOOP; END; DECLARE a CHAR; b REAL; BEGIN -- identifiers available here: a (CHAR), b DECLARE a INTEGER; c REAL; BEGIN -- identifiers available here: a (INTEGER), b, c NULL; END; DECLARE d REAL; BEGIN -- identifiers available here: a (CHAR), b, d NULL; END; -- identifiers available here: a (CHAR), b END; << outer >> DECLARE birthdate DATE; BEGIN DECLARE birthdate DATE; BEGIN IF birthdate = outer.birthdate THEN NULL; END IF; END; END; PROCEDURE check_credit(xxx REAL) IS rating NUMBER; FUNCTION valid(xxx REAL) RETURN BOOLEAN IS rating NUMBER; BEGIN IF check_credit.rating < 3 THEN NULL; END IF; END; BEGIN NULL; END; DECLARE counter INTEGER; BEGIN -- COUNTER is initially NULL, so 'COUNTER + 1' is also null. counter := counter + 1; IF counter IS NULL THEN dbms_output.put_line('Sure enough, COUNTER is NULL not 1.'); END IF; END; DECLARE done BOOLEAN; -- DONE is initially NULL counter NUMBER := 0; BEGIN done := FALSE; -- Assign a literal value WHILE done != TRUE -- Compare to a literal value LOOP counter := counter + 1; done := (counter > 500); -- If counter > 500, DONE = TRUE END LOOP; END; DECLARE emp_id employees.employee_id%TYPE := 100; emp_name employees.last_name%TYPE; wages NUMBER(7, 2); BEGIN SELECT last_name, salary + (salary * nvl(commission_pct, 0)) INTO emp_name, wages FROM employees WHERE employee_id = emp_id; dbms_output.put_line('Employee ' || emp_name || ' might make ' || wages); END; DECLARE on_hand INTEGER := 0; on_order INTEGER := 100; BEGIN -- Does not cause divide-by-zero error; evaluation stops after 1st expr. IF (on_hand = 0) OR ( (on_order / on_hand) < 5) THEN dbms_output.put_line('There are no more widgets left!'); END IF; END; DECLARE PROCEDURE assert(assertion VARCHAR2, truth BOOLEAN) IS BEGIN IF truth IS NULL THEN dbms_output.put_line('Assertion ' || assertion || ' is unknown (NULL)'); ELSIF truth = TRUE THEN dbms_output.put_line('Assertion ' || assertion || ' is TRUE'); ELSE dbms_output.put_line('Assertion ' || assertion || ' is FALSE'); END IF; END; BEGIN assert('2 + 2 = 4', 2 + 2 = 4); assert('10 > 1', 10 > 1); assert('10 <= 1', 10 <= 1); assert('5 BETWEEN 1 AND 10', 5 BETWEEN 1 AND 10); assert('NULL != 0', NULL != 0); assert('3 IN (1,3,5)', 3 IN (1, 3, 5)); assert(q'{'A'\r\n < 'Z'}', 'A' < 'Z'); assert(q'{'baseball' LIKE '%all%'}', 'baseball' LIKE '%all%'); assert(q'{'suit' || 'case' = 'suitcase'}', 'suit' || 'case' = 'suitcase'); END; DECLARE fraction BINARY_FLOAT := 1 / 3; BEGIN IF fraction = 11 / 33 THEN dbms_output.put_line('Fractions are equal (luckily!)'); END IF; END; DECLARE done BOOLEAN; BEGIN -- Each WHILE loop is equivalent done := FALSE; WHILE done = FALSE LOOP done := TRUE; END LOOP; done := FALSE; WHILE NOT (done = TRUE) LOOP done := TRUE; END LOOP; done := FALSE; WHILE NOT done LOOP done := TRUE; END LOOP; END; DECLARE grade CHAR(1) := 'B'; appraisal VARCHAR2(20); BEGIN appraisal := CASE grade WHEN 'A' THEN 'Excellent' WHEN 'B' THEN 'Very Good' WHEN 'C' THEN 'Good' WHEN 'D' THEN 'Fair' WHEN 'F' THEN 'Poor' ELSE 'No such grade' END; dbms_output.put_line('Grade ' || grade || ' is ' || appraisal); END; DECLARE grade CHAR(1) := 'B'; appraisal VARCHAR2(120); id NUMBER := 8429862; attendance NUMBER := 150; min_days CONSTANT NUMBER := 200; FUNCTION attends_this_school(id NUMBER) RETURN BOOLEAN IS BEGIN RETURN TRUE; END; BEGIN appraisal := CASE WHEN attends_this_school(id) = FALSE THEN 'N/A - Student not enrolled' -- Have to put this condition early to detect -- good students with bad attendance WHEN grade = 'F' OR attendance < min_days THEN 'Poor (poor performance or bad attendance)' WHEN grade = 'A' THEN 'Excellent' WHEN grade = 'B' THEN 'Very Good' WHEN grade = 'C' THEN 'Good' WHEN grade = 'D' THEN 'Fair' ELSE 'No such grade' END; dbms_output.put_line('Result for student ' || id || ' is ' || appraisal); END; DECLARE x NUMBER := 5; y NUMBER := NULL; BEGIN IF x != y THEN -- yields NULL, not TRUE dbms_output.put_line('x != y'); -- not executed ELSIF x = y THEN -- also yields NULL dbms_output.put_line('x = y'); ELSE dbms_output.put_line(q'{Can't tell if x and y are equal or not...}'); END IF; END; DECLARE a NUMBER := NULL; b NUMBER := NULL; BEGIN IF a = b THEN -- yields NULL, not TRUE dbms_output.put_line('a = b'); -- not executed ELSIF a != b THEN -- yields NULL, not TRUE dbms_output.put_line('a != b'); -- not executed ELSE dbms_output.put_line(q'{Can't tell if two NULLs are equal}'); END IF; END; DECLARE null_string VARCHAR2(80) := TO_CHAR(''); address VARCHAR2(80); zip_code VARCHAR2(80) := SUBSTR(address, 25, 0); NAME VARCHAR2(80); valid BOOLEAN := (NAME != ''); BEGIN NULL; END; DECLARE the_manager VARCHAR2(40); NAME employees.last_name%TYPE; BEGIN -- NULL is a valid argument to DECODE. In this case, manager_id is null -- and the DECODE function returns 'nobody'. SELECT DECODE (manager_id, NULL, 'nobody', 'somebody'), last_name INTO the_manager, NAME FROM employees WHERE employee_id = 100; dbms_output.put_line(NAME || ' is managed by ' || the_manager); END; DECLARE string_type VARCHAR2(60); old_string string_type%TYPE := 'Apples and oranges'; my_string string_type%TYPE := 'more apples'; -- NULL is a valid argument to REPLACE, but does not match -- anything so no replacement is done. new_string string_type%TYPE := REPLACE (old_string, NULL, my_string); BEGIN dbms_output.put_line('Old string = ' || old_string); dbms_output.put_line('New string = ' || new_string); END; DECLARE string_type VARCHAR2(60); dashed string_type%TYPE := 'Gold-i-locks'; -- When the substitution text for REPLACE is NULL, -- the text being replaced is deleted. NAME string_type%TYPE := REPLACE (dashed, '-', NULL); BEGIN dbms_output.put_line('Dashed name = ' || dashed); dbms_output.put_line('Dashes removed = ' || NAME); END;
PL/SQL Code after Obfuscation
Notice that comments are gone, names have been scrambled. The obfuscator uses a special list provided by the user to define names that should be preserved, ensuring that public interfaces and accesses to public libraries remain valid. If you obfuscate a set of PL/SQL source files simultaneously, only the public symbols they collectively offer will be sensibly named in the source files.
declare Oil100 number(4); iil101 boolean; Oil10i real(7, 2); iil10i constant number := 5000.00; Oil10l iil110.Oil111%type; iil111 Oil11i%rowtype; iil11l Oil1i0%rowtype; iil1i0 number(11, 2); Oil1i1 constant number(4) := 3; iil1ii constant number(5, 2) := 500.00; begin Oil1il := iil1il * Oil1l0; iil1l1 := false; Oil1li := iil1li * 0.10; Oil1ll := iili00(Oili01, iili01, Oili0i) - iili0l; select Oili10, iili10, Oili11, iili1i from Oili1l; select iili1l * 0.10 into Oil1li from Oilii0 where iilii1 = Oili01; select Oiliii(iili10) into Oil10i from Oili1l; iiliii(7788, Oil10i); for Oiliil in (select * from Oilii0) loop iilil0.Oilil1('First name = ' || Oiliil.iilil1); iilil0.Oilil1('Last name = ' || Oiliil.Oilili); end loop; iilill := iil111.Oill00; fetch Oil1i0 into iil11l; select iill00 into iil1i0 from Oill01 where iill0i = Oil1i1 for update of iill00; if iil1i0 >= iil1ii then update Oill01 set iill00 = iill00 - iil1ii where iill0i = Oil1i1; else insert into Oill0l values (Oil1i1, iil1i0, 'Insufficient funds'); end if; commit; case when iill0l = 'square' then Oill10 := iill11 * iill11; when iill0l = 'circle' then begin Oill10 := Oill1i * (iill1i * iill1i); iilil0.Oilil1('Value is not exact because pi is irrational.'); end; when iill0l = 'rectangle' then Oill10 := length * Oill1l; else begin iilil0.Oilil1('No formula to calculate area of a' || iill0l); raise iilli0; end; end case; for Oilli1 in 1 .. 500 loop insert into iilli1 values (Oilli1, Oillii(Oilli1)); end loop; end; declare iili1l Oili1l.iili10%type := 0; iillil Oili1l.Oilll0%type; Oilili Oili1l.Oili10%type; iilll0 Oili1l.Oilll1%type := 7499; begin select Oilll0 into iillil from Oili1l where Oilll1 = iilll0; while iili1l <= 2500 loop select iili10, Oilll0, Oili10 into iili1l, iillil, Oilili from Oili1l where Oilll1 = iillil; end loop; insert into Oill0l values (null, iili1l, Oilili); commit; exception when iillli then insert into Oill0l values (null, null, 'Not found'); commit; end; declare procedure Oillll(Oili01 number) is Oil1li real; iillll exception; begin select ll0000 * 0.15 into Oil1li from Oili1l where Oilll1 = Oili01; if Oil1li is null then raise iillll; else update Ol0000 set il0001 = il0001 + Oil1li where Oilll1 = Oili01; end if; exception when iillll then commit; end Oillll; begin Oil1li := 1.0; end; create package ll0001 as procedure Ol000i(Oilll1 number, Oili10 char); procedure il000i(Oili01 number); end ll0001; create package body ll0001 as procedure Ol000i(Oilll1 number, Oili10 char) is begin insert into Oili1l values (Oilll1, Oili10); end Ol000i; procedure il000i(Oili01 number) is begin delete from Oili1l where Oilll1 = Oili01; end il000i; end ll0001; declare type ll000l is table of Ol000l; il0010 Ol000l; function ll0010(Oili11 date) return ll000l is begin null; end; begin il0010 := ll0010('10-NOV-98') (5); end; declare type Ol0011 is record (il0011 smallint, ll001i smallint); type Ol001i is record (il001l date, ll001l Ol0011, Ol00i0 varchar2(20), il00i0 varchar2(50)); begin null; end; create type ll00i1 as object (Ol00i1 integer(5), il00ii real, ll00ii varchar2(10), member procedure open(Ol00il in real), member procedure il00il(Oilli1 in integer), member procedure close(Oilli1 in integer, Ol00il out real), member procedure ll00l0(Oilli1 in integer, Ol00il in real), member procedure Ol00l0(Oilli1 in integer, Ol00il in real), member function il00l1(Oilli1 in integer) return real); declare iillll exception; begin if ll00l1 is null then raise iillll; end if; Oil1li := (iili1l * 0.10) + (ll00l1 * 0.15); exception when iillll then null; end; declare Ol00li number; begin Ol00li := 10E127; end; declare il00li binary_float := ll00ll(2.0); Ol00ll binary_double := ll00ll(2.0); begin null; end; begin il0100 := 'Hello, world!'; il0100 := 'XYZ Corporation'; il0100 := '10-NOV-91'; il0100 := 'He said "Life is like licking honey from a thorn."'; il0100 := '$1,000,000'; il0100 := 'I''m a string, you''re a string.'; ll0100 := 'I''m a string, you''re a string.'; Ol0101('select index_name from user_indexes where status = ''INVALID'''); il0101 := 'where col_value like ''%é'''; end; declare ll010i date := date '1998-12-25'; Ol010i timestamp := timestamp '1997-10-22 13:01:01'; il010l timestamp with time zone := timestamp '1997-01-31 09:26:56.66 +02:00'; ll010l interval year to month := interval '3-2' year to month; Ol0110 interval day to second := interval '5 04:03:02.01' day to second; begin null; end; declare il0110 boolean; Oill1i number := 3.1415926; iill1i number := 15; Oill10 number; begin if 2 + 2 = 4 then il0110 := true; end if; Oill10 := Oill1i * iill1i ** 2; end; declare iil10i constant real := 5000.00; ll0111 constant integer := 366; Ol0111 constant boolean := false; il011i integer default 40; ll011i integer := 0; Ol011l integer(4) not null := 9999; il011l number(7, 2); ll01i0 il011l%type; name varchar2(20) := 'JoHn SmItH'; Ol01i0 name%type := il01i1(name); ll01i1 name%type := Ol01ii(name); il01ii name%type := ll01il(name); Ol01il il01l0.ll01l0%type; Ol01l1 Oilii0.iilii1%type; iil11l Oilii0%rowtype; cursor Oil1i0 is select il01l1, ll01li from Ol01li; iil111 Oil1i0%rowtype; cursor il01ll is select iilii1, ll01ll, Oilii0.Ol0i00, il0i00 from Oilii0, Ol01li where Oilii0.il01l1 = Ol01li.il01l1; ll0i01 il01ll%rowtype; begin select * into iil11l from Oilii0 where Ol0i01 < 2; if iil11l.il01l1 = 20 and iil11l.Oilili = 'JOHNSON' then iil11l.iili1l := iil11l.iili1l * 1.15; end if; end; declare il0i0i Ol01li%rowtype; ll0i0i Ol01li%rowtype; cursor Oil1i0 is select il01l1, il0i00 from Ol01li; Ol0i0l Oil1i0%rowtype; begin il0i0i := ll0i0i; end; declare iil111 Ol01li%rowtype; begin select * into iil111 from Ol01li where il01l1 = 30 and Ol0i01 < 2; end; begin for il0i0l in (select iilil1 || ' ' || Oilili ll0i10 from Oilii0 where Ol0i01 < 11) loop Ol0i10.il0i11('Employee name: ' || il0i0l.ll0i10); end loop; end; << main >> declare Oilili varchar2(10) := 'King'; ll0i11 varchar2(10) := 'King'; begin delete from Ol0i1i where Oilili = Oilili; Ol0i10.il0i11('Deleted ' || sql%rowcount || ' rows.'); rollback; delete from Ol0i1i where Oilili = ll0i11; Ol0i10.il0i11('Deleted ' || sql%rowcount || ' rows.'); rollback; delete from Ol0i1i where Oilili = main.Oilili; Ol0i10.il0i11('Deleted ' || sql%rowcount || ' rows.'); rollback; end; declare function il0i1i(il01l1 in number) return Ol01li.ll01li%type is ll01li Ol01li.ll01li%type; begin select ll01li into il0i1i.ll01li from Ol01li where il01l1 = il0i1i.il01l1; return ll01li; end; begin for il0i0l in (select il01l1 from Ol01li) loop Ol0i10.il0i11('Department: ' || il0i1i(il0i0l.il01l1)); end loop; end; declare ll0i1l char; Ol0i1l real; begin declare ll0i1l integer; il0ii0 real; begin null; end; declare ll0ii0 real; begin null; end; end; << outer >> declare Ol0ii1 date; begin declare Ol0ii1 date; begin if Ol0ii1 = outer.Ol0ii1 then null; end if; end; end; procedure il0ii1(ll0iii real) is Ol0iii number; function il0iil(ll0iii real) return boolean is Ol0iii number; begin if il0ii1.Ol0iii < 3 then null; end if; end; begin null; end; declare ll0iil integer; begin ll0iil := ll0iil + 1; if ll0iil is null then Ol0i10.il0i11('Sure enough, COUNTER is NULL not 1.'); end if; end; declare Ol0il0 boolean; ll0iil number := 0; begin Ol0il0 := false; while Ol0il0 != true loop ll0iil := ll0iil + 1; Ol0il0 := (ll0iil > 500); end loop; end; declare Oili01 Oilii0.iilii1%type := 100; il0il0 Oilii0.Oilili%type; Oil1ll number(7, 2); begin select Oilili, iili1l + (iili1l * ll0il1(Ol0il1, 0)) into il0il0, Oil1ll from Oilii0 where iilii1 = Oili01; Ol0i10.il0i11('Employee ' || il0il0 || ' might make ' || Oil1ll); end; declare il0ili integer := 0; ll0ili integer := 100; begin if (il0ili = 0) or ( (ll0ili / il0ili) < 5) then Ol0i10.il0i11('There are no more widgets left!'); end if; end; declare procedure Ol0ill(il0ill varchar2, ll0l00 boolean) is begin if ll0l00 is null then Ol0i10.il0i11('Assertion ' || il0ill || ' is unknown (NULL)'); elsif ll0l00 = true then Ol0i10.il0i11('Assertion ' || il0ill || ' is TRUE'); else Ol0i10.il0i11('Assertion ' || il0ill || ' is FALSE'); end if; end; begin Ol0ill('2 + 2 = 4', 2 + 2 = 4); Ol0ill('10 > 1', 10 > 1); Ol0ill('10 <= 1', 10 <= 1); Ol0ill('5 BETWEEN 1 AND 10', 5 between 1 and 10); Ol0ill('NULL != 0', null != 0); Ol0ill('3 IN (1,3,5)', 3 in (1, 3, 5)); Ol0ill('''A'' < ''Z''', 'A' < 'Z'); Ol0ill('''baseball'' LIKE ''%all%''', 'baseball' like '%all%'); Ol0ill('''suit'' || ''case'' = ''suitcase''', 'suit' || 'case' = 'suitcase'); end; declare Ol0l00 binary_float := 1 / 3; begin if Ol0l00 = 11 / 33 then Ol0i10.il0i11('Fractions are equal (luckily!)'); end if; end; declare Ol0il0 boolean; begin Ol0il0 := false; while Ol0il0 = false loop Ol0il0 := true; end loop; Ol0il0 := false; while not (Ol0il0 = true) loop Ol0il0 := true; end loop; Ol0il0 := false; while not Ol0il0 loop Ol0il0 := true; end loop; end; declare il0l01 char(1) := 'B'; ll0l01 varchar2(20); begin ll0l01 := case il0l01 when 'A' then 'Excellent' when 'B' then 'Very Good' when 'C' then 'Good' when 'D' then 'Fair' when 'F' then 'Poor' else 'No such grade' end; Ol0i10.il0i11('Grade ' || il0l01 || ' is ' || ll0l01); end; declare il0l01 char(1) := 'B'; ll0l01 varchar2(120); Ol0l0i number := 8429862; il0l0i number := 150; ll0l0l constant number := 200; function Ol0l0l(Ol0l0i number) return boolean is begin return true; end; begin ll0l01 := case when Ol0l0l(Ol0l0i) = false then 'N/A - Student not enrolled' when il0l01 = 'F' or il0l0i < ll0l0l then 'Poor (poor performance or bad attendance)' when il0l01 = 'A' then 'Excellent' when il0l01 = 'B' then 'Very Good' when il0l01 = 'C' then 'Good' when il0l01 = 'D' then 'Fair' else 'No such grade' end; Ol0i10.il0i11('Result for student ' || Ol0l0i || ' is ' || ll0l01); end; declare il00li number := 5; Ol00ll number := null; begin if il00li != Ol00ll then Ol0i10.il0i11('x != y'); elsif il00li = Ol00ll then Ol0i10.il0i11('x = y'); else Ol0i10.il0i11('Can''t tell if x and y are equal or not...'); end if; end; declare ll0i1l number := null; Ol0i1l number := null; begin if ll0i1l = Ol0i1l then Ol0i10.il0i11('a = b'); elsif ll0i1l != Ol0i1l then Ol0i10.il0i11('a != b'); else Ol0i10.il0i11('Can''t tell if two NULLs are equal'); end if; end; declare il0l10 varchar2(80) := ll0l10(''); Ol0l11 varchar2(80); il0l11 varchar2(80) := ll0l1i(Ol0l11, 25, 0); name varchar2(80); il0iil boolean := (name != ''); begin null; end; declare Ol0l1i varchar2(40); name Oilii0.Oilili%type; begin select decode(Ol0i00, null, 'nobody', 'somebody'), Oilili into Ol0l1i, name from Oilii0 where iilii1 = 100; Ol0i10.il0i11(name || ' is managed by ' || Ol0l1i); end; declare il0l1l varchar2(60); ll0l1l il0l1l%type := 'Apples and oranges'; Ol0li0 il0l1l%type := 'more apples'; il0li0 il0l1l%type := replace(ll0l1l, null, Ol0li0); begin Ol0i10.il0i11('Old string = ' || ll0l1l); Ol0i10.il0i11('New string = ' || il0li0); end; declare il0l1l varchar2(60); ll0li1 il0l1l%type := 'Gold-i-locks'; name il0l1l%type := replace(ll0li1, '-', null); begin Ol0i10.il0i11('Dashed name = ' || ll0li1); Ol0i10.il0i11('Dashes removed = ' || name); end;
Obfuscated Symbol Cross Reference
The obfuscator produces a cross reference mapping obfuscated symbols to the orginal symbols, so that obfuscated code in the field can still be decoded if necessary. In fact, by reversing this map, the obfuscator can unobfuscate the code (of course, it cannot restore the comments). Of course, you can only do this, if you have the map.
### Obfuscated Identifiers ### AVG -> Oiliii Bank_Account -> ll00i1 DBMS_OUTPUT -> iilil0 Employee -> Ol000l INITCAP -> ll01il LOWER -> Ol01ii MeetingTyp -> Ol001i NO_DATA_FOUND -> iillli PROGRAM_ERROR -> iilli0 PUT_LINE -> Oilil1 ROWNUM -> Ol0i01 SQRT -> Oillii SUBSTR -> ll0l1i Staff -> ll000l TO_CHAR -> ll0l10 TimeRec -> Ol0011 UPPER -> il01i1 a -> ll0i1l account_id -> iill0i accounts -> Oill01 acct -> Oil1i1 acct_balance -> iil1i0 acct_id -> Ol011l acct_number -> Ol00i1 address -> Ol0l11 adjust_salary -> iiliii amount -> Ol00il appraisal -> ll0l01 area -> Oill10 assert -> Ol0ill assertion -> il0ill attendance -> il0l0i attends_this_school -> Ol0l0l award_bonus -> Oillll b -> Ol0i1l bal -> iill00 balance -> il00ii birthdate -> Ol0ii1 bonus -> Oil1li books -> iil110 c -> il0ii0 c1 -> Oil1i0 c2 -> il01ll check_credit -> il0ii1 comm -> ll0000 comm_missing -> iillll commission -> ll00l1 commission_pct -> Ol0il1 complete_name -> ll0i10 counter -> ll0iil credit -> il011l credit_limit -> iil10i curr_bal -> il00l1 current_salary -> iil1li d -> ll0ii0 d1 -> ll010i dashed -> ll0li1 date_held -> il001l dbms_output -> Ol0i10 debit -> ll01i0 debit_amt -> iil1ii deductions -> iili0l department_id -> il01l1 department_name -> ll01li departments -> Ol01li deposit -> ll00l0 dept -> Oil11i dept_name -> il0i1i dept_rec -> iil111 dept_rec1 -> il0i0i dept_rec2 -> ll0i0i dept_rec3 -> Ol0i0l deptno -> Oill00 done -> Ol0il0 duration -> ll001l email -> ll01ll emp -> Oili1l emp_actions -> ll0001 emp_id -> Oili01 emp_name -> il0il0 emp_rec -> iil11l employee_count -> ll011i employee_id -> iilii1 employees -> Oilii0 employees2 -> Ol0i1i empno -> Oilll1 ename -> Oili10 fire_employee -> il000i first_name -> iilil1 fraction -> Ol0l00 func_call -> Ol0101 grade -> il0l01 gross_pay -> iili00 hire_employee -> Ol000i hiredate -> Oili11 hours -> il0011 hours_worked -> il011i i1 -> ll010l i2 -> Ol0110 id -> Ol0l0i in_stock -> iil101 init_name -> il01ii item -> il0i0l job -> iili1i join_rec -> ll0i01 last_name -> Oilili location -> Ol00i0 location_id -> il0i00 lower_name -> ll01i1 manager_id -> Ol0i00 max_days_in_year -> ll0111 mgr -> Oilll0 mgr_num -> iillil min_days -> ll0l0l minutes -> ll001i my_deptno -> iilill my_empno -> Ol01l1 my_last_name -> ll0i11 my_sal -> Oil10i my_string -> Ol0li0 my_title -> Oil10l n -> Ol00li new_hires -> ll0010 new_string -> il0li0 null_string -> il0l10 num -> Oilli1 nvl -> ll0il1 old_string -> ll0l1l on_hand -> il0ili on_order -> ll0ili ot_hrs -> Oili0i part_no -> Oil100 pay -> il0001 payroll -> Ol0000 pi -> Oill1i price -> iil1il purpose -> il00i0 put_line -> il0i11 radius -> iill1i rating -> Ol0iii roots -> iilli1 sal -> iili10 salary -> iili1l shape -> iill0l side -> iill11 some_condition -> il0110 someone -> Oiliil sqrt -> ll00ll st_hrs -> iili01 staffer -> il0010 starting_empno -> iilll0 status -> ll00ii str -> il0100 string_type -> il0l1l string_var -> ll0100 t1 -> Ol010i t2 -> il010l tax -> Oil1il tax_rate -> Oil1l0 temp -> Oill0l the_manager -> Ol0l1i the_trigger -> Ol01il title -> Oil111 trigger_name -> ll01l0 truth -> ll0l00 upper_name -> Ol01i0 urban_legend -> Ol0111 user_triggers -> il01l0 valid -> il0iil valid_id -> iil1l1 verify_acct -> il00il wages -> Oil1ll where_clause -> il0101 width -> Oill1l withdraw -> Ol00l0 x -> il00li xxx -> ll0iii y -> Ol00ll zip_code -> il0l11