|
Tuesday, February 14, 2006
Peek into process token: Add-ProcessOwner cmdlet
In order to get process token, I have to call Win32API – OpenProcessToken, which return a System.IntPtr type token. This token can be used to construct a System.Security. Principal.WindowsIdentity object. (It is first time I use P/Invoke. Please tell me if I did anything wrong.)
Using add-member cmdlet, I add this WindowsIdentity object to System.Diagnostics.Process object as NoteProperty. To use it:
>$ps= Get-process –ProcessName exporler | Add-ProcessOwner.msh
>$ps | get-member
…
WaitForExit Method   System.Boolean WaitForExit(Int...
WaitForInputIdle Method System.Boolean WaitForInputIdl...
__NounName NoteProperty System.String __NounName=Process
ProcessOwner NoteProperty System.Security.Principal.Wind...
…
>$ps.ProcessOwner
AuthenticationType : NTLM
ImpersonationLevel : None
IsAuthenticated :
IsGuest : False
IsSystem : False
IsAnonymous : False
Name : Domain\tony
Owner : S-1-5-21-854245398-XXXXXXXXXX-XXXXXX-XXX
User : S-1-5-21-854245398--XXXXXXXXXX-XXXXXX-XXX
Groups : {S-1-5-21-854245398--XXXXXXXXXX, , , , , }
Token : XXXX
It is pretty sad that due to local security policy, I can not get owner of processes runing as System or Network service (which are those most intersting process). I might have to mount myself as a system service first than call OpenProcessToken. Well, that is to complicated for me.
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Collections;
using System.Diagnostics;
namespace Monad.Security
{
public class OpenProcessTokenHelper
{
[Flags]
enum TOKEN_ACCESS : uint
{
TOKEN_ASSIGN_PRIMARY = 0x0001,
TOKEN_DUPLICATE = 0x0002,
TOKEN_IMPERSONATE = 0x0004,
TOKEN_QUERY = 0x0008,
TOKEN_QUERY_SOURCE = 0x0010,
TOKEN_ADJUST_PRIVILEGES = 0x0020,
TOKEN_ADJUST_GROUPS = 0x0040,
TOKEN_ADJUST_DEFAULT = 0x0080,
TOKEN_ADJUST_SESSIONID = 0x0100,
TOKEN_READ = 0x00020000 | TOKEN_QUERY,
TOKEN_WRITE = 0x00020000 | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT,
TOKEN_EXECUTE = 0x00020000,
};
[DllImport("Advapi32.dll", SetLastError = true)]
extern static int OpenProcessToken(IntPtr processHandle, TOKEN_ACCESS desiredAccess, out IntPtr tokenHandle);
[DllImport("kernel32.dll", SetLastError = true)]
extern static bool CloseHandle(IntPtr handle);
public static WindowsIdentity GetProcessesIdentities(Process process)
{
try
{
IntPtr token = IntPtr.Zero;
if (OpenProcessToken(process.Handle, TOKEN_ACCESS.TOKEN_QUERY, out token) == 0)
{
throw new ApplicationException("Can't open process token for: " + process.ProcessName);
}
WindowsIdentity id = new WindowsIdentity(token);
CloseHandle(token);
return (id);
}
catch (Exception ex)
{
throw new ApplicationException("Open process token error", ex);
}
}
}
}
#################################################
## Add-ProcessOwner.msh
## Add System.Security.Principal.WindowsIdentity object
## to System.Diagnostics.Process object as NoteProperty
## using P/invoke OpenProcessToken Win32API
##
## from http://mshforfun.blogspot.com/
################################################
begin
{
[void][Reflection.Assembly]::LoadFile("D:\msh\OpenProcessTokenHelper.dll")
}
process
{
if ($_)
{
# Only working with process object
if ($_ -isnot [System.Diagnostics.Process]) {continue}
else
{
# Get WindowsIdentityObject
$id=[Monad.Security.OpenProcessTokenHelper]::GetProcessesIdentities($_)
add-member -InputObject $_ -Type NoteProperty -Name "ProcessOwner" -Value $id -ErrorAction "SilentlyContinue"
}
}
}
Reference: http://www.sellsbrothers.com/askthewonk/secure/default.aspx?content=howcanigetthesecurityprin.htm
Comments:
<< Home
That's cool, Tony. You're 98% of the way towards making this a C# cmdlet -- why did you decide to make this a script that calls a DLL instead?
To lee,
Well, I was in a hurry last night. I will try to make it a cmdlet (dll) some time later.
Thnaks for your suggestion.
Well, I was in a hurry last night. I will try to make it a cmdlet (dll) some time later.
Thnaks for your suggestion.
<< Home
Post a Comment