cakemaker

oplock on PEB.Ldr modules against debugger attach

Sep 22nd, 2024 (edited)
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.77 KB | Pets | 0 0
  1. //
  2. // antidebug.oplocks_on_image_files.simple.cpp
  3. // src: x.com/sixtyvividtails/status/1840358359058231435
  4. //
  5. #include <conio.h>
  6. #include <stdio.h>
  7. #include <windows.h>
  8. #include "phnt.h"
  9.  
  10. // This is only stalemate antidebug example, as by the time oskrnl on behalf of attaching debugger attempts to
  11. // open the file, all our threads are already suspended. Thus both our process and debugger are deadlocked.
  12. //
  13. // That won't be true for opening main exe image file and ntdll, as only the very first process thread is suspended
  14. // at that point. Now consider that filename changes are not tracked, so you can rename image or stream, and put
  15. // other file in its place. This means non-deadlocking variant of this is possible.
  16. //
  17. // To continue running while having debugger blocked, we need threadX (other than 0) to put oplock on our main
  18. // image file (or at least on the file where our image file originally was).
  19. // Oplock break request would then arrive with only thread0 suspended; threadX will be woken up for oplock break,
  20. // and can inspect situation and resume thread0. Resumed thread0 shall put oplock on some new PEB.Ldr module,
  21. // and once oplock break on that requested, thread0 can resume other threads (including threadX). And threadX
  22. // should break main image oplock and reestablish it, possible with a "new" main image file.
  23.  
  24. int __cdecl wmain()
  25. {
  26.     // load rare module, so it'll be in our PEB.Ldr list;
  27.     // no one shall molest it; but to let honest apps touch it, use some own module in ads instead
  28.     HMODULE hauLib = LoadLibraryExW(L"KBDHAU.DLL", {}, LOAD_LIBRARY_SEARCH_SYSTEM32);
  29.     if (!hauLib)
  30.         return printf("[-] failed to load kbdhau.dll\n"), STATUS_NO_SUCH_FILE;
  31.     printf("[+] loaded kbdhau.dll\n");
  32.  
  33.     // open rare file and request oplock; we don't intend to acknowledge its break
  34.     HANDLE hauFile; // ~
  35.     IO_STATUS_BLOCK iosb;
  36.     NTSTATUS st = NtOpenFile(&hauFile, SYNCHRONIZE,         // whatever rights
  37.         ObjAttr(L"\\SystemRoot\\System32\\KBDHAU.DLL"),
  38.         &iosb, FILE_SHARE_RWD, FILE_OPEN_REQUIRING_OPLOCK|FILE_NON_DIRECTORY_FILE);
  39.     if (FAILED(st))
  40.         return printf("[-] file open failed: %08X\n", st), st;
  41.  
  42.     // let sysmon/procmon/whatever do the job (yes... not the scope right now)
  43.     printf("[ ] waiting a bit so as not to block more than we want...\n");
  44.     LARGE_INTEGER timeout{.QuadPart = -10'000'000*3};
  45.     NtDelayExecution(true, &timeout);
  46.  
  47.     REQUEST_OPLOCK_INPUT_BUFFER inp
  48.     {
  49.         .StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION,
  50.         .StructureLength = sizeof(inp),
  51.         .RequestedOplockLevel =     // sort of batch oplock
  52.             OPLOCK_LEVEL_CACHE_READ|OPLOCK_LEVEL_CACHE_HANDLE|OPLOCK_LEVEL_CACHE_WRITE,
  53.         .Flags = REQUEST_OPLOCK_INPUT_FLAG_REQUEST
  54.     };
  55.     REQUEST_OPLOCK_OUTPUT_BUFFER out{};
  56.     iosb.Status = STATUS_PENDING;   // for manual check, as we don't use event for ioctl here
  57.     st = NtFsControlFile(hauFile, {}, {}, {}, &iosb, FSCTL_REQUEST_OPLOCK,
  58.         &inp, sizeof(inp), &out, sizeof(out));
  59.     if (FAILED(st))
  60.         return printf("[-] oplock request failed: %08X\n", st), st;
  61.     printf("[+] oplock request granted\n");
  62.  
  63.     // add console handler for better experience
  64.     static bool s_shouldRundown;
  65.     SetConsoleCtrlHandler([](ULONG) -> BOOL
  66.     {
  67.         s_shouldRundown = true;
  68.         HANDLE thread0{};
  69.         NtGetNextThread(NtCurrentProcess(), {}, THREAD_ALERT, 0, 0, &thread0);
  70.         NtAlertThread(thread0);
  71.         NtClose(thread0);
  72.         return true;
  73.     }, TRUE);
  74.  
  75.     for (ULONG count = 0;; ++count)
  76.     {
  77.         NtDelayExecution(true, &timeout);
  78.         if (s_shouldRundown)
  79.             break;
  80.         if (iosb.Status == STATUS_PENDING)
  81.             printf("[ ] %05u: nothing happened\n", count);
  82.         else
  83.         {
  84.             // we won't ack/break oplock though, so this is one-time message
  85.             printf("[*] %05u: someone tried to open kbdhau.dll:\n"
  86.                 "    orig oplock level: %u, new level: %u, flags: %08X,\n"
  87.                 "    access: %08X, share mode: %u, iosb: %08X/%016I64X\n",
  88.                 count, out.OriginalOplockLevel, out.NewOplockLevel, out.Flags,
  89.                 out.AccessMode, out.ShareMode, iosb.Status, iosb.Information);
  90.             iosb.Status = STATUS_PENDING;
  91.             continue;
  92.         }
  93.     }
  94.     printf("running down...\n");
  95.     NtCancelIoFileEx(hauFile, &iosb, &iosb);
  96.     NtClose(hauFile);
  97.  
  98.     ULONG dummy;
  99.     if (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dummy) && GetConsoleProcessList(&dummy, 1) <= 1)
  100.     {
  101.         printf("press any key to continue...\n");
  102.         _flushall();
  103.         int c = _getch();
  104.         if (!c || c == 0xE0)    // arrow or function key, need to read one more
  105.             (void)_getch();
  106.     }
  107.  
  108.     return 0;
  109. }
Add Comment
Please, Sign In to add comment