- Hello, DEFCON.
Welcome to Your House is My House.
Use of Offensive Enclaves in Adversarial Operations.
My name is Dimitry Snezhkov, and I'm part of protiviti,
Attack and Penetration Testing Team,
where I have a chance to do tooling,
offensive research, and automation.
Shout out to my team at protiviti for making that happen.
So today we're gonna talk about SGX technology
as it applies to offensive operations.
Being part of the offensive team and tasked with testing,
I sometimes find myself, and we, as a team find ourselves,
on unknown boxes, and sometimes we need to leverage
the technology that exists there
to be able to withstand the kinda the onslaught
of EDR inspections or defensive technology inspections.
And so SGX technology here was a curious case
when a developer was using SGX technology
to protect the trusted credentials
and so the box was instrumented with SGX enclaves,
which we thought, why not use them?
And how can we use them to further our goals
of bringing payloads
and taking care of secure communication for us.
But first things first,
SGX is a technology developed by Intel Corporation
to essentially protect specific code or data
from disclosure or modification to adversarial parties.
Adversarial parties defined by Intel or SGX technology,
is anybody who is running in non-ring three.
For example, privileged system code, operating system,
virtual hypervisor, managers, bios,
all the things that kind of work around the hardware.
And so SGX enclaves were born in technology
that solved the issue of protecting areas,
or tries to solve the issue of protected areas
of execution and increased security on platforms
that are considered to be compromised
from all the contexts that runs around them.
So SGX, as we've defined, SGX enclave is a trusted code,
and it's also linked into application.
So the application, it kind of runs in two modes,
split personality modes, one is the untrusted part
of the code, and another is trusted part of the code.
The trust that they're safe, part of the code runs
in the SGX enclave, which we construct
and we interact with underlying bootstrapping,
and orchestration platform
to be able to execute or reach into the trusted area
and execute a very specific operations
from the untrusted memory, which is our application.
That's possible by SGX of introducing two new upcodes,
of switching in and out of the trusted area over CPU,
which is locked to the enclave
or enclave is encrypted by CPU key.
And so this technology is very kinda prevalent
in the high security environments.
Obviously, part of the wherever Intel Core processor,
six plus generation lives on laptops, servers,
and data centers, but also in cloud virtual machines.
Namely, we found it on Azure DC level
trusted computing machines.
And so if we find ourselves as operators on those machines,
we might be able to use some of that protection
for our purposes.
So the offensive goals for us here is kinda twofold.
First is understand the technology,
how to construct the application
so we can actually invoke SGX and use enclaves
to store our data, which is payloads or other things.
Also use SGX technology and SDK to try
and secure communications with our C2 without revealing keys
that we use for our payload encryption.
And then in the process, try to kinda
have the EDR divert attention from us by splitting
the kinda the deployment model between several components
that are not fully assembled or introspected.
And so in this case, we're gonna do Windows as an example.
we're gonna create a system called exclave
or kinda design, a method of communication
between our cradle to load securely our payloads.
Store them in the enclave on the box,
but also hide the algorithm of encryption
and the keys that kinda travel back and forth in clear text.
And so the Windows is the example in this case,
but the Linux side will be pretty much the same in concepts.
Although, implementation may be a little bit different
and hopefully, we're gonna have fun
going through those exercises.
One thing to mention is that this talk
is not about SGX vulnerabilities or SGX deep dives.
We're gonna touch on some of the relevant parts,
but I refer to other great talks on that matter.
The SGX components that will be interesting for us
will be the platform software that gets installed
to kinda interact with enclave.
If we're dropping into a box
that has appropriate type of CPU, and we're on the Windows,
Microsoft Windows machine, then operating system
would have already have the driver for it
because that's a standard update process for it.
But you could obviously, have more a type of,
have other type of platform software
if you're operating directly in the environment
that SGX enclaves are used by developers
to kinda help their applications be more secure.
So there's drivers there and the orchestration software
such as attestation service which talks about
and takes care of the kinda signing, and verifying
the enclaves themselves to the owner
and to the system i.e. the CPU.
And also, the second part is the SDK,
which we will use as part of the software development
to create this application, which will utilize enclaves.
There are two SDKs,
we're gonna take a look at Intel for the most part,
but open enclave is also available for our purposes.
And so the outcome of our efforts
would be an application or a set of applications
that will be created with trusted and untrusted parts.
Trusted being an SDX enclave,
and untrusted being all the bootstrapping code
that allows us to share information with our C2
and process payloads from that.
And then we're gonna go into how high level mapping
of the calls into C2, into trusted area happens,
and how we can leverage some of the primitives
in the SGX, SDK for our purposes.
Such as configuration, signing and loading.
Specifically the problem of payload transfer
can be distilled to a few things.
First of all, we do not want to load payloads in clear,
we always want to protect.
And commonly, we protect it with some XOR key
maybe a AES key, but the problem is that the key itself
maybe available in the memory because it's shared key
a lot of times.
And so it's inspectable, if not real-time in the sandbox,
than in the forensic lab.
And so if we're running long-term campaign,
we want to make sure we protect our keys in memory.
And also, the other thing is the algorithm itself
can be reversed and we can be pretty much
our algorithm can be known.
But not because we don't wanna share the algorithm,
but because that algorithm may point
to weaknesses in our communication,
which may be introspected and intercepted.
And so, what we're gonna do, the other goal
is not only to store payloads, but also use SGX
to secure communicate out to C2.
To do that, there are a few alternatives.
There's some crypto libraries that come with PSW,
the platform code in SDK, it's SGX_TCRYTPO library,
it is fairly limited in what it does because it's purpose is
to facilitate jobs of attestation and communication
for session management, it's not for general purpose crypto,
but we can use some parts of it to construct what we want.
We can also bring third-party to encryption,
to work with that, for example,
OpenSSL or wolfSSL library,
but the problem is target availability.
We do not know if these libraries runtime
are gonna be available on the target.
Plus, we want to stay away from loading things from disk
as much as we can, and operate in the memory,
and a lot of times it's too heavy or impossible to load
those libraries in memory.
And the third possibility is obviously, with the limited
kinda API that we have inside of the SGX enclave,
the trusted area, we can roll our own,
which is, probably discouraged in this exercise anyway.
I've mentioned limited access to API and the SGX enclave,
the reason being is because it is itself
because of its kind of reason for existence to protect
the code inside of it, is devoid of support for syscalls
and it has a very limited IO in and out of enclave,
mostly for state of preservation, but nothing less.
So let's see what we can do, what we're gonna take
the first approach is actually using TCRYPTO
and see what we can do, how we can build it.
So upon research, we kinda came up
with three different things that we can do with that crypto
in the SDK, we can generate an RSA key,
actually a pair, a public and private key.
We can actually sign something with our public key
and well actually, encrypted with the public key
and sign the private key, and we can actually use
a routine that works on AES symmetric keys to be able
to encrypt something of a value inside
and potentially transfer that something,
that piece of code or data outside of the enclave
into untrusted area.
And so the idea here would be for us to create
an application where we do just that,
the first step would be to generate RSA keys
sat inside of the trusted PRM,
inside of enclave, give the public key out to our C2,
have it store there, and then go to C2, and C2 would be able
to generate the symmetric key, send it to us inside
of the trusted PRM, we're gonna store the symmetric key
and then we're gonna have a shared symmetric key
without leaking it so we can kinda generate the payload
on the C2 side and then keep transferring it
into our trusted PRM without having any inspection
or being worried about the algorithm disclosure,
or payload disclosure, or key disclosure.
So it's a three-step process.
First, we're generating public, private keys,
we're sending them to C2,
C2 now has them then encrypts a symmetric key,
sends it to us, we store it in a trusted component,
which it decrypts the key because it was encrypted with RSA,
which we already had from previous step,
and now we just share the symmetric key between the two,
and that's how we achieve secure communication.
And then, so components that we want to have
in this sort of construction is we kinda thought
of splitting it in three ways, the application,
which will be inspectable by defense, it's loaded from disk,
it's your kinda implant or cradle, or a loader.
We went the route of establishing the bridge between enclave
and that loader, which kinda facilitates
and brokers interaction takes data from one process
to another, but it's also a kinda middleman
that can be taken out of the equation upon first load
so the EDR will not see all of the picture
and the bridge can come in as a memory load of module,
which will be able to kinda broker communication between
the two, the enclave and the app at their own time.
And so the bridge is also assumed inspectable
and then enclave, which is assumed obfuscated
and we're gonna have some notes on that later on,
in limitation section.
But, yeah, so enclave is where we're gonna store our keys
and our algorithm.
It will be loaded from disk, but it's also a secure library,
which may not be introspectable,
and yeah, then we need to kinda start building that.
And so we come up with that exclave system,
which we're gonna demo, and then we'll come back
to talk more about its construction limitations
and all that other things.
Let's take a look at the exclave, its components
and its operations.
Here, we have a victim machine with an application,
which is an agent or an implant.
There's a bridge DLL,
which facilitates interaction with the enclave.
It may or may not be on disk,
it may or may not come directly from the network
and being loaded that way in memory.
And obviously, as we mentioned,
there is a trusted piece of code that runs in PRM.
It makes sense to kinda put the code in perspective
and so far, is to explain those components.
The application finds the bridge,
the bridge function is invoked, which has explored,
and found the bridge itself, maps through the EDL
to the enclave calls.
Here's the EDL, essentially it's a mapping or a matrix
of trusted calls that we can invoke inside of enclave
in untrusted calls that we are not.
An enclave itself, is the trusted code
that essentially does the processing,
does the encryption and other things
that we need to keep secure.
And obviously on the other side,
it's a C2 that should be able to match
the crypto parameters one-to-one,
so it's able to successfully decrypt and communicate
with exclave that resides inside of the victim machine.
And let's take a look at how that works.
So essentially we have two screens,
one is the victim machine where all these components
are deployed and there is a C2.
Let's start with the C2, it listens on the port
and it's responding to communication.
Let's start the application.
And the first thing it does,
it's trying to create an enclave.
It's a standard procedure to create the memory mapping
and launch things into existence.
Once this is done, all checks happen,
are we running on the machine that supports SGX?
Are we able to create it, what are the parameters
and permissions that had allow us
or not allow us to do this?
And then it's trying to generate a RSA key pair
for communication.
Once this is done, the public key and private key,
our available private key, it gets stored in enclave
and publicly gets shared through the bridge,
into the application, which connects to the C2
and solicits for a storage of this public key on our side.
Once this happens, the C2 carries out the task.
It does its processing, generates the symmetric key
for communication and sends the response back
to the application, which proxies it to the bridge
into the enclave, which stores it,
and this is what we're doing here.
So the shared key is now available,
and now, we are ready to map one-to-one encryption
of the payload, or would be payload that would come from C2
into the enclave again, through the app, through the bridge,
into the secured area.
And this is what happening here, we're requesting
that payload, the payload gets generated, in this case,
it's very contrived example,
and it gets encrypted to match the mode of the capabilities
of the enclave.
All that processing happens and the payload travels back
to the agent and ultimately to the enclave.
And enclave, having the symmetric key is now able
to decrypt the payload.
After this is done, the payload gets stored in clear text
in the enclave, but it's protected from any kind of
reachability from to defense, and then the attacker
can actually work on that.
And the last but not least, then once we created
the enclave, we can destroy it if we don't need it
for whatever reason and the duration that we wanna use that.
Once this is done, everything is good
and we are ready to move on.
Okay, so we've started presentation of how exclave works.
There are some assumptions and limitations to this.
First of all, it's a bad coding practice, (chuckles)
we are weakening the enclaves we're using it,
we're misusing them.
And so, but our idea is that while the technology
it can be used as is, a lot of times EDRs
did not inspect enclaves.
In our testing, we were able to use the pre-release keys
or in pre-release or debug mode
where we're able to compile that
and then use the whitelisting, testing, signing keys
to do that, it will, in theory,
that should prevent us from debugging into it,
which is true, the EDRs themselves did not actually make
the leap on and inspecting enclaves anyway.
And so the other side of the story is that in order to
do it properly, you need to assign at the station key
and have Intel provision one, and sign it with a true key
and then you can sign your enclave,
which will be undebugable.
But in this case, you're running into attestation,
meaning attribution issue.
And so we kinda went data route and said,
Hey, what can we do with pre-release
or debug versions of it?
And so I did not attested the enclaves
are supposed to be inspected, but in practice,
they're often not.
And so, as we mentioned before, SGX provisioned
the PSW services install or platform is installed
and TCRYPTO, a library of cryptographic primitives
is present so that should let us kinda live
of the land once we arrive at SGX enabled machine.
And you know, one thing to notice is that
how do you help defenders kinda understand
what the enclaves are and how to find
the rogue ones is that you need to watch for signatures,
identify non-approved SGX enclaves,
the way you would do this,
is you basically can have a really nice tool from
Kudelski's SGX fun, to dump your DLL
and kinda see the details of that enclave,
and kinda latch onto the keys that you have not provisioned.
So I'd like to thank everybody who has gone to my talk,
here's the link to a proof of concept, the bridge library,
the enclave of an application,
which we've used in this presentation.
Thank you very much.