Dear readers
my reference in this post from Pete Finnigan book How to unwrap PL/SQL
my reference in this post from Pete Finnigan book How to unwrap PL/SQL
|
|
How to unwrap PL/SQL Pete Finnigan, Why is there a problem with wrapped PL/SQL Intellectual property can be revealed if PL/SQL is un- wrapped This can include Your own application source code Oracle shipped features hidden by the wrapper In 9i and lower wrapped PL/SQL revealed symbols Finding SQL injection bugs just became easier There are PL/SQL unwrapping tools available PL/SQL language compilation structure PL/SQL source code PL/SQL compiler front end DIANA – An intermediate language for ADA Compiler back end Virtual machine M-Code DIANA is the key for 9i and lower PL/SQL is based on ADA DIANA – Descriptive intermediate language for ADA DIANA is an abstract data type DIANA is an intermediate form of PL/SQL programs Intended to communicate between the front end and back ends of a PL/SQL compiler Each defining DIANA entity represents a PL/SQL entity Two trees – Abstract syntax tree constructed prior to semantic analysis Attributed tree (the DIANA structure) IDL – Interface description language DIANA is written down as IDL What is IDL? – Interface description language – Also derived from ADA IDL is stored in the database in 4 dictionary tables IDL_CHAR$, IDL_SB4$, IDL_UB1$ and IDL_UB2$ Wrapped PL/SQL is simply DIANA written down as IDL Oracle say that wrapped PL/SQL is simply encoded Therefore the wrap program is the front end of a PL/SQL compiler. Is wrapped PL/SQL – DIANA – reversible? A book about DIANA DIANA – An Intermediate Language Quote from page 165: for ADA Editors: G. Goos, W.A. Wulf “Appendix III – Reconstructing the A. Evans, Jr and K.J. Butler source” Springer-Verlag “One of the basic principals of DIANA is that the structure of the ISBN : 0387126953 original source program is to be Revised Edition (December 1983) retained in the DIANA representation…..” “There is a close correspondence between ADA’s syntax and DIANA’s structural attributes… It is this correspondence that permits source code reconstruction.” From Oracle’s own documentation PL/SQL User's Guide and Reference 10 g Release 1 (10.1) Part Number B10807-01 “PL/SQL is based on ADA, as a result PL/SQL uses a variant of DIANA, a tree structured language….” “It is defined using a meta notation called IDL (Interface Definition Language)…” “DIANA is used internally by compilers and other tools…..” “At compile time PL/SQL is translated into M-Code. Both DIANA and M-Code are stored in the database….” A Sample PL/SQL procedure – 9i SQL>connect sys/change_on_install as sysdba Connected. SQL>create or replace procedure AA as begin null; end; / Procedure created. SQL> Save the PL/SQL and wrap the code Wrapping is simple. Save the PL/SQL SQL>save aa.sql to a file and run the wrap utility. Created file aa.sql d:\orant\bin>wrap iname=aa.sql oname=aa.pls PL/SQL Wrapper: Release 9.2.0.1.0- Production on Mon Jun 19 18:05:57 2006 Copyright (c) Oracle Corporation 1993, 2001. All Rights Reserved. Processing aa.sql to aa.pls create or replace procedure 0 AA wrapped 0 0 f abcd 2 {snipped 15 identical lines} 0 9a b4 55 6a 4f b7 a4 3 b1 11 68 4f 1d 17 b5 7 f 9200000 2 1 0 3 17 18 1c 20 22 24 4 28 2a 36 3a 3c 3d 46 0 {file contents snipped} 1 2 :e: What is the meaning of this encoded file? – 1AA: Note the highlights – we will see them again 0 9i and below wrapped PL/SQL weaknesses SQL>create or replace procedure encode (credit_card in varchar2, str out varchar2) is key varchar2(16):='01234567890ABCDEF'; begin null; end; / Procedure created. SQL>save encode.sql 01234567890ABCDEF : G:\orant\bin>wrap iname=encode.sql oname=encode.plb PL/SQL Wrapper: Release 9.2.0.1.0- Production on Fri Jun 23 15:43:47 2006 Copyright (c) Oracle Corporation 1993, 2001. All Rights Reserved. Processing encode.sql to encode.plb Hacking wrapped PL/SQL – pre-9i The symbol table is visible For the previous example it is possible to Deduce the purpose of the procedure Find out the encryption algorithm used using DBA_DEPENDENCIES unless it is implemented internally to the procedure Decrypt Credit Cards – in this case Trojans can be planted Wrapped source can be modified without un-wrapping Example: Fixed DBMS_OUTPUT limits problem SQL injection identification is possible / DDL can be altered The relationships in 9i PL/SQL Source Diana and M-Code IDL_CHAR$ Wrap utility IDL_UB1$ IDL_UB2$ IDL_SB4$ Wrapped File Source Code SOURCE$ create or replace procedure aa wrapped 0 DBA_SOURCE abcd abcd ALL_SOURCE abcd abcd abcd Abcd …. The dictionary tables and views SQL> desc idl_ub1$ SYS.IDL_CHAR$ Name Null? Type SYS.IDL_UB1$ ------------- -------- ---------- SYS.IDL_UB2$ OBJ# NOT NULL NUMBER SYS.IDL_SB4$ PART NOT NULL NUMBER SYS.SOURCE$ VERSION NUMBER PIECE# NOT NULL NUMBER SQL> desc source$ LENGTH NOT NULL NUMBER Name Null? Type PIECE NOT NULL LONG RAW --------------- -------- ---------- ------- From $OH/rdbms/admin/sql.bsq OBJ# NOT NULL NUMBER /* part: 0 = diana, 1 = portable LINE NOT NULL NUMBER pcode, 2 = machine-dependent pcode SOURCE VARCHAR2(4000) */ Recursive SQL What is recursive SQL? – background supporting SQL needed to execute the submitted statement When compiling PL/SQL there are other background SQL statements that need to run as SYS Check for user’s privileges and roles Triggers Retrieving the PL/SQL code to run Indexes How can we see the complete picture? Using traces, dumps and events Trace the compilation of PL/SQL SQL>alter session set events '10046 trace name context forever, level 12'; Session altered. SQL>create or replace procedure aa is begin null; end; / Procedure created. SQL>alter session set events '10046 trace name context off'; Session altered. SQL> Locate the trace file and check the contents PARSING IN CURSOR #2 len=106 dep=1 uid=0 oct=6 lid=0 tim=465432930704 hv=1545875908 ad='66f37b44' update idl_ub2$ set piece#=:1 ,length=:2 , piece=:3 where obj#=:4 and part=:5 and piece#=:6 and version=:7 END OF STMT PARSE #2:c=0,e=42,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=465432930696 BINDS #2: bind 0: dty=2 mxl=22(22) mal=00 scl=00 pre=00 oacflg=08 oacfl2=1 size=24 offset=0 bfp=04822394 bln=24 avl=02 flg=05 value=4 bind 1: dty=2 mxl=22(22) mal=00 scl=00 pre=00 oacflg=08 oacfl2=1 size=24 offset=0 bfp=04822364 bln=24 avl=03 flg=05 value=123 bind 2: dty=25 mxl=4000(4000) mal=00 scl=00 pre=00 oacflg=12 oacfl2=1 size=4000 offset=0 bfp=04c67ff4 bln=4000 avl=246 flg=09 value= Those numbers Dump of memory from 0x04C67FF4 to 0x04C680EA 4C67FF0 00030000 000D000C 00250011 [..........%.] look familiar! 4C68000 002A0029 0038002C 003E003A 00000040 [).*.,.8.:.>.@...] 4C68010 001D0017 009A0068 00B40055 001100B5 [....h...U.......] 4C68020 00A400B1 004F00B7 00010000 00010001 [......O.........] 4C68030 00010001 00010001 00010001 00010001 [................] 4C68040 00000001 00010001 000B0001 00010001 [................] DIANA for package bodies is not stored (idl.sql) SQL>select count(*),'CHAR$',part,object_type from idl_char$,dba_objects where obj#=object_id and part=0 group by part,object_type union select count(*),'UB1$',part,object_type from idl_ub1$,dba_objects where obj#=object_id and part=0 group by part,object_type union select count(*),'UB2$',part,object_type from idl_ub2$,dba_objects where obj#=object_id and part=0 group by part,object_type union select count(*),'SB4$',part,object_type from idl_sb4$,dba_objects where obj#=object_id and part=0 group by part,object_type order by 2 SQL> select dbms_rowid.rowid_block_number(rowid) blk, SQL> @rowid 2 dbms_rowid.rowid_relative_fno(rowid) fno, 3 dbms_rowid.rowid_row_number(rowid) rnum, BLK FNO RNUM 'CHAR PART VERSION PIECE# LENGTH 4 'CHAR$',part,version,piece#,length ------ --- ---- ----- ---------- ---------- ---------- ---------- 5 from idl_char$ 49951 1 24 sb4$ 0 153092096 0 14 6 where obj#=(select obj# from obj$ where name = 'AA') 49951 1 48 sb4$ 0 153092096 1 2 7 union 42671 1 21 ub1$ 0 153092096 2 3 8 select dbms_rowid.rowid_block_number(rowid) blk, 35792 1 36 CHAR$ 0 153092096 3 5 9 dbms_rowid.rowid_relative_fno(rowid) fno, 50581 1 8 UB2$ 0 153092096 4 123 10 dbms_rowid.rowid_row_number(rowid) rnum, 50581 1 9 UB2$ 0 153092096 5 10 11 'UB2$',part,version,piece#,length 49951 1 50 sb4$ 2 153092096 0 18 12 from idl_ub2$ 42671 1 10 ub1$ 2 153092096 1 112 13 where obj#=(select obj# from obj$ where name = 'AA') 42671 1 13 ub1$ 2 153092096 2 1 14 union ` 15 select dbms_rowid.rowid_block_number(rowid) blk, 9 rows selected. 16 dbms_rowid.rowid_relative_fno(rowid) fno, 17 dbms_rowid.rowid_row_number(rowid) rnum, 18 'ub1$',part,version,piece#,length 19 from idl_ub1$ 20 where obj#=(select obj# from obj$ where name = 'AA') 21 union 22 select dbms_rowid.rowid_block_number(rowid) blk, 23 dbms_rowid.rowid_relative_fno(rowid) fno, 24 dbms_rowid.rowid_row_number(rowid) rnum, 25 'sb4$',part,version,piece#,length 26 from idl_sb4$ 27 where obj#=(select obj# from obj$ where name = 'AA') 28 order by part,piece# SQL> save rowid.sql Dump the datablocks to find the DIANA Why do we need to dump datablocks for the IDL$ tables? SQL>select piece from sys.idl_ub2$ where obj#=(select obj# from obj$ where name='AA') and part=0 and piece#=4; ERROR: ORA-00932: inconsistent datatypes: expected %s got %s no rows selected SQL>alter system dump datafile 1 block 50581; System altered. The contents of the block dump for IDL_UB2$ tab 0, row 8, @0x11b1 tl: 271 fb: --H-FL-- lb: 0x1 cc: 6 Those values look familiar but col 0: [ 4] c3 04 05 0a col 1: [ 1] 80 in a different order col 2: [ 6] c5 02 36 0a 15 61 col 3: [ 2] c1 05 col 4: [ 3] c2 02 18 col 5: [246] 00 00 03 00 0c 00 0d 00 11 00 25 00 29 00 2a 00 2c 00 38 00 3a 00 3e 00 40 00 00 00 17 00 1d 00 68 00 9a 00 55 00 b4 00 b5 00 11 00 b1 00 a4 00 b7 00 4f 00 00 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 01 00 01 00 01 00 0b 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 01 00 00 00 00 00 00 00 02 00 03 00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 05 00 08 00 01 00 01 00 05 00 08 00 00 00 00 00 04 00 00 00 00 00 ff 00 01 00 00 00 03 00 01 00 20 00 00 00 00 00 00 00 00 00 00 00 01 00 06 00 00 00 00 00 03 00 00 00 00 00 00 00 09 00 0b 00 0a 00 00 00 00 00 00 00 00 00 00 00 04 00 03 00 00 00 00 00 00 00 08 00 00 00 08 00 00 00 08 00 03 00 08 00 00 00 0b 00 00 00 00 00 00 00 01 00 0c 00 IDL dependencies – (a detour) SQL> select distinct owner,name,type from dba_dependencies where referenced_name like 'IDL_%'; OWNE NAME TYPE ---- -------------------- ------------ SYS ALL_PROBE_OBJECTS VIEW SYS CODE_PIECES VIEW SYS INITJVMAUX PACKAGE BODY SYS ORA_KGLR7_IDL_CHAR VIEW SYS ORA_KGLR7_IDL_SB4 VIEW SYS ORA_KGLR7_IDL_UB1 VIEW SYS ORA_KGLR7_IDL_UB2 VIEW SYS PARSED_PIECES VIEW SYS RMJVM PACKAGE BODY How are IDL tables used? SQL>desc code_pieces SQL>set long 1000000 SQL>select text from dba_views where view_name='CODE_PIECES' SQL>select text from dba_source where name='PIDL'; package PIDL is ---------------------------------------------------------------------------- -- Persistent IDL datatypes ---------------------------------------------------------------------------- subtype ptnod is binary_integer; -- generic IDL node type TRENULL CONSTANT ptnod := 0; -- a NULL node subtype ub4 is binary_integer; -- Oracle C type, unsigned byte 4 subtype ub2 is binary_integer; -- Oracle C type, unsigned byte 2 {Output snipped to 550 lines} SQL>select text from dba_source where name='DIANA'; SQL>desc diutil PROCEDURE ATTRIBUTE_USE_STATISTICS Argument Name Type In/Out Default? ----------------------- ----------------------- ------ -------- LIBUNIT_NODE BINARY_INTEGER IN ATTRIBUTE_COUNT BINARY_INTEGER OUT ATTRIBUTE_LIMIT BINARY_INTEGER OUT PROCEDURE GET_D Argument Name Type In/Out Default? ----------------------- ----------------------- ------ -------- NAME VARCHAR2 IN USR VARCHAR2 IN DBNAME VARCHAR2 IN DBOWNER VARCHAR2 IN STATUS BINARY_INTEGER IN/OUT NOD BINARY_INTEGER OUT LIBUNIT_TYPE NUMBER IN DEFAULT LOAD_SOURCE NUMBER IN DEFAULT {snipped} Dumpdiana – a script to dump the DIANA $ORACLE_HOME/rdbms/admin/dumpdian.sql Not installed by default Run the script as SYS There are two bugs to fix – remove the lines REM ---- Ensure DIANA, PIDL and DIUTIL PL/SQL packages are installed as well Run for sample ‘AA’ procedure as SYS – (output to trace) :- SQL>exec sys.dumpdiana.dump(aname => 'AA'); PL/SQL procedure successfully completed. Reconstructing PL/SQL source from DIANA - 1 Block syntax for PL/SQL Block_statement ::= [block_simple_name] [ declare declarative part] begin sequence of statements [exception exception handler {exception handler}] end [block_simple_name] ; Diana Rules block => as_item : DS_ITEM, as_stm : D_STM, as_alter : DS_ALTER; See page 166 – Goos / Wulf et al An alternate DIANA dump {output snipped} PD3(4) : D_S_BODY: [ SRCPOS: row 1 col 1 A_D_: PD4(4) : DI_PROC: [...] A_HEADER: PD5(4) : D_P_: [...] A_BLOCK_: PD8(4) : D_BLOCK: [...] A_UP: PD1(4) : <reference to D_COMP_U (262145)> ] PD4(4) : DI_PROC: [ SQL>exec sys.dumpdiana.dump(aname => 'AA',print_format => 1); Declare It is easy to see the close <DS_ITEM> relationship between PL/SQL Begin and DIANA <DS_STM> Then it is easy to see how Exception PL/SQL can be reconstructed <DS_ALTER> from DIANA End; Mapping IDL to DIANA Code Dec name Take the node names from the 0 0 ? DIANA tree or line dump 9a 154 DI_PROC b4 180 DS_PARAM Use the DIANA package 55 85 D_P_ constants 6a 106 D_S_DECL 4f 79 D_NULL_S Convert dec numbers to Hex b7 183 DS_STM a4 164 DS_ALTER These hex numbers are b1 177 DS_ITEM familiar? 11 17 D_BLOCK 68 104 D_S_BODY Wrap file / idl / diana dumps 4f 79 D_NULL_S are all the same 1d 29 D_CONTEX 17 23 D_COMP_U Hence wrap format is DIANA b5 181 DS_PRAGM Simple tree structure D_COMP_U DS_BODY DI_PROC D_P_ D_BLOCK L_symrep = ‘AA’ DS_PARAM DS_ITEM DS_STM D_NULL_S DS_ALTER DIANA utilities - pstub SQL> variable a varchar2(2000); SQL> variable b varchar2(2000); SQL> exec sys.pstub('AA',NULL,:a,:b); PL/SQL procedure successfully completed. SQL> print :b B -------------------------------------------------------------------- ------------ procedure AA is begin stproc.init('begin AA; end;'); stproc.execute; end; procedure AA is begin stproc.init('begin AA; end;'); stproc.execute; end; procedure AA is begin stproc.init('begin AA; end;'); stproc.execute; end; SQL> DIANA utilities - subptxt SQL> variable a varchar2(2000); SQL> exec sys.subptxt('AA',NULL,NULL,:a); PL/SQL procedure successfully completed. SQL> print :a A ------------------------------------------------------ procedure AA; SQL> PSTUB and SUBPTXT PSTUB and SUBPTXT are demonstration programs that use the IDL and DIANA API’s PSTUB is used to allow the calling of V2 PL/SQL in the server from V1 PL/SQL client tools such as Forms SUBPTXT allows the describing of PL/SQL Both read DIANA and not PL/SQL source code Pistub.sql and the library diutil.sql are the only public example programs to use the DIANA and PIDL packages Diutil.exprtext (private function) is an excellent example of how to use DIANA and PIDL package calls Writing a PL/SQL un-wrapper To create an unwrapping tool we need To understand the relationship between DIANA and PL/SQL language constructs A way to parse the DIANA in the correct order – API calls? A way to read and understand the DIANA node types – API calls? A way to read variable attributes for each node and to read their type and value – API calls Mapping PL/SQL to DIANA for some language constructs can be done using test programs and dumpdiana Limitations of a PL/SQL API based un-wrapper A comprehensive PL/SQL un-wrapper can be written using the IDL and DIANA PL/SQL package API’s The $OH/rdbms/admin/diutil.sql file indicates how PIDL API’s do not emit the complete DIANA The DIANA for the body of procedures and functions is not available via the dumpdiana, PIDL, DIANA interfaces (see the next slide) The DIANA dump misses PL/SQL in the block section. Local variables are also not included It could be possible to write a complete un-wrapper in PL/SQL and read the DIANA from SYS.SOURCE$ PL/SQL API limitations SQL> create or replace procedure ah (i in number, j out varchar2) is PD13(7) : DS_STM: [ 2 begin SRCPOS: row 1 col 0 3 if i = 7 then AS_LIST: PDa(7) : <sequence of 1 item: 4 j := 3; PD14(7)> 5 else A_UP: PD10(7) : <reference to D_BLOCK (458768)> 6 j := 4; ] 7 end if; PD14(7) : D_NULL_S: [ 8 end; SRCPOS: row 1 col 1 9 / C_OFFSET: ub4: '0' A_UP: PD13(7) : <reference to DS_STM (458771)> Procedure created. ] SQL> exec dumpdiana.dump(aname => 'AH',print_format => 1); PL/SQL procedure successfully completed. Enumerating DIANA nodes and attributes SQL> exec attrib(23); Node Type D_COMP_U Num Attributes 9 See attrib.sql - Also at 0: 9:A_CONTEX:1: REF 1 http://www.petefinnigan.com/att 1: 40:A_UNIT_B:1: REF 1 rib.sql 2: 62:AS_PRAGM:1: REF 1 3: 114:SS_SQL:30: REF 0 Uses PIDL to enumerate 4: 113:SS_EXLST:30: REF 0 DIANA nodes and attributes 5: 111:SS_BINDS:30: REF 0 6: 41:A_UP:1: REF 0 7: 138:A_AUTHID:2: REF 0 8: 142:A_SCHEMA:2: REF 0 PL/SQL procedure successfully completed. SQL> Creating a real PL/SQL un-wrapper Can a complete un-wrapper be written? – Of course, yes There are at least 4 unwrapping tools that I know of The complete PL/SQL and SQL grammars are needed - http://www.antlr.org/grammar/1107752678378/PLSQLGrammar.g - Also see “PL/SQL user reference guide” It is necessary to understand all DIANA nodes and to map those to PL/SQL – this is not fully documented (partly it is documented as ADA / DIANA) It is necessary to understand the wrap file format and to extract the DIANA nodes and attributes from it It may be possible to disassemble M-Code back to PL/SQL The symbols are embedded in the M-Code Keywords SQL> desc v$reserved_words Name Null? Type ----------------------- -------- ------------------- KEYWORD VARCHAR2(64) LENGTH NUMBER SQL> select count(*) from v$reserved_words; COUNT(*) ---------- 809 SQL> Showing the PL/SQL M-Code as assembler SQL>create or replace procedure ab as ae number:=1; begin ae:=ae+1; end; / Procedure created. SQL>alter session set events '10928 trace name context forever, level 1'; Session altered. SQL>exec ab; PL/SQL procedure successfully completed. SQL>alter session set events '10928 trace name context off'; Session altered. SQL> The M-Code assembler Entry #1 PL/SQL source is shown 00001: ENTER 4, 0 <source not available> When wrapped – source not 00007: XCAL 1, 1 available – is shown Entry #1 SYS.AB: 00001: ENTER 76, 0 M-Code is mapped to PL/SQL SYS.AB: 00007: INFR DS[0]+96 line numbers Frame Desc Version = 2, Size = 22 # of locals = 2 This implies that the line and TC_SSCALARi: FP+4, d=FP+12 column details are held in the M- TC_SSCALARi: FP+8, d=FP+44 Code [Line 2] ae number:=1; SYS.AB: 00012: CVTIN HS+0 =1=, FP+4 [Line 4] ae:=ae+1; SYS.AB: 00017: CVTIN HS+0 =1=, FP+8 SYS.AB: 00022: ADDN FP+4, FP+8, FP+4 SYS.AB: 00029: RET 00012: RET Native compilation and initialisation parameters PL/SQL can be natively compiled There are a number of initialisation parameters – “ sho parameter ” in SQL*Plus It is possible in some versions to use the native compilation to hack Oracle It could be possible to inject PL/SQL code via native compilation The generated C Code is M-Code VM calls for each instruction Some sample code – getting started SQL>set serveroutput on size See unwrap.sql (also on 1000000 http://www.petefinnigan.com/unw SQL>exec unwrap('AA'); rap.sql Start up Root Node :262145 Test program to Root code (hex) :23 Familiarise with the API’s Root Type :D_COMP_U -- Walk the DIANA nodes A_UNIT_B Node :262147 Read attributes A_UNIT_B Type :D_S_BODY A_UNIT_B code (hex) :104 It works! Next, work out the -- PL/SQL that should be emitted A_D_ Node :262148 for each node or node group A_D_ Type :DI_PROC A_D_ code (hex) :154 -- A_HEADER Node :262149 A_HEADER Type :D_P_ A_HEADER code (hex) :85 PL/SQL code generation “CREATE %{} END;\ DS_BODY l_symrep => PROCEDURE ‘AA’ DI_PROC = ‘AA’ {not implemented} D_P_ = params {not implemented} DS_PARAM “IS” “BEGIN” %{} “EXCEPTION” %{} D_BLOCK “END;” DS_ITEM – local variable {not implemented} DS_STM No output D_NULL_S NULL; DS_ALTER {not implemented} A proof of concept un-wrapper SQL>set serveroutput on size 1000000 SQL>exec unwrap_r('AA'); Start up Unwrap_r.sql – also available CREATE OR REPLACE from PROCEDURE AA http://www.petefinnigan.com/un IS wrap_r.sql BEGIN Implements the code NULL; generation to create PL/SQL END; \ from DIANA for a simple procedure PL/SQL procedure successfully completed. Uses a simple recursive descent parser SQL> Unwrap_r.sql recursive function create or replace procedure unwrap_r(aname varchar2) is root sys.pidl.ptnod; status sys.pidl.ub4; procedure recurse (n sys.pidl.ptnod) is seq sys.pidl.ptseqnd; len integer; begin if(pidl.ptkin(n) = diana.d_comp_u) then recurse(diana.a_unit_b(n)); elsif (pidl.ptkin(n) = diana.d_s_body) then dbms_output.put_line('CREATE OR REPLACE '); recurse(diana.a_d_(n)); recurse(diana.a_header(n)); recurse(diana.a_block_(n)); dbms_output.put_line('END;'); dbms_output.put_line('/'); {output snipped} 10g – Different but the same? New A new wrap mechanism has been provided The contents of symbol table are no longer visible The encryption involves base64 10gR2 provides the ability to wrap from within the database using DBMS_DDL There is a new optimizing compiler for PL/SQL Old The IDL$ tables still contain DIANA and M-Code The DIANA, PIDL, DIUTIL and DUMPDIANA packages are still available It is still possible to reverse simple procedures using the API’s The 10g wrapped procedure SQL>select text from dba_source where name='AA'; TEXT This is base64 character set procedure aa wrapped a000000 Using base64 decode does not 1 abcd reveal the source {identical output snipped} abcd The symbol table is not visible 7 21 55 tpZtVM0u7lC31uX+QfYfxhNmy+Awg5nnm7+fMr2ywFy49cOldIvAwDL+0oabmYEILYvAgcct yaam9+Lntg== Create procedure and check IDL use in 10g SQL>create or replace procedure aa is begin null; end; / Procedure created. Roughly the same IDL is SQL>save aa.sql replace Wrote file aa.sql created in the database as 9i SQL>!wrap iname=aa.sql oname=aa.pls SQL>@aa.pls Procedure created. SQL>@rowid BLK FNO RNUM 'CHAR PART VERSION PIECE# LENGTH ------ --- ---- ----- ---------- ---------- ---------- ---------- 49722 1 22 sb4$ 0 167772160 0 14 49722 1 23 sb4$ 0 167772160 1 2 24966 1 7 ub1$ 0 167772160 2 3 46407 1 14 CHAR$ 0 167772160 3 5 52973 1 6 UB2$ 0 167772160 4 131 52973 1 7 UB2$ 0 167772160 5 10 49722 1 24 sb4$ 2 167772160 0 18 15481 1 0 ub1$ 2 167772160 1 174 15481 1 1 ub1$ 2 167772160 2 1 9 rows selected. Simple unwrapping PL/SQL in 10g SQL>exec dumpdiana.dump(aname => 'AA'); user: SYS PL/SQL procedure successfully completed. SQL>@unwrap_r Running dumpdiana Procedure created. creates the same DIANA SQL>exec unwrap_r('AA'); tree dump trace file as 9i Start up CREATE OR REPLACE Running the proof of PROCEDURE AA concept un-wrapper still IS works in 10g BEGIN NULL; The wrap process in 10g END; is different though / PL/SQL procedure successfully completed. |
No comments:
Post a Comment