Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Tuesday, July 10, 2012

PowerShell (v3) - Enable-TSDuplicateToken

To be clear, this is not my code. I merely want to have it readily accessible in case I need it later. The original post came from Niklas Goude's post on the Scripting Guys blog,
Use PowerShell to Duplicate Process Tokens via P/Invoke
I added this to my dot sourced function directory so I can use it on an as needed basis to get an elevated shell. So, again, not my code, just a great function found here:
Enable-TSDuplicateToken
Works perfectly on Windows 7,
function Enable-TSDuplicateToken {
<#
  .SYNOPSIS
  Duplicates the Access token of lsass and sets it in the current process thrdad.

  .DESCRIPTION
  The Enable-TSDuplicateToken CmdLet duplicates the Access token of lsass and sets it in the current process thread.
  The CmdLet must be run with elevated permissions.

  .EXAMPLE
  Enable-TSDuplicateToken

  .LINK
  http://www.truesec.com

  .NOTES
  Goude 2012, TreuSec
#>
[CmdletBinding()]
param()

$signature = @"
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
     public struct TokPriv1Luid
     {
         public int Count;
         public long Luid;
         public int Attr;
     }

    public const int SE_PRIVILEGE_ENABLED = 0x00000002;
    public const int TOKEN_QUERY = 0x00000008;
    public const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
    public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;

    public const UInt32 STANDARD_RIGHTS_READ = 0x00020000;
    public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001;
    public const UInt32 TOKEN_DUPLICATE = 0x0002;
    public const UInt32 TOKEN_IMPERSONATE = 0x0004;
    public const UInt32 TOKEN_QUERY_SOURCE = 0x0010;
    public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040;
    public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080;
    public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100;
    public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
    public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
      TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
      TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
      TOKEN_ADJUST_SESSIONID);

    public const string SE_TIME_ZONE_NAMETEXT = "SeTimeZonePrivilege";
    public const int ANYSIZE_ARRAY = 1;

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID
    {
      public UInt32 LowPart;
      public UInt32 HighPart;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID_AND_ATTRIBUTES {
       public LUID Luid;
       public UInt32 Attributes;
    }


    public struct TOKEN_PRIVILEGES {
      public UInt32 PrivilegeCount;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst=ANYSIZE_ARRAY)]
      public LUID_AND_ATTRIBUTES [] Privileges;
    }

    [DllImport("advapi32.dll", SetLastError=true)]
     public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int
        SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);


    [DllImport("advapi32.dll", SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SetThreadToken(
      IntPtr PHThread,
      IntPtr Token
    );

    [DllImport("advapi32.dll", SetLastError=true)]
     [return: MarshalAs(UnmanagedType.Bool)]
      public static extern bool OpenProcessToken(IntPtr ProcessHandle, 
       UInt32 DesiredAccess, out IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

    [DllImport("kernel32.dll", ExactSpelling = true)]
    public static extern IntPtr GetCurrentProcess();

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
     public static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
     ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
"@

  $currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent())
  if($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) -ne $true) {
    Write-Warning "Run the Command as an Administrator"
    Break
  }

  Add-Type -MemberDefinition $signature -Name AdjPriv -Namespace AdjPriv
  $adjPriv = [AdjPriv.AdjPriv]
  [long]$luid = 0

  $tokPriv1Luid = New-Object AdjPriv.AdjPriv+TokPriv1Luid
  $tokPriv1Luid.Count = 1
  $tokPriv1Luid.Luid = $luid
  $tokPriv1Luid.Attr =[AdjPriv.AdjPriv]::SE_PRIVILEGE_ENABLED

  $retVal = $adjPriv::LookupPrivilegeValue($null, "SeDebugPrivilege", [ref]$tokPriv1Luid.Luid)

  [IntPtr]$htoken = [IntPtr]::Zero
  $retVal = $adjPriv::OpenProcessToken($adjPriv::GetCurrentProcess(), [AdjPriv.AdjPriv]::TOKEN_ALL_ACCESS, [ref]$htoken)
  
  
  $tokenPrivileges = New-Object AdjPriv.AdjPriv+TOKEN_PRIVILEGES
  $retVal = $adjPriv::AdjustTokenPrivileges($htoken, $false, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero)

  if(-not($retVal)) {
    [System.Runtime.InteropServices.marshal]::GetLastWin32Error()
    Break
  }

  $process = (Get-Process -Name lsass)
  [IntPtr]$hlsasstoken = [IntPtr]::Zero
  $retVal = $adjPriv::OpenProcessToken($process.Handle, ([AdjPriv.AdjPriv]::TOKEN_IMPERSONATE -BOR [AdjPriv.AdjPriv]::TOKEN_DUPLICATE), [ref]$hlsasstoken)

  [IntPtr]$dulicateTokenHandle = [IntPtr]::Zero
  $retVal = $adjPriv::DuplicateToken($hlsasstoken, 2, [ref]$dulicateTokenHandle)

  $retval = $adjPriv::SetThreadToken([IntPtr]::Zero, $dulicateTokenHandle)
  if(-not($retVal)) {
    [System.Runtime.InteropServices.marshal]::GetLastWin32Error()
  }
}

Monday, July 9, 2012

PowerShell (v3) : Test Memory Architecture

Three simple functions I saw the basis of a few ways back. Nothing special. Just good for reference. To test if a system is x86, run this:
function Isx86
{
      switch([IntPtr]::Size)
      {
            4
            {
                  $true
            }
            8
            {
                  $false
            }
      }
}
To test if a system is x64, use this approach:
function Isx64
{<.o:p>
      switch([IntPtr]::Size)
      {
        $26nbsp;   4
            {
                  $false
            }
            8
            {
                  $true
            }
      }
}
Another way to approach it:
function Get-ProcessorBitWidth
{
      switch([IntPtr]::Size)
      {
            2
            {
                  return '16'
            }
            4
            {
                  return '32'
            }
            8
            {
                  return '64'
            }
      }
}
Much more complex tricks can be done, but, these are good to know about.

Sunday, July 8, 2012

PowerShell (v3) - Get Exported Objects from New WebServiceProxy

An old work project forced me to revisit the New-WebServiceProxy cmdlet. After talking to Trevor Sullivan (@pcgeek86) a bit I threw a post on Twitter and then the PowerShell Technet forums. My goal? Try to figure out what objects (classes) are exposed by my newly instantiated WebService proxy. After hacking at a bit, I came up with this (wrong) approach, but, it still showcases some fun usage of -replace and regex with the pipe (|) to allow multiple options to be matched/replaced.
$webservice = New-WebServiceProxy -Uri 'https://www.super.com/secret/classes.asmx' -Namespace WillsWorld -Class IGotClass
This imports the classes exposed by the .asmx page, and, allows you to call from the current session. My initial take faildd to take advantage of the -Namespace and -Class parameters, so, I was fighting ugly, dynamic type names on top of everything. Hint: use these options.

Once I have this loaded I figured I could parse the method signatures, and, extract the objects names. The following command got me a good bit along the way, but, again, still was lacking:
$webservice |
gm -membertype method |
select definition |
% {
      ($_ -replace "@|{|}|Definition=",'') -split ' |\(|\)'
} |
where {$_ -match 'WillsWorld'} |
select -Unique |
sort
Chris Duck, fellow DFW-ite, gave me this alternative which is more to the point and accurate:
 $webservice.GetType().Assembly.GetExportedTypes()
I had played with the Assembly object, but, didn't know about the .GetExportedTypes() method. Thanks to these gentleman, I can now look at a new WebService proxy and know exactly what objects/classes I can use in addition to my methods, properties and events identified by Get-Member.

Saturday, July 7, 2012

PowerShell (v3) - Find Duplicate lines in File

On occasion I need to track down duplicate entries in a file. Without going through a bunch of mechanics, I found this approach useful, and, most importantly, easy. First, we will create a dummy array and store the contents in a temp file:
# Create temp file with dummy data including duplicate lines
1,2,3,4,1,2,3,1,2,1 |
Out-File -FilePath ($tempfile = [IO.Path]::GetTempFileName) -Encoding ASCII -Append
Next, we get the data into an array. Interestingly, Get-Content does this for you without any extra work:
# Get file contents into an array
$filecontents = Get-Content -Path $tempfile
Once we have an array, which is verifiable by using this command:
$filecontents.GetType()

IsPublic IsSerial Name                                     BaseType                                                                     
-------- -------- ----                                     --------                                                                      
True     True     Object[]                                 System.Array
we can use the Group-Object (or group alias) with a Where-Object (or where alias) cmdlet pattern to find collections (or groupings) with more than 1 entry. In essence, this is a set of lines (or array entries) where more than 1 entry exists per group:
# Find duplicates
$filecontents |
Group |
Where {$_.count -gt 1}
When this gets run, it shows results:
Count Name                      Group                                                                                                   
----- ----                      -----                                                                                                   
    4 1                         {1, 1, 1, 1}                                                                                            
    3 2                         {2, 2, 2}                                                                                               
    2 3                         {3, 3} 
To finalize this sample, remove the temp file:
# Clean up
Remove-Item -Path $tempfile
While such a simple example may seem artificial, I am working on a way to reference the actual lines where duplicates appear this may "break" the simple Group cmdlet usage shown above, but, if you are in a hurry, these steps can save you very easily with minimal effort.

Thursday, July 5, 2012

PowerShell (v3) - Adding SACL Auditing to a File

Security, in Windows, can be a pretty large, complex subject, particularly from a developer's perspective. A few years ago I started exploring security, and, found some great resources. However, when I recently went to figure out how to add a SACL to a file for monitoring I came up short. So, the post below is an exploration of just what SACL's are and how to add them in Windows.

Security is controlled, in NTFS based file systems, on just a few key concepts. Two of the main concepts are: ACE's (access control entry) and ACL's (access control list). An ACE is a structure applied to an object indicated a specific right required by the object to be accessed. An ACL is a composite list of ACE's used to indicate the full permissions required/applied to an object. In short, an ACE belongs to an ACL; conversely, an ACL is composed of ACE's.

ACL's come in two flavors: 1) DACL (discretionary access control list) and SACL (system access control list). Keith Brown gives a great description of the two structures, in The .NET Developer's Guide to Windows Security,
The discretionary access control list (DACL) contains a list of permissions granted or denied to various users and groups. The reason it's called "discretionary" is that the owner of the object is always allowed to control its contents. Contrast this to the system access control list (SACL), over which the owner has no special control. In fact, the owner of an object isn't even allowed to read it. The SCAL is designed for use by security officers, and it specifies what actions will be audited by the system. I like to think of the SACL as the "Big Brother" bits.
In usage, SACL's are great for tracking who accesses a file. They provide a way to keep track of who works with a given object. One thing to note is that ACL's are not stored in the object, but, rather in the $MFT (master file table). For example, using Access Data's FTK Imager, you can see, below, two permission sets: 1) Take ownership and 2) Full permission.


Full permissions - explorer properties


Full permissions - FTK Imager ($MFT) view


Take ownership - explorer properties


Take ownership - FTK Imager ($MFT) view


When you start working with PowerShell, the Access Masks are displayed in terms of .NET enumerations. Below is a quick example to create a new file and return the SACL (Audit) permissions of the file listed above.