|
|
/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
saferbox.c (WinSafer Test application)
Abstract:
This module implements a utility program that tests some of the major child-execution and restricted token functionality.
Author:
Jeffrey Lawson (JLawson) - Nov 1999 John Lambert (johnla) - Nov 2000
Environment:
User mode only.
Revision History:
Created - Nov 1999
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <wincrypt.h>
#include <aclapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <wintrust.h>
#include <winsafer.h>
#include <winsaferp.h>
#include <tchar.h>
#include <winuser.h>
#include "resource.h"
#include <crypto\wintrustp.h>
#include <softpub.h> // WINTRUST_ACTION_GENERIC_VERIFY_V2
HMODULE hModule=NULL;
#ifdef DBG
//this is some bogus stuff to help when debugging in assembly
//To use this:
// run cdb saferbox args
//type: bp saferbox!_STACKMARK
//type g (this will break when the stackmark function is called.
//type t after it breaks
//look at eax to know what the stackmarker is
//type t two more times to exit the function
DWORD _S=0;
int _fastcall _STACKMARK(int a) { _S=a; return _S; } #define STACKMARK(X) _STACKMARK(X)
#else
#define STACKMARK(X) {}
#endif
//some forward declarations
void __cdecl printLastErrorWithIDSMessage(UINT resID); void printLastErrorWithMessage(LPTSTR lpErrorMessage); void printLastError(void);
LPTSTR getSystemMessage(long error_code) { LPVOID message; const LPTSTR defaultMessage = TEXT("Format Message failed"); if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &message, 0, NULL)) { message = (LPTSTR) LocalAlloc(LPTR, (_tcslen(defaultMessage) +1)* sizeof(TCHAR)); _tcscpy(message, defaultMessage); return message; } else { return message; } }
BOOL InitModule(void) { if(!(hModule=GetModuleHandle(NULL))) return FALSE; return TRUE; }
//caller must free string with LocalFree
LPTSTR AllocAndLoadStringFromModule(HINSTANCE hModule, UINT resID) { LPTSTR lpString = NULL; int cChars=0;
lpString = (LPTSTR) LocalAlloc(LPTR, (MAX_USAGE_LEN + 1) * sizeof(TCHAR) );//add one for null char
if (!lpString) { printLastError(); return NULL; } cChars = LoadString( hModule, resID, lpString, (MAX_USAGE_LEN + 1) * sizeof(TCHAR)); //could pass in NULL for hModule here.
if (cChars > 0) { //we alloc'ed a big string before, realloc the string to only the needed size
lpString = (LPTSTR) LocalReAlloc(lpString, (cChars + 1) * sizeof(TCHAR) , 0); return lpString; //will be NULL on LocalReAlloc error
} else { return NULL; } }
//caller must free string with LocalFree
LPTSTR AllocAndLoadString(UINT resID) { return AllocAndLoadStringFromModule(hModule, resID); }
void IDS_printString(UINT resID) { LPTSTR lpString = NULL;
lpString = AllocAndLoadString(resID); if (lpString) { _putts(lpString); } else { _tprintf(TEXT("[String resource not found: 0x%x (%d)]\n"), resID, resID); } if (lpString) LocalFree(lpString); return; }
void __cdecl IDS_tprintf(UINT resID, ...) { va_list ap; LPTSTR lpString; STACKMARK(0xAABB0000); lpString = AllocAndLoadString(resID); va_start(ap, resID); if (lpString) { _vtprintf(lpString, ap); } else { _tprintf(TEXT("[String resource not found: 0x%x (%d)]\n"), resID, resID); } if (lpString) LocalFree (lpString); va_end(ap); }
void __cdecl printLastErrorWithIDSMessage(UINT resID) { LPTSTR message = NULL; LPTSTR lpString = NULL; long err = GetLastError(); message = getSystemMessage(err); lpString = AllocAndLoadString(resID); if (lpString) { _tprintf(TEXT("%s: 0x%X %s\n"), lpString, err, message); } else { _tprintf(TEXT("[String resource not found: 0x%x (%d)]\n"), resID, resID); _tprintf(TEXT("0x%X %s\n"), err, message); } if (message) LocalFree (message); if (lpString) LocalFree (lpString); }
void printLastErrorWithMessage(LPTSTR lpErrorMessage) { LPTSTR message; long err = GetLastError(); message = getSystemMessage(err); _tprintf(TEXT("%s : 0x%X %s\n"), lpErrorMessage, err, message); if (message) LocalFree (message); }
void printLastError(void) { LPTSTR message; message = getSystemMessage(GetLastError()); _tprintf(TEXT("Error (%d) %s\n"), GetLastError(), message); if (message) LocalFree(message); }
/*++
Routine Description:
Displays a simple command line syntax help screen.
Arguments:
nothing
Return Value:
always returns 1.
--*/ int DisplaySyntax( void ) { IDS_tprintf(IDS_USAGE_SYNTAX); return 1; }
BOOL GetSignedFileHash( IN LPCTSTR lpzFilename, OUT BYTE rgbFileHash[SAFER_MAX_HASH_SIZE], OUT DWORD *pcbFileHash, OUT ALG_ID *pHashAlgid ) { BOOL retval = TRUE; HRESULT hr; const DWORD SHA1_HASH_LEN = 20; const DWORD MD5_HASH_LEN = 16; if ( !lpzFilename || !rgbFileHash || !pcbFileHash || !pHashAlgid ) return FALSE;
//
// Call WTHelperGetFileHash
//
*pcbFileHash = SAFER_MAX_HASH_SIZE; STACKMARK(0xBBBB0000); hr = WTHelperGetFileHash( (LPWSTR)lpzFilename, //TODO: convert from ANSI to UNICODE. WTHelperGetFileHash doesn't support ANSI
0, NULL, rgbFileHash, pcbFileHash, pHashAlgid); if ( SUCCEEDED (hr) ) { if ( SHA1_HASH_LEN == *pcbFileHash ) *pHashAlgid = CALG_SHA; else if ( MD5_HASH_LEN == *pcbFileHash ) *pHashAlgid = CALG_MD5; } else { retval = FALSE; }
return retval; }
/*++
Routine Description:
Computes the MD5 hash of a given file's contents and prints the resulting hash value to the screen.
Arguments:
szFilename - filename to compute hash of.
Return Value:
Returns 0 on success, or a non-zero exit code on failure.
--*/ BOOL ComputeMD5Hash(IN HANDLE hFile, OUT BYTE* hashResult, OUT DWORD* pdwHashSize) { BOOL retval = TRUE;
//
// Open the specified file and map it into memory.
//
if (hFile != NULL) { HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if ( hMapping ) { DWORD dwDataLen = GetFileSize (hFile, NULL); if (dwDataLen != -1) { LPBYTE pbData = (LPBYTE) MapViewOfFile (hMapping, FILE_MAP_READ, 0, 0, dwDataLen); if ( pbData ) { //
// Generate the hash value of the specified file.
//
HCRYPTPROV hProvider = 0; if ( CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_SIG, CRYPT_VERIFYCONTEXT) || CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) ) { HCRYPTHASH hHash = 0; if ( CryptCreateHash(hProvider, CALG_MD5, 0, 0, &hHash) ) { if ( CryptHashData (hHash, pbData, dwDataLen, 0) ) { *pdwHashSize = SAFER_MAX_HASH_SIZE; if (!CryptGetHashParam(hHash, HP_HASHVAL, hashResult, pdwHashSize, 0)) { *pdwHashSize = 0; retval = FALSE; } } else { retval = FALSE; } CryptDestroyHash(hHash); } else { retval = FALSE; } CryptReleaseContext(hProvider, 0); } else { retval = FALSE; } } else { retval = FALSE; } } CloseHandle(hMapping); } }
return retval; }
/*++
Routine Description:
Arguments:
szFilename - filename to compute hash of.
Return Value:
Returns TRUE on success, or FALSE on failure.
--*/ BOOL ComputeHash( IN LPCTSTR szFilename) { BYTE hashResult[SAFER_MAX_HASH_SIZE]; DWORD dwHashsize = 0; DWORD dwFilesize = 0; HANDLE hFile = NULL; BOOL retval = FALSE; ALG_ID algId = 0; BOOL result = FALSE;
hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile) { dwFilesize= GetFileSize(hFile, NULL); result = GetSignedFileHash(szFilename, hashResult, &dwHashsize, &algId); if (!result && (GetLastError() != TRUST_E_NOSIGNATURE) && //a recognized format, but no sig
(GetLastError() != TRUST_E_SUBJECT_FORM_UNKNOWN)) //unrecognized format, don't know how to get sig
{ printLastError(); retval = FALSE; goto ExitHandler; } else if (!result) { if (!ComputeMD5Hash(hFile, hashResult, &dwHashsize)) { printLastError(); retval = FALSE; goto ExitHandler; } algId = CALG_MD5; } else { _tprintf(TEXT("This file is signed.\n")); } //
// Print out the results.
//
if (dwHashsize != 0) {
DWORD Index; _tprintf(TEXT("%s:\n"), szFilename); _tprintf(TEXT("Hash Algorithm: ")); if (algId == CALG_MD5) { _tprintf(TEXT("MD5\n")); } else if (algId == CALG_SHA) { _tprintf(TEXT("SHA\n")); } _tprintf(TEXT("Hash: ")); for (Index = 0; Index < dwHashsize; Index++) printf("%02X", hashResult[Index]); _tprintf(TEXT("\nFile size: ")); _tprintf(TEXT("%d\n"), dwFilesize); retval = TRUE; goto ExitHandler; } else { printLastError(); retval = FALSE; goto ExitHandler; } } else { printLastError(); retval = FALSE; goto ExitHandler; }
ExitHandler: if (hFile) CloseHandle(hFile); return retval; }
/*++
Routine Description:
Creates the process with a given WinSafer restriction Level.
Arguments:
hAuthzLevel - an opened WinSafer Level handle that specifies how the specified program should be launched.
appname - filename of the program to be launched.
cmdline - command line supplied to the program that is launched.
pi - pointer to a structure that will be filled with information about the process that is created.
bStartSuspended - if this argument is TRUE, then the process will be started in a suspended state, and its primary thread must be explicitly resumed by the calling program in order to begin execution.
Return Value:
returns 0 on success, or a non-zero exit code on failure.
--*/ int CreateProcessRestricted( IN SAFER_LEVEL_HANDLE hAuthzLevel, IN LPCTSTR appname, IN LPTSTR cmdline, OUT PROCESS_INFORMATION *pi, IN BOOL bStartSuspended) { HANDLE hToken; STARTUPINFO si;
// Generate the restricted token that we will use.
if (!SaferComputeTokenFromLevel( hAuthzLevel, // Safer Level handle
NULL, // source token
&hToken, // target token
0, // no flags
NULL)) // reserved
{ _tprintf(TEXT("Failed to compute restricted access token.\n")); return 2; }
// Prepare the startup info structure.
ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO);
// Launch the child process under the context of the restricted token.
if (!CreateProcessAsUser( hToken, // token representing the user
appname, // name of executable module
cmdline, // command-line string
NULL, // process security attributes
NULL, // thread security attributes
FALSE, // if process inherits handles
(bStartSuspended ? CREATE_SUSPENDED : 0), // creation flags
NULL, // new environment block
NULL, // current directory name
&si, // startup information
pi // process information
)) { _tprintf(TEXT("Failed to execute child.\n")); CloseHandle(hToken); return 3; }
// success.
CloseHandle(hToken); return 0; }
/*++
Routine Description:
Prints the description and friendly name associated with an opened WinSafer Level handle.
Arguments:
hAuthzLevel - the opened WinSafer Level handle to analyze.
Return Value:
does not return a value.
--*/ void PrintLevelNameDescription( IN SAFER_LEVEL_HANDLE hAuthzLevel, BOOL bPrintDescription) { WCHAR namebuffer[200]; DWORD dwordbuffer;
if (SaferGetLevelInformation( hAuthzLevel, SaferObjectLevelId, &dwordbuffer, sizeof(DWORD), NULL)) { if (SaferGetLevelInformation( hAuthzLevel, SaferObjectFriendlyName, namebuffer, sizeof(namebuffer), NULL)) { IDS_tprintf(IDS_SECURITYLEVEL, namebuffer, dwordbuffer, dwordbuffer); } else { printLastErrorWithMessage(TEXT("Error getting level friendly name")); }
if (bPrintDescription) { if (SaferGetLevelInformation( hAuthzLevel, SaferObjectDescription, namebuffer, sizeof(namebuffer), NULL)) { IDS_tprintf(IDS_SECURITYLEVELDESC, namebuffer); } else { printLastErrorWithMessage(TEXT("Error getting level description")); } } } else { printLastErrorWithMessage(TEXT("Error retrieving level information")); }
}
BOOL ListSingleIdentity( IN SAFER_LEVEL_HANDLE hAuthzLevel, IN REFGUID rEntryGuid ) /*++
Routine Description:
Prints out details about a specific already existing Code Identity that has been defined for a WinSafer Level.
Arguments:
hAuthzLevel - handle of the WinSafer Level to which the indicated Code Identity GUID belongs.
rEntryGuid - pointer to the GUID of the Code Identity requested.
Return Value:
returns TRUE on success, FALSE on failure.
--*/ { BOOL bRVal; DWORD dwBufferSize; SAFER_IDENTIFICATION_HEADER caiCommon;
#if 0 // just testing
SAFER_PATHNAME_IDENTIFICATION newimageid;
ZeroMemory(&newimageid, sizeof(SAFER_PATHNAME_IDENTIFICATION)); newimageid.header.cbStructSize = sizeof(SAFER_PATHNAME_IDENTIFICATION); newimageid.header.dwIdentificationType = SaferIdentityTypeImageName; CopyMemory(&newimageid.header.IdentificationGuid, rEntryGuid, sizeof(GUID)); newimageid.bOnlyExeFiles = TRUE; lstrcpyW(newimageid.Description, L"new sample identity"); newimageid.dwUIFlags = 42; lstrcpyW(newimageid.ImageName, L"c:\\temp\\foo\\bar.txt"); bRVal = SetInformationCodeAuthzLevelW ( hAuthzLevel, SaferObjectSingleIdentification, &newimageid, sizeof(newimageid)); if (!bRVal) { printf("SetInformationCodeAuthzLevelW failed with error %d\n", GetLastError()); } else { printf("SetInformationCodeAuthzLevelW was successful\n"); } #endif
#if 0 // just testing
dwBufferSize = sizeof(SAFER_IDENTIFICATION_HEADER); ZeroMemory(&caiCommon, sizeof(SAFER_IDENTIFICATION_HEADER)); caiCommon.cbStructSize = dwBufferSize; caiCommon.dwIdentificationType = 0; memcpy(&caiCommon.IdentificationGuid, rEntryGuid, sizeof(GUID)); bRVal = SetInformationCodeAuthzLevelW (hAuthzLevel, SaferObjectSingleIdentification, &caiCommon, dwBufferSize); if (!bRVal) { printf("Failed to delete identity (error=%d)\n", GetLastError()); } else { printf("Identity successfully deleted.\n"); } #endif
dwBufferSize = sizeof(SAFER_IDENTIFICATION_HEADER); ZeroMemory (&caiCommon, sizeof(SAFER_IDENTIFICATION_HEADER)); caiCommon.cbStructSize = dwBufferSize; memcpy (&caiCommon.IdentificationGuid, rEntryGuid, sizeof (GUID));
bRVal = SaferGetLevelInformation (hAuthzLevel, SaferObjectSingleIdentification, &caiCommon, dwBufferSize, &dwBufferSize); if ( !bRVal && ERROR_INSUFFICIENT_BUFFER == GetLastError () ) { PBYTE pBytes = (PBYTE) LocalAlloc (LPTR, dwBufferSize); if ( pBytes ) { PSAFER_IDENTIFICATION_HEADER pCommon = (PSAFER_IDENTIFICATION_HEADER) pBytes; ZeroMemory(pCommon, dwBufferSize); pCommon->cbStructSize = sizeof(SAFER_IDENTIFICATION_HEADER); memcpy (&pCommon->IdentificationGuid, rEntryGuid, sizeof (GUID));
bRVal = SaferGetLevelInformation (hAuthzLevel, SaferObjectSingleIdentification, pBytes, dwBufferSize, &dwBufferSize); if ( bRVal ) { switch (pCommon->dwIdentificationType) { case SaferIdentityTypeImageName: { PSAFER_PATHNAME_IDENTIFICATION pImageName = (PSAFER_PATHNAME_IDENTIFICATION) pCommon; ASSERT(pCommon->cbStructSize == sizeof(SAFER_PATHNAME_IDENTIFICATION)); printf(" ImageName: %S\n", pImageName->ImageName); printf("Description: %S\n", pImageName->Description); #ifdef AUTHZPOL_SAFERFLAGS_ONLY_EXES
printf(" SaferFlags: %d OnlyExecutables: %s\n\n", pImageName->dwSaferFlags, (pImageName->dwSaferFlags & AUTHZPOL_SAFERFLAGS_ONLY_EXES) != 0 ? "yes" : "no"); #else
printf(" SaferFlags: %d\n\n", pImageName->dwSaferFlags); #endif
return TRUE; }
case SaferIdentityTypeImageHash: { ULONG i; PSAFER_HASH_IDENTIFICATION pImageHash = (PSAFER_HASH_IDENTIFICATION) pCommon; ASSERT(pCommon->cbStructSize == sizeof(SAFER_HASH_IDENTIFICATION)); printf(" ImageHash: "); for (i = 0; i < pImageHash->HashSize; i++) { printf("%02X ", pImageHash->ImageHash[i]); } printf("(%d bytes, ImageSize=%d bytes)\n", pImageHash->HashSize, pImageHash->ImageSize.LowPart); printf("Description: %S\n", pImageHash->Description); printf(" SaferFlags: %d\n\n", pImageHash->dwSaferFlags); return TRUE; }
case SaferIdentityTypeUrlZone: { PSAFER_URLZONE_IDENTIFICATION pUrlZone = (PSAFER_URLZONE_IDENTIFICATION) pCommon; ASSERT(pCommon->cbStructSize == sizeof(SAFER_URLZONE_IDENTIFICATION)); printf(" UrlZone: %d\n", pUrlZone->UrlZoneId); printf("SaferFlags: %d\n\n", pUrlZone->dwSaferFlags); return TRUE; }
default: printf(" Unexpectedly encountered identity type %d\n", pCommon->dwIdentificationType); break; }
} else { printf(" GetInfo failed with LastError=%d\n", GetLastError()); } LocalFree(pBytes); } else { printf(" Failed to allocate memory for query.\n"); } } else { printf(" First GetInfo failed with LastError=%d\n", GetLastError()); } return FALSE; }
/*++
Routine Description:
Prints all associated Code Identifiers for a given WinSafer Level.
Arguments:
hAuthzLevel - the WinSafer Level handle to analyze.
Return Value:
returns 0.
--*/ int ListAllIdentities( IN SAFER_LEVEL_HANDLE hAuthzLevel) { DWORD dwInfoBufferSize; GUID *pIdentGuids;
if (!SaferGetLevelInformation( hAuthzLevel, SaferObjectAllIdentificationGuids, NULL, 0, &dwInfoBufferSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && dwInfoBufferSize != 0) { pIdentGuids = (GUID*) HeapAlloc(GetProcessHeap(), 0, dwInfoBufferSize); if (pIdentGuids != NULL) { DWORD dwFinalBufferSize; if (SaferGetLevelInformation( hAuthzLevel, SaferObjectAllIdentificationGuids, pIdentGuids, dwInfoBufferSize, &dwFinalBufferSize)) { ULONG ulNumIdentities = dwFinalBufferSize / sizeof(GUID); ULONG i;
ASSERT(dwFinalBufferSize == dwInfoBufferSize); _tprintf(TEXT(" Found %d identity GUIDs.\n"), ulNumIdentities); for (i = 0; i < ulNumIdentities; i++) { if (!ListSingleIdentity(hAuthzLevel, &pIdentGuids[i])) { _tprintf(TEXT(" Failed to retrieve details on identity.\n")); } } } else { _tprintf(TEXT(" Failed to retrieve ident guid list (error=%d).\n"), GetLastError()); } HeapFree( GetProcessHeap(), 0, pIdentGuids); } } else { IDS_tprintf(IDS_NORULESFOUND); }
return 0; }
/*++
Routine Description:
Prints out a list of all defined WinSafer Levels, and optionally all Code Identifiers associated with them.
Arguments:
bDisplayIdentifier - if this argument is TRUE, then the list of associated Code Identifiers will also be listed along with each WinSafer Level as they are enumerated.
Return Value:
returns 0 on success, or a non-zero exit code on failure.
--*/ int ListAllLevels(DWORD dwScope, BOOL bDisplayIdentifiers) { DWORD dwInfoBufferSize; LPBYTE InfoBuffer = NULL;
// Fetch the list of all WinSafer LevelIds.
if (!SaferGetPolicyInformation( dwScope, SaferPolicyLevelList, 0, NULL, &dwInfoBufferSize, NULL) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { InfoBuffer = (LPBYTE) HeapAlloc(GetProcessHeap(), 0, dwInfoBufferSize); if (InfoBuffer != NULL) { DWORD dwInfoBufferSize2; if (!SaferGetPolicyInformation( dwScope, SaferPolicyLevelList, dwInfoBufferSize, InfoBuffer, &dwInfoBufferSize2, NULL)) { _tprintf(TEXT("Failed to retrieve Level list (error=%d)\n"), GetLastError()); HeapFree(GetProcessHeap(), 0, InfoBuffer); InfoBuffer = NULL; } ASSERTMSG("got different final size", dwInfoBufferSize2 == dwInfoBufferSize); ASSERTMSG("expecting whole number of DWORD values", dwInfoBufferSize % sizeof(DWORD) == 0); dwInfoBufferSize = dwInfoBufferSize2; } else { _tprintf(TEXT("Failed to allocate %d bytes of memory.\n"), dwInfoBufferSize); return 1; } }
// Iterate through and add all of the items.
if (InfoBuffer != NULL) { PDWORD pLevelIdList = (PDWORD) InfoBuffer; DWORD Index; for (Index = 0; Index < dwInfoBufferSize / sizeof(DWORD); Index++) { SAFER_LEVEL_HANDLE hAuthzLevel; WCHAR namebuffer[200]; DWORD dwLevelId = pLevelIdList[Index];
if (SaferCreateLevel(dwScope, dwLevelId, SAFER_LEVEL_OPEN, &hAuthzLevel, NULL)) { _tprintf(TEXT("\n")); PrintLevelNameDescription(hAuthzLevel, !bDisplayIdentifiers); /*
if (SaferGetLevelInformation(hAuthzLevel, SaferObjectFriendlyName, namebuffer, sizeof(namebuffer), NULL)) _tprintf(TEXT("LevelId %d: \"%s\"\n"), dwLevelId, namebuffer); else _tprintf(TEXT("LevelId %d: unknown\n"), dwLevelId); */ if (bDisplayIdentifiers) { ListAllIdentities(hAuthzLevel); }
SaferCloseLevel(hAuthzLevel); } else { _tprintf(TEXT("LevelId %d: unknown\n"), dwLevelId); } } HeapFree(GetProcessHeap(), 0, InfoBuffer);
// Fetch the default level
//TODO: for some reason my default level isn't in the registry and this part returns NOT_FOUND
dwInfoBufferSize=0; STACKMARK(0xAAAC0000); if (!SaferGetPolicyInformation( dwScope, SaferPolicyDefaultLevel, 0, NULL, &dwInfoBufferSize, NULL) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { SAFER_LEVEL_HANDLE hAuthzLevel; DWORD dwLevelId = 0;
InfoBuffer = (LPBYTE) HeapAlloc(GetProcessHeap(), 0, dwInfoBufferSize);
if (InfoBuffer != NULL) { if (!SaferGetPolicyInformation( dwScope, SaferPolicyDefaultLevel, dwInfoBufferSize, InfoBuffer, &dwInfoBufferSize, NULL)) { _tprintf(TEXT("Failed to retrieve default level (error=%d)\n"), GetLastError()); HeapFree(GetProcessHeap(), 0, InfoBuffer); InfoBuffer = NULL; return 1; } else { ASSERT(dwInfoBufferSize==sizeof(dwLevelId)); memcpy(&dwLevelId,InfoBuffer, dwInfoBufferSize); if (SaferCreateLevel(dwScope, dwLevelId, SAFER_LEVEL_OPEN, &hAuthzLevel, NULL)) { _tprintf(TEXT("\n")); IDS_tprintf(IDS_DEFAULTLEVEL); PrintLevelNameDescription(hAuthzLevel, FALSE); } } SaferCloseLevel(hAuthzLevel); } else { _tprintf(TEXT("Failed to allocate %d bytes of memory.\n"), dwInfoBufferSize); return 1; } } else { printLastErrorWithMessage(TEXT("Failed to retrieve default level")); return 1; }
return 0; } _tprintf(TEXT("No Levels found in this scope.\n")); return 1; }
BOOL PrintMatchingRule( IN SAFER_LEVEL_HANDLE hAuthzLevel) { DWORD dwBufferSize=0; UNICODE_STRING UnicodeTemp; WCHAR lpzGuid[200]; PSAFER_IDENTIFICATION_HEADER lpQueryBuf=NULL; SAFER_IDENTIFICATION_HEADER comheader; STACKMARK(0xAAAB0000); memset(&comheader,0,sizeof(SAFER_IDENTIFICATION_HEADER)); comheader.cbStructSize=sizeof(SAFER_IDENTIFICATION_HEADER); dwBufferSize = sizeof(SAFER_IDENTIFICATION_HEADER); if (!SaferGetLevelInformation( hAuthzLevel, SaferObjectSingleIdentification, &comheader, dwBufferSize, &dwBufferSize)) { printLastError(); return FALSE; } if (GetLastError() == ERROR_NOT_FOUND) { IDS_tprintf(IDS_USINGDEFAULTRULE); } else { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER && GetLastError() != ERROR_SUCCESS) { printLastError(); return FALSE; } ASSERT(dwBufferSize >= sizeof (SAFER_IDENTIFICATION_HEADER)); lpQueryBuf = (PSAFER_IDENTIFICATION_HEADER)LocalAlloc(LPTR, dwBufferSize ); if (!lpQueryBuf) { printLastError(); return FALSE; } lpQueryBuf->cbStructSize = dwBufferSize; if (!SaferGetLevelInformation(hAuthzLevel, SaferObjectSingleIdentification, lpQueryBuf, dwBufferSize, &dwBufferSize) ) { printLastError(); return FALSE; } UnicodeTemp.Buffer=(PWSTR)lpzGuid; UnicodeTemp.MaximumLength = sizeof(lpzGuid); RtlStringFromGUID (&(lpQueryBuf->IdentificationGuid),&UnicodeTemp); //TODO: could print out whether rule was from CU or LM
if (lpQueryBuf->dwIdentificationType == SaferIdentityTypeImageName) { IDS_tprintf(IDS_MATCHPATH, ((PSAFER_PATHNAME_IDENTIFICATION)lpQueryBuf)->ImageName); } else if (lpQueryBuf->dwIdentificationType == SaferIdentityTypeImageHash ){ IDS_tprintf(IDS_MATCHHASH); } else if (lpQueryBuf->dwIdentificationType == SaferIdentityTypeUrlZone ){ IDS_tprintf(IDS_MATCHZONE); } else { //must be a publisher certificate rule.
IDS_tprintf(IDS_MATCHCERTORDEFAULT); } IDS_tprintf(IDS_GUIDRULEIS,UnicodeTemp.Buffer); LocalFree(lpQueryBuf); } _tprintf(TEXT("\n")); PrintLevelNameDescription(hAuthzLevel, TRUE); return TRUE; }
//VerifyVersionInfo
BOOL IsMinimumVersion() { DWORD tmp; LPVOID lpVerInfo = NULL; LPVOID lpValue = NULL; LPTSTR lpFileToVersion = TEXT("advapi32.dll"); UINT uLen; //must be at least post beta 1 of whistler
const DWORD PROD_MAJOR = 5; const DWORD PROD_MINOR = 1; const DWORD BUILD_MAJOR = 2400;
DWORD dwBuildMajor=0, dwProductMajor=0, dwProductMinor=0; DWORD dwSize = GetFileVersionInfoSize(lpFileToVersion, &tmp);
if (!dwSize) { printLastErrorWithIDSMessage(IDS_ERR_GETVERERR); return FALSE; } lpVerInfo = (LPVOID) LocalAlloc(LPTR, dwSize); if (!lpVerInfo) { printLastError(); return FALSE; } if (! GetFileVersionInfo(lpFileToVersion, 0, dwSize, lpVerInfo)) { printLastErrorWithIDSMessage(IDS_ERR_GETVERERR); if (lpVerInfo) LocalFree(lpVerInfo); return FALSE; } if (!VerQueryValue(lpVerInfo, TEXT("\\"), &lpValue, &uLen)) { // '\' indicates the root version info block
printLastErrorWithIDSMessage(IDS_ERR_GETVERERR); if (lpVerInfo) LocalFree(lpVerInfo); return FALSE; } /*
_tprintf(TEXT("dwFileVersionMS is %d\n"), (((VS_FIXEDFILEINFO*)lpValue)->dwFileVersionMS) >> 16); _tprintf(TEXT("dwFileVersionMS is %d\n"), (((VS_FIXEDFILEINFO*)lpValue)->dwFileVersionMS) & 0x0000FFFF); _tprintf(TEXT("dwFileVersionLS is %d\n"), (((VS_FIXEDFILEINFO*)lpValue)->dwFileVersionLS) >> 16); _tprintf(TEXT("dwFileVersionLS is %d\n"), (((VS_FIXEDFILEINFO*)lpValue)->dwFileVersionLS) & 0x0000FFFF); _tprintf(TEXT("dwProductVersionMS is %d\n"), (((VS_FIXEDFILEINFO*)lpValue)->dwProductVersionMS) >>16); _tprintf(TEXT("dwProductVersionMS is %d\n"), (((VS_FIXEDFILEINFO*)lpValue)->dwProductVersionMS) & 0x0000FFFF); _tprintf(TEXT("dwProductVersionLS is %d\n"), (((VS_FIXEDFILEINFO*)lpValue)->dwProductVersionLS) >>16); _tprintf(TEXT("dwProductVersionLS is %d\n"), (((VS_FIXEDFILEINFO*)lpValue)->dwProductVersionLS) & 0x0000FFFF); */ dwProductMajor = (((VS_FIXEDFILEINFO*)lpValue)->dwProductVersionMS) >>16; dwProductMinor = (((VS_FIXEDFILEINFO*)lpValue)->dwProductVersionMS) & 0x0000FFFF; dwBuildMajor = (((VS_FIXEDFILEINFO*)lpValue)->dwProductVersionLS) >>16; if ((dwProductMajor < PROD_MAJOR) || (dwProductMajor == PROD_MAJOR && dwProductMinor < PROD_MINOR ) || (dwProductMinor == PROD_MAJOR && dwProductMinor == PROD_MINOR && dwBuildMajor < BUILD_MAJOR)) { IDS_tprintf(IDS_ERR_INCORRECTOSVER, dwProductMajor, dwProductMinor, dwBuildMajor, PROD_MAJOR, PROD_MINOR, BUILD_MAJOR); if (lpVerInfo) LocalFree(lpVerInfo); return FALSE; } else { if (lpVerInfo) LocalFree(lpVerInfo); return TRUE; } }
BOOL GetPathFromKeyKey(LPCTSTR lpzRegKey) { HKEY hKey, hKeyHive; LPTSTR lpKeyname=NULL; LPCTSTR LP_CU_HIVE = TEXT("%HKEY_CURRENT_USER"); LPCTSTR LP_LM_HIVE = TEXT("%HKEY_LOCAL_MACHINE"); LPCTSTR lpLastPercentSign=NULL; BYTE buffer[MAX_PATH]; LPTSTR lpValue; DWORD dwBufferSize = sizeof(buffer); LPTSTR lpHivename; LONG retval;
memset(buffer, 0, dwBufferSize); lpHivename = _tcsstr(lpzRegKey, LP_CU_HIVE); if (lpHivename != NULL) { hKeyHive = HKEY_CURRENT_USER; lpKeyname = _tcsdup(&lpzRegKey[_tcslen(LP_CU_HIVE)+1]); //remove '\' char in front
} else { lpHivename = _tcsstr(lpzRegKey, LP_LM_HIVE); if (lpHivename != NULL) { hKeyHive = HKEY_LOCAL_MACHINE; lpKeyname = _tcsdup(&lpzRegKey[_tcslen(LP_LM_HIVE)+1]); //remove '\' char in front
} else { IDS_tprintf(IDS_ERR_REGNOTFOUND); return FALSE; } } lpLastPercentSign = wcsrchr(lpzRegKey,'%'); if (lpLastPercentSign != &lpzRegKey[wcslen(lpzRegKey)-1]) { _tprintf(TEXT("bad substitution char.\n")); return FALSE; }
lpValue = _tcsrchr(lpKeyname, '\\'); if (lpValue==NULL) { IDS_tprintf(IDS_ERR_REGNOTFOUND); return FALSE; } *lpValue = '\0'; lpValue = lpValue + 1; lpValue[wcslen(lpValue)-1] = '\0';
if (retval = RegOpenKeyEx(hKeyHive, lpKeyname, 0, KEY_READ, &hKey)) { SetLastError(retval); printLastError(); return FALSE; } else { if (retval = RegQueryValueEx(hKey, lpValue, NULL, NULL, buffer, &dwBufferSize)) { SetLastError(retval); printLastError(); return FALSE; } else { _tprintf(TEXT("\n")); IDS_tprintf(IDS_REGVALUE); _tprintf(TEXT("%s"), buffer); }
} free(lpKeyname); RegCloseKey(hKey); return TRUE; } void PrintAndRecurse(HKEY hkey, LPCWSTR lpParentKeyname) { DWORD cValue=MAX_PATH; DWORD cKey=MAX_PATH; DWORD cbData=100; LPWSTR lpValue[MAX_PATH * sizeof(WCHAR)]; LPWSTR lpKey[MAX_PATH * sizeof(WCHAR)]; LPWSTR lpFullKey[MAX_PATH * sizeof(WCHAR)]; LPBYTE lpData=NULL; DWORD idx=0; DWORD dwType=0; DWORD retval=0; FILETIME filetime; BOOL bDone=FALSE; HKEY nextKey=NULL; DWORD dwNumSubKeys=0; DWORD dwNumValues=0; DWORD dwMaxValueLen=0; RegQueryInfoKey(hkey,NULL,NULL, NULL, &dwNumSubKeys, NULL, NULL, &dwNumValues,NULL, &dwMaxValueLen, NULL,NULL); do { lpValue[0]=L"\0"; cbData = dwMaxValueLen; lpData = (LPBYTE)LocalAlloc(LPTR, dwMaxValueLen); if (!lpData) { printLastError(); return; } cValue=MAX_PATH; retval = RegEnumValue(hkey, idx, (LPWSTR)lpValue, &cValue, NULL, &dwType, lpData, &cbData); if (retval==ERROR_NO_MORE_ITEMS) { bDone=TRUE; } else if (retval != ERROR_SUCCESS) { SetLastError(retval); bDone=TRUE; printLastError(); } if (!bDone) { wprintf(L"\t%s",lpValue); switch (dwType) { case REG_DWORD: { DWORD dwValue; memcpy(&dwValue,lpData, sizeof(DWORD)); wprintf(L" : 0x%08X\n", dwValue); } break; case REG_QWORD: { __int64 qwValue; memcpy(&qwValue, lpData, sizeof(__int64)); wprintf(L" : 0x%I64x\n", qwValue); } break; case REG_BINARY: wprintf(L" : "); { int i; for (i=0;i<(int)cbData;i++) { wprintf(L"%02X", *(lpData+i)); } wprintf(L"\n"); } break; case REG_SZ: case REG_EXPAND_SZ: wprintf(L" : %s\n", lpData); break; case REG_MULTI_SZ: {int idx=0; LPWSTR lpMultiPtr=(LPWSTR)lpData; WCHAR nullchar = L'\0'; wprintf(L" : "); do { wprintf(L" %s ", lpMultiPtr); lpMultiPtr+=wcslen(lpMultiPtr)+1 ; } while (*(lpMultiPtr+1)!=0); wprintf(L"\n"); } break; default: wprintf(L" ??????: 0x%X\n", lpData); } if (lpData) LocalFree(lpData); idx++; } } while (!bDone); if (dwNumSubKeys != 0) { idx=0; bDone=FALSE; do { lpKey[0]=L"\0"; cKey=MAX_PATH; retval = RegEnumKeyEx(hkey, idx, (LPWSTR)lpKey, &cKey, NULL, NULL, NULL, &filetime); if (retval==ERROR_NO_MORE_ITEMS) { bDone=TRUE; } else if (retval != ERROR_SUCCESS) { SetLastError(retval); bDone=TRUE; printLastError(); } if (!bDone) { wprintf(L"%s\\%s\n",lpParentKeyname,lpKey); if (RegOpenKeyEx(hkey, (LPWSTR)lpKey, 0, KEY_READ, &nextKey)) { bDone=TRUE; printLastError(); return; } else { memset(lpFullKey,0,sizeof(lpFullKey)); wcscat((LPWSTR)lpFullKey, lpParentKeyname); wcscat((LPWSTR)lpFullKey, L"\\"); wcscat((LPWSTR)lpFullKey, (LPWSTR)lpKey); wcscat((LPWSTR)lpFullKey, L"\0"); PrintAndRecurse(nextKey, (LPWSTR)lpFullKey); RegCloseKey(nextKey); } idx++; } } while (!bDone); } }
LONG DumpRegistry() { DWORD class,subkeys,maxsubkeylen, numvalues, maxvaluename, maxvaluedatalen; const UNICODE_STRING HKLMSAFERKey = RTL_CONSTANT_STRING(SAFER_HKLM_REGBASE); const UNICODE_STRING HKCUSAFERKey = RTL_CONSTANT_STRING(SAFER_HKCU_REGBASE); const UNICODE_STRING HKPublisherKey = RTL_CONSTANT_STRING(L"Software\\Policies\\Microsoft\\SystemCertificates\\TrustedPublisher\\Certificates"); HKEY hkey; int i; if (!RegOpenKeyEx(HKEY_CURRENT_USER, HKCUSAFERKey.Buffer, 0, KEY_READ, &hkey)) { IDS_tprintf(IDS_LISTING_HKCU); wprintf(L"%s\n",HKCUSAFERKey.Buffer); PrintAndRecurse(hkey, HKCUSAFERKey.Buffer); RegCloseKey(hkey); } if (!RegOpenKeyEx(HKEY_CURRENT_USER, HKPublisherKey.Buffer, 0, KEY_READ, &hkey)) { wprintf(L"%s\n",HKPublisherKey.Buffer); PrintAndRecurse(hkey, HKPublisherKey.Buffer); RegCloseKey(hkey); } if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, HKLMSAFERKey.Buffer, 0, KEY_READ, &hkey)) { wprintf(L"\n"); IDS_tprintf(IDS_LISTING_HKLM); wprintf(L"%s\n",HKLMSAFERKey.Buffer); PrintAndRecurse(hkey, HKCUSAFERKey.Buffer); RegCloseKey(hkey); } if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, HKPublisherKey.Buffer, 0, KEY_READ, &hkey)) { wprintf(L"%s\n",HKPublisherKey.Buffer); PrintAndRecurse(hkey, HKPublisherKey.Buffer); RegCloseKey(hkey); } return ERROR_SUCCESS; }
/*++
Routine Description:
Main entry point.
Arguments:
argc - count of command line arguments.
argv - pointers to command line arguments.
Return Value:
returns the program exit code.
--*/ int __cdecl _tmain(int argc, _TCHAR **argv, _TCHAR **envp) { PROCESS_INFORMATION pi; DWORD dwLevelId = 0; BOOL fLevelIdSupplied = FALSE; _TCHAR appname[MAX_PATH]; _TCHAR cmdline[1024]; LPTSTR lpRegkey=NULL; int nextarg; SAFER_LEVEL_HANDLE hAuthzLevel; int retval; DWORD dwSuppliedCheckFlags=0; DWORD dwScopeId=(DWORD)-1; //means check both LM + CU
BOOL useBreakMode = FALSE; enum { CMD_RUN, CMD_QUERY, CMD_HASH, CMD_LIST, CMD_LISTRULES, CMD_REGKEY, CMD_DUMPREG } commandMode = -1; LPTSTR A_LP_CMD_QUERY = AllocAndLoadString(IDS_CMD_QUERY); LPTSTR A_LP_CMD_RUN= AllocAndLoadString(IDS_CMD_RUN); LPTSTR A_LP_CMD_HASH= AllocAndLoadString(IDS_CMD_HASH); LPTSTR A_LP_CMD_LIST= AllocAndLoadString(IDS_CMD_LIST); LPTSTR A_LP_CMD_LISTRULES= AllocAndLoadString(IDS_CMD_LISTRULES); LPTSTR A_LP_CMD_REGKEY= AllocAndLoadString(IDS_CMD_REGKEY ); LPTSTR A_LP_CMD_DUMPREG= AllocAndLoadString(IDS_CMD_DUMPREG ); LPTSTR A_LP_FLAG_LEVELID= AllocAndLoadString(IDS_FLAG_LEVELID); LPTSTR A_LP_FLAG_RULETYPES= AllocAndLoadString(IDS_FLAG_RULETYPES); LPTSTR A_LP_RULETYPES_PATH= AllocAndLoadString(IDS_RULETYPES_PATH); LPTSTR A_LP_RULETYPES_HASH= AllocAndLoadString(IDS_RULETYPES_HASH); LPTSTR A_LP_RULETYPES_CERTIFICATE= AllocAndLoadString(IDS_RULETYPES_CERTIFICATE); LPTSTR A_LP_FLAG_SCOPE= AllocAndLoadString(IDS_FLAG_SCOPE); LPTSTR A_LP_SCOPE_HKLM= AllocAndLoadString(IDS_SCOPE_HKLM); LPTSTR A_LP_SCOPE_HKCU= AllocAndLoadString(IDS_SCOPE_HKCU);
UNREFERENCED_PARAMETER(envp); STACKMARK(0xAAAA0001);
//IDS_tprintf(IDS_TEST1,66,TEXT("hellow"),45456); //test string
//get the module handle
if(!InitModule()) { return 1; }
// if we are going to run in an altered registry
// scope, open and set it now.
/*
if (dwScopeId == SAFER_SCOPEID_REGISTRY) { HKEY hkeyBase;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"TestKey", 0, KEY_READ, &hkeyBase) != ERROR_SUCCESS) { _tprintf(TEXT("Failed to open registry scope key (error=%d)\n"), GetLastError()); return 1; }
if (!CodeAuthzChangeRegistryScope(hkeyBase)) { _tprintf(TEXT("Failed to change registry scope (error=%d)\n"), GetLastError()); return 1; } RegCloseKey(hkeyBase); } */
if (!IsMinimumVersion()) { return 1; }
// quick check of command line length.
if (argc < 2) { _tprintf(TEXT("No arguments.\n")); return DisplaySyntax(); }
// Parse the command line.
appname[0] = '\0'; cmdline[0] = '\0'; for (nextarg = 1; nextarg < argc; nextarg++) { if (_tcsicmp(argv[nextarg],A_LP_CMD_QUERY) == 0 ) { commandMode = CMD_QUERY; } else if (_tcsicmp(argv[nextarg],A_LP_CMD_RUN) == 0 ) { commandMode = CMD_RUN; } else if (_tcsicmp(argv[nextarg],A_LP_CMD_HASH) == 0 ) { commandMode = CMD_HASH; } else if (_tcsicmp(argv[nextarg],A_LP_CMD_DUMPREG) == 0 ) { commandMode = CMD_DUMPREG; } else if (_tcsicmp(argv[nextarg],A_LP_CMD_REGKEY) == 0 ) { commandMode = CMD_REGKEY; nextarg++; if (nextarg!=argc) { lpRegkey = argv[nextarg]; } else { return DisplaySyntax(); } } else if (_tcsicmp(argv[nextarg],A_LP_CMD_LIST) == 0 ) { commandMode = CMD_LIST; } else if (_tcsicmp(argv[nextarg],A_LP_CMD_LISTRULES) == 0 ) { commandMode = CMD_LISTRULES; } else if (argv[nextarg][0] == '-' || argv[nextarg][0] == '/') { if (_tcsicmp(&argv[nextarg][1], A_LP_FLAG_LEVELID) == 0) { STACKMARK(0xAAAA000D); dwLevelId = _ttoi(argv[++nextarg]); fLevelIdSupplied = TRUE; } else if (_tcsicmp(&argv[nextarg][1], A_LP_FLAG_RULETYPES) == 0) { STACKMARK(0xAAAA000B); nextarg++; if (nextarg >= argc) { return DisplaySyntax(); } //unknown rule types are ignored
if (_tcscspn(argv[nextarg], A_LP_RULETYPES_PATH) < _tcslen(argv[nextarg])) { dwSuppliedCheckFlags = dwSuppliedCheckFlags | SAFER_CRITERIA_IMAGEPATH; } if (_tcscspn(argv[nextarg], A_LP_RULETYPES_HASH) < _tcslen(argv[nextarg])) { dwSuppliedCheckFlags = dwSuppliedCheckFlags | SAFER_CRITERIA_IMAGEHASH; } if (_tcscspn(argv[nextarg], A_LP_RULETYPES_CERTIFICATE) < _tcslen(argv[nextarg] )) { dwSuppliedCheckFlags = dwSuppliedCheckFlags | SAFER_CRITERIA_AUTHENTICODE; } } else if (_tcsicmp(&argv[nextarg][1], A_LP_FLAG_SCOPE) == 0) { nextarg++; if (nextarg >= argc) { return DisplaySyntax(); } STACKMARK(0xAAAA000F); if (_tcscspn(argv[nextarg], A_LP_SCOPE_HKLM) < _tcslen(argv[nextarg])) { dwScopeId = SAFER_SCOPEID_MACHINE; } else if (_tcscspn(argv[nextarg], A_LP_SCOPE_HKCU) < _tcslen(argv[nextarg])) { dwScopeId = SAFER_SCOPEID_USER; } else { return DisplaySyntax(); } } else { return DisplaySyntax(); } } else if (commandMode==CMD_RUN || commandMode == CMD_QUERY || commandMode == CMD_HASH) { LPTSTR fn; STACKMARK(0xAAAA000C); if (commandMode==CMD_RUN && !fLevelIdSupplied) { IDS_tprintf(IDS_ERR_NOLEVELID); return DisplaySyntax(); } //
// This argument is an explicitly named application exe.
//
// if (!GetFullPathName(argv[nextarg],
// sizeof(appname) / sizeof(appname[0]),
// appname, &fn) &&
if (!SearchPath(NULL, argv[nextarg], NULL, sizeof(appname) / sizeof(appname[0]), appname, &fn)) { STACKMARK(0xAAAA000A);
appname[0] = 0; } else { _tprintf(TEXT("Program to launch: %s\n"),appname); }
if (commandMode == CMD_RUN) { //
// All following arguments is the child's command line.
//
nextarg++; if (nextarg > argc) { return DisplaySyntax(); } for (; nextarg < argc; nextarg++) { if (_tcslen(cmdline) + _tcslen(argv[nextarg]) + 2 < sizeof(cmdline)) { if (cmdline[0]) { _tcscat(cmdline, TEXT(" ")); } _tcscat(cmdline, argv[nextarg]); } else { IDS_tprintf(IDS_ERR_CMDLINETOOLONG); return 0; } } break; } } else { // Unknown garbage encountered at the end of the line.
return DisplaySyntax(); } } STACKMARK(0xAAAA0002); //
// Application exe must always be specified for some cases.
//
if (commandMode == CMD_RUN || commandMode == CMD_QUERY || commandMode == CMD_HASH) { if (appname == NULL || appname[0] == '\0') { IDS_tprintf(IDS_ERR_NOAPPNAME); return DisplaySyntax(); } }
switch (commandMode) { case CMD_HASH: return ComputeHash(appname); break; case CMD_DUMPREG: return DumpRegistry(); break; case CMD_REGKEY: return GetPathFromKeyKey(lpRegkey); break; case CMD_LIST: case CMD_LISTRULES: if (dwScopeId == -1) { _tprintf(TEXT("\n")); IDS_tprintf(IDS_LISTING_HKCU); retval = ListAllLevels(SAFER_SCOPEID_USER, commandMode == CMD_LISTRULES); _tprintf(TEXT("\n")); IDS_tprintf(IDS_LISTING_HKLM); retval = ListAllLevels(SAFER_SCOPEID_MACHINE, commandMode == CMD_LISTRULES); } else { retval = ListAllLevels(dwScopeId, commandMode == CMD_LISTRULES); } break; case CMD_QUERY: { SAFER_CODE_PROPERTIES codeproperties; STACKMARK(0xAAAA0003); ASSERT(appname != NULL); // prepare the code properties struct.
memset(&codeproperties, 0, sizeof(codeproperties)); codeproperties.cbSize = sizeof(codeproperties); codeproperties.dwCheckFlags = (!dwSuppliedCheckFlags) ? SAFER_CRITERIA_IMAGEPATH | SAFER_CRITERIA_IMAGEHASH | SAFER_CRITERIA_AUTHENTICODE : dwSuppliedCheckFlags; codeproperties.ImagePath = appname; codeproperties.dwWVTUIChoice = WTD_UI_ALL; //ignored if SAFER_CRITERIA_AUTHENTICODE is not passed in
// Ask the system to find the authorization Level that classifies it.
if (!SaferIdentifyLevel(1, &codeproperties, &hAuthzLevel, NULL)) { if (GetLastError() == ERROR_NOT_FOUND) { IDS_tprintf(IDS_ERR_NOLEVELSFOUND); } else { printLastErrorWithIDSMessage(IDS_ERR_IMGACCESSERR); } return 1; } //print information about the rule that matched the program
if (!PrintMatchingRule(hAuthzLevel)) { printLastErrorWithIDSMessage(IDS_ERR_ERRMATCHRULE); return 1; } SaferCloseLevel(hAuthzLevel); } break; case CMD_RUN: // Launch the process with the specified WinSafer Level restrictions.
STACKMARK(0xAAAA0005); if (dwLevelId == SAFER_LEVELID_DISALLOWED) { IDS_tprintf(IDS_ERR_PROCESSNOLAUNCH); return 0; } if (dwScopeId == -1) { dwScopeId = SAFER_SCOPEID_USER; //user didn't pass in a scope, so set it for them
} if (!SaferCreateLevel(dwScopeId, dwLevelId, SAFER_LEVEL_OPEN, &hAuthzLevel, NULL)) { printLastError(); IDS_tprintf(IDS_ERR_LEVELOPENERR, dwLevelId); return 1; } PrintLevelNameDescription(hAuthzLevel, FALSE); if (!CreateProcessRestricted(hAuthzLevel, appname, cmdline, &pi, useBreakMode)) { if (useBreakMode) { INPUT_RECORD inputrec; DWORD dwNum; IDS_tprintf(IDS_PROCSUSPENDED, pi.dwProcessId); for (;;) { if (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &inputrec, 1, &dwNum) && inputrec.EventType == KEY_EVENT && inputrec.Event.KeyEvent.bKeyDown) break; } ResumeThread(pi.hThread); IDS_tprintf(IDS_THREADRESUMED); } // Close the unnecessary handle
CloseHandle(pi.hThread); // Wait for the process to terminate and then cleanup.
WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); } else { printLastErrorWithIDSMessage(IDS_ERR_PROCESSLAUNCHERR); } SaferCloseLevel(hAuthzLevel);
break; /*
// Compare or execute as appropriate.
if (commandMode == CMD_QUERY) { // Compare the Authorization Level with the current access token.
DWORD dwResult; if (!SaferComputeTokenFromLevel( hAuthzLevel, NULL, NULL, AUTHZTOKEN_COMPARE_ONLY, (LPVOID) &dwResult)) { _tprintf(TEXT("Authorization comparison failed (lasterror=%d)\n"), GetLastError()); } else if (dwResult != -1) { _tprintf(TEXT("Authorization comparison equal or greater privileged.\n"), GetLastError()); } else { _tprintf(TEXT("Authorization comparison less privileged.\n"), GetLastError()); } return 0; } else { // Launch the process with the specified WinSafer Level restrictions.
ASSERT(commandMode == CMD_RUN); if (!CreateProcessRestricted(hAuthzLevel, appname, cmdline, &pi, useBreakMode)) { if (useBreakMode) { INPUT_RECORD inputrec; DWORD dwNum; _tprintf(TEXT("Process %d launched and suspended. Attach a debugger and then\n") TEXT("strike any key to resume the thread and allow debugging."), pi.dwProcessId); for (;;) { if (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &inputrec, 1, &dwNum) && inputrec.EventType == KEY_EVENT && inputrec.Event.KeyEvent.bKeyDown) break; } ResumeThread(pi.hThread); _tprintf(TEXT("Thread resumed.\n")); } // Close the unnecessary handle
CloseHandle(pi.hThread); // Wait for the process to terminate and then cleanup.
WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); // close the Authorization Level handle.
SaferCloseLevel(hAuthzLevel); retval = 0; } } _tprintf(TEXT("Could not launch process (error=%d).\n"), GetLastError()); retval = 1; */ } if (A_LP_CMD_QUERY) LocalFree(A_LP_CMD_QUERY); if (A_LP_CMD_RUN) LocalFree(A_LP_CMD_RUN); if (A_LP_CMD_HASH) LocalFree(A_LP_CMD_HASH); if (A_LP_CMD_LIST) LocalFree(A_LP_CMD_LIST); if (A_LP_CMD_LISTRULES) LocalFree(A_LP_CMD_LISTRULES); if (A_LP_FLAG_LEVELID) LocalFree(A_LP_FLAG_LEVELID); if (A_LP_FLAG_RULETYPES) LocalFree(A_LP_FLAG_RULETYPES); if (A_LP_RULETYPES_PATH) LocalFree(A_LP_RULETYPES_PATH); if (A_LP_RULETYPES_HASH) LocalFree(A_LP_RULETYPES_HASH); if (A_LP_RULETYPES_CERTIFICATE) LocalFree(A_LP_RULETYPES_CERTIFICATE);
return TRUE; }
|