Skip to content

Finding Secrets...

One of the main advantages of SGX technology is that it cannot only protect against external attackers but also against internal attackers that have root access. We introduce a simple approach to demonstrate that your application is indeed running inside of an enclave and that its secrets are not accessible.


To ensure that your SCONE application runs inside of an enclave and to distribute secrets, please to use the SCONE configuration and attestation service.

To demonstrate how one can check that SGX/SCONE can protect against users with root access1, let's consider a simplistic example: we store some secret in a variable secret2. By default, binaries are not encrypted. Hence, do not store any secrets in a binary as it is done in this simplistic example.

Finding secret in simulation mode

If you really need to to protect your binaries - for example, since you have some legacy code with embedded secrets - SCONE can protect these secrets by permitting to encrypt shared libraries.


We use the SCONE crosscompiler image and start an container with access to the SGX device. We determine which SGX device to mount with function determine_sgx_device.

docker pull
docker run $MOUNT_SGXDEVICE -it

Let's create some program that stores a secret (MYBIGS) in a local variable secret:

cat > mysecret.c << EOF
#include <stdio.h>
#include <unistd.h>

const char *code_is_not_encrypted="THIS_IS_NOT_SECRET";

int main() {
    char secret[7];
    secret[0] ='M';
    secret[1] ='Y';
    secret[2] ='B';
    secret[3] ='I';
    secret[4] ='G';
    secret[5] ='S';
    secret[6] =0;
    printf("'%s' SECRET at %lx\n", secret, secret);
    printf("Kill with Ctrl-C.\n");
        sleep(1); // loop forever

Compile this program with the SCONE crosscompiler (i.e., gcc):

gcc -g -o mysecret mysecret.c

Simulation Mode

You can run this program in SIMULATION MODE, i.e., this program does not protect your secrets:


Log into a different terminal on your host. Let us figure out the process ID of the mysecret program:

SPID=$(ps -a | grep -v grep | grep mysecret | awk  '{print $1}')

Now, we can dump the memory of this process via the /proc filesystem. You can determine the different memory regions of your process via cat /proc/$SPID/maps and the memory is stored in /proc/$SPID/mem. We can use the following Python program to write all pages to stdout:

cat > << EOF
import sys,re

pid = sys.argv[1]
print("PID = %s \n" % pid)
maps_file = open("/proc/%s/maps" % pid, 'r')
mem_file= open("/proc/%s/mem" % pid, 'rb')

for line in maps_file.readlines():
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r][-w])', line)
    if == "rw" or == "r-" :
            start = int(, 16)
            if start > 0xFFFFFFFFFFFF:
            print("\nOK : \n" + line+"\n")
            end = int(, 16)
            chunk = - start)
        except Exception as e:
        print("\nPASS : \n" + line+"\n")


Run this program and grep for the prefix of our secret:

sudo python3 $SPID >& memdump.log
grep -o MYBIGS memdump.log

This will take some time but eventually it will print the full secret MYBIGS.

Enclaves in SIM mode

You will find your secret in memory region used by enclave but you will notice that SGX device is not used.

Hardware Mode

Let us now run the program in hardware mode. First, ensure that you kill the original program by typing control-C.

Finding secret in prerelease mode

Let's start mysecret in an enclave, i.e., in hardware mode inside the container:


Update environment variable SPID in a second terminal on your host:

SPID=$(ps -a | grep -v grep | grep mysecret | awk  '{print $1}')

and then try to find the secret:

sudo python3 $SPID >& memdump_HW.log
grep -o MYBIGS memdump_HW.log

And in few seconds you will see your secret.

Enclaves in debug mode do not protect your secrets

If your enclave is in debug mode, one can access all secrets of the enclave.

Production Mode

To protect your secrets you have provided them only to the attested production enclaves. If enclave is signed with a suitable key, it will start in production mode. One can simply generate such a key for CPU that supports FLC. To check, if your CPU supports FLC use:

cpuid | grep SGX_LC
lscpu | grep sgx_lc

You can generate a key with following script:

openssl genrsa -3 -out key.pem 3072

And sign a binary with scone signer like this:

scone-signer sign -p --key=key.pem ./mysecret

Then, kill the original program by typing control-C and start a new one that will run in production mode. And one more time, update environment variable SPID in a second terminal on your host:

And then you run:

sudo python3 $SPID >& memdump_PRD.log
grep -o MYBIGS memdump_PRD.log

This time grep will not find secretes on stack. That is because enclave memory is encrypted and protected from outside access. Also, this example shows that if you provide secretes after attestation, it can not be extracted from SGX enclave.

Note that secrets stored in the binaries can be found because the binary is not encrypted: a copy of the original binary - which is used to start the enclave - stays in the main memory outside the enclave.

Let's look for the string THIS_IS_NOT_SECRET in our example application. We can find this secret as follows:

sudo python3 $SPID | strings -n 5 | grep THIS_IS_NOT_SECRET

Always use SCONE policy to provide secrets to enclaves.

  1. Note that the enclave runs in this example runs in debug mode, i.e., one can still attach to this enclave with scone-gdb. To prevent access via the debugger, you need to run your enclave in production mode

  2. Note that an adversary could analyse the binary and figure out the secret. The standard way to provide an enclave with secrets is to use SCONE CAS