WEBVTT

00:00:00.240 --> 00:00:04.100
As explained previously, stagers contain hardcoded shellcode,

00:00:04.110 --> 00:00:05.760
which is easy to detect.

00:00:06.240 --> 00:00:10.150
Metasploit ships with various encoders and encryptors that can

00:00:10.150 --> 00:00:13.650
be used by passing the ‑e flag to msfvenom.

00:00:14.540 --> 00:00:15.410
Alternatively,

00:00:15.420 --> 00:00:19.370
encrypters can be used by passing the ‑‑encrypt and

00:00:19.370 --> 00:00:23.060
‑‑encrypt‑key flags to msfvenom.

00:00:23.540 --> 00:00:28.250
Some encoders are polymorphic, which makes them particularly hard to detect.

00:00:28.740 --> 00:00:33.000
A good example is the 64‑bit Zutto Dekiru encoder.

00:00:33.040 --> 00:00:36.060
Let's take a closer look at how this encoder works.

00:00:36.540 --> 00:00:41.680
This diagram demonstrates how the Zutto Dekiru encoder works at a high level.

00:00:41.890 --> 00:00:44.550
The first step consists of compiling the stager.

00:00:45.040 --> 00:00:48.370
The shellcode is then sent to the encoder if a ‑e

00:00:48.370 --> 00:00:50.590
flag was specified in msfvenom.

00:00:50.590 --> 00:00:54.020
The encoder generates a random 8‑byte key,

00:00:54.030 --> 00:00:58.460
which is used to perform an XOR operation on 8‑byte chunks.

00:00:58.940 --> 00:01:03.560
It repeats the process until every byte in the stager has been encoded.

00:01:04.140 --> 00:01:04.810
At this point,

00:01:04.810 --> 00:01:10.250
a small stub of shellcode is built using randomly chosen CPU registers.

00:01:10.500 --> 00:01:12.850
This makes it hard to create a signature since the

00:01:12.850 --> 00:01:14.360
code will always be different.

00:01:14.840 --> 00:01:15.920
When executed,

00:01:15.930 --> 00:01:20.620
this stub will loop over all the encoded bytes and apply the same XOR key,

00:01:20.630 --> 00:01:22.920
which was used whilst encoding the stager.

00:01:23.340 --> 00:01:28.650
This will effectively restore the original stager code at runtime in memory.

00:01:29.140 --> 00:01:31.000
Because this is happening in memory,

00:01:31.010 --> 00:01:34.750
it makes this technique ideal to hide our stager on disk.

00:01:34.980 --> 00:01:35.560
However,

00:01:35.560 --> 00:01:40.000
it does require us to specify read/write execute permissions on the

00:01:40.000 --> 00:01:44.940
section of the executable, which will hold this data since the code needs

00:01:44.940 --> 00:01:48.530
to modify itself and execute itself at runtime.

00:01:48.730 --> 00:01:52.260
This should be avoided as we will discover it later on in the module.

00:01:53.140 --> 00:01:56.560
Let's take a look at the Zutto Dekiru encoder in practice.

00:01:57.140 --> 00:02:02.560
The code for this encoder can be found in the zutto_dekiru.rb file.

00:02:03.140 --> 00:02:07.250
As explained, the Zutto Dekiru encoder is an XOR encoder.

00:02:07.940 --> 00:02:13.160
The function which performs the encoding is the xor_string function.

00:02:13.740 --> 00:02:16.130
As you can see, it takes two parameters.

00:02:16.240 --> 00:02:20.160
The first is text, which contains the compiled stager shellcode.

00:02:20.540 --> 00:02:22.880
The second is the random XOR key,

00:02:22.890 --> 00:02:25.660
which will be used to encode the stager shellcode.

00:02:26.140 --> 00:02:29.530
If we now take a look at the encode_block function,

00:02:29.720 --> 00:02:31.760
we can see all the CPU registers,

00:02:31.770 --> 00:02:35.530
which can be used to build the polymorphic decoder stub,

00:02:35.540 --> 00:02:39.550
which will be responsible for decoding the stager in memory when executed.

00:02:40.040 --> 00:02:44.520
Because the registers are shuffled and some instructions are chosen randomly,

00:02:44.520 --> 00:02:49.660
it makes it very difficult for an antivirus to develop a reliable signature.

00:02:50.240 --> 00:02:52.200
If we go down to the end of the function,

00:02:52.210 --> 00:02:55.300
we will see the polymorphic decoder stub being added in

00:02:55.300 --> 00:02:57.960
front of the encoded stager shellcode.

00:02:58.220 --> 00:03:01.270
Let's take a closer look at this by generating a stager and

00:03:01.270 --> 00:03:04.480
debugging the Ruby code. I have already placed breakpoints

00:03:04.480 --> 00:03:05.960
before and after the encoding,

00:03:05.960 --> 00:03:10.020
so we can take a look at our stager before and after the encoding occurs.

00:03:10.020 --> 00:03:14.700
We can now go ahead and run the following command to generate an encoded stager,

00:03:14.710 --> 00:03:16.980
which we will place in our shellcode runner.

00:03:17.140 --> 00:03:18.980
Once our first breakpoint is hit,

00:03:18.990 --> 00:03:21.890
we can take a look at the stager before the encoding occurs.

00:03:21.890 --> 00:03:25.920
We can see the IP address of the handler and the wininet string

00:03:25.930 --> 00:03:28.900
which gets passed to the LoadLibraryA API,

00:03:28.910 --> 00:03:30.260
as well as the URI.

00:03:30.590 --> 00:03:33.410
If we let the code run until the next breakpoint, and we

00:03:33.410 --> 00:03:35.510
take a look at the stager once again,

00:03:35.740 --> 00:03:39.830
you will notice that the artifacts we saw previously are no longer visible.

00:03:40.040 --> 00:03:44.290
We can take a look at the decoder stub and get its size in bytes.

00:03:44.640 --> 00:03:47.300
We can do the same for the encoded stager.

00:03:47.500 --> 00:03:51.960
We will use this when analyzing the stager executing in our shellcode runner.

00:03:52.340 --> 00:03:55.620
We can then let the code run, which should generate a stager,

00:03:55.630 --> 00:03:58.200
which can be embedded inside our shellcode runner.

00:03:58.300 --> 00:04:02.400
We can then place a breakpoint before executing our stager so we can

00:04:02.400 --> 00:04:05.070
take a look at the decoding process in memory.

00:04:05.380 --> 00:04:06.820
Once the breakpoint is hit,

00:04:06.830 --> 00:04:10.360
we can switch to the assembly view and step into our stager.

00:04:10.840 --> 00:04:14.930
We can get the address of our encoded stager by adding the size in bytes of

00:04:14.930 --> 00:04:18.850
our decoder stub and copy the address into the Memory view.

00:04:19.339 --> 00:04:23.800
We can place a breakpoint just after our decoder stub and let the code run.

00:04:24.010 --> 00:04:25.780
If we then check the Memory view,

00:04:25.790 --> 00:04:28.330
we can see that the stager's shellcode has been

00:04:28.330 --> 00:04:31.530
deobfuscated in memory by the decoder stub.

00:04:31.530 --> 00:04:36.170
And we can now see the IP address and the URI of our stager,

00:04:36.210 --> 00:04:38.960
as well as the wininet string we saw previously.

00:04:39.140 --> 00:04:43.060
If we now attempt to upload our encoded stager to VirusTotal,

00:04:43.440 --> 00:04:47.850
you will notice that only 10 antivirus scanners have flagged our file.

00:04:48.240 --> 00:04:50.990
You may recall that our shellcode runner with the

00:04:50.990 --> 00:04:54.300
unencoded stager was flagged by 24 scanners.

00:04:54.560 --> 00:04:59.070
If we encode the stager and leverage the exe‑only format with the 7 zip

00:04:59.080 --> 00:05:02.280
executable file template and upload it to VirusTotal,

00:05:02.280 --> 00:05:06.060
our stager is only flagged by 5 antivirus scanners.

00:05:06.130 --> 00:05:08.060
This is a significant improvement.

00:05:08.240 --> 00:05:12.350
If we take a closer look at the detections in the VirusTotal report,

00:05:12.740 --> 00:05:16.430
you will notice that some of these detections were due to heuristic

00:05:16.440 --> 00:05:20.150
runtime analysis and not due to on‑disk scans.
