当前位置:网站首页>New de debugging

New de debugging

2022-06-24 15:36:00 franket

First , We will introduce two new methods related to thread suspension . They are not the most revolutionary or useful , But I will try my best .

Bypass process freeze

This is a Microsoft stay 19H1 Add a cute little thread creation tag in . Have you ever thought about why In the thread creation flag There is Loophole ? ok , This vulnerability is already full of what I call a flag THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE( I don't know its actual name ), Its value is naturally 0x40.

To demonstrate what it does , I will show PsSuspendProcess How it works :

NTSTATUS PsSuspendProcess(_EPROCESS* Process)
{
  const auto currentThread = KeGetCurrentThread();
  KeEnterCriticalRegionThread(currentThread);

  NTSTATUS status = STATUS_SUCCESS;
  if ( ExAcquireRundownProtection(&Process->RundownProtect) )
  {
    auto targetThread = PsGetNextProcessThread(Process, nullptr);
    while ( targetThread )
    {
      // Our flag in action
      if ( !targetThread->Tcb.MiscFlags.BypassProcessFreeze )
        PsSuspendThread(targetThread, nullptr);

      targetThread = PsGetNextProcessThread(Process, targetThread);
    }
    ExReleaseRundownProtection(&Process->RundownProtect);
  }
  else
    status = STATUS_PROCESS_IS_TERMINATING;

  if ( Process->Flags3.EnableThreadSuspendResumeLogging )
    EtwTiLogSuspendResumeProcess(status, Process, Process, 0);

  KeLeaveCriticalRegionThread(currentThread);
  return status;
}

As you can see ,NtSuspendProcess This call PsSuspendProcess Only threads with this flag will be ignored . Another benefit is that the thread will not be suspended NtDebugActiveProcess! as far as I am concerned , Once the thread is created with this thread , You cannot query or disable this flag , So you can't do much about it .

In terms of its usefulness , I want to say that this is just a good way to prevent dumping , When you are in Processhacker Middle click “ Pause ” when , It will cause confusion , And the process continues , Like nothing happened .

Example

for example , This is a bit of interesting code , It will continue to print I am running. I'm sure , Seeing this when backing up can cause a lot of confusion , Why hell would stop his own process .

#define THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE 0x40

NTSTATUS printer(void*) {
    while(true) {
        std::puts("I am running\n");
        Sleep(1000);
    }
    return STATUS_SUCCESS;
}

HANDLE handle;
NtCreateThreadEx(&handle, MAXIMUM_ALLOWED, nullptr, NtCurrentProcess(),
                 &printer, nullptr, THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE,
                 0, 0, 0, nullptr);

NtSuspendProcess(NtCurrentProcess());

Hang up on me

Continue the trend of disorderly behavior NtSuspendProcess, We will again abuse how it detects whether our process is suspended .

The trick is , The pause count is a signed 8 A value . Just like the last one , Here's some code to let you know how it works inside :

ULONG KeSuspendThread(_ETHREAD *Thread)
{
  auto irql = KeRaiseIrql(DISPATCH_LEVEL);
  KiAcquireKobjectLockSafe(&Thread->Tcb.SuspendEvent);

  auto oldSuspendCount = Thread->Tcb.SuspendCount;
  if ( oldSuspendCount == MAXIMUM_SUSPEND_COUNT ) // 127
  {
    _InterlockedAnd(&Thread->Tcb.SuspendEvent.Header.Lock, 0xFFFFFF7F);
    KeLowerIrql(irql);
    ExRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);
  }

  auto prcb = KeGetCurrentPrcb();
  if ( KiSuspendThread(Thread, prcb) )
    ++Thread->Tcb.SuspendCount;

  _InterlockedAnd(&Thread->Tcb.SuspendEvent.Header.Lock, 0xFFFFFF7F);
  KiExitDispatcher(prcb, 0, 1, 0, irql);
  return oldSuspendCount;
}

If you look at the first code example ,PsSuspendProcess It has no error checking , I don't care if I don't suspend threads anymore . So what happens when you make a phone call NtResumeProcess Well ? It reduces the pending count ! What we need to do is to make the most of it , When someone decides to suspend and resume us , They will actually keep the count in a state that they were not in before .

Example

The following simple code is quite effective :

  • Visual Studio- Prevent it from pausing the process after attaching .
  • WinDbg- Detected while connecting .
  • x64dbg- The pause button becomes coarse , With such as “ The program is not running ” Error messages like that , Until you manually switch to the main thread .
  • ScyllaHide- Use an older version NtSuspendProcess And cause it to detect , But it has been fixed after my report .
for(size_t i = 0; i < 128; ++i)
  NtSuspendThread(thread, nullptr);

while(true) {
  if(NtSuspendThread(thread, nullptr) != STATUS_SUSPEND_COUNT_EXCEEDED)
    std::puts("I was suspended\n");
  Sleep(1000);
}

Conclusion

If any , I hope this shows that it is best not to rely on NtSuspendProcess The tools you expect to handle potentially malicious or protected code . I hope you like this article , And hope to have more content in the next few weeks .

原网站

版权声明
本文为[franket]所创,转载请带上原文链接,感谢
https://yzsam.com/2021/05/20210508173802693i.html