WEBVTT

00:00:00.040 --> 00:00:05.050
As we saw previously in the antivirus and EDR modules, API monitoring

00:00:05.060 --> 00:00:09.160
is usually performed by injecting a DLL inside newly‑created

00:00:09.160 --> 00:00:13.870
processes to hook various APIs and notify the antivirus to enable

00:00:13.870 --> 00:00:18.690
heuristic analysis of the process at runtime. This DLL is injected

00:00:18.690 --> 00:00:20.560
inside our stager's process.

00:00:20.640 --> 00:00:24.810
And since we have full control over our processes' virtual address space,

00:00:24.890 --> 00:00:28.230
we can tamper with this DLL to avoid detection when we

00:00:28.230 --> 00:00:30.570
call the monitored API functions.

00:00:30.630 --> 00:00:35.160
We have many options at our disposal when it comes to evading API hooks.

00:00:35.160 --> 00:00:39.330
Usually, to hook an API, the entry point of the function you want to

00:00:39.330 --> 00:00:45.180
hook is patched to redirect code execution into the injected DLL, which

00:00:45.180 --> 00:00:47.340
will proxy the call to spy on it.

00:00:47.470 --> 00:00:52.340
This means that, in some cases, removing the hook can consist of restoring

00:00:52.340 --> 00:00:55.600
the original bytes at the entry point of the function,

00:00:55.610 --> 00:00:57.910
which will effectively remove the hook.

00:00:57.940 --> 00:01:02.730
Alternatively, you could read the DLL file, which contains the API you want

00:01:02.730 --> 00:01:08.600
to use and overwrite the entire code section of the DLL in memory to remove

00:01:08.600 --> 00:01:11.350
the hooks for all of its exported functions.

00:01:11.360 --> 00:01:15.150
Both of these techniques could be detected by the antivirus if it

00:01:15.150 --> 00:01:18.240
checks the integrity of the hooks at runtime.

00:01:18.250 --> 00:01:22.060
In such cases, it might be better to simply avoid them completely.

00:01:22.070 --> 00:01:24.320
This can be done by copying the DLL,

00:01:24.330 --> 00:01:28.620
which contains the APIs you want to call and renaming it so

00:01:28.620 --> 00:01:31.470
that it can be reloaded using LoadLibrary.

00:01:31.480 --> 00:01:35.500
You can then use GetProcAddress to obtain function pointers on the APIs you

00:01:35.500 --> 00:01:38.980
want to call, as we did previously in our custom stager.

00:01:39.160 --> 00:01:39.940
Finally,

00:01:39.950 --> 00:01:43.560
you can, of course, avoid using the hooked APIs and perform

00:01:43.560 --> 00:01:47.050
syscalls without relying on the APIs to perform them.

00:01:47.140 --> 00:01:48.080
This will, however,

00:01:48.080 --> 00:01:53.700
impact portability since syscalls may change between operating system versions.

00:01:53.790 --> 00:01:54.850
As a side note,

00:01:54.860 --> 00:02:00.010
some of these techniques will also blind certain ETW providers. Bear in mind

00:02:00.020 --> 00:02:03.320
that this is not an exhaustive list of all possible bypasses,

00:02:03.320 --> 00:02:04.990
but it is a good starting point.

00:02:05.260 --> 00:02:08.229
Let's take a look at how we could remove API hooks,

00:02:08.440 --> 00:02:11.530
You may recall that in the antivirus and EDR modules,

00:02:11.540 --> 00:02:15.310
we saw how a driver could inject a monitoring DLL inside our

00:02:15.310 --> 00:02:18.250
shell code runner to monitor API calls.

00:02:18.340 --> 00:02:21.460
You may also recall that we were able to spy on calls

00:02:21.460 --> 00:02:23.830
to VirtualAlloc and LoadLibrary.

00:02:23.860 --> 00:02:27.840
I have made some adjustments to the custom stager we wrote previously by

00:02:27.840 --> 00:02:33.020
adding two new functions, unhook_kernel32 and unhook_ntdll.

00:02:33.100 --> 00:02:36.500
The former will use one of the techniques we talked about previously

00:02:36.510 --> 00:02:40.930
to overwrite the kernel32 module's code section in memory by reading

00:02:40.930 --> 00:02:43.360
a fresh copy of the module on disk.

00:02:43.630 --> 00:02:48.340
This has the effect of removing all hooks, which the API monitoring DLL

00:02:48.350 --> 00:02:51.960
may have placed in memory for the kernel32 module.

00:02:52.340 --> 00:02:56.060
The unhook _ntdll function uses the same technique to

00:02:56.060 --> 00:02:58.960
remove the hooks from the ntdll module.

00:02:59.540 --> 00:03:05.330
Our stager makes use of the LoadLibrary API to load the WinINet module. And

00:03:05.330 --> 00:03:09.800
if you recall, the payload's reflective loader also makes use of the

00:03:09.800 --> 00:03:15.090
VirtualAlloc and LoadLibrary APIs. We can launch the driver and start

00:03:15.090 --> 00:03:23.600
capturing debug output in DebugView. We can then run our modified stager. We

00:03:23.600 --> 00:03:27.380
can stop the driver to avoid capturing too much information and then take a

00:03:27.380 --> 00:03:31.760
look at DebugView and process Explorer to see what the monitoring DLL was

00:03:31.760 --> 00:03:33.500
able to record at runtime.

00:03:33.510 --> 00:03:37.530
As you can see, the driver did inject the monitoring DLL inside

00:03:37.530 --> 00:03:41.840
our stager's process, and the DLL was able to hook the LoadLibrary

00:03:41.850 --> 00:03:44.380
and VirtualAlloc APIs successfully,

00:03:44.390 --> 00:03:47.970
as it did previously when I demonstrated API monitoring

00:03:47.980 --> 00:03:50.570
in the antivirus and EDR modules.

00:03:50.700 --> 00:03:51.730
This time, however,

00:03:51.740 --> 00:03:56.630
you will notice that it did not log the calls to LoadLibrary or VirtualAlloc.

00:03:56.640 --> 00:04:00.960
The reason being that we removed the hooks, which the DLL had placed in memory.
