Page 2 of 3

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Fri Apr 07, 2017 8:47 am
by madshi
Ok, I'll work on a fix, already have something in mind.

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Fri Apr 07, 2017 10:17 am
by madshi
@Iconic, AFAIU, a thread can only disable dynamic code restrictions if the process allows threads to do that (AllowThreadOptOut). Isn't it unlikely that any Microsoft process which enables dynamic code restriction would allow threads to opt out?

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Fri Apr 07, 2017 10:27 am
by EaSy
You have 3 options:
1) Leave dynamic code prohibited processes be.
2) Implement NtTestAlert hook without VirtualProtect calls (maybe indirect jmp).
3) Call driver/serverapp to manipulate process memory for you. Set event or smth like that (From the presentation I included in this thread before: Mitigation check is done on the calling process and not on the target process).

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Fri Apr 07, 2017 10:30 am
by madshi
As I said, I already have a plan on how to fix the injection stability problem. That's not the problem. The problem is if it will be possible to load dlls and hook apis in processes like dllhost by trying to change the mitigation somehow. But probably doing so might harm security, so it might not be a good idea to automatically do such things from within madCodeHook.

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Fri Apr 07, 2017 10:39 am
by EaSy
We will be satisfied even if no "dynamic code prohibited" process is injected at all for now. But it can change in time when we will know what are the clear intentions behind this and how the apps will use this in future.

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Fri Apr 07, 2017 11:35 pm
by madshi
Here's a beta build which should fix the problem, for both 32bit and 64bit win10. Can you confirm?

http://madshi.net/madCollectionBeta.exe (installer 2.8.2.1)

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Sat Apr 08, 2017 2:29 am
by iconic
Ran some quick tests (mainly out of curiosity), SetProcessMitigationPolicy() will definitely not allow threads to opt out if a previous call to SetProcessMitigationPolicy() was already made which prevents it. However, since this is called at run-time and not a linker flag handed to it at compile time it can definitely be worked around, although perhaps not advisable since this is meant to be a security enhancement for the process' address space. These policies are designed to allow you to reconfigure them only if you're adding enhanced restrictions, not removing any of the current policy restrictions.

Anyhow, my test code is below as there aren't a lot of great examples online from what I see, at least with definitions all in one place.

Code: Select all

typedef enum _PROCESS_MITIGATION_POLICY { 
     ProcessDEPPolicy                    = 0,
     ProcessASLRPolicy                   = 1,
     ProcessDynamicCodePolicy            = 2,
     ProcessStrictHandleCheckPolicy      = 3,
     ProcessSystemCallDisablePolicy      = 4,
     ProcessMitigationOptionsMask        = 5,
     ProcessExtensionPointDisablePolicy  = 6,
     ProcessControlFlowGuardPolicy       = 7,
     ProcessSignaturePolicy              = 8,
     ProcessFontDisablePolicy            = 9,
     ProcessImageLoadPolicy              = 10,
     MaxProcessMitigationPolicy          = 11
   } PROCESS_MITIGATION_POLICY, *PPROCESS_MITIGATION_POLICY;




  typedef struct _PROCESS_MITIGATION_DYNAMIC_CODE_POLICY {
      union {
          DWORD  Flags;
        struct {
             DWORD ProhibitDynamicCode  :1;
             DWORD AllowThreadOptOut  :1;
            DWORD ReservedFlags  :30;
           };
        };
     } PROCESS_MITIGATION_DYNAMIC_CODE_POLICY, *PPROCESS_MITIGATION_DYNAMIC_CODE_POLICY;



  typedef BOOL (WINAPI *PSetProcessMitigationPolicy)(PROCESS_MITIGATION_POLICY MitigationPolicy,
                                                     PVOID lpBuffer,
						     SIZE_T dwLength);


/* 
  Get/SetThreadInformation() share the same prototype, no sense in creating 2
*/

  typedef BOOL (WINAPI *PGetSetThreadInformation)(HANDLE hThread,
                                                  ULONG ThreadInformationClass,
                                                  PULONG ThreadInformation,
                                                  ULONG ThreadInformationSize);


   #define THREAD_DYNAMIC_CODE_DISALLOW 0
   #define THREAD_DYNAMIC_CODE_ALLOW 1
   #define ThreadDynamicCodePolicy 2
   #define ERROR_DYNAMIC_CODE_BLOCKED 0x677
   #define gpa_SpmP "SetProcessMitigationPolicy"
   #define gpa_Sti "SetThreadInformation"
   #define gpa_Gti "GetThreadInformation"
   #define KRNL32 L"kernel32.dll"




void TestDynCodeModify()
{
   HMODULE hKrnl32 = GetModuleHandleW(KRNL32);

   PSetProcessMitigationPolicy Spmp = 
                         (PSetProcessMitigationPolicy)GetProcAddress(hKrnl32,
		                    "SetProcessMitigationPolicy");

   PGetSetThreadInformation Sti = 
		                 (PGetSetThreadInformation)GetProcAddress(hKrnl32, 
						   "SetThreadInformation");

   PGetSetThreadInformation Gti = 
                        (PGetSetThreadInformation)GetProcAddress(hKrnl32, 
						"GetThreadInformation");

  if (Spmp == NULL || Sti == NULL || Gti == NULL)
  {
     printf("A function pointer is NULL... Aborting\n");
     getchar();
     return;
  }

   PROCESS_MITIGATION_DYNAMIC_CODE_POLICY Pmdcp = {0};
   /* 
      prohibit dynamic code modifications but allow threads to opt out individually 
   */
   Pmdcp.ProhibitDynamicCode = 1;
   /* 
      has to be set in first call to SetProcessMitigationPolicy() otherwise it is ignored 
   */
   Pmdcp.AllowThreadOptOut = 1;

 if (Spmp(ProcessDynamicCodePolicy, &Pmdcp, sizeof(PROCESS_MITIGATION_DYNAMIC_CODE_POLICY)))
 {
     printf("SetProcessMitigationPolicy(DYNAMIC_CODE_POLICY) Success!!!\n\n");
 }
  else
 {
     printf("SetProcessMitigationPolicy() Failed - 0x%08x\n", GetLastError());
     getchar();
     return;
 }

    DWORD dwThreadPolicy = THREAD_DYNAMIC_CODE_ALLOW;

 if (Sti(GetCurrentThread(), ThreadDynamicCodePolicy, &dwThreadPolicy, sizeof(DWORD)))
  {
     printf("Allowing Current Thread to Make PAGE_EXECUTE_XxX Modifications\n");
  }
else
  { 
     printf("SetThreadInformation() Failed - 0x%08x\n", GetLastError());
     getchar();
     return;
  }

    printf("Checking Current Thread Policy for Dynamic Code Modifications...\n");

  if (Gti(GetCurrentThread(), ThreadDynamicCodePolicy, &dwThreadPolicy, sizeof(DWORD)))
  {
     printf("Current Thread Policy Allows for Dynamic Code Modifications: %s\n", ((dwThreadPolicy != 0) ? "YES" : "NO"));
  }
else
  {
     printf("GetThreadInformation() Failed - 0x%08x\n", GetLastError());
     getchar();
     return;
  }

    ULONG oldProtect;

 if (VirtualProtect((void*)GetModuleHandle(NULL), 2, PAGE_EXECUTE_READWRITE, &oldProtect))
 {
     printf("VirtualProtect() Succeeded!\n");
     VirtualProtect((void*)GetModuleHandle(NULL), 2, oldProtect, &oldProtect);
 }
else
  {
     printf("VirtualProtect() Failed - 0x%08x\n", GetLastError());
     getchar();
     return;
  }

    printf("\n");

   dwThreadPolicy = THREAD_DYNAMIC_CODE_DISALLOW;
  
 if (Sti(GetCurrentThread(), ThreadDynamicCodePolicy, &dwThreadPolicy, sizeof(DWORD)))
  {
    printf("DisAllowing Current Thread to Make PAGE_EXECUTE_XxX Modifications\n");
  }
else
  { 
    printf("SetThreadInformation() Failed - 0x%08x\n", GetLastError());
    getchar();
    return;
  } 

    printf("Checking Current Thread Policy for Dynamic Code Modifications...\n");

  if (Gti(GetCurrentThread(), ThreadDynamicCodePolicy, &dwThreadPolicy, sizeof(DWORD)))
  {
    printf("Current Thread Policy Allows for Dynamic Code Modifications: %s\n", ((dwThreadPolicy != 0) ? "YES" : "NO"));
  }
else
  {
     printf("GetThreadInformation() Failed - 0x%08x\n", GetLastError());
     getchar();
     return;
  }

 if (VirtualProtect((void*)GetModuleHandle(NULL), 2, PAGE_EXECUTE_READWRITE, &oldProtect))
 {
     printf("Success! VirtualProtect() Succeeded!\n");
     VirtualProtect((void*)GetModuleHandle(NULL), 2, oldProtect, &oldProtect);
     getchar();
 }
else
  {
     printf("VirtualProtect() Failed - 0x%08x\n", GetLastError());
     printf("Expected Error on Failure (ERROR_DYNAMIC_CODE_BLOCKED) Returned: %s\n", (GetLastError() ==            ERROR_DYNAMIC_CODE_BLOCKED) ? "YES" : "NO");
     getchar();
     return;
  }
}
--Iconic

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Sat Apr 08, 2017 6:23 am
by EaSy
You can set mitigation policies as startup info or in registry without any api call.


PP

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Sat Apr 08, 2017 7:53 am
by madshi
Thanks iconic, having some sample code might come in handy in the future!

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Sat Apr 08, 2017 5:45 pm
by iconic
Ahh yes, I do recall seeing the STARTUPINFO structure modified prior to a CreateProcess call with some of these policies in the past now that I think about it. But I've personally not used them, yet. Seems that MS is making the building of a sandbox more attractive as an option. Thanks for the additional info, EaSy

--Iconic

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Mon Apr 10, 2017 7:32 am
by madshi
EaSy wrote:sorry, but I must ask you. Will you be able to fix this or at least work around this before the creators update goes live (in 4 days)? Thx.
We would love to have at least 1 day to prepare updates, because it also affects all versions of MCH previously released.
Have you had a chance to test my fixed beta build yet? Thanks...

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Mon Apr 10, 2017 9:49 am
by EaSy
Hi,
I am testing it now. Second RW memory page works OK, so the dllhost is not crashing or hanging anymore.
But I am experiencing some issue with "non-main thread waiting" part of the code you have implemeted. I am debugging it right now. Maybe it is related, maybe not.

PP

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Mon Apr 10, 2017 9:50 am
by madshi
Ok, thanks.

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Mon Apr 10, 2017 9:52 am
by madshi
P.S: Which program did you use to list the mitigations (see screenshot first page)? Is it the Process Explorer? Or something else?

Re: MCH3: W10 Insider DllHost injecting crash

Posted: Mon Apr 10, 2017 10:33 am
by EaSy
Hi,
I am taking my suspicion back. It was caused by windbg breakpoint on nttestalert (MCH wasn't able to rewrite it). Everything looks OK.

Thx for quick fix!

PS: I am using Process Hacker http://processhacker.sourceforge.net/

PP