//////////////////////////////////////////////////////////////
// File: // main.cpp
// File time: // 25.04.2005 12:14
// Version: // 1.0
/******************************************************************************
Module: AccessMaster.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
Modified: Sergey Kolomenkin, 2005
******************************************************************************/
// Description: //////////////////////////////////////////////
// Some useful routines...
//
#include "stdafx.h"
//#include <windows.h>
#include "CmnHdr.h" /* See Appendix A. */
#include <WindowsX.h>
#include <stdio.h>
#include "SecurityInformation.h"
#include "Resource.h"
///////////////////////////////////////////////////////////////////////////////
typedef struct _ObjEntry
{
OB_TYPE_ENUM m_nSpecificType;
PTSTR m_pszComboText;
PTSTR m_pszUsageText;
BOOL m_fUseName;
BOOL m_fUseHandle;
BOOL m_fUsePID;
} ObjEntry;
ObjEntry g_objMap[] =
{
{OB_TYPE_TOKEN, TEXT("Access Token"),
TEXT("To view the access rights of an access token enter the ")
TEXT("numerical value of its handle and process ID in the ")
TEXT("\"Handle\" and \"PID/TID\" fields."),
FALSE, TRUE, TRUE},
{OB_TYPE_ANONPIPE, TEXT("Anonymous Pipe"),
TEXT("To view the access rights of an Anonymous Pipe enter the ")
TEXT("numerical value of its handle and process ID in the ")
TEXT("\"Handle\" and \"PID/TID\" fields."),
FALSE, TRUE, TRUE},
{OB_TYPE_DESKTOP, TEXT("Desktop"), // XXXXXXXXX
TEXT("To view the access rights of a Desktop object either enter ")
TEXT("the Window Station and Desktop names in the \"Name\" field, ")
TEXT("or the numerical value of its handle and process ID in the ")
TEXT("\"Handle\" and \"PID/TID\" ")
TEXT("fields.\r\nExample: \"Winsta0\\Default\""),
TRUE, TRUE, TRUE},
{OB_TYPE_DIRECTORY, TEXT("Directory"), // XXXXXXXXX
TEXT("To view the access rights of a directory enter the fully ")
TEXT("qualified path in the \"Name\" field."),
TRUE, FALSE, FALSE}, // !!!!!!!!!!!!!!!!!!
{OB_TYPE_EVENT, TEXT("Event"),
TEXT("To view the access rights of an Event either enter the ")
TEXT("object's name in the \"Name\" field, or the numerical value ")
TEXT("of its handle and process ID in ")
TEXT("the \"Handle\" and \"PID/TID\" fields."),
TRUE, TRUE, TRUE},
{OB_TYPE_FILE, TEXT("File"), // XXXXXXXXX
TEXT("To view the access rights of a file either enter the fully ")
TEXT("qualified path and filname in the \"Name\" field, or the ")
TEXT("numerical value of the handle and process in the \"Handle\" ")
TEXT("and \"PID/TID\" fields."),
TRUE, TRUE, TRUE}, // !!!!!!!!!!!!!!!!!!
{OB_TYPE_SECTION, TEXT("File Mapping"),
TEXT("To view the access rights of a file mapping either enter ")
TEXT("the object's name in the \"Name\" field, or the numerical ")
TEXT("value of its handle and process ID in the \"Handle\" and ")
TEXT("\"PID/TID\" fields."),
TRUE, TRUE, TRUE},
{OB_TYPE_JOB, TEXT("Job"),
TEXT("Enter the numerical value of the Job's handle and process ")
TEXT("ID's in the \"Handle\" and \"PID/TID\" fields."),
FALSE, TRUE, TRUE},
{OB_TYPE_MUTANT, TEXT("Mutex"),
TEXT("To view the access rights of a Mutex either enter the ")
TEXT("object's name in the \"Name\" field, or the numerical value ")
TEXT("of its handle and process ID in ")
TEXT("the \"Handle\" and \"PID/TID\" fields."),
TRUE, TRUE, TRUE},
{OB_TYPE_NAMEDPIPE, TEXT("Named Pipe"),
TEXT("To view the access rights of a Named Pipe enter the numerical ")
TEXT("value of its handle and process ID in ")
TEXT("the \"Handle\" and \"PID/TID\" fields."),
FALSE, TRUE, TRUE},
{OB_TYPE_PRINTER, TEXT("Printer"), // XXXXXXXXX
TEXT("To view the access rights of a printer or print server enter ")
TEXT("the object's fully qualified UNC name in the \"Name\" field."),
TRUE, FALSE, FALSE},
{OB_TYPE_PROCESS, TEXT("Process"),
TEXT("Enter a Process' ID in the \"PID/TID\" field."),
FALSE, FALSE, TRUE},
{OB_TYPE_KEY, TEXT("Registry Key"), // XXXXXXXXX
TEXT("To view the access rights of a registry key either enter the ")
TEXT("fully qualified path and keyname in the \"Name\" field, or ")
TEXT("the numerical value of the handle and process in the ")
TEXT("\"Handle\" and \"PID/TID\" fields. \r\nExample: \"\\\\machine")
TEXT("name\\CLASSES_ROOT\\somepath\r\n\r\nThe following predefined ")
TEXT("registry key values can be used: \"CLASSES_ROOT\", \"CURRENT_")
TEXT("USER\", \"MACHINE\", and \"USERS\"."),
TRUE, TRUE, TRUE}, // !!!!!!!!!!!!!!!!!!
{OB_TYPE_SEMAPHORE, TEXT("Semaphore"),
TEXT("To view the access rights of a Semaphore either enter the ")
TEXT("object's name in the \"Name\" field, or the numerical value ")
TEXT("of its handle and process ID in the \"Handle\" ")
TEXT("and \"PID/TID\" fields."),
TRUE, TRUE, TRUE},
{OB_TYPE_SERVICE, TEXT("Service"), // XXXXXXXXX
TEXT("To view the access rights of a service enter the service's ")
TEXT("programmatic name in the \"Name\" field."),
TRUE, FALSE, FALSE},
{OB_TYPE_SHARE, TEXT("Share"), // XXXXXXXXX
TEXT("Enter a network share name in the \"Name\" field. A share ")
TEXT("object can be local, such as \"sharename\"; or ")
TEXT("remote, such as \"\\\\machinename\\sharename\"."),
TRUE, FALSE, FALSE},
{OB_TYPE_THREAD, TEXT("Thread"),
TEXT("Enter a Thread's Thread-ID or TID in the \"PID/TID\" field"),
FALSE, FALSE, TRUE},
{OB_TYPE_TIMER, TEXT("Waitable Timer"),
TEXT("To view the access rights of a Waitable Timer either enter ")
TEXT("the object's name in the \"Name\" field, or the numerical value ")
TEXT("of its handle and process ID in ")
TEXT("the \"Handle\" and \"PID/TID\" fields."),
TRUE, TRUE, TRUE},
{OB_TYPE_WINDOW_STATION, TEXT("Window Station"), // XXXXXXXXX
TEXT("To view the access rights of a Window Station either enter ")
TEXT("the object's name in the \"Name\" field, or the numerical ")
TEXT("value of its handle and process ID in the \"Handle\" and ")
TEXT("\"PID/TID\" fields.\r\nExample: \"Winsta0\""),
TRUE, TRUE, TRUE}
};
///////////////////////////////////////////////////////////////////////////////
void ReportError(PTSTR szFunction, ULONG lErr)
{
TCHAR szBuf[200] = _T("");
_stprintf( szBuf, _T("An error occurred calling function \"%s\": error %d"), szFunction, lErr );
MessageBox(NULL, szBuf, TEXT("Security Notice"), MB_OK);
}
///////////////////////////////////////////////////////////////////////////////
void UpdateObjDependentCtrls(HWND hwnd)
{
// Setup controls for selected object type
HWND hwndCtrl = GetDlgItem(hwnd, IDC_TYPE);
int nIndex = ComboBox_GetCurSel(hwndCtrl);
SetDlgItemText(hwnd, IDE_USAGE, g_objMap[nIndex].m_pszUsageText);
hwndCtrl = GetDlgItem(hwnd, IDE_NAME);
EnableWindow(hwndCtrl, g_objMap[nIndex].m_fUseName);
hwndCtrl = GetDlgItem(hwnd, IDE_HANDLE);
EnableWindow(hwndCtrl, g_objMap[nIndex].m_fUseHandle);
hwndCtrl = GetDlgItem(hwnd, IDE_PID);
EnableWindow(hwndCtrl, g_objMap[nIndex].m_fUsePID);
if (g_objMap[nIndex].m_fUsePID || g_objMap[nIndex].m_fUseHandle) {
hwndCtrl = GetDlgItem(hwnd, IDR_HANDLE);
EnableWindow(hwndCtrl, TRUE);
} else {
hwndCtrl = GetDlgItem(hwnd, IDR_HANDLE);
EnableWindow(hwndCtrl, FALSE);
CheckRadioButton(hwnd, IDR_NAME, IDR_HANDLE, IDR_NAME);
}
if (g_objMap[nIndex].m_fUseName) {
hwndCtrl = GetDlgItem(hwnd, IDR_NAME);
EnableWindow(hwndCtrl, TRUE);
} else {
hwndCtrl = GetDlgItem(hwnd, IDR_NAME);
EnableWindow(hwndCtrl, FALSE);
CheckRadioButton(hwnd, IDR_NAME, IDR_HANDLE, IDR_HANDLE);
}
}
///////////////////////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
chSETDLGICONS(hwnd, IDI_ACCESSMASTER);
CheckDlgButton(hwnd, IDR_NAME, BST_CHECKED);
TCHAR szTitle[1024];
lstrcpy(szTitle, TEXT("AccessMaster is running as \""));
ULONG lSize = chDIMOF(szTitle)-lstrlen(szTitle);
GetUserName(szTitle+lstrlen(szTitle),&lSize);
lstrcat(szTitle, TEXT("\""));
SetWindowText(hwnd, szTitle);
// Set-up the object type combo
int nIndex = chDIMOF(g_objMap);
HWND hwndCtrl = GetDlgItem(hwnd, IDC_TYPE);
while (nIndex-- != 0) {
ComboBox_InsertString(hwndCtrl, 0, g_objMap[nIndex].m_pszComboText);
}
ComboBox_SetCurSel(hwndCtrl, 0);
UpdateObjDependentCtrls(hwnd);
return(TRUE);
}
///////////////////////////////////////////////////////////////////////////////
void HandleType(HWND hwnd, UINT codeNotify, HWND hwndCtl)
{
if (codeNotify == CBN_SELCHANGE)
UpdateObjDependentCtrls(hwnd);
}
///////////////////////////////////////////////////////////////////////////////
void HandleRadio(HWND hwnd, UINT codeNotify, UINT nCtrl)
{
if (codeNotify == EN_SETFOCUS)
CheckRadioButton(hwnd, IDR_NAME, IDR_HANDLE, nCtrl);
}
///////////////////////////////////////////////////////////////////////////////
BOOL FillInfo(HWND hwnd, ObjectInformation* pInfo, ObjEntry** pEntry)
{
BOOL fReturn = FALSE;
// Map object type to data block in the object map
HWND hwndCtrl = GetDlgItem(hwnd, IDC_TYPE);
int nIndex = ComboBox_GetCurSel(hwndCtrl);
// pInfo->m_pEntry = g_objMap + nIndex;
ObjEntry* m_pEntry = NULL;
/*
for( int i=0; i<chDIMOF(g_objMap); i++ )
{
if( g_objMap[i].m_objType == ??? )
{
m_pEntry = &g_objMap[i];
break;
}
}
*/
m_pEntry = g_objMap + nIndex;
pInfo->m_objInternalType = m_pEntry->m_nSpecificType;
*pEntry = m_pEntry;
// USES_CONVERSION;
// Copy the object's name into the info block for building the title text
// lstrcpyW(pInfo->m_szObjectName, T2W(m_pEntry->m_pszComboText) );
// Is it a named item?
if (IsDlgButtonChecked(hwnd, IDR_NAME)) {
switch (m_pEntry->m_nSpecificType) {
case OB_TYPE_WINDOW_STATION:
{ // If windowstation, we must translate the name to a handle
HWINSTA hwinsta = NULL;
GetDlgItemText(hwnd, IDE_NAME, pInfo->m_szName,
chDIMOF(pInfo->m_szName));
// Get the maximum possible access
hwinsta = OpenWindowStation(pInfo->m_szName, FALSE,
MAXIMUM_ALLOWED);
if (hwinsta == NULL) // Still failed?
ReportError(TEXT("OpenWindowStation"), GetLastError());
else { // Otherwise finish title text
fReturn = TRUE;
pInfo->m_hHandle = (HANDLE) hwinsta;
// lstrcatW(pInfo->m_szObjectName, L" - " );
// lstrcatW(pInfo->m_szObjectName, T2W(pInfo->m_szName) );
// lstrcat(pInfo->m_szObjectName, _T(" - ") );
lstrcpy(pInfo->m_szObjectName, pInfo->m_szName );
pInfo->m_szName[0] = 0;
}
}
break;
case OB_TYPE_DESKTOP:
{ // If desktop, we must translate the name to a handle
HWINSTA hwinstaOld;
HWINSTA hwinstaTemp;
HDESK hdesk=NULL;
PTSTR pszWinSta;
PTSTR pszDesktop;
int nIndex;
GetDlgItemText(hwnd, IDE_NAME, pInfo->m_szName,
chDIMOF(pInfo->m_szName));
pszWinSta = pInfo->m_szName;
nIndex = lstrlen(pInfo->m_szName);
// Parse the text for windowstation and desktop
while (nIndex-- != 0) {
if (pInfo->m_szName[nIndex] == TEXT('\\')
|| pInfo->m_szName[nIndex] == TEXT('/')) {
pInfo->m_szName[nIndex] = 0;
break;
}
}
// Desktop string
nIndex++;
pszDesktop = pInfo->m_szName + nIndex;
// Open the windowstation
hwinstaTemp = OpenWindowStation(pszWinSta, FALSE,
DESKTOP_ENUMERATE);
if (hwinstaTemp != NULL) {
// Save the last one
hwinstaOld = GetProcessWindowStation();
SetProcessWindowStation(hwinstaTemp);
// Get maximum access to the desktop
hdesk = OpenDesktop(pszDesktop, 0, FALSE,
MAXIMUM_ALLOWED);
if (hdesk == NULL)// failed?
ReportError(TEXT("OpenDesktop"), GetLastError());
else { // build title
fReturn = TRUE;
pInfo->m_hHandle = (HANDLE) hdesk;
// lstrcatW(pInfo->m_szObjectName, L" - " );
// lstrcatW(pInfo->m_szObjectName, T2W(pszDesktop) );
// lstrcat(pInfo->m_szObjectName, _T(" - ") );
lstrcpy(pInfo->m_szObjectName, pszDesktop );
pInfo->m_szName[0] = 0;
}
// Close and reset window stations for the process
CloseWindowStation(hwinstaTemp);
SetProcessWindowStation(hwinstaOld);
} else // Failed open winsta
ReportError(TEXT("OpenWindowStation"), GetLastError());
}
break;
default: // The rest of named objects work with GetNamedSecurity...
GetDlgItemText(hwnd, IDE_NAME, pInfo->m_szName,
chDIMOF(pInfo->m_szName));
// lstrcatW(pInfo->m_szObjectName, L" - " );
// lstrcatW(pInfo->m_szObjectName, T2W(pInfo->m_szName) );
// lstrcat(pInfo->m_szObjectName, _T(" - ") );
lstrcpy(pInfo->m_szObjectName, pInfo->m_szName );
fReturn = TRUE;
break;
}
} else { // Is it a handle and or process id we are dealing with?
BOOL fTrans;
// Get the actual numbers
ULONG lPid = GetDlgItemInt(hwnd, IDE_PID, &fTrans, FALSE);
HANDLE hHandle = (HANDLE) GetDlgItemInt(hwnd, IDE_HANDLE, &fTrans,
FALSE);
HANDLE hObj = NULL;
switch (m_pEntry->m_nSpecificType) {
case OB_TYPE_THREAD: // Maximum access to the thread
hObj = OpenThread(MAXIMUM_ALLOWED, FALSE, lPid);
if (hObj == NULL) // None == failure
ReportError(TEXT("OpenThread"), GetLastError());
break;
case OB_TYPE_PROCESS: // Get maximum access to the process
hObj = OpenProcess(MAXIMUM_ALLOWED, FALSE, lPid);
if (hObj == NULL) // None == failure
ReportError(TEXT("OpenProcess"), GetLastError());
break;
default: // The rest work with duplicate handle
{
HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, lPid);
if (hProcess != NULL) {
// Get as much access as possible
if (!DuplicateHandle(hProcess, hHandle, GetCurrentProcess(),
&hObj, MAXIMUM_ALLOWED, FALSE, 0))
ReportError(TEXT("DuplicateHandle"), GetLastError());
} else
ReportError(TEXT("OpenProcess"), GetLastError());
}
break;
}
if (hObj != NULL) {
pInfo->m_hHandle = hObj;
fReturn = TRUE;
}
}
// wsprintfW( pInfo->m_szObjectName, L"%hs-%hs", m_pEntry->m_pszComboText, pInfo->m_szName );
return(fReturn);
}
//////////////////////////////////////////////////////////////
void HandleEdit(HWND hwnd)
{
// Maintains information about the object whose security we are editing
ObjectInformation info = { 0 };
// Fill the info structure with info from the UI
ObjEntry* m_pEntry = NULL;
if (FillInfo(hwnd, &info, &m_pEntry)) {
// Create instance of class derived from interface ISecurityInformation
CSecurityInformation* pSec = CSecurityInformation::CreateInstance( info,
IsDlgButtonChecked(hwnd, IDC_BINARY) == BST_CHECKED);
// Common dialog box for ACL editing
pSec->EditSecurity(hwnd);
if (pSec != NULL)
pSec->Release();
TRACE( _T("Cleanup if we had opened a handle before...\n") );
// Cleanup if we had opened a handle before
if (info.m_szName[0] == 0) {
switch (m_pEntry->m_nSpecificType) {
case OB_TYPE_KEY:
RegCloseKey((HKEY) info.m_hHandle);
break;
case OB_TYPE_WINDOW_STATION:
CloseWindowStation((HWINSTA) info.m_hHandle);
break;
case OB_TYPE_DESKTOP:
CloseDesktop((HDESK) info.m_hHandle);
break;
case OB_TYPE_FILE:
case OB_TYPE_PROCESS:
case OB_TYPE_THREAD:
case OB_TYPE_JOB:
case OB_TYPE_SEMAPHORE:
case OB_TYPE_EVENT:
case OB_TYPE_MUTANT:
case OB_TYPE_SECTION:
case OB_TYPE_TIMER:
case OB_TYPE_TOKEN:
case OB_TYPE_NAMEDPIPE:
case OB_TYPE_ANONPIPE:
default:
CloseHandle(info.m_hHandle);
break;
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id) {
case IDCANCEL:
EndDialog(hwnd, 0);
break;
case IDC_TYPE:
HandleType(hwnd, codeNotify, hwndCtl);
break;
case IDE_PID:
case IDE_HANDLE:
HandleRadio(hwnd, codeNotify, IDR_HANDLE);
break;
case IDE_NAME:
HandleRadio(hwnd, codeNotify, IDR_NAME);
break;
case IDB_EDIT:
HandleEdit(hwnd);
break;
}
}
///////////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
///////////////////////////////////////////////////////////////////////////////
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) {
// HANDLE hPipe = CreateNamedPipe( _T("\\\\.\\pipe\\MyPipeName"), PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE,
// PIPE_UNLIMITED_INSTANCES, 8192, 8192, NMPWAIT_USE_DEFAULT_WAIT, NULL );
// HANDLE hPipe1 = NULL;
// HANDLE hPipe2 = NULL;
// CreatePipe( &hPipe1, &hPipe2, NULL, 8192 );
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_DIALOG), NULL, Dlg_Proc);
return(0);
}
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////