WEBVTT

00:00:00.640 --> 00:00:02.340
Now that we have covered how payloads work,

00:00:02.340 --> 00:00:05.950
we need to understand this concept of reflective DLL injection,

00:00:05.960 --> 00:00:08.260
which is used extensively by Meterpreter.

00:00:09.340 --> 00:00:12.460
DLL files are normally located on the file system.

00:00:13.540 --> 00:00:17.920
They can be loaded at runtime by calling a load library API or

00:00:17.920 --> 00:00:21.400
dynamically by the operating system's loader and dynamic linker

00:00:21.400 --> 00:00:23.860
when a process is being created.

00:00:23.860 --> 00:00:29.050
The operating system does not officially support loading DLLs from memory.

00:00:30.440 --> 00:00:33.260
The Reflective DLL injection library used by

00:00:33.260 --> 00:00:35.560
Meterpreter provides this functionality.

00:00:37.240 --> 00:00:41.080
It will perform all the operations required to load a DLL file

00:00:41.080 --> 00:00:44.750
into a process, just as the operating system's loader would if

00:00:44.750 --> 00:00:46.750
it was loading a DLL from disk.

00:00:48.540 --> 00:00:52.310
This makes the payload very evasive because the only way to detect the

00:00:52.310 --> 00:00:55.210
actual payload is by analyzing memory at runtime,

00:00:55.210 --> 00:00:57.900
since it is never written to disk.

00:00:57.900 --> 00:01:01.960
You may recall that when we compiled the payload,

00:01:02.340 --> 00:01:05.550
there were multiple DLL files in the output folder.

00:01:06.440 --> 00:01:09.130
These files are all extensions which can expand

00:01:09.130 --> 00:01:11.560
Meterpreter's functionality at runtime.

00:01:12.640 --> 00:01:17.650
These extensions are also reflectively loaded and are sent over by the handler.

00:01:19.140 --> 00:01:22.070
If we go back to the Meterpreter solution in Visual Studio,

00:01:22.080 --> 00:01:24.550
we can take a closer look at what this reflective

00:01:24.550 --> 00:01:26.760
DLL injection library looks like.

00:01:27.340 --> 00:01:30.690
The code is located in the ReflectiveLoader.c file in the

00:01:30.690 --> 00:01:33.660
external dependencies of the metsrv project.

00:01:40.540 --> 00:01:44.560
If we open the file and scroll down to the ReflectiveLoader function,

00:01:46.640 --> 00:01:49.360
we will see several variable declarations.

00:01:49.940 --> 00:01:53.500
If we scroll down, we can view the first step,

00:01:53.500 --> 00:01:56.660
which consists of obtaining the caller's address.

00:01:57.540 --> 00:02:00.980
You may recall that the caller was the stub of shell code which

00:02:00.980 --> 00:02:03.660
was patched in the DOS header by the handler.

00:02:05.040 --> 00:02:09.289
The code then iterates backwards to find the payload's base address

00:02:09.300 --> 00:02:13.560
in memory by using the well‑known MZ ASCII string,

00:02:14.940 --> 00:02:18.960
which corresponds to the first two bytes of all DLL files.

00:02:19.940 --> 00:02:23.090
The library then uses the same technique which is used by the

00:02:23.090 --> 00:02:26.560
stager shell code we saw earlier to locate APIs.

00:02:27.740 --> 00:02:31.800
It accesses the Process Environment Block and iterates over the linked list

00:02:31.810 --> 00:02:37.220
of modules, computing the ROT13 hash of each module until it finds one which

00:02:37.220 --> 00:02:41.140
matches the precomputed ROT13 hash of kernel32.

00:02:41.140 --> 00:02:44.900
Once the base address of kernel32 has been found,

00:02:44.900 --> 00:02:50.190
it accesses its export table and loops over all the module's exported functions,

00:02:50.190 --> 00:02:54.050
computing the ROT13 and comparing it with the

00:02:54.050 --> 00:02:57.410
precomputed hashes of APIs which are required.

00:02:58.440 --> 00:03:02.060
It keeps iterating until all the APIs have been found.

00:03:03.040 --> 00:03:09.600
The APIs in question are LoadLibraryA, GetProcAddress, and VirtualAlloc.

00:03:09.600 --> 00:03:13.760
It repeats this process for APIs in Ntdll,

00:03:14.140 --> 00:03:18.630
which are also required, and then moves on to allocate some memory,

00:03:18.640 --> 00:03:20.350
in which it will load the payload.

00:03:22.440 --> 00:03:26.040
It does this using the pointer to the VirtualAlloc API,

00:03:26.050 --> 00:03:27.960
which was resolved previously.

00:03:29.540 --> 00:03:34.460
It then starts to copy the headers and sections into the allocated memory.

00:03:35.040 --> 00:03:40.850
It then imports the payload's dependencies using the LoadLibraryA API, similar

00:03:40.850 --> 00:03:46.300
to how the stager loaded the WinINet module so that it could communicate over

00:03:46.300 --> 00:03:51.140
HTTP. Once all the dependencies have been loaded,

00:03:51.150 --> 00:03:53.560
it moves on to process relocations.

00:03:55.740 --> 00:04:00.560
When the DLL file is compiled, a preferred base address is added to the file.

00:04:01.820 --> 00:04:05.660
If the memory of the DLL's preferred base address is already in use,

00:04:06.040 --> 00:04:09.550
the operating system will load the DLL at a different base address,

00:04:09.670 --> 00:04:12.160
which means that some parts of the code need to be

00:04:12.160 --> 00:04:14.260
updated to account for this change.

00:04:16.339 --> 00:04:18.589
Once these relocations have been processed,

00:04:18.600 --> 00:04:19.519
the entry point,

00:04:19.529 --> 00:04:24.350
which, in the case of our DLL, is DllMain, is returned to the caller,

00:04:24.940 --> 00:04:26.010
which, if you recall,

00:04:26.020 --> 00:04:28.750
is the stub of shell code which was patched in the DOS

00:04:28.750 --> 00:04:30.760
head of the payload by the handler.

00:04:31.740 --> 00:04:33.080
And as we saw previously,

00:04:33.090 --> 00:04:37.260
it does indeed call DllMain, which initializes the Meterpreter shell.
