|
Bitdefender Hypervisor Memory Introspection
|
This file contains a workaround for the CVE-2019-1125 vulnerability. More...
#include "swapgs.h"#include "guests.h"#include "icache.h"#include "memcloak.h"#include "slack.h"#include "winpe.h"Go to the source code of this file.
Data Structures | |
| struct | _SWAPGS_HANDLER |
| struct | _SWAPGS_GADGET |
Typedefs | |
| typedef struct _SWAPGS_HANDLER | SWAPGS_HANDLER |
| typedef struct _SWAPGS_GADGET | SWAPGS_GADGET |
| typedef enum _SWAPGS_SSTATE | SWAPGS_SSTATE |
Enumerations | |
| enum | _SWAPGS_SSTATE { swapgsSstateNone = 0, swapgsSstateJcc, swapgsSstatePush, swapgsSstateSwapgs, swapgsSstateGsBasedAccess } |
Functions | |
| static SWAPGS_HANDLER * | IntSwapgsInstallHandler (QWORD Section, BYTE Instruction[16], BYTE Length) |
| Install a handler for a given instruction. More... | |
| INTSTATUS | IntSwapgsStartMitigation (void) |
| Scan the kernel for vulnerable SWAPGS gadgets, and mitigate CVE-2019-1125, when such gadgets are found. More... | |
| void | IntSwapgsUninit (void) |
| Uninit the SWAPGS mitigation. More... | |
| void | IntSwapgsDisable (void) |
| Disable SWAPGS mitigations. Must be used only for PrepareUninit. More... | |
| BOOLEAN | IntSwapgsIsPtrInHandler (QWORD Ptr, THS_PTR_TYPE Type, QWORD *Gadget) |
| Check if a pointer points inside a SWAPGS handler. More... | |
| QWORD | IntSwapgsRelocatePtrIfNeeded (QWORD Ptr) |
| Relocate a pointer if it points inside a SWAPGS gadget, and make it point inside the installed handler. More... | |
Variables | |
| LIST_HEAD | gGadgets = LIST_HEAD_INIT(gGadgets) |
| List of all the hooked gadgets. More... | |
| LIST_HEAD | gHandlers = LIST_HEAD_INIT(gHandlers) |
| List of all distinct handlers. More... | |
| BOOLEAN | gMitigated |
| TRUE if we mitigated the SWAPGS issue. More... | |
This file contains a workaround for the CVE-2019-1125 vulnerability.
Since we have discovered the SWAPGS attack (CVE-2019-1125), we were able to provide a workaround, directly inside the introspection engine, in order to mitigate the vulnerability. The way this works is by simply serializing all the SWAPGS gadgets that are vulnerable. Note that we focus mainly on SWAPGS variant 2, which is the more dangerous form - executing the SWAPGS instruction even if it shouldn't.
IMPORTANT 1: All SWAPGS instructions lie in .text or KVASCODE sections, which are non-paged! IMPORTANT 2: All gadgets are followed by GS based addressing, which simplified hooking! IMPORTANT 3: Gadgets which are located inside the KVASCODE section must be relocated inside the same section. The reason is that under KPTI, only KVASCODE section is mapped in user-mode, and the CR3 switch takes place in that section. If we place the handler in the .text section, the handler would execute before switching the CR3, and it would cause a triple-fault in guest.
Definition in file swapgs.c.
| typedef struct _SWAPGS_GADGET SWAPGS_GADGET |
Describes one intercepted gadget. Unlike the template, this describes each intercepted vulnerable code sequence. Multiple such gadgets may be handled by a single SWAPGS_HANDLER.
| typedef struct _SWAPGS_HANDLER SWAPGS_HANDLER |
Describes one SWAPGS handler. A SWAPGS handler may be shared by multiple SWAPGS gadgets.
| typedef enum _SWAPGS_SSTATE SWAPGS_SSTATE |
SWAPGS gadget state.
| enum _SWAPGS_SSTATE |
SWAPGS gadget state.
| void IntSwapgsDisable | ( | void | ) |
Disable SWAPGS mitigations. Must be used only for PrepareUninit.
Definition at line 501 of file swapgs.c.
Referenced by IntGuestPrepareUninit().
|
static |
Install a handler for a given instruction.
This function searched for a handler for the specified instruction (which follows SWAPGS). If one is found, it will be installed as a mitigation handler for the identified gadget. Otherwise, a new handler will be allocated. The handler is very simple: LFENCE Instruction PUSHFQ ADD [rsp + 8], Length POPFQ RETN
| [in] | Section | The section inside NT of the required handler (.text or KVASCODE) |
| [in] | Instruction | Instruction bytes of the instruction following the SWAPGS (must be GS based addressing). |
| [in] | Length | Length of the identified instruction. |
| The | handler installed for this instruction. |
Definition at line 70 of file swapgs.c.
Referenced by IntSwapgsStartMitigation().
| BOOLEAN IntSwapgsIsPtrInHandler | ( | QWORD | Ptr, |
| THS_PTR_TYPE | Type, | ||
| QWORD * | Gadget | ||
| ) |
Check if a pointer points inside a SWAPGS handler.
| [in] | Ptr | The pointer to be checked. |
| [in] | Type | Live RIP or stack value. |
| [out] | Gadget | The gadget address, if any is found, or NULL otherwise. |
| True | if the Ptr points inside a gadget, false otherwise. |
Definition at line 531 of file swapgs.c.
Referenced by IntThrSafeIsLiveRIPInIntro(), and IntThrSafeIsStackPtrInIntro().
Relocate a pointer if it points inside a SWAPGS gadget, and make it point inside the installed handler.
| [in] | Ptr | The pointer to be checked. |
| The | new value for the pointer, if it was relocated. |
Definition at line 579 of file swapgs.c.
Referenced by IntThrSafeMoveReturn(), and IntThrSafeMoveRip().
| INTSTATUS IntSwapgsStartMitigation | ( | void | ) |
Scan the kernel for vulnerable SWAPGS gadgets, and mitigate CVE-2019-1125, when such gadgets are found.
This function scans the NT image (.text and KVASCODE sections) for code sequences that are vulnerable to SWAPGS variant 2. When such a sequence is found, it will replace the first GS based access after the SWAPGS with a JMP to a small handler installed inside the NT slack space, which will simply serialize execution using LFENCE. Example: Considering the sequence: TEST [mem], imm JZ skip_swapgs SWAPGS skip_swapgs: MOV r10, gs:[0x188] ... we will replace the "MOV r10, gs:[0x188]" instruction with a "CALL" to a handler installed inside the slack space, which will force a "LFENCE" before actually doing the GS based addressing. NOTE: This scanning & instrumentation is done with the VCPUs paused.
| INT_STATUS_SUCCESS | On success. |
| INT_STATUS_NOT_NEEDED_HINT | If KPTI is not active, or if the guest is not x64, or if it is not Windows. |
| INT_STATUS_INVALID_INTERNAL_STATE | If the NT image headers are corrupt. |
| INT_STATUS_NOT_SUPPORTED | If a handler cannot be installed. |
| INT_STATUS_INSUFFICIENT_RESOURCES | If a memory alloc fails. |
Definition at line 190 of file swapgs.c.
Referenced by DbgMitigateSwapgs(), and IntWinGuestFinishInit().
| void IntSwapgsUninit | ( | void | ) |
Uninit the SWAPGS mitigation.
All gadgets will be restored, making the OS vulnerable again.
Definition at line 446 of file swapgs.c.
Referenced by DbgMitigateSwapgs(), and IntGuestUninit().
| LIST_HEAD gGadgets = LIST_HEAD_INIT(gGadgets) |
| LIST_HEAD gHandlers = LIST_HEAD_INIT(gHandlers) |
| BOOLEAN gMitigated |
TRUE if we mitigated the SWAPGS issue.
Definition at line 66 of file swapgs.c.
Referenced by IntSwapgsStartMitigation(), and IntSwapgsUninit().