Dumping SGA to read encrypted blocks

by Kamil Stawiarski

After my last article AMM vs security, Martin Berger wrote to me:

even without AMM you can do it:
write your own process which attaches to the same shm segments – and use its memory mapping (?)

My response was that it is also possible with ASMM but AMM makes it extremely easy. And this is because you can treat memory as regular binary files when operating on AMM.

Today I want to show you how dump blocks from SGA which is configured as ASMM to get into encrypted data which is also protected by Oracle Database Vault. To set up the environment I will use examples from a previous blog post.

Code for sgadump is written in GoLang, so please use those instructions to setup your environment: https://golang.org/doc/install

Please make sure that your ENV is set up properly:

[oracle@rokoko ~]$ cat .bash_profile | grep go

After installing GoLang you can do the following to compile my tool:

[oracle@rokoko ~]$ mkdir -p ~/go/src/github.com/ghetzel
[oracle@rokoko ~]$ mkdir -p ~/go/src/github.com/ora600pl
[oracle@rokoko ~]$ cd ~/go/src/github.com/ghetzel
[oracle@rokoko ghetzel]$ git clone https://github.com/ghetzel/shmtool
Cloning into 'shmtool'...
remote: Counting objects: 92, done.
remote: Total 92 (delta 0), reused 0 (delta 0), pack-reused 92
Unpacking objects: 100% (92/92), done.
[oracle@rokoko ghetzel]$ cd ~/go/src/github.com/ora600pl
[oracle@rokoko ora600pl]$ git clone https://github.com/ora600pl/sgadump
Cloning into 'sgadump'...
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 9 (delta 0), reused 9 (delta 0), pack-reused 0
Unpacking objects: 100% (9/9), done.
[oracle@rokoko ora600pl]$ cd sgadump/
[oracle@rokoko sgadump]$ ls
README.md  sgadump.go
[oracle@rokoko sgadump]$ go install

If your ENV was setup properly, you’ll find a binary file under ~/go/bin/sgadump and use it like this:

[oracle@rokoko sgadump]$ sgadump
sgadump by Kamil Stawiarski (@ora600pl) - dumps database blocks from SGA.
Usage: sgadump -b block_size -d data_object_id -s shmid -o output_file_name

Cool, now let’s make sure, that we are using ASMM and not AMM:

SQL> sho parameters memory_target

------------------------------------ ----------- ------------------------------
memory_target			     big integer 0
SQL> sho parameters sga_target

------------------------------------ ----------- ------------------------------
sga_target			     big integer 1120M

Now we will check if the tool works – first of all we have to check data_object_id of HR.EMPLOYEES, load encrypted data to memory, get ID_SHM for SGA and dump blocks. Easy, right? 🙂

SQL> alter system flush buffer_cache;

Zmieniono system.

SQL> select data_object_id
  2  from dba_objects
  3  where object_name='EMPLOYEES'
  4  and   owner='HR';


SQL> select dbms_rowid.rowid_block_number(rowid) as bno, count(1)
  2  from   hr.employees
  3  group by dbms_rowid.rowid_block_number(rowid);

       BNO   COUNT(1)
---------- ----------
       132	    9
       131	   98

So we now that rows from that table fit in 2 database blocks.
Now let’s try to dump them into a file using my simple tool.

[oracle@rokoko sgadump]$ ipcs -m

------ Segmenty pamięci dzielonej ----
klucz      id_shm     właściciel uprawn.    bajtów    podłączeń stan
0x00000000 262144     oracle     600        8622080    116
0x00000000 294913     oracle     600        1157627904 58
0x00000000 327682     oracle     600        8155136    58
0x91a6a268 360451     oracle     600        8192       58
[oracle@rokoko sgadump]$ sgadump -b 8192 -d 73865 -s 294913 -o emps
shmid = 294913	 size is 1157627904, blocks = 141312
Dumped 2 blocks to emps

Awesome! Now we can use rico2 to compare the content of encrypted blocks in a datafile and unencrypted ones in SGA.

[oracle@rokoko ~]$ cat listfile.rico2
1 /home/oracle/go/src/github.com/ora600pl/sgadump/emps
2 /u01/app/oracle/oradata/DUPA12/datafile/o1_mf_secure_d_fn9jj6xy_.dbf
[oracle@rokoko ~]$ python rico2.py listfile.rico2
RICO v2 by Kamil Stawiarski (@ora600pl | www.ora-600.pl)
This is open source project to map BBED functionality.
If you know how to use BBED, you will know how to use this one.
Not everything is documented but in most cases the code is trivial to interpret it.
So if you don't know how to use this tool - then maybe you shouldn't 😉

Usage: python2.7 rico2.py listfile.txt
The listfile.txt should contain the list of the DBF files you want to read

 !!! CAUTION !!!!

This tool should be used only to learn or in critical situations!
The usage is not supported!
If found on production system, this software should be considered as malware and deleted immediately!

1	/home/oracle/go/src/github.com/ora600pl/sgadump/emps
2	/u01/app/oracle/oradata/DUPA12/datafile/o1_mf_secure_d_fn9jj6xy_.dbf
rico2 > set dba 2,131
	DBA		0x800083 (8388739 2,131)
rico2 > map
 File: /u01/app/oracle/oradata/DUPA12/datafile/o1_mf_secure_d_fn9jj6xy_.dbf(2)
 Block: 131			Dba: 0x800083
Wrong kind of block. Currently supported: 6.1
rico2 > d
 File: /u01/app/oracle/oradata/DUPA12/datafile/o1_mf_secure_d_fn9jj6xy_.dbf(2)
 Block: 131 Offsets: 0 to 512		Dba: 0x800083
06a20000 83004001 1f6d1900 00000114 | ......@..m......
c2d40000 b64bd34f 98dcff3f 23d0c822 | .....K.O...?#.."
ba1b1249 8e0d572f 740b8db7 f7fd6a15 | ...I..W/t.....j.
679856ef a61c8130 896c0066 cd6b7a45 | g.V....0.l.f.kzE
b3751eb2 b40cdeb6 8f16bbdf f9b4f53d | .u.............=
50199851 dbe0dde9 5688576b 9e9df4a0 | P..Q....V.Wk....
0f481d54 b36b746f b98f6a21 0d13fb51 | .H.T.kto..j!...Q
489b7825 4e94fd05 d2bbe1ce 7b117069 | H.x%N.......{.pi
38c5ab56 e4ae4a77 2ff41926 5bb135d7 | 8..V..Jw/..&[.5.
b4432e7a 630ca876 a52f5905 31ddcc10 | .C.zc..v./Y.1...
dfcb778a 4573f718 44c1bb9d f89ab735 | ..w.Es..D......5
3518bf50 be236042 c49efe31 c72865dc | 5..P.#`B...1.(e.
88827881 6c6ce355 2b14f312 bf9119af | ..x.ll.U+.......
5f53c4c5 7fd4c1a7 ac29c784 1c124019 | _S......)....@.
46098a1e 42dd8b48 640b777b 49f20b58 | F...B..Hd.w{I..X
0cfd6491 cff43be9 a48013bc d336796b | ..d...;......6yk
7b3a2a3b 513dee44 8f7a5d6d 948c9d54 | {:*;Q=.D.z]m...T
7decaea7 37f35331 4b1a36a2 0fcd0c70 | }...7.S1K.6....p
4e83beae 72e03920 c7a218ba f4cb17e4 | N...r.9 ........
d10d09f8 bb3e5aa4 be827849 b4b9522e | .....>Z...xI..R.
0c171483 fce82a0c 64b184da 7da1ef73 | ......*.d...}..s
8cd53b7b 66e46885 8855018a babb6669 | ..;{f.h..U....fi
e1a79636 b66210d7 c27b6f43 43929a58 | ...6.b...{oCC..X
915d44bf e6efe9d0 845c4c97 3c25d5fa | .]D......\L.<%..
29d90c7d 11fe47f7 73213529 8c75a98b | )..}..G.s!5).u..
cd30d13f a76adf74 c2bfe501 ec853a74 | .0.?.j.t......:t
605f6641 b57c9a85 614d28f8 75c2253f | `_fA.|..aM(.u.%?
7dfcb3d8 7bcc1386 ab40d7e1 7a37b999 | }...{....@..z7..
f9837dc3 c5073575 9181feaf 038ae706 | ..}...5u........
c344ff1d 075b3b6b 7c07b118 3a88a3fd | .D...[;k|...:...
23bb4a29 7170a48a 975818b7 21ce08a9 | #.J)qp...X..!...

<16 bytes per line>

As you can see I can’t read the encrypted block in a datafile. But let’s check the dump from SGA:

rico2 > set dba 1,0
	DBA		0x400000 (4194304 1,0)
rico2 > map
 File: /home/oracle/go/src/github.com/ora600pl/sgadump/emps(1)
 Block: 0			Dba: 0x400000
 DATA Table/Cluster

 struct kcbh, 20 bytes				@0

 struct ktbbh,  96 bytes 			@20

 struct kdbh, 14 bytes 				@124

 struct kdbt[1], 4 bytes			@138

 sb2 kdbr[9]					@142

 ub1 freespace[7406]				@160

 ub1 rowdata[622]				@7566

 ub4 tailchk					@8188

rico2 > p *kdbr[0]
rowdata[549]				@8115	0x2c
flag@8115:	0x2c
lock@8116:	0x0
cols@8117:	11

col    0[3]     @8118:  c20263
col    1[6]     @8122:  446f6e616c64
col    2[8]     @8129:  4f436f6e6e656c6c
col    3[8]     @8138:  444f434f4e4e454c
col    4[12]    @8147:  3635302e3530372e39383333
col    5[7]     @8160:  786b0615010101
col    6[8]     @8168:  53485f434c45524b
col    7[2]     @8177:  c21b
col    8[0]     @8180:  *NULL*
col    9[3]     @8181:  c20219
col   10[2]     @8185:  c133

rico2 > x /rncccctcnnnn
rowdata[549]				@8115	0x2c
flag@8115:	0x2c
lock@8116:	0x0
cols@8117:	11

col    0[3]     @8118:  c20263                                   198
col    1[6]     @8122:  446f6e616c64                             Donald
col    2[8]     @8129:  4f436f6e6e656c6c                         OConnell
col    3[8]     @8138:  444f434f4e4e454c                         DOCONNEL
col    4[12]    @8147:  3635302e3530372e39383333                 650.507.9833
col    5[7]     @8160:  786b0615010101                           2007-06-21:00:00:00
col    6[8]     @8168:  53485f434c45524b                         SH_CLERK
col    7[2]     @8177:  c21b                                     2600
col    8[0]     @8180:  *NULL*
col    9[3]     @8181:  c20219                                   124
col   10[2]     @8185:  c133                                     50

KaBoom! 🙂

So as you can see – it is possible even with ASMM but it is much, much harder and we don’t want to make things easy for potential "hackers" ;).
And nothing is impossible in IT. It can be just unaffordable… or it can take longer than a life of one generation 😉

Good security is made by people you know and people you should trust. Nothing will protect itself – no matter how fancy software you’ll buy. Even the most advanced autonomous software – human immunology system – requires maintenance and correct usage and – from time to time – diagnostic by an expert you trust.



Database Whisperers sp. z o. o. sp. k.
Al. Jerozolimskie 200
Wejście B, III piętro/ pokój 342
02-486 Warszawa
NIP: 5272744987
+48 508 943 051
+48 661 966 009

Newsletter zapisz się żeby być na bieżąco