WEBVTT

00:00:00.000 --> 00:00:03.490
Let's now take a look at some of the modifications which we can make to

00:00:03.490 --> 00:00:06.900
the payloads and extensions to make them more evasive.

00:00:07.110 --> 00:00:10.350
You may recall from the Meterpreter Deep Dive module that the

00:00:10.350 --> 00:00:13.870
Meterpreter payloads and extensions are loaded reflectively.

00:00:13.880 --> 00:00:20.210
You may also recall that the reflective loader uses ROT13 hashes to locate APIs,

00:00:20.210 --> 00:00:23.760
which it needs to perform reflective DLL injection.

00:00:23.800 --> 00:00:28.700
These ROT13 hashes are ideal for developing signatures since they are

00:00:28.700 --> 00:00:31.820
hard‑coded values which will always be in memory.

00:00:31.820 --> 00:00:33.790
We can modify these hashes,

00:00:33.800 --> 00:00:36.530
just as we did when modifying the stager's shellcode

00:00:36.540 --> 00:00:39.260
and leverage a ROT16 hash instead.

00:00:39.440 --> 00:00:44.470
I have already pre‑calculated the ROT16 hashes and replaced them in the code.

00:00:44.540 --> 00:00:50.210
I have also changed the value 13 to 16, since we want to perform a ROT16 hash.

00:00:50.210 --> 00:00:53.320
This will ensure that there won't be any traces of

00:00:53.320 --> 00:00:57.570
these well‑known values in memory, which may be detected by scans.

00:00:57.620 --> 00:01:01.040
Let's now take a look at one of the extensions, which is used by Meterpreter.

00:01:01.540 --> 00:01:04.530
The STT API extension provides some of the core

00:01:04.530 --> 00:01:07.330
functionality when interacting with the payload.

00:01:07.400 --> 00:01:11.250
It is automatically loaded when the Meterpreter session is initializing.

00:01:11.330 --> 00:01:14.380
We can attempt to modify some of the code inside this

00:01:14.380 --> 00:01:17.200
extension in an attempt to make it more evasive.

00:01:17.210 --> 00:01:21.200
I randomly chose to modify the steal_token functionality.

00:01:21.300 --> 00:01:24.360
I added a very simple xor encryptor function.

00:01:24.460 --> 00:01:28.220
Its job will be to decrypt strings at runtime to avoid

00:01:28.220 --> 00:01:32.560
hard‑coding blacklisted strings, which may be frowned upon by antivirus.

00:01:32.600 --> 00:01:35.440
I chose the value 9 as the encryption key.

00:01:35.450 --> 00:01:38.420
The section of code I chose to modify makes use of

00:01:38.420 --> 00:01:41.430
the ImpersonateLoggedOnUser API.

00:01:41.430 --> 00:01:45.820
Currently, this API will be added to the extensions import address table.

00:01:45.830 --> 00:01:48.630
Therefore, if an antivirus was to scan memory,

00:01:48.630 --> 00:01:51.990
it would find the ImpersonateLoggedOnUser string

00:01:52.000 --> 00:01:53.810
inside the import address table.

00:01:53.950 --> 00:01:56.820
We can get around this using a technique we already covered,

00:01:56.820 --> 00:02:00.960
which makes use of the GetProcAddress API and function pointers.

00:02:00.960 --> 00:02:04.970
To call GetProcAddress, however, we need a handle to the module,

00:02:04.980 --> 00:02:08.259
which involves calling the GetModuleHandle API,

00:02:08.259 --> 00:02:11.460
which in turn requires the name of the module.

00:02:11.540 --> 00:02:15.150
This is obviously an issue, since we want to avoid hard‑coded strings.

00:02:15.150 --> 00:02:19.350
We also encounter the same issue when calling the GetProcAddress API,

00:02:19.350 --> 00:02:21.740
which requires the API name.

00:02:21.820 --> 00:02:22.520
At this point,

00:02:22.520 --> 00:02:25.190
we can make use of the encryption function we saw

00:02:25.190 --> 00:02:28.910
previously so that instead of hard‑coding the advapi32.dll

00:02:28.910 --> 00:02:34.840
and ImpersonateLoggedOnUser strings, we can hard code their encrypted values,

00:02:34.840 --> 00:02:39.230
which can be decrypted at runtime and re‑encrypted if required,

00:02:39.230 --> 00:02:42.210
to ensure in‑memory scans will not detect them.

00:02:42.440 --> 00:02:45.820
These values can be pre‑calculated using a simple program

00:02:45.820 --> 00:02:48.260
or script and embedded inside the code.

00:02:48.270 --> 00:02:51.560
We can go ahead and compile the payload and extensions.

00:02:52.140 --> 00:02:55.850
If we now compare two copies of the STD API extension,

00:02:55.980 --> 00:03:00.730
you will notice that the original file contains 278 imports,

00:03:00.930 --> 00:03:04.710
whereas our modified version only contains 277.

00:03:04.990 --> 00:03:10.340
You will also notice that the blacklisted ImpersonateLoggedOnUser API is

00:03:10.340 --> 00:03:13.350
not listed in the modified version of the extension.

00:03:13.540 --> 00:03:16.810
If we take a look at the strings located inside both files,

00:03:16.820 --> 00:03:21.000
you will also notice that the ImpersonateLoggedOnUser string is not

00:03:21.000 --> 00:03:24.230
found in the modified version of the extension either.

00:03:24.230 --> 00:03:29.310
We can now copy our recompiled payload and extensions to our

00:03:29.310 --> 00:03:31.720
Kali machine and replace the old files.

00:03:31.900 --> 00:03:34.950
We can then start up a Metasploit handler and run our stager,

00:03:34.950 --> 00:03:36.560
which we wrote previously.

00:03:40.340 --> 00:03:43.750
As you can see, the Meterpreter session is still fully functional,

00:03:43.750 --> 00:03:45.950
despite our changes to the source code.

00:03:45.950 --> 00:03:49.230
We can now elevate our privileges using the getsystem command,

00:03:49.230 --> 00:03:51.600
and list processes running on the machine.

00:03:51.610 --> 00:03:56.000
I randomly chose a process from which I want to steal the user's security token.

00:03:56.010 --> 00:04:00.850
I then ran the steal_token command, which will make use of our modified code.

00:04:00.850 --> 00:04:05.710
As you can see, the code behaved as expected, despite the changes we made.

00:04:05.710 --> 00:04:08.490
Manually refactoring the Meterpreter code base is

00:04:08.490 --> 00:04:10.250
going to be very time consuming.

00:04:10.510 --> 00:04:14.050
There are ways this can be automated using custom tools and scripts,

00:04:14.050 --> 00:04:17.350
which make use of regular expressions, for example.

00:04:17.350 --> 00:04:19.480
Alternatively, a more elegant approach,

00:04:19.480 --> 00:04:22.860
which makes use of libraries designed to pass source code,

00:04:22.860 --> 00:04:24.160
can also be chosen.

00:04:24.240 --> 00:04:27.490
A series of excellent blog posts which demonstrate this

00:04:27.490 --> 00:04:31.450
process in detail, can be found on SCRT's blog.

00:04:31.570 --> 00:04:34.390
It covers string and import address table obfuscation

00:04:34.390 --> 00:04:36.590
techniques using an automated approach,

00:04:36.590 --> 00:04:41.020
which can help save time and avoid error‑prone manual code refactoring.

00:04:41.640 --> 00:04:45.580
If you do decide to manually refactor parts of the Meterpreter code base,

00:04:45.580 --> 00:04:49.470
a good starting point is the cyberspacekittens fork of the

00:04:49.470 --> 00:04:52.150
Meterpeter payload GitHub repository.

00:04:52.360 --> 00:04:53.740
You can check out the changes,

00:04:53.740 --> 00:04:58.110
which were made to the project in an attempt to make it more evasive.

00:04:58.120 --> 00:05:01.280
This should give you plenty of ideas regarding the artifacts,

00:05:01.290 --> 00:05:04.350
which you should attempt to remove to improve your tradecraft,

00:05:04.350 --> 00:05:07.760
and stay clear of antivirus and EDR solutions.
