* Terminator test: TD1 (debugs a process and closes the debug object)

* added DebugObjectHandle
* added copyright headers

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1259 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
wj32
2009-05-10 09:29:40 +00:00
parent a131b3116b
commit f028ca4ca6
13 changed files with 380 additions and 115 deletions
+1
View File
@@ -7,6 +7,7 @@ Process Hacker
* KProcessHacker can now bypass all handle-opening protections
* Ability to set handle flags such as protect-from-close and inherit
* Better highlighting
* Terminator test: TD1 (debugs a process and closes the debug object)
* Terminator test: TT3 (TT1 is now completely user-mode)
* Shows function file and line numbers where available
* FIXED:
+6
View File
@@ -102,6 +102,12 @@ namespace ProcessHacker.Native.Api
CreateIgnoreSystemDefault = 0x80000000
}
[Flags]
public enum DebugObjectFlags : uint
{
KillOnClose = 0x1
}
public enum DepFlags : uint
{
Disable = 0x00000000,
+62 -16
View File
@@ -93,6 +93,28 @@ namespace ProcessHacker.Native.Api
#endregion
#region Debugging
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DebugActiveProcess(
[In] int Pid
);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DebugActiveProcessStop(
[In] int Pid
);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DebugSetProcessKillOnExit(
[In] bool KillOnExit
);
#endregion
#region Error Handling
[DllImport("ntdll.dll")]
@@ -493,6 +515,20 @@ namespace ProcessHacker.Native.Api
[In] IntPtr ThreadHandle
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtAlertResumeThread(
[In] IntPtr ThreadHandle,
[Out] [Optional] out int PreviousSuspendCount
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtCreateDebugObject(
[Out] out IntPtr DebugObjectHandle,
[In] DebugObjectAccess DesiredAccess,
[In] [Optional] IntPtr ObjectAttributes,
[In] DebugObjectFlags Flags
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtCreateProcess(
[Out] out IntPtr ProcessHandle,
@@ -516,6 +552,12 @@ namespace ProcessHacker.Native.Api
[In] [Optional] IntPtr FileHandle
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtDebugActiveProcess(
[In] IntPtr ProcessHandle,
[In] IntPtr DebugObjectHandle
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtDuplicateObject(
[In] IntPtr SourceProcessHandle,
@@ -529,7 +571,7 @@ namespace ProcessHacker.Native.Api
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtGetNextProcess(
[In] IntPtr ProcessHandle,
[In] [Optional] IntPtr ProcessHandle,
[In] ProcessAccess DesiredAccess,
[In] int HandleAttributes,
[In] int Flags,
@@ -538,11 +580,12 @@ namespace ProcessHacker.Native.Api
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtGetNextThread(
[In] IntPtr ProcessHandle,
[In] ProcessAccess DesiredAccess,
[In] [Optional] IntPtr ProcessHandle,
[In] [Optional] IntPtr ThreadHandle,
[In] ThreadAccess DesiredAccess,
[In] int HandleAttributes,
[In] int Flags,
[Out] out int NewProcessHandle
[Out] out IntPtr NewThreadHandle
);
[DllImport("ntdll.dll", SetLastError = true)]
@@ -559,6 +602,12 @@ namespace ProcessHacker.Native.Api
[Out] [Optional] out int DataWritten
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtRemoveProcessDebug(
[In] IntPtr ProcessHandle,
[In] IntPtr DebugObjectHandle
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtResumeProcess(
[In] IntPtr ProcessHandle
@@ -569,6 +618,15 @@ namespace ProcessHacker.Native.Api
[In] IntPtr ProcessHandle
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtQueueApcThread(
[In] IntPtr ThreadHandle,
[In] IntPtr ApcRoutine,
[In] [Optional] IntPtr ApcArgument1,
[In] [Optional] IntPtr ApcArgument2,
[In] [Optional] IntPtr ApcArgument3
);
[DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtQuerySection(
[In] IntPtr SectionHandle,
@@ -935,18 +993,6 @@ namespace ProcessHacker.Native.Api
[In] int ProcessId
);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DebugActiveProcess(
[In] int Pid
);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DebugActiveProcessStop(
[In] int Pid
);
[DllImport("psapi.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumProcessModules(
@@ -0,0 +1,53 @@
/*
* Process Hacker -
* debug object handle
*
* Copyright (C) 2009 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Text;
using ProcessHacker.Native.Api;
using ProcessHacker.Native.Security;
namespace ProcessHacker.Native.Objects
{
public class DebugObjectHandle : Win32Handle<DebugObjectAccess>
{
public static DebugObjectHandle Create(DebugObjectAccess access, DebugObjectFlags flags)
{
int status;
IntPtr handle;
if ((status = Win32.NtCreateDebugObject(
out handle,
access,
IntPtr.Zero,
flags
)) < 0)
Win32.ThrowLastError(status);
return new DebugObjectHandle(handle, true);
}
private DebugObjectHandle(IntPtr handle, bool owned)
: base(handle, owned)
{ }
}
}
@@ -1,4 +1,26 @@
using System;
/*
* Process Hacker -
* desktop handle
*
* Copyright (C) 2009 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Text;
using ProcessHacker.Native.Api;
@@ -185,13 +185,15 @@ namespace ProcessHacker.Native.Objects
public enum JobObjectInformationClass : int
{
JobObjectBasicAccountingInformation = 1,
JobObjectBasicLimitInformation = 2,
JobObjectBasicProcessIdList = 3,
JobObjectBasicUIRestrictions = 4,
JobObjectSecurityLimitInformation = 5,
JobObjectBasicAndIoAccountingInformation = 8,
JobObjectExtendedLimitInformation = 9,
JobObjectGroupInformation = 11
JobObjectBasicLimitInformation,
JobObjectBasicProcessIdList,
JobObjectBasicUIRestrictions,
JobObjectSecurityLimitInformation,
JobObjectEndOfJobTimeInformation,
JobObjectAssociateCompletionPortInformation,
JobObjectBasicAndIoAccountingInformation,
JobObjectExtendedLimitInformation,
JobObjectJobSetInformation
}
[Flags]
@@ -2,7 +2,7 @@
* Process Hacker -
* local security authority handle
*
* Copyright (C) 2008 wj32
* Copyright (C) 2008-2009 wj32
*
* This file is part of Process Hacker.
*
@@ -2,7 +2,7 @@
* Process Hacker -
* local security policy handle
*
* Copyright (C) 2008 wj32
* Copyright (C) 2008-2009 wj32
*
* This file is part of Process Hacker.
*
@@ -234,6 +234,19 @@ namespace ProcessHacker.Native.Objects
return new ThreadHandle(this.CreateThread(startAddress, parameter), access);
}
/// <summary>
/// Debugs the process with the specified debug object. This requires the
/// PROCESS_SUSPEND_RESUME permission.
/// </summary>
/// <param name="debugObjectHandle">A handle to a debug object.</param>
public void Debug(DebugObjectHandle debugObjectHandle)
{
int status;
if ((status = Win32.NtDebugActiveProcess(this, debugObjectHandle)) < 0)
Win32.ThrowLastError(status);
}
/// <summary>
/// Removes as many pages as possible from the process' working set. This requires the
/// PROCESS_QUERY_INFORMATION and PROCESS_SET_INFORMATION permissions.
@@ -744,6 +757,52 @@ namespace ProcessHacker.Native.Objects
}
}
/// <summary>
/// Opens the next linked process.
/// </summary>
/// <param name="access">The desired access to the next process.</param>
/// <returns>A process handle.</returns>
public ProcessHandle GetNextProcess(ProcessAccess access)
{
int status;
IntPtr handle;
if ((status = Win32.NtGetNextProcess(
this,
access,
0,
0,
out handle
)) < 0)
Win32.ThrowLastError(status);
return new ProcessHandle(handle, true);
}
/// <summary>
/// Opens the next linked thread belonging to the process.
/// </summary>
/// <param name="threadHandle">A thread handle. You may specify null.</param>
/// <param name="access">The desired access to the next thread.</param>
/// <returns>A thread handle.</returns>
public ThreadHandle GetNextThread(ThreadHandle threadHandle, ThreadAccess access)
{
int status;
IntPtr handle;
if ((status = Win32.NtGetNextThread(
this,
threadHandle != null ? threadHandle : IntPtr.Zero,
access,
0,
0,
out handle
)) < 0)
Win32.ThrowLastError(status);
return new ThreadHandle(handle, true);
}
/// <summary>
/// Gets the process' page priority, ranging from 0-7.
/// </summary>
@@ -909,9 +968,6 @@ namespace ProcessHacker.Native.Objects
/// Determines whether the process is running in a job.
/// </summary>
/// <returns>A boolean.</returns>
/// <remarks>According to this function, almost every single
/// process is in a job! This function does not tell us
/// the name of the job though.</remarks>
public bool IsInJob()
{
bool result;
@@ -921,6 +977,22 @@ namespace ProcessHacker.Native.Objects
return result;
}
/// <summary>
/// Determines whether the process is running in the specified job.
/// </summary>
/// <param name="jobObjectHandle">The job object to check.</param>
/// <returns>A boolean.</returns>
public bool IsInJob(JobObjectHandle jobObjectHandle)
{
bool result;
if (!Win32.IsProcessInJob(this, jobObjectHandle, out result))
Win32.ThrowLastError();
return result;
}
/// <summary>
/// Gets whether the process is a NTVDM process.
/// </summary>
@@ -1007,6 +1079,18 @@ namespace ProcessHacker.Native.Objects
return readLen;
}
/// <summary>
/// Stops debugging the process attached to the specified debug object.
/// </summary>
/// <param name="debugObjectHandle">The debug object which was used to debug the process.</param>
public void RemoveDebug(DebugObjectHandle debugObjectHandle)
{
int status;
if ((status = Win32.NtRemoveProcessDebug(this, debugObjectHandle)) < 0)
Win32.ThrowLastError(status);
}
/// <summary>
/// Resumes the process. This requires the PROCESS_SUSPEND_RESUME permission.
/// </summary>
@@ -1,4 +1,26 @@
using System;
/*
* Process Hacker -
* window station handle
*
* Copyright (C) 2009 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Text;
using ProcessHacker.Native.Api;
@@ -49,6 +49,7 @@
<Compile Include="KProcessHacker.cs" />
<Compile Include="IntPtrExtensions.cs" />
<Compile Include="Memory\LocalMemoryAlloc.cs" />
<Compile Include="Objects\DebugObjectHandle.cs" />
<Compile Include="Objects\DesktopHandle.cs" />
<Compile Include="Objects\SectionHandle.cs" />
<Compile Include="Objects\WindowStationHandle.cs" />
@@ -77,6 +78,7 @@
<Compile Include="Memory\LsaMemoryAlloc.cs" />
<Compile Include="Memory\MemoryAlloc.cs" />
<Compile Include="Memory\WtsMemoryAlloc.cs" />
<Compile Include="Security\DebugObjectAccess.cs" />
<Compile Include="Security\DesktopAccess.cs" />
<Compile Include="Security\TimerAccess.cs" />
<Compile Include="Security\SemaphoreAccess.cs" />
@@ -0,0 +1,15 @@
using System;
namespace ProcessHacker.Native.Security
{
[Flags]
public enum DebugObjectAccess : uint
{
ReadEvent = 0x1,
ProcessAssign = 0x2,
SetInformation = 0x4,
QueryInformation = 0x8,
All = StandardRights.Required | StandardRights.Synchronize |
ReadEvent | ProcessAssign | SetInformation | QueryInformation
}
}
+97 -85
View File
@@ -23,6 +23,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using ProcessHacker.Native;
using ProcessHacker.Native.Api;
@@ -47,10 +48,11 @@ namespace ProcessHacker
this.AddTest("TP1", "Terminates the process using TerminateProcess");
this.AddTest("TP2", "Creates a remote thread in the process which terminates the process");
this.AddTest("TJ1", "Assigns the process to a job object and terminates the job");
this.AddTest("TT1", "Terminates the process' threads");
this.AddTest("TT2", "Modifies the process' threads with contexts which terminate the process");
this.AddTest("CH1", "Closes the process' handles");
this.AddTest("TJ1", "Assigns the process to a job object and terminates the job");
this.AddTest("TD1", "Debugs the process and closes the debug object");
this.AddTest("TP3", "Terminates the process in kernel-mode (if possible)");
this.AddTest("TT3", "Terminates the process' threads in kernel-mode (if possible)");
this.AddTest("M1", "Writes garbage to the process' memory regions");
@@ -122,6 +124,97 @@ namespace ProcessHacker
return false;
}
private void CH1()
{
using (ProcessHandle phandle = new ProcessHandle(_pid, ProcessAccess.DupHandle))
{
int i = 0;
while (true)
{
if (i >= 0x1000)
break;
try
{
Win32.DuplicateObject(phandle, new IntPtr(i), 0, 0, 0x1);
}
catch
{ }
i++;
}
}
}
private void M1()
{
this.M1Internal();
}
private unsafe void M1Internal()
{
using (MemoryAlloc alloc = new MemoryAlloc(0x1000))
{
using (ProcessHandle phandle = new ProcessHandle(_pid,
ProcessAccess.QueryInformation |
Program.MinProcessWriteMemoryRights))
{
phandle.EnumMemory((info) =>
{
for (int i = 0; i < info.RegionSize; i += 0x1000)
{
try
{
phandle.WriteMemory(info.BaseAddress.Increment(i), alloc, 0x1000);
}
catch
{ }
}
return true;
});
}
}
}
private void M2()
{
using (ProcessHandle phandle = new ProcessHandle(_pid,
ProcessAccess.QueryInformation | ProcessAccess.VmOperation))
{
phandle.EnumMemory((info) =>
{
phandle.ProtectMemory(info.BaseAddress, info.RegionSize, MemoryProtection.NoAccess);
return true;
});
}
}
private void TD1()
{
using (var dhandle =
DebugObjectHandle.Create(DebugObjectAccess.ProcessAssign, DebugObjectFlags.KillOnClose))
{
using (var phandle = new ProcessHandle(_pid, ProcessAccess.SuspendResume))
phandle.Debug(dhandle);
}
}
private void TJ1()
{
using (var jhandle = JobObjectHandle.Create(null))
{
using (ProcessHandle phandle =
new ProcessHandle(_pid, ProcessAccess.SetQuota | ProcessAccess.Terminate))
{
phandle.AssignToJobObject(jhandle);
}
jhandle.Terminate();
}
}
private void TP1()
{
using (ProcessHandle phandle = new ProcessHandle(_pid, ProcessAccess.Terminate))
@@ -143,17 +236,11 @@ namespace ProcessHacker
Win32.ThrowLastError();
}
private void TJ1()
private void TP3()
{
using (var jhandle = JobObjectHandle.Create(null))
using (ProcessHandle phandle = new ProcessHandle(_pid, Program.MinProcessQueryRights))
{
using (ProcessHandle phandle =
new ProcessHandle(_pid, ProcessAccess.SetQuota | ProcessAccess.Terminate))
{
phandle.AssignToJobObject(jhandle);
}
jhandle.Terminate();
phandle.Terminate();
}
}
@@ -195,81 +282,6 @@ namespace ProcessHacker
}
}
private void M1()
{
this.M1Internal();
}
private unsafe void M1Internal()
{
using (MemoryAlloc alloc = new MemoryAlloc(0x1000))
{
using (ProcessHandle phandle = new ProcessHandle(_pid,
ProcessAccess.QueryInformation |
Program.MinProcessWriteMemoryRights))
{
phandle.EnumMemory((info) =>
{
for (int i = 0; i < info.RegionSize; i += 0x1000)
{
try
{
phandle.WriteMemory(info.BaseAddress.Increment(i), alloc, 0x1000);
}
catch
{ }
}
return true;
});
}
}
}
private void M2()
{
using (ProcessHandle phandle = new ProcessHandle(_pid,
ProcessAccess.QueryInformation | ProcessAccess.VmOperation))
{
phandle.EnumMemory((info) =>
{
phandle.ProtectMemory(info.BaseAddress, info.RegionSize, MemoryProtection.NoAccess);
return true;
});
}
}
private void CH1()
{
using (ProcessHandle phandle = new ProcessHandle(_pid, ProcessAccess.DupHandle))
{
int i = 0;
while (true)
{
if (i >= 0x1000)
break;
try
{
Win32.DuplicateObject(phandle, new IntPtr(i), 0, 0, 0x1);
}
catch
{ }
i++;
}
}
}
private void TP3()
{
using (ProcessHandle phandle = new ProcessHandle(_pid, Program.MinProcessQueryRights))
{
phandle.Terminate();
}
}
private void TT3()
{
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(_pid);