суббота, 23 августа 2008 г.

Sysinternals Desktops v1.0

«Широко известный в узких кругах» пакет утилит Sysinternals Suit пополнился еще одним приложением – Desktops v1.0. Эта утилита решает проблему переполненности панели задач и позволяет создавать до 4 виртуальных рабочих столов и работать раздельно с приложениями на каждом из них. Например, разрабатывать приложение в одном и просматривать почту и писать отчет в другом. Между приложениями на разных десктопах удобно переносить данные, так как они имеют один общий буфер обмена. Переключаться между десктопами можно по горячим клавишам или при помощи иконки в трэе.

В целом с приложением удобно работать, хотя есть определенные ограничения. Некоторые сочетания клавиш, например, Ctrl+Shif+ Esc (запуск Windows Task Manager) работают только в первом рабочем столе, (там, где была утилита запущена), не смотря на то, в каком рабочем столе такое сочетание клавиш было нажато, приложение запустится в первом.
Скачать утилиту можно здесь.

среда, 6 августа 2008 г.

Определение Integrity Level для процесса на c#

В Windows Vista появился дополнительный механизм защиты – Integrity Levels. В зависимости от его уровня различаются и возможности приложения по работе с защищенными ресурсами системы. Поэтому актуальной задачей является определение значения Integrity Level процесса. В MSDN есть пример по определению Integrity Level текущего процесса для неуправляемого кода (статья Appendix D: Getting the Integrity Level for an Access Token). Ниже я привел подобный код на C#. Я постарался сохранить стиль кода с оригиналом, что бы их было проще сравнивать. Так же, на мой взгляд, в оригинальном примере есть ошибка в определении уровней High и System. Поэтому я заменил фрагмент кода
else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) 
{
// High Integrity
...
}

на
else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID && 
dwIntegrityLevel < SECURITY_MANDATORY_SYSTEM_RID)
{
// High Integrity
...
}

А вот и пример консольного приложения, которое определяет свой текущий Integrity Level.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Diagnostics;

namespace IntegrityLevel
{
class Program
{
static void Main(string[] args)
{
ShowProcessIntegrityLevel();
}

public static void ShowProcessIntegrityLevel()
{
IntPtr hProcess = Process.GetCurrentProcess().Handle;
IntPtr hToken;
if (!OpenProcessToken(hProcess,
TokenAccessLevels.MaximumAllowed,
out hToken))
{
return;
}

try
{
uint dwLengthNeeded;
if (GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel,
IntPtr.Zero,
0,
out dwLengthNeeded))

uint dwError = (uint)Marshal.GetLastWin32Error();
if (dwError == ERROR_INSUFFICIENT_BUFFER)
{
IntPtr pTIL = Marshal.AllocHGlobal((int)dwLengthNeeded);
try
{
if (!GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel,
pTIL,
dwLengthNeeded,
out dwLengthNeeded))
{
return;
}

TOKEN_MANDATORY_LABEL TIL =
(TOKEN_MANDATORY_LABEL)Marshal.PtrToStructure(pTIL,
typeof(TOKEN_MANDATORY_LABEL));

IntPtr SubAuthorityCount = GetSidSubAuthorityCount(TIL.Label.Sid);

IntPtr IntegrityLevelPtr = GetSidSubAuthority(TIL.Label.Sid,
Marshal.ReadByte(SubAuthorityCount) - 1);

int dwIntegrityLevel = Marshal.ReadInt32(IntegrityLevelPtr);

if (dwIntegrityLevel == SECURITY_MANDATORY_LOW_RID)
{
// Low Integrity
Console.WriteLine("Low Process");
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID &&
dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID)
{
// Medium Integrity
Console.WriteLine("Medium Process");
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID &&
dwIntegrityLevel < SECURITY_MANDATORY_SYSTEM_RID)
{
// High Integrity
Console.WriteLine("High Integrity Process");
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_SYSTEM_RID)
{
// System Integrity
Console.WriteLine("System Integrity Process");
}
}
finally
{
Marshal.FreeHGlobal(pTIL);
}
}
}
finally
{
CloseHandle(hToken);
}
}

// interop
const uint ERROR_INSUFFICIENT_BUFFER = 122;
const long SECURITY_MANDATORY_LOW_RID = 0x00001000L;
const long SECURITY_MANDATORY_MEDIUM_RID = 0x00002000L;
const long SECURITY_MANDATORY_HIGH_RID = 0x00003000L;
const long SECURITY_MANDATORY_SYSTEM_RID = 0x00004000L;

enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups = 2,
TokenPrivileges = 3,
TokenOwner = 4,
TokenPrimaryGroup = 5,
TokenDefaultDacl = 6,
TokenSource = 7,
TokenType = 8,
TokenImpersonationLevel = 9,
TokenStatistics = 10,
TokenRestrictedSids = 11,
TokenSessionId = 12,
TokenGroupsAndPrivileges = 13,
TokenSessionReference = 14,
TokenSandBoxInert = 15,
TokenAuditPolicy = 16,
TokenOrigin = 17,
TokenElevationType = 18,
TokenLinkedToken = 19,
TokenElevation = 20,
TokenHasRestrictions = 21,
TokenAccessInformation = 22,
TokenVirtualizationAllowed = 23,
TokenVirtualizationEnabled = 24,
TokenIntegrityLevel = 25,
TokenUIAccess = 26,
TokenMandatoryPolicy = 27,
TokenLogonSid = 28,
MaxTokenInfoClass = 29
}

[StructLayout(LayoutKind.Sequential)]
struct TOKEN_MANDATORY_LABEL
{
public SID_AND_ATTRIBUTES Label;
}

[StructLayout(LayoutKind.Sequential)]
struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public int Attributes;
}

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);

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

[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetTokenInformation(IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
uint TokenInformationLength,
out uint ReturnLength);

[DllImport("kernel32.dll")]
static extern IntPtr LocalAlloc(uint uFlags, UIntPtr uBytes);

[DllImport("advapi32.dll", SetLastError = true)]
static extern IntPtr GetSidSubAuthority(IntPtr pSid, int nSubAuthority);

[DllImport("advapi32.dll", SetLastError = true)]
static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
}
}