You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4564 lines
136 KiB
4564 lines
136 KiB
//+-----------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (c) Microsoft Corporation 1991 - 1992
|
|
//
|
|
// File:
|
|
//
|
|
// Contents:
|
|
//
|
|
//
|
|
// History:
|
|
//
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
extern "C"
|
|
{
|
|
#include "lsasrvp.h"
|
|
#include "ausrvp.h"
|
|
#include "spmgr.h"
|
|
#include "sidcache.h"
|
|
}
|
|
#include <stdio.h>
|
|
#include <malloc.h>
|
|
|
|
#include <dbghelp.h>
|
|
#include <ntsdexts.h>
|
|
|
|
#include <dsysdbg.h>
|
|
#define SECURITY_PACKAGE
|
|
#include <security.h>
|
|
#include <secint.h>
|
|
#include <cryptdll.h>
|
|
|
|
#include "debugp.h"
|
|
|
|
#include "..\spmgr.h"
|
|
#include "..\sphelp.h"
|
|
#include "..\sesmgr.h"
|
|
#include "..\scavenge.hxx"
|
|
#include "..\negotiat.hxx"
|
|
#include "..\sht.hxx"
|
|
#include "..\lht.hxx"
|
|
|
|
|
|
#define DBP_TYPES_ONLY
|
|
#include "..\dspolicy\dbp.h"
|
|
#define LSAEXTS
|
|
#include "..\dspolicy\dbftrust.h"
|
|
|
|
#define FlagSize(x) (sizeof(x) / sizeof(char *))
|
|
char * AccessMask[] = { "Delete", "ReadControl", "WriteDac", "WriteOwner",
|
|
"Synch", "", "", "",
|
|
"Sacl", "MaxAllowed", "", "",
|
|
"GenericAll", "GenericExec", "GenericWrite", "GenericRead"};
|
|
|
|
char * HandleFlags[] = { "Locked", "DeletePending", "NoCallback" };
|
|
char * LhtFlags[] = { "NoSerialize", "Callback", "Unique",
|
|
"Child", "LimitDepth", "DeletePending", "NoFree"};
|
|
char * LhtSubFlags[] = { "SubTable" };
|
|
char * ShtFlags[] = { "NoSerialize", "Callback", "Unique",
|
|
"NoFree", "DeletePending" };
|
|
|
|
char * ScavFlags[] = { "NewThread", "One Shot", "FreeHandle", "",
|
|
"", "", "", "",
|
|
"", "", "", "", "", "", "", "",
|
|
"", "", "", "", "", "", "", "",
|
|
"", "TriggerFree", "StateChange", "Immediate",
|
|
"DebugBreak", "AboutToDie", "InProgress", "Seconds" };
|
|
|
|
char * ScavClasses[] = { "<Invalid>", "PackageChange" };
|
|
#define ScavClassName(x) (x < (sizeof(ScavClasses) / sizeof(char *) ) ? \
|
|
ScavClasses[ x ] : "<Invalid>" )
|
|
|
|
char * QueueTypes[] = { "Shared", "Single", "ShareRead", "Zombie" };
|
|
#define QueueTypeName(x) (x < (sizeof( QueueTypes ) / sizeof( char * ) ) ? \
|
|
QueueTypes[ x ] : "<Invalid>" )
|
|
|
|
char * SessFlags[] = { "Queue", "TcbPriv", "Clone", "Impersonate",
|
|
"Desktop", "Untrusted", "InProc", "Autonomous",
|
|
"Default", "Unload", "Scavenger", "Cleanup",
|
|
"Kernel", "Restricted", "MaybeKernel", "EFS",
|
|
"Shadow", "Wow64", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "" };
|
|
|
|
char * PackageFlags[] = {"Invalid", "Unload", "Never Load", "Internal", "Never Call",
|
|
"Preferred", "Delete", "Info", "ContextThunk", "Shutdown Pending",
|
|
"Shutdown", "WowSupport", "", "", "", "", "AuthPkg"
|
|
};
|
|
|
|
char * Capabilities[] = {"Sign/Verify", "Seal/Unseal", "Token Only", "Datagram",
|
|
"Connection", "Multi-Required", "ClientOnly", "ExtError",
|
|
"Impersonation", "Win32Name", "Stream", "Negotiable",
|
|
"GSS Compat", "Logon", "AsciiBuffer", "Fragment",
|
|
"MutualAuth", "Delegation", "", "",
|
|
"", "", "", ""
|
|
};
|
|
|
|
char * APIFlags[] = {"Error", "Memory", "PrePack", "GetState",
|
|
"AnsiCall", "HandleChange", "CallBack", "VmAlloc",
|
|
"ExecNow", "Win32Error", "KMap Mem", ""
|
|
};
|
|
|
|
char * CallInfoFlags[] = { "Kernel", "Ansi", "Urgent", "Recursive",
|
|
"InProc", "Cleanup", "WowClient", ""
|
|
};
|
|
|
|
char * LsaCallInfoFlags[] = { "Impersonating", "InProcCall", "SupressAudits",
|
|
"NoHandleCheck", "KernelPool", "KMap Used" };
|
|
|
|
|
|
char * NegCredFlags[] = { "DefaultPlaceholder","Default","Multi",
|
|
"UseSnego","Kernel","Explicit", "MultiPart",
|
|
"AllowNtlm", "NegNtlm", "NtlmLoopback" };
|
|
char * NegContextFlags[] = { "PackageCalled", "FreeEachMech",
|
|
"Negotiating", "Fragmenting",
|
|
"FragInbound", "FragOutbound",
|
|
"Uplevel", "MutualAuth", };
|
|
|
|
char * NegPackageFlags[] = { "Preferred", "NT4", "ExtraOID", "Inbound",
|
|
"Outbound", "Loopback" };
|
|
|
|
char * SDFlags[] = {"OwnerDef","GroupDef","DaclPresent","DaclDef","SaclPresent",
|
|
"SaclDef","SelfRelative"};
|
|
|
|
char * ImpLevels[] = {"Anonymous", "Identification", "Impersonation", "Delegation"};
|
|
#define ImpLevel(x) ((x < (sizeof(ImpLevels) / sizeof(char *))) ? ImpLevels[x] : "Illegal!")
|
|
|
|
char * SecBufferTypes[] = {"Empty", "Data", "Token", "Package", "Missing", "Extra",
|
|
"Trailer", "Header" };
|
|
#define SecBufferType(x) (((x & ~(SECBUFFER_ATTRMASK)) < (sizeof(SecBufferTypes) / sizeof(char *))) ? \
|
|
SecBufferTypes[ (x & ~(SECBUFFER_ATTRMASK)) ] : "Invalid" )
|
|
|
|
char * LogonTypes[] = {"Invalid", "Invalid",
|
|
"Interactive",
|
|
"Network",
|
|
"Batch",
|
|
"Service",
|
|
"Proxy",
|
|
"Unlock",
|
|
"NetworkCleartext",
|
|
"NewCredentials" };
|
|
|
|
#define LogonTypeName( x ) ( ( x < sizeof( LogonTypes ) / sizeof( char * )) ? \
|
|
LogonTypes[ x ] : "Invalid" )
|
|
|
|
char * MessageNames[] = { "<Disconnect>",
|
|
"<Connect>",
|
|
"LsaLookupPackage",
|
|
"LsaLogonUser",
|
|
"LsaCallPackage",
|
|
"LsaDeregisterLogonProcess",
|
|
"<empty>",
|
|
"(I) GetBinding",
|
|
"(I) SetSession",
|
|
"(I) FindPackage",
|
|
"EnumeratePackages",
|
|
"AcquireCredentialHandle",
|
|
"EstablishCredentials",
|
|
"FreeCredentialHandle",
|
|
"InitializeSecurityContext",
|
|
"AcceptSecurityContext",
|
|
"ApplyControlToken",
|
|
"DeleteSecurityContext",
|
|
"QueryPackage",
|
|
"GetUserInfo",
|
|
"GetCredentials",
|
|
"SaveCredentials",
|
|
"DeleteCredentials",
|
|
"QueryCredAttributes",
|
|
"AddPackage",
|
|
"DeletePackage",
|
|
"GenerateKey",
|
|
"GenerateDirEfs",
|
|
"DecryptFek",
|
|
"GenerateSessionKey",
|
|
"Callback",
|
|
"QueryContextAttributes",
|
|
"PolicyChangeNotify",
|
|
"GetUserName",
|
|
"AddCredential",
|
|
"EnumLogonSession",
|
|
"GetLogonSessionData",
|
|
"SetContextAttribute",
|
|
"LookupAccountSid",
|
|
"LookupAccountName",
|
|
"<empty>" };
|
|
#define ApiLabel(x) (((x+2) < sizeof(MessageNames) / sizeof(char *)) ? \
|
|
MessageNames[(x+2)] : "[Illegal API Number!]")
|
|
|
|
#define NAME_BASE "lsasrv"
|
|
#define PACKAGE_LIST NAME_BASE "!pPackageControlList"
|
|
#define PACKAGE_COUNT NAME_BASE "!PackageControlCount"
|
|
#define DLL_COUNT NAME_BASE "!PackageDllCount"
|
|
#define DLL_LIST NAME_BASE "!pPackageDllList"
|
|
#define SESSION_LIST NAME_BASE "!SessionList"
|
|
#define MEMORY_LIST NAME_BASE "!pLastBlock"
|
|
#define TLS_SESSION NAME_BASE "!dwSession"
|
|
#define PFASTMEM NAME_BASE "!pFastMem"
|
|
#define CFASTMEM NAME_BASE "!cFastMem"
|
|
#define FFASTMEM NAME_BASE "!fFastMemStats"
|
|
|
|
#define MAXPOOLTHREADS NAME_BASE "!MaxPoolThreads"
|
|
#define GLOBALQUEUE NAME_BASE "!GlobalQueue"
|
|
|
|
#define SCAVLIST NAME_BASE "!ScavList"
|
|
#define NOTIFYLIST NAME_BASE "!NotifyList"
|
|
|
|
|
|
#define LPC_APILOG NAME_BASE "!LpcApiLog"
|
|
#define INTERNAL_APILOG NAME_BASE "!InternalApiLog"
|
|
|
|
#define FAULTINGTID NAME_BASE "!FaultingTid"
|
|
#define EXCEPTIONINFO NAME_BASE "!dwExceptionInfo"
|
|
#define TLS_CALLINFO NAME_BASE "!dwCallInfo"
|
|
|
|
|
|
WCHAR *Packages[] = {L"Kerberos", L"NTLM", L"MSV" };
|
|
|
|
#define AllocHeap(x) RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, x)
|
|
#define FreeHeap(x) RtlFreeHeap(RtlProcessHeap(), 0, x)
|
|
void PrintToken(HANDLE, PNTSD_EXTENSION_APIS);
|
|
void LocalDumpSid(PSID);
|
|
|
|
PNTSD_EXTENSION_APIS pExtApis;
|
|
HANDLE hDbgThread;
|
|
HANDLE hDbgProcess;
|
|
|
|
#define DebuggerOut (pExtApis->lpOutputRoutine)
|
|
#define LsaGetSymbol (pExtApis->lpGetSymbolRoutine)
|
|
#define GetExpr (PVOID) (pExtApis->lpGetExpressionRoutine)
|
|
#define InitDebugHelp(hProc,hThd,pApis) {hDbgProcess = hProc; hDbgThread = hThd; pExtApis = pApis;}
|
|
|
|
#define DBG_STACK_TRACE 8
|
|
|
|
CHAR*
|
|
SidNameUseXLate(
|
|
INT i
|
|
)
|
|
{
|
|
switch ( i ) {
|
|
|
|
case SidTypeUser:
|
|
return "User";
|
|
case SidTypeGroup:
|
|
return "Group";
|
|
case SidTypeDomain:
|
|
return "Domain";
|
|
case SidTypeAlias:
|
|
return "Alias";
|
|
case SidTypeWellKnownGroup:
|
|
return "WellKnownGroup";
|
|
case SidTypeDeletedAccount:
|
|
return "Deleted Account";
|
|
case SidTypeInvalid:
|
|
return "Invalid Sid";
|
|
case SidTypeUnknown:
|
|
return "Unknown Type";
|
|
case SidTypeComputer:
|
|
return "Computer";
|
|
default:
|
|
return "Really Unknown -- This is a bug";
|
|
}
|
|
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
LsaReadMemory( PVOID pvAddress,
|
|
ULONG cbMemory,
|
|
PVOID pvLocalMemory)
|
|
{
|
|
SIZE_T cbActual = cbMemory;
|
|
|
|
if (ReadProcessMemory(hDbgProcess, pvAddress, pvLocalMemory, cbMemory, &cbActual))
|
|
{
|
|
if (cbActual != cbMemory)
|
|
{
|
|
return(-1);
|
|
}
|
|
return(0);
|
|
}
|
|
return(GetLastError());
|
|
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
LsaWriteMemory(PVOID pvLocalMemory,
|
|
ULONG cbMemory,
|
|
PVOID pvAddress)
|
|
{
|
|
SIZE_T cbActual = cbMemory;
|
|
|
|
if (WriteProcessMemory(hDbgProcess, pvAddress, pvLocalMemory, cbMemory, &cbActual))
|
|
{
|
|
if (cbActual != cbMemory)
|
|
{
|
|
return(-1);
|
|
}
|
|
return(0);
|
|
}
|
|
return(GetLastError());
|
|
}
|
|
|
|
DWORD
|
|
GetDword(PVOID pvMemory)
|
|
{
|
|
DWORD dwVal;
|
|
SIZE_T cbActual = sizeof(DWORD);
|
|
|
|
if (ReadProcessMemory(hDbgProcess, pvMemory, &dwVal, sizeof(DWORD), &cbActual))
|
|
{
|
|
if (cbActual != sizeof(DWORD))
|
|
{
|
|
return((DWORD) -1);
|
|
}
|
|
return(dwVal);
|
|
}
|
|
return((DWORD) -1);
|
|
}
|
|
|
|
TEB *
|
|
GetTeb(HANDLE hThread)
|
|
{
|
|
NTSTATUS Status;
|
|
THREAD_BASIC_INFORMATION ThreadInfo;
|
|
ULONG cbReturned;
|
|
PTEB Teb;
|
|
|
|
Status = NtQueryInformationThread( hThread,
|
|
ThreadBasicInformation,
|
|
&ThreadInfo,
|
|
sizeof(ThreadInfo),
|
|
&cbReturned);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DebuggerOut("Failed to read Teb, %x\n", Status);
|
|
return(NULL);
|
|
}
|
|
|
|
Teb = (PTEB) AllocHeap(sizeof(TEB));
|
|
|
|
if ( Teb )
|
|
{
|
|
LsaReadMemory(ThreadInfo.TebBaseAddress, sizeof(TEB), Teb);
|
|
}
|
|
|
|
|
|
return(Teb);
|
|
|
|
}
|
|
|
|
PVOID
|
|
GetTlsFromTeb(
|
|
ULONG Index,
|
|
TEB * Teb)
|
|
{
|
|
return(Teb->TlsSlots[Index]);
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
GetTlsEntry(ULONG TlsValue,
|
|
PVOID * ppvValue)
|
|
{
|
|
TEB * Teb;
|
|
|
|
Teb = GetTeb(hDbgThread);
|
|
|
|
if (!Teb)
|
|
{
|
|
DebuggerOut("Could not read teb for thread\n");
|
|
return(STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
*ppvValue = GetTlsFromTeb(TlsValue, Teb);
|
|
|
|
FreeHeap(Teb);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DisplayFlags( DWORD Flags,
|
|
DWORD FlagLimit,
|
|
char *flagset[],
|
|
UCHAR * buffer)
|
|
{
|
|
char * offset;
|
|
DWORD mask, test, i;
|
|
DWORD scratch;
|
|
|
|
if (!Flags) {
|
|
strcpy((CHAR *)buffer, "None");
|
|
return;
|
|
}
|
|
buffer[0] = '0';
|
|
|
|
mask = 0;
|
|
offset = (CHAR *) buffer;
|
|
test = 1;
|
|
for (i = 0 ; i < FlagLimit ; i++ ) {
|
|
if (Flags & test) {
|
|
scratch = sprintf(offset, "%s", flagset[i]);
|
|
offset += scratch;
|
|
mask |= test;
|
|
if (Flags & (~mask)) {
|
|
*offset++ = ',';
|
|
}
|
|
}
|
|
test <<= 1;
|
|
}
|
|
}
|
|
|
|
#define TIMEBUF_SZ 64
|
|
char *Months[] = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
|
|
"Aug", "Sep", "Oct", "Nov", "Dec" };
|
|
void CTimeStamp(
|
|
PTimeStamp ptsTime,
|
|
LPSTR pszTimeBuf,
|
|
BOOL LocalOnly)
|
|
{
|
|
SYSTEMTIME stTime;
|
|
FILETIME tLocal;
|
|
SYSTEMTIME stLocal;
|
|
|
|
if (ptsTime->HighPart == 0)
|
|
{
|
|
strcpy(pszTimeBuf, "<Zero>");
|
|
return;
|
|
}
|
|
else if (ptsTime->HighPart >= 0x7FFFFFFF)
|
|
{
|
|
strcpy(pszTimeBuf, "<Never>");
|
|
return;
|
|
}
|
|
FileTimeToLocalFileTime((LPFILETIME) ptsTime, &tLocal);
|
|
FileTimeToSystemTime((LPFILETIME) ptsTime, &stTime);
|
|
FileTimeToSystemTime(&tLocal, &stLocal);
|
|
if ( LocalOnly )
|
|
{
|
|
sprintf( pszTimeBuf, "%02d:%02d:%02d.%03d",
|
|
stLocal.wHour, stLocal.wMinute, stLocal.wSecond, stLocal.wMilliseconds);
|
|
|
|
}
|
|
else
|
|
{
|
|
sprintf(pszTimeBuf, "%02d:%02d:%02d.%03d, %s %02d, %d UTC (%02d:%02d %s %02d Local)", stTime.wHour,
|
|
stTime.wMinute, stTime.wSecond, stTime.wMilliseconds,
|
|
Months[stTime.wMonth], stTime.wDay, stTime.wYear,
|
|
stLocal.wHour, stLocal.wMinute, Months[stLocal.wMonth], stLocal.wDay);
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
MapString(
|
|
PSECURITY_STRING pClientString,
|
|
PSECURITY_STRING pLocalString)
|
|
{
|
|
if (!pLocalString->Buffer)
|
|
{
|
|
pLocalString->Buffer = (PWSTR) AllocHeap(pClientString->Length + 2);
|
|
pLocalString->MaximumLength = pClientString->Length + 2;
|
|
}
|
|
|
|
if ( !pLocalString->Buffer )
|
|
{
|
|
return;
|
|
}
|
|
|
|
RtlZeroMemory(pLocalString->Buffer, pLocalString->MaximumLength);
|
|
|
|
if (!LsaReadMemory(pClientString->Buffer, pClientString->Length, pLocalString->Buffer))
|
|
{
|
|
pLocalString->Length = pClientString->Length;
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("\nWarning: could not read string @%p\n", pClientString->Buffer);
|
|
}
|
|
|
|
}
|
|
|
|
BOOL
|
|
MapSid(
|
|
PSID RemoteSid,
|
|
PSID * LocalSid
|
|
)
|
|
{
|
|
SID Temp ;
|
|
PSID Copy ;
|
|
|
|
*LocalSid = NULL ;
|
|
|
|
if ( RemoteSid == NULL )
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
if ( !LsaReadMemory( RemoteSid, sizeof( SID ), &Temp ) )
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
Copy = AllocHeap( RtlLengthSid( &Temp ) );
|
|
|
|
if ( !Copy )
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
if ( !LsaReadMemory( RemoteSid, RtlLengthSid( &Temp ), Copy ) )
|
|
{
|
|
FreeHeap( Copy );
|
|
return FALSE ;
|
|
}
|
|
|
|
*LocalSid = Copy ;
|
|
|
|
return TRUE ;
|
|
|
|
|
|
}
|
|
|
|
WCHAR * GetPackageName(
|
|
DWORD_PTR dwPackageId)
|
|
{
|
|
switch (dwPackageId)
|
|
{
|
|
case SPMGR_ID:
|
|
return(L"SPMgr");
|
|
|
|
default:
|
|
return(L"");
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#define PACKAGE_VERBOSE 0x00000001
|
|
#define PACKAGE_NOISY 0x00000002
|
|
#define PACKAGE_TITLE 0x00000004
|
|
void
|
|
ShowPackageControl(
|
|
PVOID Base,
|
|
PLSAP_SECURITY_PACKAGE pSecPkgCtrl,
|
|
DWORD fVerbose)
|
|
{
|
|
SECURITY_STRING sLocal;
|
|
UCHAR buffer[ MAX_PATH ];
|
|
ULONG_PTR Disp;
|
|
PSECPKG_FUNCTION_TABLE pTable;
|
|
|
|
sLocal.Buffer = NULL;
|
|
|
|
MapString(&pSecPkgCtrl->Name, &sLocal);
|
|
|
|
if (fVerbose & PACKAGE_TITLE)
|
|
{
|
|
DebuggerOut("Security Package Control structure at %p\n", Base);
|
|
}
|
|
|
|
DebuggerOut("ID \t%d\n", pSecPkgCtrl->dwPackageID);
|
|
DebuggerOut("Name \t%ws\n", sLocal.Buffer);
|
|
FreeHeap(sLocal.Buffer);
|
|
if (fVerbose & PACKAGE_VERBOSE)
|
|
{
|
|
DisplayFlags(pSecPkgCtrl->fPackage, FlagSize(PackageFlags), PackageFlags, buffer);
|
|
DebuggerOut(" Flags \t%#x: %s\n", pSecPkgCtrl->fPackage, buffer);
|
|
DisplayFlags(pSecPkgCtrl->fCapabilities, 18, Capabilities, buffer);
|
|
DebuggerOut(" Capabilities\t%#x: %s\n", pSecPkgCtrl->fCapabilities, buffer);
|
|
DebuggerOut(" RPC ID \t%d\n", pSecPkgCtrl->dwRPCID);
|
|
DebuggerOut(" Version \t%d\n", pSecPkgCtrl->Version );
|
|
DebuggerOut(" TokenSize\t%d\n", pSecPkgCtrl->TokenSize );
|
|
DebuggerOut(" Thunks \t%p\n", pSecPkgCtrl->Thunks );
|
|
}
|
|
|
|
sLocal.Buffer = NULL;
|
|
|
|
if (fVerbose & PACKAGE_NOISY)
|
|
{
|
|
pTable = &pSecPkgCtrl->FunctionTable;
|
|
DebuggerOut(" Function table:\n");
|
|
LsaGetSymbol((ULONG_PTR)pTable->Initialize, buffer, &Disp);
|
|
DebuggerOut(" Initialize \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->GetInfo, buffer, &Disp);
|
|
DebuggerOut(" GetInfo \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->LogonUser, buffer, &Disp);
|
|
DebuggerOut(" LogonUser \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->AcceptCredentials, buffer, &Disp);
|
|
DebuggerOut(" AcceptCreds \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->AcquireCredentialsHandle, buffer, &Disp);
|
|
DebuggerOut(" AcquireCreds \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->FreeCredentialsHandle, buffer, &Disp);
|
|
DebuggerOut(" FreeCreds \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->SaveCredentials, buffer, &Disp);
|
|
DebuggerOut(" SaveCredentials \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->GetCredentials, buffer, &Disp);
|
|
DebuggerOut(" GetCredentials \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->DeleteCredentials, buffer, &Disp);
|
|
DebuggerOut(" DeleteCredentials \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->InitLsaModeContext, buffer, &Disp);
|
|
DebuggerOut(" InitLsaModeContext \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->LogonTerminated, buffer, &Disp);
|
|
DebuggerOut(" LogonTerminated \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->AcceptLsaModeContext, buffer, &Disp);
|
|
DebuggerOut(" AcceptLsaModeContext\t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->DeleteContext, buffer, &Disp);
|
|
DebuggerOut(" DeleteContext \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->ApplyControlToken, buffer, &Disp);
|
|
DebuggerOut(" ApplyControlToken \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->Shutdown, buffer, &Disp);
|
|
DebuggerOut(" Shutdown \t%s\n", buffer);
|
|
LsaGetSymbol((ULONG_PTR)pTable->GetUserInfo, buffer, &Disp);
|
|
DebuggerOut(" GetUserInfo \t%s\n", buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
ShowSession(
|
|
PVOID pvSessionStart,
|
|
PSession pSession)
|
|
{
|
|
UCHAR Buffer[128];
|
|
ULONG_PTR Disp;
|
|
LSAP_SESSION_RUNDOWN Rundown ;
|
|
LSAP_SHARED_SECTION Section ;
|
|
int i;
|
|
PUCHAR ListEnd ;
|
|
PVOID There ;
|
|
DWORD Tag;
|
|
LARGE_HANDLE_TABLE Large ;
|
|
SMALL_HANDLE_TABLE Small ;
|
|
PVOID Table ;
|
|
|
|
|
|
|
|
DebuggerOut("Session @%p:\n", pvSessionStart);
|
|
DebuggerOut(" Process ID\t%x\n", pSession->dwProcessID);
|
|
DebuggerOut(" LPC Port \t%x\n", pSession->hPort);
|
|
|
|
DisplayFlags(pSession->fSession, // Flags
|
|
32, // Flag limit
|
|
SessFlags, // Flag set
|
|
Buffer);
|
|
|
|
|
|
DebuggerOut(" Flags \t%x: %s\n", pSession->fSession, Buffer);
|
|
|
|
Table = pSession->SharedData->CredTable ;
|
|
LsaReadMemory( Table, sizeof(DWORD), &Tag );
|
|
|
|
if ( Tag == LHT_TAG )
|
|
{
|
|
LsaReadMemory( Table, sizeof( Large ), &Large );
|
|
|
|
DebuggerOut(" CredTable \t%p, %d handles\n", Table, Large.Count );
|
|
|
|
}
|
|
else if ( Tag == SHT_TAG )
|
|
{
|
|
LsaReadMemory( Table, sizeof( Small ), &Small );
|
|
|
|
DebuggerOut(" CredTable \t%p, %d handles\n", Table, Small.Count );
|
|
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut(" CredTable \t%p, not a valid table\n", Table );
|
|
}
|
|
|
|
Table = pSession->SharedData->ContextTable ;
|
|
|
|
LsaReadMemory( Table, sizeof(DWORD), &Tag );
|
|
|
|
if ( Tag == LHT_TAG )
|
|
{
|
|
LsaReadMemory( Table, sizeof( Large ), &Large );
|
|
|
|
DebuggerOut(" ContextTable\t%p, %d handles\n", Table, Large.Count );
|
|
|
|
}
|
|
else if ( Tag == SHT_TAG )
|
|
{
|
|
LsaReadMemory( Table, sizeof( Small ), &Small );
|
|
|
|
DebuggerOut(" ContextTable\t%p, %d handles\n", Table, Small.Count );
|
|
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut(" ContextTable\t%p, not a valid table\n", Table );
|
|
}
|
|
DebuggerOut(" RefCount \t%d\n", pSession->RefCount );
|
|
|
|
ListEnd = (PUCHAR) pvSessionStart + FIELD_OFFSET( Session, RundownList ) ;
|
|
|
|
if ( pSession->RundownList.Flink == (PLIST_ENTRY) ListEnd )
|
|
{
|
|
DebuggerOut(" No rundown functions\n" );
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut(" Rundown Functions:\n" );
|
|
|
|
There = pSession->RundownList.Flink ;
|
|
|
|
do
|
|
{
|
|
LsaReadMemory( There,
|
|
sizeof( LSAP_SESSION_RUNDOWN ),
|
|
&Rundown );
|
|
|
|
LsaGetSymbol( (ULONG_PTR) Rundown.Rundown, Buffer, &Disp );
|
|
DebuggerOut(" %s( %p )\n", Buffer, Rundown.Parameter );
|
|
|
|
There = Rundown.List.Flink ;
|
|
|
|
if (pExtApis->lpCheckControlCRoutine())
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while ( There != ListEnd );
|
|
|
|
}
|
|
|
|
ListEnd = (PUCHAR) pvSessionStart + FIELD_OFFSET( Session, SectionList ) ;
|
|
|
|
if ( pSession->SectionList.Flink == (PLIST_ENTRY) ListEnd )
|
|
{
|
|
DebuggerOut(" No shared sections\n");
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut(" Shared Sections\n");
|
|
|
|
There = pSession->SectionList.Flink ;
|
|
|
|
do
|
|
{
|
|
LsaReadMemory( There,
|
|
sizeof( LSAP_SHARED_SECTION ),
|
|
&Section );
|
|
|
|
DebuggerOut(" Section %p, base at %p\n",
|
|
Section.Section, Section.Base );
|
|
|
|
There = Section.List.Flink ;
|
|
|
|
if (pExtApis->lpCheckControlCRoutine())
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while ( There != ListEnd );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
DumpSessionList(HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID pvSessionStart;
|
|
PVOID pvAddress;
|
|
Session Sess;
|
|
NTSTATUS Status;
|
|
LSAP_SHARED_SESSION_DATA SharedData ;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
pvAddress = (PVOID) GetExpr(SESSION_LIST);
|
|
(void) LsaReadMemory(pvAddress, sizeof(PVOID), &pvSessionStart);
|
|
DebuggerOut("psSessionList (@%p) = %p\n", pvAddress, pvSessionStart);
|
|
|
|
do
|
|
{
|
|
Status = LsaReadMemory(pvSessionStart, sizeof(Session), &Sess);
|
|
if (Status != 0)
|
|
{
|
|
DebuggerOut("Failed reading memory @%p\n", pvSessionStart);
|
|
break;
|
|
}
|
|
|
|
LsaReadMemory( Sess.SharedData, sizeof( SharedData ), &SharedData );
|
|
|
|
Sess.SharedData = &SharedData ;
|
|
|
|
ShowSession(pvSessionStart, &Sess);
|
|
|
|
pvSessionStart = Sess.List.Flink ;
|
|
|
|
} while (pvSessionStart != pvAddress );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
void
|
|
DumpSession(HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID pvAddress;
|
|
PVOID BaseAddress ;
|
|
Session Sess;
|
|
NTSTATUS Status;
|
|
UINT_PTR id;
|
|
LSAP_SHARED_SESSION_DATA SharedData ;
|
|
BOOL Found;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
pvAddress = GetExpr( pszCommand );
|
|
|
|
id = ( UINT_PTR ) pvAddress;
|
|
if ( id < 0x00010000 )
|
|
{
|
|
//
|
|
// Search by process id:
|
|
//
|
|
|
|
pvAddress = (PVOID) GetExpr( SESSION_LIST );
|
|
BaseAddress = pvAddress ;
|
|
LsaReadMemory( pvAddress, sizeof( PVOID ), &pvAddress );
|
|
Found = FALSE ;
|
|
|
|
do
|
|
{
|
|
Status = LsaReadMemory(pvAddress, sizeof(Session), &Sess);
|
|
if (Status != 0)
|
|
{
|
|
DebuggerOut("Failed reading memory @%p\n", pvAddress );
|
|
break;
|
|
}
|
|
|
|
if ( Sess.dwProcessID == id )
|
|
{
|
|
LsaReadMemory( Sess.SharedData, sizeof( SharedData ), &SharedData );
|
|
|
|
Sess.SharedData = &SharedData ;
|
|
|
|
ShowSession( pvAddress, &Sess );
|
|
Found = TRUE ;
|
|
}
|
|
|
|
pvAddress = Sess.List.Flink ;
|
|
|
|
} while (pvAddress != BaseAddress );
|
|
|
|
if ( !Found )
|
|
{
|
|
DebuggerOut( "No session found with process id == %x\n", id );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
Status = LsaReadMemory(pvAddress, sizeof(Session), &Sess);
|
|
|
|
LsaReadMemory( Sess.SharedData, sizeof( SharedData ), &SharedData );
|
|
|
|
Sess.SharedData = &SharedData ;
|
|
|
|
ShowSession(pvAddress, &Sess);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
ReadCallInfo(
|
|
PLSA_CALL_INFO CallInfo
|
|
)
|
|
{
|
|
DWORD TlsValue ;
|
|
PVOID pvInfo ;
|
|
NTSTATUS Status ;
|
|
|
|
TlsValue = GetDword(GetExpr(TLS_CALLINFO));
|
|
|
|
Status = GetTlsEntry(TlsValue, &pvInfo);
|
|
|
|
if (Status != 0)
|
|
{
|
|
DebuggerOut("Could not get TLS %d for Thread\n", TlsValue);
|
|
return Status ;
|
|
}
|
|
|
|
if ( pvInfo )
|
|
{
|
|
Status = LsaReadMemory( pvInfo, sizeof( LSA_CALL_INFO ), CallInfo );
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_UNSUCCESSFUL ;
|
|
}
|
|
|
|
return Status ;
|
|
}
|
|
|
|
VOID
|
|
ShowCallInfo(
|
|
PVOID pv,
|
|
PLSA_CALL_INFO CallInfo
|
|
)
|
|
{
|
|
ULONG i;
|
|
CHAR Flags[ 128 ];
|
|
|
|
|
|
DisplayFlags(CallInfo->CallInfo.Attributes, // Flags
|
|
8, // Flag limit
|
|
CallInfoFlags, // Flag set
|
|
(PUCHAR) Flags );
|
|
|
|
|
|
DebuggerOut("LSA_CALL_INFO at %p\n", pv );
|
|
DebuggerOut(" Message %p\n", CallInfo->Message );
|
|
DebuggerOut(" Session %p\n", CallInfo->Session );
|
|
DebuggerOut(" CallInfo.ThreadId %x\n", CallInfo->CallInfo.ThreadId );
|
|
DebuggerOut(" CallInfo.ProcessId %x\n", CallInfo->CallInfo.ProcessId );
|
|
DebuggerOut(" CallInfo.Attributes %x : %s\n", CallInfo->CallInfo.Attributes, Flags );
|
|
DebuggerOut(" InProcToken %x\n", CallInfo->InProcToken );
|
|
DebuggerOut(" InProcCall %x\n", CallInfo->InProcCall );
|
|
DisplayFlags(CallInfo->Flags, 6, LsaCallInfoFlags, (PUCHAR) Flags );
|
|
DebuggerOut(" Flags %x : %s\n", CallInfo->Flags, Flags );
|
|
DebuggerOut(" Allocs %d\n", CallInfo->Allocs );
|
|
for (i = 0 ; i < CallInfo->Allocs ; i++ )
|
|
{
|
|
DebuggerOut(" Buffers[%d] %p\n", CallInfo->Buffers[i]);
|
|
}
|
|
DebuggerOut(" KMap %p\n", CallInfo->KMap );
|
|
}
|
|
|
|
VOID
|
|
DumpThreadCallInfo(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand
|
|
)
|
|
{
|
|
LSA_CALL_INFO CallInfo ;
|
|
NTSTATUS Status ;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
Status = ReadCallInfo( &CallInfo );
|
|
|
|
if ( Status == 0 )
|
|
{
|
|
ShowCallInfo( NULL, &CallInfo );
|
|
}
|
|
}
|
|
|
|
VOID
|
|
DumpCallInfo(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand
|
|
)
|
|
{
|
|
LSA_CALL_INFO CallInfo ;
|
|
NTSTATUS Status ;
|
|
PVOID pv ;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
pv = GetExpr( pszCommand );
|
|
|
|
if ( pv )
|
|
{
|
|
LsaReadMemory( pv, sizeof( LSA_CALL_INFO ), &CallInfo );
|
|
|
|
ShowCallInfo( pv, &CallInfo );
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpThreadSession( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID pvSessionStart;
|
|
Session Session;
|
|
NTSTATUS Status;
|
|
DWORD TlsValue;
|
|
LSAP_SHARED_SESSION_DATA SharedData ;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
TlsValue = GetDword(GetExpr(TLS_SESSION));
|
|
|
|
Status = GetTlsEntry(TlsValue, &pvSessionStart);
|
|
|
|
if (Status != 0)
|
|
{
|
|
DebuggerOut("Could not get TLS %d for Thread\n", TlsValue);
|
|
return;
|
|
}
|
|
|
|
if (pvSessionStart)
|
|
{
|
|
|
|
Status = LsaReadMemory(pvSessionStart, sizeof(Session), &Session);
|
|
|
|
LsaReadMemory( Session.SharedData, sizeof( SharedData ), &SharedData );
|
|
|
|
Session.SharedData = &SharedData ;
|
|
|
|
ShowSession(pvSessionStart, &Session);
|
|
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("TLS entry was NULL!\n");
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
DumpPackage( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID pvSPC = NULL;
|
|
PVOID pSPC;
|
|
PLSAP_SECURITY_PACKAGE pControl;
|
|
UINT_PTR dwExpr;
|
|
PVOID pcPackage;
|
|
DWORD cPackages;
|
|
DWORD cb;
|
|
DWORD fDump;
|
|
BOOLEAN fDumpAll;
|
|
BOOLEAN fDumpSingle;
|
|
UINT_PTR Index;
|
|
LSAP_SECURITY_PACKAGE Package;
|
|
PLSAP_SECURITY_PACKAGE * pPackageList ;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
fDump = 0;
|
|
dwExpr = 0;
|
|
fDumpAll = FALSE;
|
|
fDumpSingle = FALSE;
|
|
pSPC = NULL;
|
|
Index = 0;
|
|
|
|
pcPackage = GetExpr(PACKAGE_COUNT);
|
|
LsaReadMemory(pcPackage, sizeof(DWORD), &cPackages);
|
|
DebuggerOut(" There are %d package in the system\n", cPackages);
|
|
|
|
if (pszCommand && *pszCommand != '\0' )
|
|
{
|
|
DebuggerOut("Processing '%s'\n", pszCommand);
|
|
|
|
while (*pszCommand)
|
|
{
|
|
while (*pszCommand == ' ')
|
|
{
|
|
pszCommand++;
|
|
}
|
|
|
|
if (*pszCommand == '-')
|
|
{
|
|
pszCommand++;
|
|
switch (*pszCommand)
|
|
{
|
|
case 'V':
|
|
case 'v':
|
|
fDump |= PACKAGE_VERBOSE;
|
|
break;
|
|
case 'B':
|
|
case 'b':
|
|
fDump |= PACKAGE_NOISY;
|
|
break;
|
|
case 'a':
|
|
case 'A':
|
|
fDumpAll = TRUE;
|
|
break;
|
|
default:
|
|
DebuggerOut("Invalid switch '%c'\n", *pszCommand);
|
|
break;
|
|
}
|
|
pszCommand++;
|
|
continue;
|
|
}
|
|
|
|
dwExpr = (UINT_PTR) GetExpr(pszCommand);
|
|
fDumpAll = FALSE;
|
|
if (dwExpr < cPackages)
|
|
{
|
|
Index = dwExpr;
|
|
fDumpSingle = TRUE;
|
|
}
|
|
else if (dwExpr < 0x00010000)
|
|
{
|
|
DebuggerOut("Invalid package ID (%d)\n", dwExpr);
|
|
return;
|
|
} else
|
|
pSPC = (PVOID) dwExpr;
|
|
|
|
while (*pszCommand && *pszCommand != ' ')
|
|
{
|
|
pszCommand++;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
fDumpAll = TRUE;
|
|
}
|
|
|
|
if (pSPC == NULL)
|
|
{
|
|
pvSPC = GetExpr(PACKAGE_LIST);
|
|
|
|
LsaReadMemory(pvSPC, sizeof(PVOID), &pSPC);
|
|
|
|
}
|
|
DebuggerOut(" Package table pointer is at %p, address is %p\n", pvSPC, pSPC);
|
|
|
|
pPackageList = (PLSAP_SECURITY_PACKAGE *) AllocHeap( sizeof(PVOID) * cPackages );
|
|
|
|
if ( pPackageList )
|
|
{
|
|
LsaReadMemory( pSPC, sizeof(PVOID) * cPackages, pPackageList );
|
|
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("Out of memory\n");
|
|
return;
|
|
}
|
|
|
|
|
|
if (fDumpSingle)
|
|
{
|
|
|
|
LsaReadMemory( pPackageList[ Index ], sizeof( LSAP_SECURITY_PACKAGE ), &Package );
|
|
|
|
ShowPackageControl( pPackageList[ Index ],
|
|
&Package,
|
|
fDump | PACKAGE_TITLE );
|
|
|
|
}
|
|
else
|
|
{
|
|
for ( Index = 0 ; Index < cPackages ; Index++ )
|
|
{
|
|
LsaReadMemory( pPackageList[ Index ], sizeof( LSAP_SECURITY_PACKAGE ), &Package );
|
|
|
|
ShowPackageControl( pPackageList[ Index ], &Package, fDump );
|
|
}
|
|
}
|
|
|
|
FreeHeap( pPackageList );
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
ShowScavItem(
|
|
PVOID Base,
|
|
PLSAP_SCAVENGER_ITEM Item
|
|
)
|
|
{
|
|
ULONG_PTR Disp ;
|
|
UCHAR Symbol[ MAX_PATH ];
|
|
DWORD Handle ;
|
|
PVOID HandleTable ;
|
|
|
|
if ( (Item->ScavCheck != SCAVMAGIC_ACTIVE) &&
|
|
(Item->ScavCheck != SCAVMAGIC_FREE) )
|
|
{
|
|
DebuggerOut("Invalid scavenger item (check value not matched)\n");
|
|
return FALSE ;
|
|
}
|
|
|
|
DebuggerOut( "LSAP_SCAVENGER_ITEM at %#x\n", Base );
|
|
|
|
LsaGetSymbol((ULONG_PTR)Item->Function, Symbol, &Disp);
|
|
|
|
DebuggerOut( " Function \t%s\n", Symbol );
|
|
DebuggerOut( " Parameter \t%p\n", Item->Parameter );
|
|
|
|
DisplayFlags(Item->Flags, 32, ScavFlags, (PUCHAR) Symbol );
|
|
DebuggerOut( " Flags \t%x:%s\n", Item->Flags, Symbol );
|
|
DebuggerOut( " PackageId \t%d\n", Item->PackageId );
|
|
if ( Item->TimerHandle )
|
|
{
|
|
DebuggerOut( " TimerHandle \t%x\n", Item->TimerHandle );
|
|
}
|
|
|
|
switch ( Item->Type )
|
|
{
|
|
case NOTIFIER_TYPE_INTERVAL:
|
|
DebuggerOut( " Type \tInterval\n" );
|
|
break;
|
|
|
|
case NOTIFIER_TYPE_HANDLE_WAIT:
|
|
DebuggerOut( " Type \tHandle Wait\n");
|
|
break;
|
|
|
|
case NOTIFIER_TYPE_NOTIFY_EVENT:
|
|
DebuggerOut( " Type \tNotify Event\n" );
|
|
DebuggerOut( " Class \t%x\n", Item->Class );
|
|
break;
|
|
|
|
default:
|
|
DebuggerOut( " Type \tUNKNOWN\n" );
|
|
break;
|
|
|
|
}
|
|
|
|
return TRUE ;
|
|
}
|
|
|
|
void
|
|
DumpScavList( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
LSAP_SCAVENGER_ITEM Item ;
|
|
PVOID ListAddress ;
|
|
LIST_ENTRY List ;
|
|
PLIST_ENTRY Scan ;
|
|
UINT_PTR index = 0 ;
|
|
BOOL DumpAll = FALSE ;
|
|
DWORD max = 0 ;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
if ( _strnicmp( pszCommand, "notify", 6 ) == 0 )
|
|
{
|
|
ListAddress = GetExpr( NOTIFYLIST );
|
|
}
|
|
else
|
|
{
|
|
ListAddress = GetExpr( SCAVLIST );
|
|
}
|
|
|
|
LsaReadMemory( ListAddress, sizeof( LIST_ENTRY ), &List );
|
|
|
|
Scan = List.Flink ;
|
|
|
|
while ( Scan != ListAddress )
|
|
{
|
|
LsaReadMemory( Scan, sizeof( LSAP_SCAVENGER_ITEM ), &Item );
|
|
|
|
if ( !ShowScavItem( Scan, &Item ) )
|
|
{
|
|
break;
|
|
|
|
}
|
|
|
|
Scan = Item.List.Flink ;
|
|
|
|
if (pExtApis->lpCheckControlCRoutine())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
PrintSid( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
PVOID pvSid )
|
|
{
|
|
SID Sid;
|
|
PSID pSid;
|
|
|
|
if (LsaReadMemory(pvSid, sizeof(SID), &Sid))
|
|
{
|
|
DebuggerOut("Could not read from %p\n", pvSid);
|
|
}
|
|
|
|
pSid = AllocHeap(RtlLengthRequiredSid(Sid.SubAuthorityCount));
|
|
|
|
if (pSid == NULL)
|
|
{
|
|
DebuggerOut("Unable to allocate memory to print SID\n");
|
|
}
|
|
else
|
|
{
|
|
if (LsaReadMemory(pvSid, RtlLengthRequiredSid(Sid.SubAuthorityCount), pSid))
|
|
{
|
|
DebuggerOut("Could not read from %p\n", pvSid);
|
|
}
|
|
|
|
LocalDumpSid(pSid);
|
|
DebuggerOut("\n");
|
|
|
|
FreeHeap(pSid);
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpSid( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID pvSid;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
pvSid = GetExpr(pszCommand);
|
|
|
|
PrintSid(hProcess, hThread, lpExt, pvSid );
|
|
}
|
|
|
|
|
|
void
|
|
DumpToken( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
DWORD fDump = 0;
|
|
HANDLE hToken;
|
|
HANDLE hRemoteToken;
|
|
|
|
#define DUMP_HEX 1
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
while (*pszCommand == '-')
|
|
{
|
|
pszCommand++;
|
|
if (*pszCommand == 'x')
|
|
{
|
|
fDump |= DUMP_HEX;
|
|
}
|
|
if (*pszCommand == 'a')
|
|
{
|
|
fDump |= 0x80; // Dump SD
|
|
}
|
|
pszCommand++;
|
|
}
|
|
|
|
hRemoteToken = GetExpr(pszCommand);
|
|
|
|
if (DuplicateHandle(hProcess,
|
|
hRemoteToken,
|
|
GetCurrentProcess(),
|
|
&hToken,
|
|
0, FALSE,
|
|
DUPLICATE_SAME_ACCESS) )
|
|
{
|
|
PrintToken(hToken, lpExt);
|
|
|
|
CloseHandle(hToken);
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("Error %d duplicating token handle\n", GetLastError());
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpThreadToken( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
DWORD fDump = 0;
|
|
HANDLE hToken;
|
|
HANDLE hRemoteToken = NULL;
|
|
PVOID pad;
|
|
NTSTATUS Status;
|
|
|
|
#define DUMP_HEX 1
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
while (*pszCommand == '-')
|
|
{
|
|
pszCommand++;
|
|
if (*pszCommand == 'x')
|
|
{
|
|
fDump |= DUMP_HEX;
|
|
}
|
|
if (*pszCommand == 'a')
|
|
{
|
|
fDump |= 0x80; // Dump SD
|
|
}
|
|
pszCommand++;
|
|
}
|
|
|
|
Status = NtOpenThreadToken(hThread, TOKEN_QUERY, FALSE, &hRemoteToken);
|
|
|
|
if ((Status == STATUS_NO_TOKEN) || (hRemoteToken == NULL))
|
|
{
|
|
DebuggerOut("Thread is not impersonating. Using process token.\n");
|
|
|
|
Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hRemoteToken);
|
|
|
|
}
|
|
|
|
hToken = hRemoteToken;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
PrintToken(hToken, lpExt);
|
|
|
|
CloseHandle(hToken);
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("Error %#x getting thread token\n", Status);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SATYPE_USER 1
|
|
#define SATYPE_GROUP 2
|
|
#define SATYPE_PRIV 3
|
|
|
|
void
|
|
LocalDumpSid(PSID pxSid)
|
|
{
|
|
PISID pSid = (PISID) pxSid;
|
|
UNICODE_STRING ucsSid;
|
|
#if 0
|
|
if (fHex)
|
|
{
|
|
|
|
DebuggerOut(" S-%d-0x", pSid->Revision);
|
|
for (i = 0;i < 6 ; i++ )
|
|
{
|
|
if (j)
|
|
{
|
|
DebuggerOut("%x", pSid->IdentifierAuthority.Value[i]);
|
|
}
|
|
else
|
|
{
|
|
if (pSid->IdentifierAuthority.Value[i])
|
|
{
|
|
j = 1;
|
|
DebuggerOut("%x", pSid->IdentifierAuthority.Value[i]);
|
|
}
|
|
}
|
|
if (i==4)
|
|
{
|
|
j = 1;
|
|
}
|
|
}
|
|
for (i = 0; i < pSid->SubAuthorityCount ; i++ )
|
|
{
|
|
DebuggerOut("-0x%x", pSid->SubAuthority[i]);
|
|
}
|
|
}
|
|
else
|
|
#endif // 0
|
|
{
|
|
RtlConvertSidToUnicodeString(&ucsSid, pxSid, TRUE);
|
|
DebuggerOut(" %wZ", &ucsSid);
|
|
RtlFreeUnicodeString(&ucsSid);
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpSidAttr(PSID_AND_ATTRIBUTES pSA,
|
|
int SAType)
|
|
{
|
|
LocalDumpSid(pSA->Sid);
|
|
|
|
if (SAType == SATYPE_GROUP)
|
|
{
|
|
DebuggerOut("\tAttributes - ");
|
|
if (pSA->Attributes & SE_GROUP_MANDATORY)
|
|
{
|
|
DebuggerOut("Mandatory ");
|
|
}
|
|
if (pSA->Attributes & SE_GROUP_ENABLED_BY_DEFAULT)
|
|
{
|
|
DebuggerOut("Default ");
|
|
}
|
|
if (pSA->Attributes & SE_GROUP_ENABLED)
|
|
{
|
|
DebuggerOut("Enabled ");
|
|
}
|
|
if (pSA->Attributes & SE_GROUP_OWNER)
|
|
{
|
|
DebuggerOut("Owner ");
|
|
}
|
|
if (pSA->Attributes & SE_GROUP_LOGON_ID)
|
|
{
|
|
DebuggerOut("LogonId ");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
WCHAR * GetPrivName(PLUID pPriv)
|
|
{
|
|
switch (pPriv->LowPart)
|
|
{
|
|
case SE_CREATE_TOKEN_PRIVILEGE:
|
|
return(SE_CREATE_TOKEN_NAME);
|
|
case SE_ASSIGNPRIMARYTOKEN_PRIVILEGE:
|
|
return(SE_ASSIGNPRIMARYTOKEN_NAME);
|
|
case SE_LOCK_MEMORY_PRIVILEGE:
|
|
return(SE_LOCK_MEMORY_NAME);
|
|
case SE_INCREASE_QUOTA_PRIVILEGE:
|
|
return(SE_INCREASE_QUOTA_NAME);
|
|
case SE_UNSOLICITED_INPUT_PRIVILEGE:
|
|
return(SE_UNSOLICITED_INPUT_NAME);
|
|
case SE_TCB_PRIVILEGE:
|
|
return(SE_TCB_NAME);
|
|
case SE_SECURITY_PRIVILEGE:
|
|
return(SE_SECURITY_NAME);
|
|
case SE_TAKE_OWNERSHIP_PRIVILEGE:
|
|
return(SE_TAKE_OWNERSHIP_NAME);
|
|
case SE_LOAD_DRIVER_PRIVILEGE:
|
|
return(SE_LOAD_DRIVER_NAME);
|
|
case SE_SYSTEM_PROFILE_PRIVILEGE:
|
|
return(SE_SYSTEM_PROFILE_NAME);
|
|
case SE_SYSTEMTIME_PRIVILEGE:
|
|
return(SE_SYSTEMTIME_NAME);
|
|
case SE_PROF_SINGLE_PROCESS_PRIVILEGE:
|
|
return(SE_PROF_SINGLE_PROCESS_NAME);
|
|
case SE_INC_BASE_PRIORITY_PRIVILEGE:
|
|
return(SE_INC_BASE_PRIORITY_NAME);
|
|
case SE_CREATE_PAGEFILE_PRIVILEGE:
|
|
return(SE_CREATE_PAGEFILE_NAME);
|
|
case SE_CREATE_PERMANENT_PRIVILEGE:
|
|
return(SE_CREATE_PERMANENT_NAME);
|
|
case SE_BACKUP_PRIVILEGE:
|
|
return(SE_BACKUP_NAME);
|
|
case SE_RESTORE_PRIVILEGE:
|
|
return(SE_RESTORE_NAME);
|
|
case SE_SHUTDOWN_PRIVILEGE:
|
|
return(SE_SHUTDOWN_NAME);
|
|
case SE_DEBUG_PRIVILEGE:
|
|
return(SE_DEBUG_NAME);
|
|
case SE_AUDIT_PRIVILEGE:
|
|
return(SE_AUDIT_NAME);
|
|
case SE_SYSTEM_ENVIRONMENT_PRIVILEGE:
|
|
return(SE_SYSTEM_ENVIRONMENT_NAME);
|
|
case SE_CHANGE_NOTIFY_PRIVILEGE:
|
|
return(SE_CHANGE_NOTIFY_NAME);
|
|
case SE_REMOTE_SHUTDOWN_PRIVILEGE:
|
|
return(SE_REMOTE_SHUTDOWN_NAME);
|
|
case SE_UNDOCK_PRIVILEGE:
|
|
return(SE_UNDOCK_NAME);
|
|
case SE_SYNC_AGENT_PRIVILEGE:
|
|
return(SE_SYNC_AGENT_NAME);
|
|
case SE_ENABLE_DELEGATION_PRIVILEGE:
|
|
return(SE_ENABLE_DELEGATION_NAME);
|
|
default:
|
|
return(L"Unknown Privilege");
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpLuidAttr(PLUID_AND_ATTRIBUTES pLA,
|
|
int LAType)
|
|
{
|
|
|
|
DebuggerOut("0x%x%08x", pLA->Luid.HighPart, pLA->Luid.LowPart);
|
|
DebuggerOut(" %-32ws", GetPrivName(&pLA->Luid));
|
|
|
|
if (LAType == SATYPE_PRIV)
|
|
{
|
|
DebuggerOut(" Attributes - ");
|
|
if (pLA->Attributes & SE_PRIVILEGE_ENABLED)
|
|
{
|
|
DebuggerOut("Enabled ");
|
|
}
|
|
|
|
if (pLA->Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT)
|
|
{
|
|
DebuggerOut("Default ");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
PrintToken(HANDLE hToken,
|
|
PNTSD_EXTENSION_APIS lpExt)
|
|
{
|
|
PTOKEN_USER pTUser;
|
|
PTOKEN_GROUPS pTGroups;
|
|
PTOKEN_PRIVILEGES pTPrivs;
|
|
PTOKEN_PRIMARY_GROUP pTPrimaryGroup;
|
|
TOKEN_STATISTICS TStats;
|
|
ULONG cbRetInfo;
|
|
NTSTATUS status;
|
|
DWORD i;
|
|
DWORD dwSessionId;
|
|
|
|
pTUser = (PTOKEN_USER) alloca (256);
|
|
pTGroups = (PTOKEN_GROUPS) alloca (4096);
|
|
pTPrivs = (PTOKEN_PRIVILEGES) alloca (1024);
|
|
pTPrimaryGroup = (PTOKEN_PRIMARY_GROUP) alloca (128);
|
|
|
|
if ( pTUser == NULL ||
|
|
pTGroups == NULL ||
|
|
pTPrivs == NULL ||
|
|
pTPrimaryGroup == NULL ) {
|
|
|
|
DebuggerOut( "Failed to allocate memory\n" );
|
|
return;
|
|
}
|
|
|
|
status = NtQueryInformationToken( hToken,
|
|
TokenSessionId,
|
|
&dwSessionId,
|
|
sizeof(dwSessionId),
|
|
&cbRetInfo);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
DebuggerOut("Failed to query token: %#x\n", status);
|
|
return;
|
|
}
|
|
DebuggerOut("TS Session ID: %x\n", dwSessionId);
|
|
|
|
status = NtQueryInformationToken( hToken,
|
|
TokenUser,
|
|
pTUser,
|
|
256,
|
|
&cbRetInfo);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
DebuggerOut("Failed to query token: %#x\n", status);
|
|
return;
|
|
}
|
|
|
|
DebuggerOut("User\n ");
|
|
DumpSidAttr(&pTUser->User, SATYPE_USER);
|
|
|
|
DebuggerOut("\nGroups");
|
|
status = NtQueryInformationToken( hToken,
|
|
TokenGroups,
|
|
pTGroups,
|
|
4096,
|
|
&cbRetInfo);
|
|
|
|
for (i = 0; i < pTGroups->GroupCount ; i++ )
|
|
{
|
|
DebuggerOut("\n %02d ", i);
|
|
DumpSidAttr(&pTGroups->Groups[i], SATYPE_GROUP);
|
|
}
|
|
|
|
status = NtQueryInformationToken( hToken,
|
|
TokenPrimaryGroup,
|
|
pTPrimaryGroup,
|
|
128,
|
|
&cbRetInfo);
|
|
|
|
DebuggerOut("\nPrimary Group:\n ");
|
|
LocalDumpSid(pTPrimaryGroup->PrimaryGroup);
|
|
|
|
DebuggerOut("\nPrivs\n");
|
|
status = NtQueryInformationToken( hToken,
|
|
TokenPrivileges,
|
|
pTPrivs,
|
|
1024,
|
|
&cbRetInfo);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
printf("NtQueryInformationToken returned %#x\n", status);
|
|
return;
|
|
}
|
|
for (i = 0; i < pTPrivs->PrivilegeCount ; i++ )
|
|
{
|
|
DebuggerOut("\n %02d ", i);
|
|
DumpLuidAttr(&pTPrivs->Privileges[i], SATYPE_PRIV);
|
|
}
|
|
|
|
status = NtQueryInformationToken( hToken,
|
|
TokenStatistics,
|
|
&TStats,
|
|
sizeof(TStats),
|
|
&cbRetInfo);
|
|
|
|
DebuggerOut("\n\nAuth ID %x:%x\n", TStats.AuthenticationId.HighPart, TStats.AuthenticationId.LowPart);
|
|
DebuggerOut("Impersonation Level: %s\n", ImpLevel(TStats.ImpersonationLevel));
|
|
DebuggerOut("TokenType %s\n", TStats.TokenType == TokenPrimary ? "Primary" : "Impersonation");
|
|
}
|
|
|
|
VOID
|
|
ElapsedTimeToString(
|
|
PLARGE_INTEGER Time,
|
|
CHAR * String
|
|
)
|
|
{
|
|
TIME_FIELDS ElapsedTime ;
|
|
|
|
|
|
RtlTimeToElapsedTimeFields( Time, &ElapsedTime );
|
|
|
|
if ( ElapsedTime.Hour )
|
|
{
|
|
sprintf( String, "%d:%02d:%02d.%03d",
|
|
ElapsedTime.Hour,
|
|
ElapsedTime.Minute,
|
|
ElapsedTime.Second,
|
|
ElapsedTime.Milliseconds );
|
|
}
|
|
else if ( ElapsedTime.Minute )
|
|
{
|
|
sprintf( String, "%02d:%02d.%03d",
|
|
ElapsedTime.Minute,
|
|
ElapsedTime.Second,
|
|
ElapsedTime.Milliseconds );
|
|
}
|
|
else if ( ElapsedTime.Second )
|
|
{
|
|
sprintf( String, "%02.%03d",
|
|
ElapsedTime.Second,
|
|
ElapsedTime.Milliseconds );
|
|
}
|
|
else if ( ElapsedTime.Milliseconds )
|
|
{
|
|
sprintf( String, "0.%03d",
|
|
ElapsedTime.Milliseconds );
|
|
}
|
|
else
|
|
{
|
|
strcpy( String, "0" );
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
DumpLpc( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
|
|
PVOID pRemote;
|
|
DWORD i;
|
|
PLSAP_API_LOG pLog ;
|
|
LSAP_API_LOG LocalLog ;
|
|
ULONG Size ;
|
|
FILETIME LocalTime ;
|
|
PLSAP_API_LOG_ENTRY Entry ;
|
|
PVOID Table ;
|
|
CHAR timebuf[ 128 ];
|
|
CHAR timebuf2[ 64 ];
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
if ( _stricmp( pszCommand, "internal" ) == 0 )
|
|
{
|
|
pRemote = GetExpr( INTERNAL_APILOG );
|
|
}
|
|
else
|
|
{
|
|
pRemote = GetExpr( LPC_APILOG );
|
|
|
|
}
|
|
|
|
LsaReadMemory( pRemote, sizeof( PVOID ), &Table );
|
|
|
|
LsaReadMemory( Table, sizeof( LocalLog ), &LocalLog );
|
|
|
|
Size = (LocalLog.TotalSize - 1) * sizeof( LSAP_API_LOG_ENTRY ) +
|
|
sizeof( LSAP_API_LOG ) ;
|
|
|
|
pLog = (PLSAP_API_LOG) LocalAlloc( LMEM_FIXED, Size );
|
|
|
|
if ( !pLog )
|
|
{
|
|
DebuggerOut( "no memory\n" );
|
|
return;
|
|
}
|
|
|
|
LsaReadMemory( Table, Size, pLog );
|
|
|
|
|
|
DebuggerOut("MessageId\tStatus and Time\n");
|
|
for (i = 0; i < pLog->TotalSize ; i++ )
|
|
{
|
|
Entry = &pLog->Entries[ i ];
|
|
DebuggerOut("%08x%c\t", Entry->MessageId,
|
|
( i == pLog->Current ? '*' : ' ') );
|
|
|
|
if (Entry->ThreadId == 0)
|
|
{
|
|
CTimeStamp( (PTimeStamp) &Entry->QueueTime, timebuf, TRUE );
|
|
DebuggerOut("Queued, Message @%p, Task @%p (%s)\n",
|
|
Entry->pvMessage,
|
|
Entry->WorkItem,
|
|
timebuf );
|
|
|
|
}
|
|
else if (Entry->ThreadId == 0xFFFFFFFF)
|
|
{
|
|
// CTimeStamp( (PTimeStamp) &Entry->QueueTime, timebuf, TRUE );
|
|
timebuf[0] = '\0';
|
|
|
|
ElapsedTimeToString( &Entry->WorkTime, timebuf2 );
|
|
|
|
DebuggerOut("Completed, (%s, status %x), %s [%s]\n",
|
|
ApiLabel( (UINT_PTR) Entry->pvMessage ),
|
|
Entry->WorkItem,
|
|
timebuf,
|
|
timebuf2 );
|
|
}
|
|
else
|
|
{
|
|
CTimeStamp( (PTimeStamp) &Entry->WorkTime, timebuf, TRUE );
|
|
DebuggerOut("Active, thread %x, Message @%p, %s\n",
|
|
Entry->ThreadId,
|
|
Entry->pvMessage,
|
|
timebuf );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
ShowSecBuffer(
|
|
PSTR Banner,
|
|
PSecBuffer Buffer)
|
|
{
|
|
DWORD Mask;
|
|
|
|
Mask = Buffer->BufferType & SECBUFFER_ATTRMASK ;
|
|
|
|
DebuggerOut("%s\t", Banner);
|
|
DebuggerOut("%s%s%s %d bytes, %p\n",
|
|
Mask & SECBUFFER_READONLY ? "[RO]" : "",
|
|
Mask & SECBUFFER_UNMAPPED ? "[!Map]" : "",
|
|
SecBufferType( Buffer->BufferType ),
|
|
Buffer->cbBuffer,
|
|
Buffer->pvBuffer );
|
|
}
|
|
|
|
VOID
|
|
ShowLpcMessage(
|
|
PVOID pvMessage,
|
|
PSPM_LPC_MESSAGE pMessage)
|
|
{
|
|
SPMInitContextAPI * pInit;
|
|
SPMAcceptContextAPI * pAccept;
|
|
SPMDeleteContextAPI * pDelete ;
|
|
SPMFreeCredHandleAPI * pFreeCred ;
|
|
SPMAcquireCredsAPI * pAcquire;
|
|
SPMCallbackAPI * pCallback ;
|
|
SPMAddCredentialAPI * pAddCred ;
|
|
SPMQueryCredAttributesAPI * pQueryCred ;
|
|
SPMEfsGenerateKeyAPI * pGenKey ;
|
|
SPMEfsGenerateDirEfsAPI * pGenDir ;
|
|
SPMEfsDecryptFekAPI * pDecryptFek ;
|
|
SPMGetBindingAPI * pGetBinding ;
|
|
DWORD i;
|
|
UCHAR Flags[ 80 ];
|
|
|
|
DebuggerOut("SPM_LPC_MESSAGE at %p\n", pvMessage);
|
|
DebuggerOut(" Message id \t%x\n", pMessage->pmMessage.MessageId);
|
|
DebuggerOut(" From \t%x.%x\n", pMessage->pmMessage.ClientId.UniqueProcess,pMessage->pmMessage.ClientId.UniqueThread);
|
|
DebuggerOut(" API Number \t%d\n", pMessage->ApiMessage.dwAPI);
|
|
DebuggerOut(" Result \t%#x\n",pMessage->ApiMessage.scRet);
|
|
DebuggerOut(" LSA Args \t%p\n", (PUCHAR) pvMessage + (DWORD_PTR) ((PUCHAR) &pMessage->ApiMessage.Args) - ((PUCHAR) pMessage));
|
|
DebuggerOut(" SPM Args \t%p\n", (PUCHAR) pvMessage + (DWORD_PTR) ((PUCHAR) &pMessage->ApiMessage.Args.SpmArguments.API) - ((PUCHAR) pMessage));
|
|
DebuggerOut(" Data \t%p\n", (PUCHAR) pvMessage + (DWORD_PTR) (&pMessage->ApiMessage.bData[0]) - ((PUCHAR) pMessage));
|
|
if ( pMessage->ApiMessage.dwAPI > LsapAuMaxApiNumber)
|
|
{
|
|
Flags[0] = '\0';
|
|
|
|
DisplayFlags( pMessage->ApiMessage.Args.SpmArguments.fAPI,
|
|
12,
|
|
APIFlags,
|
|
Flags );
|
|
|
|
DebuggerOut(" Flags \t%x: %s\n",
|
|
pMessage->ApiMessage.Args.SpmArguments.fAPI,
|
|
Flags );
|
|
DebuggerOut(" Context \t%p\n",
|
|
pMessage->ApiMessage.Args.SpmArguments.ContextPointer );
|
|
}
|
|
|
|
switch (pMessage->ApiMessage.dwAPI)
|
|
{
|
|
case LsapAuLookupPackageApi:
|
|
DebuggerOut(" LsapAuLookupPackageApi\n");
|
|
DebuggerOut(" (o) Number \t%d\n",pMessage->ApiMessage.Args.LsaArguments.LookupPackage.AuthenticationPackage);
|
|
DebuggerOut(" (i) Length \t%d\n",pMessage->ApiMessage.Args.LsaArguments.LookupPackage.PackageNameLength);
|
|
DebuggerOut(" (i) Name \t%s\n",pMessage->ApiMessage.Args.LsaArguments.LookupPackage.PackageName);
|
|
break;
|
|
|
|
case LsapAuLogonUserApi:
|
|
DebuggerOut(" LsapAuLogonUserApi\n");
|
|
DebuggerOut(" (i) Origin \t{%d,%d,%p}\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.OriginName.Length,
|
|
pMessage->ApiMessage.Args.LsaArguments.LogonUser.OriginName.MaximumLength,
|
|
pMessage->ApiMessage.Args.LsaArguments.LogonUser.OriginName.Buffer);
|
|
DebuggerOut(" (i) LogonTyp\t%d\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.LogonType);
|
|
DebuggerOut(" (i) Package \t%d\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.AuthenticationPackage);
|
|
DebuggerOut(" (i) AuthInfo\t%p\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.AuthenticationInformation);
|
|
DebuggerOut(" (i) AuthInfo\t%d\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.AuthenticationInformationLength);
|
|
DebuggerOut(" (i) GroupCou\t%d\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.LocalGroupsCount);
|
|
DebuggerOut(" (i) Groups \t%p\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.LocalGroups);
|
|
DebuggerOut(" (i) Source \t%s\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.SourceContext.SourceName);
|
|
DebuggerOut(" (o) SubStat \t%x\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.SubStatus);
|
|
DebuggerOut(" (o) Profile \t%p\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.ProfileBuffer);
|
|
DebuggerOut(" (o) ProfLen \t%x\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.ProfileBufferLength);
|
|
DebuggerOut(" (o) LogonId \t%x:%x\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.LogonId.HighPart,pMessage->ApiMessage.Args.LsaArguments.LogonUser.LogonId.LowPart);
|
|
DebuggerOut(" (o) Token \t%x\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.Token);
|
|
DebuggerOut(" (o) Quota \t%x\n",pMessage->ApiMessage.Args.LsaArguments.LogonUser.Quotas.PagedPoolLimit);
|
|
break;
|
|
|
|
case LsapAuCallPackageApi:
|
|
DebuggerOut(" LsapCallPackageApi\n");
|
|
DebuggerOut(" (i) Package\t%d\n",pMessage->ApiMessage.Args.LsaArguments.CallPackage.AuthenticationPackage);
|
|
DebuggerOut(" (i) Buffer \t%d\n",pMessage->ApiMessage.Args.LsaArguments.CallPackage.ProtocolSubmitBuffer);
|
|
DebuggerOut(" (i) Length \t%d\n",pMessage->ApiMessage.Args.LsaArguments.CallPackage.SubmitBufferLength);
|
|
DebuggerOut(" (o) Status \t%d\n",pMessage->ApiMessage.Args.LsaArguments.CallPackage.ProtocolStatus);
|
|
DebuggerOut(" (o) RBuffer\t%d\n",pMessage->ApiMessage.Args.LsaArguments.CallPackage.ProtocolReturnBuffer);
|
|
DebuggerOut(" (o) Length \t%d\n",pMessage->ApiMessage.Args.LsaArguments.CallPackage.ReturnBufferLength);
|
|
break;
|
|
|
|
case LsapAuDeregisterLogonProcessApi:
|
|
DebuggerOut(" LsapAuDeregisterLogonProcessApi\n");
|
|
break;
|
|
|
|
case SPMAPI_GetBinding:
|
|
DebuggerOut(" GetBinding\n");
|
|
pGetBinding = &pMessage->ApiMessage.Args.SpmArguments.API.GetBinding ;
|
|
DebuggerOut(" (i) ulPackageId \t%p\n", pGetBinding->ulPackageId) ;
|
|
|
|
break;
|
|
|
|
case SPMAPI_InitContext:
|
|
DebuggerOut(" InitContext\n");
|
|
pInit = &pMessage->ApiMessage.Args.SpmArguments.API.InitContext;
|
|
DebuggerOut(" (i) hCredentials \t%p:%p\n", pInit->hCredential.dwUpper, pInit->hCredential.dwLower);
|
|
DebuggerOut(" (i) hContext \t%p:%p\n", pInit->hContext.dwUpper, pInit->hContext.dwLower);
|
|
DebuggerOut(" (i) ssTarget \t%p\n", pInit->ssTarget.Buffer);
|
|
DebuggerOut(" (i) fContextReq \t%x\n", pInit->fContextReq);
|
|
DebuggerOut(" (i) Reserved1 \t%x\n", pInit->dwReserved1);
|
|
DebuggerOut(" (i) TargetDataRep \t%x\n", pInit->TargetDataRep);
|
|
DebuggerOut(" (i) sbdInput \t%d : %p\n", pInit->sbdInput.cBuffers, pInit->sbdInput.pBuffers );
|
|
DebuggerOut(" (i) Reserved2 \t%x\n", pInit->dwReserved2);
|
|
DebuggerOut(" (o) hNewContext \t%p:%p\n", pInit->hNewContext.dwUpper, pInit->hNewContext.dwLower );
|
|
DebuggerOut(" (b) sbdOutput \t%d : %p\n", pInit->sbdOutput.cBuffers, pInit->sbdOutput.pBuffers );
|
|
DebuggerOut(" (o) fContextAttr \t%x\n", pInit->fContextAttr );
|
|
DebuggerOut(" (o) tsExpiry \t%s\n","");
|
|
DebuggerOut(" (o) MappedContext \t%x\n", pInit->MappedContext );
|
|
ShowSecBuffer(" (o) ContextData \t", &pInit->ContextData );
|
|
for ( i = 0 ; i < pInit->sbdInput.cBuffers ; i++ )
|
|
{
|
|
ShowSecBuffer(" (i) InputBuffer\t", &pInit->sbData[i]);
|
|
}
|
|
for ( i = 0; i < pInit->sbdOutput.cBuffers ; i++ )
|
|
{
|
|
ShowSecBuffer(" (b) OutputBuffer\t", &pInit->sbData[i + pInit->sbdInput.cBuffers]);
|
|
}
|
|
|
|
break;
|
|
|
|
case SPMAPI_AcceptContext:
|
|
DebuggerOut(" AcceptContext\n");
|
|
pAccept = &pMessage->ApiMessage.Args.SpmArguments.API.AcceptContext;
|
|
DebuggerOut(" (i) hCredentials \t%p : %p\n", pAccept->hCredential.dwUpper, pAccept->hCredential.dwLower );
|
|
DebuggerOut(" (i) hContext \t%p : %p\n", pAccept->hContext.dwUpper, pAccept->hContext.dwLower );
|
|
DebuggerOut(" (i) sbdInput \t%d : %p\n", pAccept->sbdInput.cBuffers, pAccept->sbdInput.pBuffers );
|
|
DebuggerOut(" (i) fContextReq \t%x\n", pAccept->fContextReq );
|
|
DebuggerOut(" (i) TargetDataRep \t%x\n", pAccept->TargetDataRep );
|
|
DebuggerOut(" (o) hNewContext \t%p : %p\n", pAccept->hNewContext.dwUpper, pAccept->hNewContext.dwLower );
|
|
DebuggerOut(" (b) sbdOutput \t%d : %p\n", pAccept->sbdOutput.cBuffers, pAccept->sbdOutput.pBuffers );
|
|
DebuggerOut(" (o) fContextAttr \t%x \n", pAccept->fContextAttr );
|
|
DebuggerOut(" (o) MappedContext \t%x\n", pAccept->MappedContext );
|
|
ShowSecBuffer(" (o) ContextData \t", &pAccept->ContextData );
|
|
for ( i = 0 ; i < pAccept->sbdInput.cBuffers ; i++ )
|
|
{
|
|
ShowSecBuffer(" (i) InputBuffer\t", &pAccept->sbData[i]);
|
|
}
|
|
for ( i = 0; i < pAccept->sbdOutput.cBuffers ; i++ )
|
|
{
|
|
ShowSecBuffer(" (b) OutputBuffer\t", &pAccept->sbData[i + pAccept->sbdInput.cBuffers]);
|
|
}
|
|
break;
|
|
|
|
case SPMAPI_FindPackage:
|
|
DebuggerOut(" FindPackage\n");
|
|
break;
|
|
|
|
case SPMAPI_EnumPackages:
|
|
DebuggerOut(" EnumPackages\n");
|
|
break;
|
|
|
|
case SPMAPI_AcquireCreds:
|
|
DebuggerOut(" AcquireCreds\n");
|
|
pAcquire = &pMessage->ApiMessage.Args.SpmArguments.API.AcquireCreds ;
|
|
DebuggerOut(" (i) fCredentialUse \t%x\n", pAcquire->fCredentialUse );
|
|
DebuggerOut(" (i) LogonId \t%x : %x\n", pAcquire->LogonID.LowPart, pAcquire->LogonID.HighPart );
|
|
DebuggerOut(" (i) pvAuthData \t%p\n", pAcquire->pvAuthData );
|
|
DebuggerOut(" (i) pvGetKeyFn \t%p\n", pAcquire->pvGetKeyFn );
|
|
DebuggerOut(" (i) ulGetKeyArgs \t%p\n", pAcquire->ulGetKeyArgument );
|
|
DebuggerOut(" (o) hCredentials \t%p : %p\n", pAcquire->hCredential.dwUpper, pAcquire->hCredential.dwLower );
|
|
break;
|
|
|
|
case SPMAPI_EstablishCreds:
|
|
DebuggerOut(" EstablishCreds\n");
|
|
break;
|
|
|
|
case SPMAPI_FreeCredHandle:
|
|
DebuggerOut(" FreeCredHandle\n");
|
|
pFreeCred = &pMessage->ApiMessage.Args.SpmArguments.API.FreeCredHandle ;
|
|
DebuggerOut(" (i) hCredential \t%p : %p\n", pFreeCred->hCredential.dwUpper, pFreeCred->hCredential.dwLower );
|
|
break;
|
|
|
|
case SPMAPI_ApplyToken:
|
|
DebuggerOut(" ApplyToken\n");
|
|
break;
|
|
|
|
case SPMAPI_DeleteContext:
|
|
DebuggerOut(" DeleteContext\n");
|
|
pDelete = &pMessage->ApiMessage.Args.SpmArguments.API.DeleteContext ;
|
|
DebuggerOut(" (i) hContext \t%p : %p\n", pDelete->hContext.dwUpper, pDelete->hContext.dwLower );
|
|
break;
|
|
|
|
case SPMAPI_QueryPackage:
|
|
DebuggerOut(" QueryPackage\n");
|
|
break;
|
|
|
|
case SPMAPI_GetUserInfo:
|
|
DebuggerOut(" GetUserInfo\n");
|
|
break;
|
|
|
|
case SPMAPI_GetCreds:
|
|
DebuggerOut(" GetCreds\n");
|
|
break;
|
|
|
|
case SPMAPI_SaveCreds:
|
|
DebuggerOut(" SaveCreds\n");
|
|
break;
|
|
|
|
case SPMAPI_DeleteCreds:
|
|
DebuggerOut(" DeleteCreds\n");
|
|
break;
|
|
|
|
case SPMAPI_QueryCredAttributes:
|
|
DebuggerOut(" QueryCredAttributes\n");
|
|
pQueryCred = &pMessage->ApiMessage.Args.SpmArguments.API.QueryCredAttributes ;
|
|
DebuggerOut(" (i) hCredentials \t%p : %p\n", pQueryCred->hCredentials.dwUpper, pQueryCred->hCredentials.dwLower );
|
|
DebuggerOut(" (i) ulAttribute \t%d\n", pQueryCred->ulAttribute );
|
|
DebuggerOut(" (i) pBuffer \t%p\n", pQueryCred->pBuffer );
|
|
DebuggerOut(" (o) Allocs \t%d\n", pQueryCred->Allocs );
|
|
for ( i = 0 ; i < pQueryCred->Allocs ; i++ )
|
|
{
|
|
DebuggerOut(" (o) Buffers[%d] \t %p\n", pQueryCred->Buffers[ i ] );
|
|
}
|
|
break;
|
|
|
|
case SPMAPI_AddPackage:
|
|
DebuggerOut(" AddPackage\n");
|
|
break;
|
|
|
|
case SPMAPI_DeletePackage:
|
|
DebuggerOut(" DeletePackage\n");
|
|
break;
|
|
|
|
case SPMAPI_EfsGenerateKey:
|
|
DebuggerOut(" EfsGenerateKey\n" );
|
|
pGenKey = &pMessage->ApiMessage.Args.SpmArguments.API.EfsGenerateKey ;
|
|
DebuggerOut(" (i) EfsStream \t%p\n", pGenKey->EfsStream );
|
|
DebuggerOut(" (i) DirectoryEfsStream\t%p\n", pGenKey->DirectoryEfsStream);
|
|
DebuggerOut(" (i) DirectoryStreamLen\t%#x\n", pGenKey->DirectoryEfsStreamLength );
|
|
DebuggerOut(" (i) Fek \t%p\n", pGenKey->Fek );
|
|
DebuggerOut(" (o) BufferLength \t%#x\n", pGenKey->BufferLength );
|
|
DebuggerOut(" (o) BufferBase \t%p\n", pGenKey->BufferBase );
|
|
break;
|
|
|
|
case SPMAPI_EfsGenerateDirEfs:
|
|
DebuggerOut(" EfsGenerateDirEfs\n" );
|
|
pGenDir = &pMessage->ApiMessage.Args.SpmArguments.API.EfsGenerateDirEfs ;
|
|
DebuggerOut(" (i) DirectoryEfsStream\t%p\n", pGenDir->DirectoryEfsStream);
|
|
DebuggerOut(" (i) DirectoryStreamLen\t%#x\n", pGenDir->DirectoryEfsStreamLength );
|
|
DebuggerOut(" (i) EfsStream \t%p\n", pGenDir->EfsStream );
|
|
DebuggerOut(" (o) BufferBase \t%p\n", pGenDir->BufferBase );
|
|
DebuggerOut(" (o) BufferLength \t%#x\n", pGenDir->BufferLength );
|
|
break;
|
|
|
|
case SPMAPI_EfsDecryptFek:
|
|
DebuggerOut(" EfsDecryptFek\n" );
|
|
pDecryptFek = &pMessage->ApiMessage.Args.SpmArguments.API.EfsDecryptFek ;
|
|
DebuggerOut(" (i) Fek \t%p\n", pDecryptFek->Fek );
|
|
DebuggerOut(" (i) EfsStream \t%p\n", pDecryptFek->EfsStream );
|
|
DebuggerOut(" (i) EfsStreamLength\t%p\n", pDecryptFek->EfsStreamLength );
|
|
DebuggerOut(" (i) OpenType \t%#x\n", pDecryptFek->OpenType );
|
|
DebuggerOut(" (?) NewEfs \t%p\n", pDecryptFek->NewEfs );
|
|
DebuggerOut(" (o) BufferBase \t%p\n", pDecryptFek->BufferBase );
|
|
DebuggerOut(" (o) BufferLength \t%#x\n", pDecryptFek->BufferLength );
|
|
break;
|
|
|
|
case SPMAPI_EfsGenerateSessionKey:
|
|
DebuggerOut(" EfsGenerateSessionKey\n" );
|
|
break;
|
|
|
|
case SPMAPI_Callback:
|
|
DebuggerOut(" Callback\n" );
|
|
pCallback = &pMessage->ApiMessage.Args.SpmArguments.API.Callback ;
|
|
DebuggerOut(" (i) Type \t%x\n", pCallback->Type );
|
|
DebuggerOut(" (i) CallbackFunction\t%p\n", pCallback->CallbackFunction );
|
|
DebuggerOut(" (i) Argument1 \t%p\n", pCallback->Argument1 );
|
|
DebuggerOut(" (i) Argument2 \t%p\n", pCallback->Argument2 );
|
|
ShowSecBuffer(" (i) Input \t", &pCallback->Input );
|
|
ShowSecBuffer(" (o) Output \t", &pCallback->Output );
|
|
|
|
break;
|
|
|
|
case SPMAPI_QueryContextAttr:
|
|
DebuggerOut(" QueryContextAttributes\n" );
|
|
break;
|
|
|
|
case SPMAPI_LsaPolicyChangeNotify:
|
|
DebuggerOut(" LsaPolicyChangeNotify\n" );
|
|
break;
|
|
|
|
case SPMAPI_GetUserNameX:
|
|
DebuggerOut(" GetUserName\n" );
|
|
break;
|
|
|
|
case SPMAPI_AddCredential:
|
|
DebuggerOut(" AddCredential\n" );
|
|
pAddCred = &pMessage->ApiMessage.Args.SpmArguments.API.AddCredential ;
|
|
DebuggerOut(" (i) hCredentials \t%p : %p\n",
|
|
pAddCred->hCredentials.dwUpper, pAddCred->hCredentials.dwLower );
|
|
DebuggerOut(" (i) fCredentialUse \t%x\n", pAddCred->fCredentialUse );
|
|
DebuggerOut(" (i) LogonId \t%x : %x\n", pAddCred->LogonID.LowPart, pAddCred->LogonID.HighPart );
|
|
DebuggerOut(" (i) pvAuthData \t%p\n", pAddCred->pvAuthData );
|
|
DebuggerOut(" (i) pvGetKeyFn \t%p\n", pAddCred->pvGetKeyFn );
|
|
DebuggerOut(" (i) ulGetKeyArgs \t%p\n", pAddCred->ulGetKeyArgument );
|
|
break;
|
|
|
|
case SPMAPI_EnumLogonSession:
|
|
DebuggerOut(" EnumLogonSession\n" );
|
|
break;
|
|
|
|
case SPMAPI_GetLogonSessionData:
|
|
DebuggerOut(" GetLogonSessionData\n" );
|
|
break;
|
|
|
|
case SPMAPI_SetContextAttr:
|
|
DebuggerOut(" SetContextAttr\n" );
|
|
break;
|
|
|
|
case SPMAPI_LookupAccountSidX:
|
|
DebuggerOut(" LookupAccountSid\n");
|
|
break;
|
|
|
|
case SPMAPI_LookupAccountNameX:
|
|
DebuggerOut(" LookupAccountName\n");
|
|
break;
|
|
|
|
default:
|
|
DebuggerOut("No message parsing for this message\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpLpcMessage( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
SPM_LPC_MESSAGE Message;
|
|
PVOID pvMessage;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
pvMessage = GetExpr(pszCommand);
|
|
|
|
if (!pvMessage)
|
|
{
|
|
DebuggerOut("no message\n");
|
|
return;
|
|
}
|
|
|
|
LsaReadMemory(pvMessage, sizeof(SPM_LPC_MESSAGE), &Message);
|
|
|
|
ShowLpcMessage( pvMessage, &Message );
|
|
|
|
}
|
|
|
|
|
|
void
|
|
DumpThreadLpc(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
SPM_LPC_MESSAGE Message;
|
|
PVOID pvMessage;
|
|
NTSTATUS Status;
|
|
LSA_CALL_INFO CallInfo ;
|
|
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
Status = ReadCallInfo( &CallInfo );
|
|
|
|
if (Status != 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( CallInfo.Message )
|
|
{
|
|
Status = LsaReadMemory(CallInfo.Message, sizeof(SPM_LPC_MESSAGE), &Message);
|
|
|
|
ShowLpcMessage(CallInfo.Message, &Message);
|
|
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("TLS entry was NULL!\n");
|
|
|
|
}
|
|
}
|
|
|
|
extern"C"
|
|
void
|
|
GetTls( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
TEB * Teb;
|
|
DWORD Index;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
Index = (DWORD)((ULONG_PTR)GetExpr(pszCommand));
|
|
|
|
Teb = GetTeb(hThread);
|
|
if (!Teb)
|
|
{
|
|
DebuggerOut("Could not read TEB\n");
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("TLS %#x is %p\n", Index, Teb->TlsSlots[Index]);
|
|
|
|
FreeHeap(Teb);
|
|
}
|
|
|
|
}
|
|
|
|
PVOID
|
|
ShowTask(
|
|
PVOID pTask)
|
|
{
|
|
LSAP_THREAD_TASK Task;
|
|
UCHAR Symbol[256];
|
|
ULONG_PTR Disp;
|
|
|
|
if (pTask)
|
|
{
|
|
LsaReadMemory(pTask, sizeof(LSAP_THREAD_TASK), &Task);
|
|
}
|
|
else
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
DebuggerOut("Task at %p:\n", pTask);
|
|
LsaGetSymbol((ULONG_PTR)Task.pFunction, Symbol, &Disp);
|
|
DebuggerOut(" Function \t%s\n", Symbol);
|
|
DebuggerOut(" Parameter \t%p\n", Task.pvParameter);
|
|
DebuggerOut(" Session \t%p\n", Task.pSession);
|
|
|
|
return(Task.Next.Flink);
|
|
}
|
|
|
|
void
|
|
DumpQueue( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
LSAP_TASK_QUEUE Queue;
|
|
PVOID pTask;
|
|
PVOID pQueue;
|
|
BOOL Single = FALSE;
|
|
UCHAR Symbol[ MAX_PATH ];
|
|
ULONG_PTR Offset;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
pQueue = GetExpr(pszCommand);
|
|
|
|
if (!pQueue)
|
|
{
|
|
pQueue = (PVOID) GetExpr(GLOBALQUEUE);
|
|
}
|
|
|
|
LsaReadMemory(pQueue, sizeof(Queue), &Queue);
|
|
|
|
DebuggerOut("Queue at %p\n", pQueue);
|
|
DebuggerOut(" Type \t%d : %s\n", Queue.Type, QueueTypeName( Queue.Type ) );
|
|
DebuggerOut(" Semaphore\t%d\n", Queue.hSemaphore);
|
|
DebuggerOut(" Tasks \t%d\n", Queue.Tasks);
|
|
DebuggerOut(" pTasks \t%p %p\n", Queue.pTasks.Flink,
|
|
Queue.pTasks.Blink);
|
|
DebuggerOut(" pNext \t%p\n", Queue.pNext);
|
|
DebuggerOut(" pShared \t%p\n", Queue.pShared);
|
|
DebuggerOut(" TotalThd \t%d\n", Queue.TotalThreads);
|
|
DebuggerOut(" IdleThd \t%d\n", Queue.IdleThreads);
|
|
if ( Queue.OwnerSession )
|
|
{
|
|
DebuggerOut(" Session \t%p\n", Queue.OwnerSession );
|
|
}
|
|
LsaGetSymbol((ULONG_PTR) Queue.pOriginal, Symbol, &Offset );
|
|
if ( Offset )
|
|
{
|
|
DebuggerOut(" Parent \t%p\n", Queue.pOriginal );
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut(" Parent \t%s\n", Symbol );
|
|
}
|
|
DebuggerOut(" Tasks Queued\t%d\n", Queue.QueuedCounter);
|
|
DebuggerOut(" Tasks Read\t%d\n", Queue.TaskCounter);
|
|
DebuggerOut(" Tasks Missed\t%d\n", Queue.MissedTasks );
|
|
DebuggerOut(" Tasks High Water\t%d\n", Queue.TaskHighWater );
|
|
DebuggerOut(" StartSync\t%x\n", Queue.StartSync );
|
|
DebuggerOut(" Req Thread\t%d\n", Queue.ReqThread );
|
|
DebuggerOut(" Max Threads\t%d\n", Queue.MaxThreads );
|
|
|
|
pTask = Queue.pTasks.Flink;
|
|
|
|
while ((pTask != NULL) && (pTask != (PLSAP_THREAD_TASK) Queue.pTasks.Blink))
|
|
{
|
|
pTask = ShowTask(pTask);
|
|
|
|
if (lpExt->lpCheckControlCRoutine())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
DumpThreadTask( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
LSAP_THREAD_TASK Task;
|
|
PVOID pTask;
|
|
BOOL Single = FALSE;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
pTask = GetExpr(pszCommand);
|
|
if (!pTask)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
Single = TRUE;
|
|
}
|
|
|
|
do
|
|
{
|
|
pTask = ShowTask( pTask );
|
|
|
|
if (lpExt->lpCheckControlCRoutine())
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while ( pTask && !Single );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
ShowNegCreds(
|
|
PNEG_CREDS pCreds,
|
|
PVOID pOriginalAddr)
|
|
{
|
|
DWORD i;
|
|
UCHAR Buffer[ MAX_PATH ];
|
|
|
|
DebuggerOut("NEG_CREDS at %p\n", pOriginalAddr );
|
|
|
|
DebuggerOut(" List \t%p %p\n", pCreds->List.Flink, pCreds->List.Blink );
|
|
DebuggerOut(" RefCount \t%d\n", pCreds->RefCount );
|
|
DebuggerOut(" Process \t%x\n", pCreds->ClientProcessId );
|
|
DebuggerOut(" LogonId \t%x %x\n",
|
|
pCreds->ClientLogonId.HighPart, pCreds->ClientLogonId.LowPart );
|
|
|
|
DisplayFlags( pCreds->Flags, 5, NegCredFlags, Buffer );
|
|
DebuggerOut(" Flags \t%x : %s\n", pCreds->Flags, Buffer );
|
|
if ( pCreds->Flags & NEGCRED_MULTI )
|
|
{
|
|
DebuggerOut(" AdditionalCreds\t%p %p\n",
|
|
pCreds->AdditionalCreds.Flink, pCreds->AdditionalCreds.Blink );
|
|
}
|
|
|
|
DebuggerOut(" Count \t%d\n", pCreds->Count );
|
|
for ( i = 0 ; i < pCreds->Count ; i++ )
|
|
{
|
|
DebuggerOut(" Creds[%2d] \tPackage %p, Handle %p : %p \n", i,
|
|
pCreds->Creds[i].Package, pCreds->Creds[i].Handle.dwUpper,
|
|
pCreds->Creds[i].Handle.dwLower );
|
|
}
|
|
}
|
|
|
|
PVOID
|
|
ReadAndDumpNegCred(
|
|
PVOID Address
|
|
)
|
|
{
|
|
#define CRED_SIZE (sizeof( NEG_CREDS ) + 16 * sizeof( NEG_CRED_HANDLE ) )
|
|
|
|
UCHAR Buffer[ CRED_SIZE ];
|
|
PNEG_CREDS pCreds ;
|
|
DWORD Size;
|
|
|
|
|
|
|
|
LsaReadMemory( Address, sizeof( NEG_CREDS ), Buffer );
|
|
|
|
pCreds = (PNEG_CREDS) Buffer ;
|
|
|
|
Size = sizeof( NEG_CREDS ) + (pCreds->Count - 1) * sizeof( NEG_CRED_HANDLE );
|
|
|
|
|
|
if ( Size <= CRED_SIZE )
|
|
{
|
|
LsaReadMemory( Address, Size, Buffer );
|
|
}
|
|
else
|
|
{
|
|
LsaReadMemory( Address, CRED_SIZE, Buffer );
|
|
pCreds->Count = 16;
|
|
}
|
|
|
|
ShowNegCreds( pCreds, Address );
|
|
|
|
return pCreds->List.Flink ;
|
|
|
|
}
|
|
|
|
VOID
|
|
DumpNegCred(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID Base ;
|
|
PVOID Next ;
|
|
PVOID p ;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
p = GetExpr(pszCommand);
|
|
|
|
if ( p != 0 )
|
|
{
|
|
ReadAndDumpNegCred( p );
|
|
}
|
|
else
|
|
{
|
|
p = GetExpr( "lsasrv!NegCredList" );
|
|
|
|
LsaReadMemory( p, sizeof(PVOID), &Next );
|
|
|
|
while ( Next != p )
|
|
{
|
|
Next = ReadAndDumpNegCred( Next );
|
|
|
|
if (lpExt->lpCheckControlCRoutine())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
ShowNegContext(
|
|
PNEG_CONTEXT Context,
|
|
PVOID pOriginalAddr)
|
|
{
|
|
UCHAR TimeBuf[ MAX_PATH ];
|
|
|
|
if ( ( Context->CheckMark != NEGCONTEXT_CHECK ) &&
|
|
( Context->CheckMark != NEGCONTEXT2_CHECK ) )
|
|
{
|
|
DebuggerOut("****** Invalid Context Record *******\n");
|
|
return;
|
|
}
|
|
|
|
DebuggerOut("NEG_CONTEXT at %p\n", pOriginalAddr);
|
|
DebuggerOut(" Creds \t%#x\n", Context->Creds );
|
|
DebuggerOut(" CredIndex \t%d\n", Context->CredIndex );
|
|
DebuggerOut(" Handle \t%p : %p\n", Context->Handle.dwUpper, Context->Handle.dwLower );
|
|
DebuggerOut(" Target at \t%p \n", Context->Target.Buffer );
|
|
DebuggerOut(" Attributes \t%x\n", Context->Attributes );
|
|
ShowSecBuffer(" MappedBuffer ",&Context->MappedBuffer );
|
|
DebuggerOut(" Mapped \t%s\n", Context->Mapped ? "TRUE" : "FALSE");
|
|
DebuggerOut(" CallCount \t%d\n", Context->CallCount );
|
|
DebuggerOut(" LastStatus \t%x\n", Context->LastStatus );
|
|
DebuggerOut(" Check \t%p\n", Context->Check );
|
|
DebuggerOut(" Buffer \t%p\n", Context->Buffer );
|
|
CTimeStamp( &Context->Expiry, (PCHAR)TimeBuf, FALSE );
|
|
DebuggerOut(" Expiry \t%s\n", TimeBuf );
|
|
DisplayFlags( Context->Flags, 7, NegContextFlags, TimeBuf );
|
|
DebuggerOut(" Flags \t%x : %s\n", Context->Flags, TimeBuf );
|
|
DebuggerOut(" Message \t%p\n", Context->Message );
|
|
DebuggerOut(" CurrentSize \t%#x\n", Context->CurrentSize );
|
|
DebuggerOut(" TotalSize \t%#x\n", Context->TotalSize );
|
|
DebuggerOut(" SupportedMechs\t%p\n", Context->SupportedMechs );
|
|
}
|
|
|
|
VOID
|
|
DumpNegContext(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
|
|
NEG_CONTEXT Context ;
|
|
PVOID p;
|
|
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
p = GetExpr(pszCommand);
|
|
|
|
LsaReadMemory( p, sizeof( NEG_CONTEXT ), &Context );
|
|
|
|
ShowNegContext( &Context, p );
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpSecBuffer(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
SecBuffer Buf;
|
|
PVOID p;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
p = GetExpr(pszCommand);
|
|
|
|
LsaReadMemory( p, sizeof(SecBuffer), &Buf );
|
|
|
|
ShowSecBuffer("Buffer\t", &Buf );
|
|
|
|
}
|
|
|
|
VOID
|
|
DumpSecBufferDesc(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
SecBuffer Buf[16];
|
|
SecBufferDesc Desc;
|
|
PVOID p;
|
|
ULONG i;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
p = GetExpr(pszCommand);
|
|
|
|
LsaReadMemory( p, sizeof(SecBufferDesc), &Desc );
|
|
|
|
LsaReadMemory( Desc.pBuffers, sizeof(SecBuffer) * min(Desc.cBuffers, 16), Buf);
|
|
|
|
DebuggerOut("SecBufferDesc at %p\n", p);
|
|
DebuggerOut(" ulVersion \t%d\n", Desc.ulVersion );
|
|
DebuggerOut(" pBuffers \t%p\n", Desc.pBuffers );
|
|
DebuggerOut(" cBuffers \t%x\n", Desc.cBuffers );
|
|
for (i = 0 ; i < min(Desc.cBuffers, 16) ; i++ )
|
|
{
|
|
ShowSecBuffer(" Buffer\t", &Buf[i] );
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
DumpHandleList(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
SEC_HANDLE_ENTRY List ;
|
|
PVOID p;
|
|
ULONG i;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
p = GetExpr(pszCommand);
|
|
|
|
List.List.Flink = (PLIST_ENTRY) p;
|
|
|
|
do
|
|
{
|
|
LsaReadMemory( List.List.Flink, sizeof( List ), &List );
|
|
DebuggerOut(" Handle %p : %p, Ref = %d, Context = %p \n",
|
|
List.Handle.dwLower,
|
|
List.Handle.dwUpper,
|
|
List.RefCount,
|
|
List.Context );
|
|
|
|
if (lpExt->lpCheckControlCRoutine())
|
|
{
|
|
break;
|
|
}
|
|
} while ( List.List.Flink != p );
|
|
}
|
|
|
|
VOID
|
|
ShowSmallTable(
|
|
PSMALL_HANDLE_TABLE Table,
|
|
LONG Indent
|
|
)
|
|
{
|
|
UCHAR Buffer[ 64 ];
|
|
UCHAR IndentString[ 80 ];
|
|
ULONG_PTR i;
|
|
|
|
for ( i = 0 ; i < ( DWORD )Indent; i++)
|
|
{
|
|
IndentString[ i ] = ' ';
|
|
}
|
|
IndentString[ Indent ] = '\0' ;
|
|
|
|
DisplayFlags( Table->Flags, 3, ShtFlags, Buffer );
|
|
DebuggerOut("%s Flags \t%x: %s\n", IndentString, Table->Flags, Buffer );
|
|
DebuggerOut("%s Count \t%d\n", IndentString, Table->Count );
|
|
DebuggerOut("%s Pending\t%p\n", IndentString, Table->PendingHandle );
|
|
DebuggerOut("%s ListHead\t%p\n", IndentString, Table->List.Flink );
|
|
|
|
if ( Table->DeleteCallback )
|
|
{
|
|
LsaGetSymbol((ULONG_PTR) Table->DeleteCallback, Buffer, &i );
|
|
DebuggerOut( "%s Callback\t%s\n", IndentString, Buffer );
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
ShowLargeTable(
|
|
int indent,
|
|
PLARGE_HANDLE_TABLE Table
|
|
)
|
|
{
|
|
LARGE_HANDLE_TABLE SubTable ;
|
|
UCHAR Buffer[ 64 ];
|
|
UCHAR Indent[ 64 ];
|
|
ULONG_PTR i;
|
|
|
|
for (i = 0 ; i < ( ULONG )indent ; i++ )
|
|
{
|
|
Indent[i] = ' ';
|
|
}
|
|
Indent[indent] = '\0';
|
|
|
|
DisplayFlags( Table->Flags, 3, LhtFlags, Buffer );
|
|
DebuggerOut("%s Flags \t%x: %s\n", Indent, Table->Flags, Buffer );
|
|
DebuggerOut("%s Depth \t%d\n", Indent, Table->Depth );
|
|
DebuggerOut("%s Parent \t%p\n", Indent, Table->Parent );
|
|
DebuggerOut("%s Count \t%d\n", Indent, Table->Count );
|
|
if ( Table->DeleteCallback )
|
|
{
|
|
LsaGetSymbol((ULONG_PTR) Table->DeleteCallback, Buffer, &i );
|
|
DebuggerOut("%s Callback \t%s\n", Indent, Buffer );
|
|
}
|
|
DebuggerOut("%s Lists\n", Indent );
|
|
for ( i = 0 ; i < HANDLE_TABLE_SIZE ; i++ )
|
|
{
|
|
if ( Table->Lists[i].Flags & LHT_SUB_TABLE )
|
|
{
|
|
if ( Table->Lists[i].Flags & (~LHT_SUB_TABLE))
|
|
{
|
|
DebuggerOut("%s CORRUPT\n", Indent);
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("%s %x : Sub Table at %p\n", Indent, i, Table->Lists[i].List.Flink );
|
|
LsaReadMemory( Table->Lists[i].List.Flink,
|
|
sizeof( LARGE_HANDLE_TABLE),
|
|
&SubTable );
|
|
|
|
ShowLargeTable( 4+indent, &SubTable );
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("%s List %x\n", Indent, i );
|
|
ShowSmallTable( &Table->Lists[i], 4+indent );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpHandleTable(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
DWORD Tag;
|
|
LARGE_HANDLE_TABLE Large ;
|
|
SMALL_HANDLE_TABLE Small ;
|
|
PVOID Table ;
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
Table = GetExpr( pszCommand );
|
|
|
|
if ( Table == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
LsaReadMemory( Table, sizeof(DWORD), &Tag );
|
|
|
|
if ( Tag == LHT_TAG )
|
|
{
|
|
DebuggerOut("LARGE_HANDLE_TABLE at %p\n", Table );
|
|
|
|
LsaReadMemory( Table, sizeof( Large ), &Large );
|
|
|
|
ShowLargeTable( 0, &Large );
|
|
|
|
}
|
|
else if ( Tag == SHT_TAG )
|
|
{
|
|
DebuggerOut("SMALL_HANDLE_TABLE at %p\n", Table );
|
|
|
|
LsaReadMemory( Table, sizeof( Small ), &Small );
|
|
|
|
ShowSmallTable( &Small, 0 );
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("%p - not a handle table\n", Table );
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ShowLogonSession(
|
|
PVOID Base,
|
|
PLSAP_LOGON_SESSION LogonSession,
|
|
BOOL Verbose
|
|
)
|
|
{
|
|
SECURITY_STRING LocalString = { 0 };
|
|
PWSTR Temp ;
|
|
SECURITY_STRING LocalCopy = { 0 };
|
|
CHAR Buffer[ 80 ];
|
|
|
|
DebuggerOut( "LSAP_LOGON_SESSION at %p\n", Base );
|
|
|
|
MapString( &LogonSession->AuthorityName, &LocalString );
|
|
|
|
Temp = LocalString.Buffer ;
|
|
LocalString.Buffer = NULL ;
|
|
|
|
MapString( &LogonSession->AccountName, &LocalString );
|
|
|
|
DebuggerOut( " LogonId %x:%x (%s) %ws \\ %ws \n",
|
|
LogonSession->LogonId.HighPart,
|
|
LogonSession->LogonId.LowPart,
|
|
LogonTypeName( LogonSession->LogonType),
|
|
Temp, LocalString.Buffer );
|
|
|
|
FreeHeap( Temp );
|
|
FreeHeap( LocalString.Buffer );
|
|
|
|
if ( Verbose )
|
|
{
|
|
DebuggerOut( " Package %d, caller <%x>, attr = %x\n",
|
|
LogonSession->CreatingPackage,
|
|
LogonSession->Process,
|
|
LogonSession->ContextAttr );
|
|
|
|
DebuggerOut( " SID\t" );
|
|
LocalDumpSid( LogonSession->UserSid );
|
|
CTimeStamp( &LogonSession->LogonTime, Buffer, TRUE );
|
|
DebuggerOut( " Logon Time\t%s\n", Buffer );
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
DumpLogonSession(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID p, p1;
|
|
PVOID Actual ;
|
|
PSTR Colon ;
|
|
LSAP_LOGON_SESSION LogonSession ;
|
|
LUID Luid ;
|
|
BOOLEAN DumpAll;
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
Colon = strchr( pszCommand, ':' );
|
|
|
|
if ( Colon )
|
|
{
|
|
if (2 != sscanf( pszCommand, "%x:%x", &Luid.HighPart, &Luid.LowPart ))
|
|
{
|
|
DebuggerOut( "Invalid argument: '%s'\n", pszCommand );
|
|
}
|
|
|
|
DumpAll = TRUE ;
|
|
p = NULL ;
|
|
}
|
|
else
|
|
{
|
|
Luid.HighPart = Luid.LowPart = 0 ;
|
|
p = GetExpr( pszCommand );
|
|
DumpAll = FALSE ;
|
|
}
|
|
|
|
if ( p == NULL )
|
|
{
|
|
p1 = GetExpr( "lsasrv!logonsessionlist" );
|
|
LsaReadMemory( p1, sizeof( PVOID ), &p );
|
|
DumpAll = TRUE ;
|
|
}
|
|
else
|
|
{
|
|
p1 = NULL ;
|
|
}
|
|
|
|
if ( p == NULL )
|
|
{
|
|
DebuggerOut( "Unable to get value of lsasrv!logonsessionlist\n" );
|
|
return;
|
|
}
|
|
|
|
while ( p != p1 )
|
|
{
|
|
if ( DumpAll )
|
|
{
|
|
Actual = CONTAINING_RECORD( p, LSAP_LOGON_SESSION, List );
|
|
}
|
|
else
|
|
{
|
|
Actual = p ;
|
|
}
|
|
|
|
LsaReadMemory( Actual, sizeof( LSAP_LOGON_SESSION ), &LogonSession );
|
|
|
|
if ( RtlIsZeroLuid( &Luid) ||
|
|
RtlEqualLuid( &Luid, &LogonSession.LogonId) ||
|
|
(!DumpAll) )
|
|
{
|
|
ShowLogonSession( Actual, &LogonSession, (!DumpAll) );
|
|
|
|
}
|
|
p = LogonSession.List.Flink ;
|
|
|
|
if ( (!DumpAll) || ( p1 == NULL ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
void
|
|
ShowLsaHandle(
|
|
IN LSAP_DB_HANDLE DbHandle,
|
|
IN BOOLEAN Index
|
|
)
|
|
{
|
|
SECURITY_STRING LocalString;
|
|
#ifdef DBG
|
|
LARGE_INTEGER LocalTime;
|
|
TIME_FIELDS TimeFields;
|
|
NTSTATUS Status;
|
|
#endif
|
|
|
|
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "Next \t0x%lp\n", DbHandle->Next );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "Previous \t0x%lp\n", DbHandle->Previous );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "UserHandleList Flink \t0x%lp\n", DbHandle->UserHandleList.Flink );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "UserHandleList Blink \t0x%lp\n", DbHandle->UserHandleList.Blink );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "Allocated \t%s\n", DbHandle->Allocated ? "TRUE" : "FALSE" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "ReferenceCount\t%lu\n", DbHandle->ReferenceCount );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
|
|
LocalString.Buffer = NULL;
|
|
MapString( ( PSECURITY_STRING )( &DbHandle->LogicalNameU ),
|
|
&LocalString );
|
|
DebuggerOut( "LogicalNameU \t%ws\n", LocalString.Buffer );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
FreeHeap( LocalString.Buffer );
|
|
|
|
LocalString.Buffer = NULL;
|
|
MapString( ( PSECURITY_STRING )( &DbHandle->PhysicalNameU ),
|
|
&LocalString );
|
|
DebuggerOut( "PhysicalNameU \t%ws\n", LocalString.Buffer );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
FreeHeap( LocalString.Buffer );
|
|
|
|
if ( DbHandle->Sid ) {
|
|
|
|
DebuggerOut( "Sid \t" );
|
|
LocalDumpSid( DbHandle->Sid );
|
|
DebuggerOut( "\n" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "Sid \t%s\n", "<NULL>" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
}
|
|
|
|
DebuggerOut( "KeyHandle \t0x%lx\n", DbHandle->KeyHandle );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "ObjectTypeId \t0x%lu\n", DbHandle->ObjectTypeId );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "ContainerHandle\t0x%lp\n", DbHandle->ContainerHandle );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "DesiredAccess \t0x%08lx\n", DbHandle->DesiredAccess );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "GrantedAccess \t0x%08lx\n", DbHandle->GrantedAccess );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "RequestAccess \t0x%08lx\n", DbHandle->RequestedAccess );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "GenerateOnClose\t%s\n",DbHandle->GenerateOnClose ? "TRUE" : "FALSE" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "Trusted \t%s\n", DbHandle->Trusted ? "TRUE" : "FALSE" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "DeletedObject \t%s\n", DbHandle->DeletedObject ? "TRUE" : "FALSE" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "NetworkClient \t%s\n",DbHandle->NetworkClient ? "TRUE" : "FALSE" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "Options \t0x%08lx\n", DbHandle->Options);
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
|
|
if ( DbHandle->PhysicalNameDs.Length == 0 ) {
|
|
|
|
DebuggerOut( "PhysicalNameDs\t%s\n", "<NULL>" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
|
|
} else {
|
|
|
|
LocalString.Buffer = NULL;
|
|
MapString( ( PSECURITY_STRING )( &DbHandle->PhysicalNameDs ),
|
|
&LocalString );
|
|
|
|
DebuggerOut( "PhysicalNameDs\t%ws\n", LocalString.Buffer );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
FreeHeap( LocalString.Buffer );
|
|
}
|
|
|
|
DebuggerOut( "fWriteDs \t%s\n", DbHandle->fWriteDs ? "TRUE" : "FALSE" );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "ObjectOptions \t0x%08lx\n", DbHandle->ObjectOptions );
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "UserEntry \t0x%lp\n", DbHandle->UserEntry );
|
|
#ifdef DBG
|
|
|
|
Status = RtlSystemTimeToLocalTime( &DbHandle->HandleCreateTime, &LocalTime );
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
|
|
DebuggerOut( "Can't convert create time from GMT to Local time: 0x%lx\n", Status );
|
|
|
|
} else {
|
|
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "HandleCreateTime \t%ld/%ld/%ld %ld:%2.2ld:%2.2ld (%8.8lx %8.8lx)\n",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second,
|
|
DbHandle->HandleCreateTime.LowPart,
|
|
DbHandle->HandleCreateTime.HighPart );
|
|
}
|
|
|
|
Status = RtlSystemTimeToLocalTime( &DbHandle->HandleLastAccessTime, &LocalTime );
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
|
|
DebuggerOut( "Can't convert LastAccess time from GMT to Local time: 0x%lx\n", Status );
|
|
|
|
} else {
|
|
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
DebuggerOut( "%c", Index ? '\t' : '\0' );
|
|
DebuggerOut( "HandleLastAccessTime \t%ld/%ld/%ld %ld:%2.2ld:%2.2ld (%8.8lx %8.8lx)\n",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second,
|
|
DbHandle->HandleLastAccessTime.LowPart,
|
|
DbHandle->HandleLastAccessTime.HighPart );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
VOID
|
|
DumpLsaHandle(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
_LSAP_DB_HANDLE DbHandle;
|
|
PVOID Handle;
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
Handle = GetExpr( pszCommand );
|
|
|
|
if ( Handle == NULL ) {
|
|
|
|
return;
|
|
}
|
|
|
|
LsaReadMemory( Handle,
|
|
sizeof( _LSAP_DB_HANDLE ),
|
|
&DbHandle );
|
|
|
|
ShowLsaHandle( &DbHandle, FALSE );
|
|
}
|
|
|
|
|
|
void
|
|
ShowLsaHandleTable(
|
|
IN LSAP_DB_HANDLE HandleTable
|
|
)
|
|
{
|
|
_LSAP_DB_HANDLE ThisHandle, *Stop;
|
|
ULONG i = 0;
|
|
|
|
LsaReadMemory( HandleTable->Next,
|
|
sizeof( _LSAP_DB_HANDLE ),
|
|
&ThisHandle );
|
|
Stop = ThisHandle.Previous;
|
|
|
|
while ( ThisHandle.Next != Stop ) {
|
|
|
|
DebuggerOut( "LsaHandleTable entry %lu\n", i++ );
|
|
ShowLsaHandle( &ThisHandle, TRUE );
|
|
|
|
LsaReadMemory( ThisHandle.Next,
|
|
sizeof( _LSAP_DB_HANDLE ),
|
|
&ThisHandle );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DumpLsaHandleTable(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
_LSAP_DB_HANDLE HandleTable;
|
|
PVOID Table;
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
Table = GetExpr( pszCommand );
|
|
|
|
if ( Table == NULL ) {
|
|
|
|
return;
|
|
}
|
|
|
|
LsaReadMemory( Table,
|
|
sizeof( _LSAP_DB_HANDLE ),
|
|
&HandleTable );
|
|
|
|
ShowLsaHandleTable( &HandleTable );
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpLsaSidCache(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
|
|
PVOID RawAddress;
|
|
PVOID pEntry;
|
|
LSAP_DB_SID_CACHE_ENTRY Entry;
|
|
NTSTATUS Status;
|
|
|
|
LARGE_INTEGER LocalTime;
|
|
TIME_FIELDS TimeFields;
|
|
|
|
UNICODE_STRING Dummy;
|
|
WCHAR NameBuffer[256];
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
pEntry = GetExpr( pszCommand );
|
|
|
|
if ( pEntry == NULL ) {
|
|
//
|
|
// Find the address of the sid cache
|
|
//
|
|
RawAddress = (VOID *) GetExpr("lsasrv!LsapSidCache");
|
|
|
|
if ( NULL == RawAddress ) {
|
|
|
|
DebuggerOut( "Can't locate the variable lsasrv!SidCache\nPlease get correct symbols or update this debugger extension\n" );
|
|
|
|
return;
|
|
}
|
|
|
|
pEntry = RawAddress;
|
|
|
|
(VOID) LsaReadMemory( RawAddress, sizeof(pEntry), (PVOID) &pEntry );
|
|
|
|
if ( NULL == pEntry ) {
|
|
|
|
DebuggerOut( "Sid cache is empty!\n" );
|
|
|
|
return;
|
|
|
|
}
|
|
} else {
|
|
|
|
RtlZeroMemory( &Entry, sizeof( Entry ) );
|
|
(VOID) LsaReadMemory( pEntry, sizeof(Entry), (PVOID) &Entry );
|
|
pEntry = Entry.Next;
|
|
|
|
}
|
|
|
|
//
|
|
// The first is the head and as such is empty
|
|
//
|
|
DebuggerOut( "Head of list located at address 0x%p\n", pEntry );
|
|
|
|
if ( !pEntry ) {
|
|
DebuggerOut( "Sid cache is empty!\n" );
|
|
|
|
return;
|
|
}
|
|
|
|
while ( pEntry ) {
|
|
|
|
//
|
|
// Read the entry
|
|
//
|
|
RtlZeroMemory( &Entry, sizeof( Entry ) );
|
|
(VOID) LsaReadMemory( pEntry, sizeof(Entry), (PVOID) &Entry );
|
|
|
|
//
|
|
// Print the entry
|
|
//
|
|
DebuggerOut( "New entry located at address 0x%p, next entry 0x%p\n", pEntry, Entry.Next );
|
|
|
|
if ( Entry.AccountName.Buffer ) {
|
|
|
|
RtlZeroMemory( NameBuffer, sizeof(NameBuffer) );
|
|
(VOID) LsaReadMemory( Entry.AccountName.Buffer,
|
|
Entry.AccountName.MaximumLength,
|
|
(PVOID) NameBuffer );
|
|
|
|
RtlInitUnicodeString( &Dummy, NameBuffer );
|
|
|
|
DebuggerOut( "Account Name: %wZ\n", &Dummy );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "No Account Name\n" );
|
|
}
|
|
|
|
if ( Entry.Sid ) {
|
|
|
|
DebuggerOut( "Account Sid: " );
|
|
|
|
PrintSid( hProcess,
|
|
hThread,
|
|
lpExt,
|
|
Entry.Sid );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "No Account Sid\n" );
|
|
|
|
}
|
|
|
|
if ( Entry.DomainName.Buffer ) {
|
|
|
|
RtlZeroMemory( NameBuffer, sizeof(NameBuffer) );
|
|
(VOID) LsaReadMemory( Entry.DomainName.Buffer,
|
|
Entry.DomainName.MaximumLength,
|
|
(PVOID) NameBuffer );
|
|
|
|
RtlInitUnicodeString( &Dummy, NameBuffer );
|
|
|
|
DebuggerOut( "Domain Name: %wZ\n", &Dummy );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "No Domain Name\n" );
|
|
}
|
|
|
|
if ( Entry.DomainSid ) {
|
|
|
|
DebuggerOut( "Domain Sid: " );
|
|
|
|
PrintSid( hProcess,
|
|
hThread,
|
|
lpExt,
|
|
Entry.DomainSid );
|
|
|
|
}
|
|
|
|
DebuggerOut( "Sid Type: %s\n", SidNameUseXLate( Entry.SidType ) );
|
|
|
|
Status = RtlSystemTimeToLocalTime( &Entry.CreateTime, &LocalTime );
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
|
|
DebuggerOut( "Can't convert create time from GMT to Local time: 0x%lx\n", Status );
|
|
|
|
} else {
|
|
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
DebuggerOut( "Create Time %ld/%ld/%ld %ld:%2.2ld:%2.2ld (%8.8lx %8.8lx)\n",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second,
|
|
Entry.CreateTime.LowPart,
|
|
Entry.CreateTime.HighPart );
|
|
}
|
|
|
|
Status = RtlSystemTimeToLocalTime( &Entry.RefreshTime, &LocalTime );
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
|
|
DebuggerOut( "Can't convert Last Use time from GMT to Local time: 0x%lx\n", Status );
|
|
|
|
} else {
|
|
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
DebuggerOut( "Refresh Time %ld/%ld/%ld %ld:%2.2ld:%2.2ld (%8.8lx %8.8lx)\n",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second,
|
|
Entry.LastUse.LowPart,
|
|
Entry.LastUse.HighPart );
|
|
}
|
|
|
|
Status = RtlSystemTimeToLocalTime( &Entry.ExpirationTime, &LocalTime );
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
|
|
DebuggerOut( "Can't convert expiration time from GMT to Local time: 0x%lx\n", Status );
|
|
|
|
} else {
|
|
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
DebuggerOut( "Expiration Time %ld/%ld/%ld %ld:%2.2ld:%2.2ld (%8.8lx %8.8lx)\n",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second,
|
|
Entry.ExpirationTime.LowPart,
|
|
Entry.ExpirationTime.HighPart );
|
|
}
|
|
|
|
Status = RtlSystemTimeToLocalTime( &Entry.LastUse, &LocalTime );
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
|
|
DebuggerOut( "Can't convert Last Use time from GMT to Local time: 0x%lx\n", Status );
|
|
|
|
} else {
|
|
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
DebuggerOut( "Last Used %ld/%ld/%ld %ld:%2.2ld:%2.2ld (%8.8lx %8.8lx)\n",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second,
|
|
Entry.LastUse.LowPart,
|
|
Entry.LastUse.HighPart );
|
|
}
|
|
|
|
DebuggerOut( "Flags: %d\n", Entry.Flags );
|
|
|
|
DebuggerOut( "\n" );
|
|
|
|
//
|
|
// Get the next entry
|
|
//
|
|
pEntry = Entry.Next;
|
|
|
|
} // while
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
void
|
|
DumpLsaHandleTypeList(
|
|
IN PLIST_ENTRY ListEntry
|
|
)
|
|
{
|
|
PLIST_ENTRY Next, Read;
|
|
_LSAP_DB_HANDLE Handle, *HandlePtr;
|
|
ULONG i = 0;
|
|
|
|
Next = ListEntry->Flink;
|
|
|
|
while ( Next != ListEntry ) {
|
|
|
|
HandlePtr = CONTAINING_RECORD( Next,
|
|
struct _LSAP_DB_HANDLE,
|
|
Next );
|
|
|
|
LsaReadMemory( HandlePtr,
|
|
sizeof( _LSAP_DB_HANDLE ),
|
|
&Handle );
|
|
DebuggerOut( "Handle entry %lu\n", i++);
|
|
ShowLsaHandle( &Handle, TRUE );
|
|
|
|
Next = HandlePtr->UserHandleList.Flink;
|
|
}
|
|
|
|
|
|
}
|
|
void
|
|
ShowLsaHandleTableEx(
|
|
IN PLSAP_DB_HANDLE_TABLE HandleTable
|
|
)
|
|
{
|
|
PLIST_ENTRY HandleEntry;
|
|
PLSAP_DB_HANDLE_TABLE_USER_ENTRY CurrentUserEntry = NULL;
|
|
LSAP_DB_HANDLE_TABLE_USER_ENTRY ThisUserEntry;
|
|
ULONG i = 0;
|
|
|
|
HandleEntry = HandleTable->UserHandleList.Flink;
|
|
for ( i = 0; i < HandleTable->UserCount; i++ ) {
|
|
|
|
CurrentUserEntry = CONTAINING_RECORD( HandleEntry,
|
|
LSAP_DB_HANDLE_TABLE_USER_ENTRY,
|
|
Next );
|
|
|
|
LsaReadMemory( CurrentUserEntry,
|
|
sizeof( LSAP_DB_HANDLE_TABLE_USER_ENTRY ),
|
|
&ThisUserEntry );
|
|
|
|
DebuggerOut( "HandleTable Entry #%lu\n", i );
|
|
DebuggerOut( "User id %x:%x\n",
|
|
ThisUserEntry.LogonId.HighPart,
|
|
ThisUserEntry.LogonId.LowPart);
|
|
|
|
#if DBG
|
|
DebuggerOut( "UserToken 0x%lx\n", ThisUserEntry.UserToken );
|
|
#endif
|
|
DebuggerOut( "Policy Handle List:\n" );
|
|
DumpLsaHandleTypeList( &ThisUserEntry.PolicyHandles );
|
|
|
|
DebuggerOut( "Object Handle List:\n" );
|
|
DumpLsaHandleTypeList( &ThisUserEntry.ObjectHandles );
|
|
|
|
HandleEntry = &ThisUserEntry.Next;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpLsaHandleTableEx(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
LSAP_DB_HANDLE_TABLE HandleTableEx;
|
|
PVOID Table;
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
Table = GetExpr( pszCommand );
|
|
|
|
if ( Table == NULL ) {
|
|
|
|
return;
|
|
}
|
|
|
|
LsaReadMemory( Table,
|
|
sizeof( LSAP_DB_HANDLE_TABLE ),
|
|
&HandleTableEx );
|
|
|
|
ShowLsaHandleTableEx( &HandleTableEx );
|
|
}
|
|
|
|
|
|
VOID
|
|
ShowTopLevelNameEntry(
|
|
IN FTCache::TLN_ENTRY * EntryAddr,
|
|
IN FTCache::TLN_ENTRY * EntryData
|
|
)
|
|
{
|
|
FTCache::TDO_ENTRY TdoEntry;
|
|
FTCache::TLN_KEY TlnKey;
|
|
SECURITY_STRING sLocal;
|
|
|
|
DebuggerOut( "TopLevelNameEntry: %p\n", EntryAddr );
|
|
DebuggerOut( "TdoListEntry: %p %p\n", EntryData->TdoListEntry.Flink, EntryData->TdoListEntry.Blink );
|
|
DebuggerOut( "AvlListEntry: %p %p\n", EntryData->AvlListEntry.Flink, EntryData->TdoListEntry.Blink );
|
|
DebuggerOut( "Excluded: %s\n", ( EntryData->Excluded ? "Yes" : "No" ));
|
|
DebuggerOut( "Flags: %d\n", EntryData->m_Flags );
|
|
|
|
if ( EntryData->Excluded ) {
|
|
|
|
FTCache::TLN_ENTRY TlnEntry;
|
|
|
|
LsaReadMemory(
|
|
EntryData->SuperiorEntry,
|
|
sizeof( FTCache::TLN_ENTRY ),
|
|
&TlnEntry
|
|
);
|
|
|
|
LsaReadMemory(
|
|
TlnEntry.TlnKey,
|
|
sizeof( FTCache::TLN_KEY ),
|
|
&TlnKey
|
|
);
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &TlnKey.TopLevelName, &sLocal );
|
|
DebuggerOut( "SuperiorEntry: %p (%ws)\n", EntryData->SuperiorEntry, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
} else if ( EntryData->SubordinateEntry ) {
|
|
|
|
FTCache::TLN_ENTRY TlnEntry;
|
|
|
|
LsaReadMemory(
|
|
EntryData->SubordinateEntry,
|
|
sizeof( FTCache::TLN_ENTRY ),
|
|
&TlnEntry
|
|
);
|
|
|
|
LsaReadMemory(
|
|
TlnEntry.TlnKey,
|
|
sizeof( FTCache::TLN_KEY ),
|
|
&TlnKey
|
|
);
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &TlnKey.TopLevelName, &sLocal );
|
|
DebuggerOut( "SubordinateEntry: %p (%ws)\n", EntryData->SubordinateEntry, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "SubordinateEntry: NULL\n" );
|
|
}
|
|
|
|
LsaReadMemory(
|
|
EntryData->TdoEntry,
|
|
sizeof( FTCache::TDO_ENTRY ),
|
|
&TdoEntry
|
|
);
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &TdoEntry.TrustedDomainName, &sLocal );
|
|
DebuggerOut( "TdoEntry: %p (%ws)\n", EntryData->TdoEntry, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
LsaReadMemory(
|
|
EntryData->TlnKey,
|
|
sizeof( FTCache::TLN_KEY ),
|
|
&TlnKey
|
|
);
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &TlnKey.TopLevelName, &sLocal );
|
|
DebuggerOut( "TlnKey: %p (%ws)\n", EntryData->TlnKey, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
DebuggerOut( "\n" );
|
|
}
|
|
|
|
VOID
|
|
ShowDomainInfoEntry(
|
|
IN FTCache::DOMAIN_INFO_ENTRY * EntryAddr,
|
|
IN FTCache::DOMAIN_INFO_ENTRY * EntryData
|
|
)
|
|
{
|
|
FTCache::TDO_ENTRY TdoEntry;
|
|
FTCache::TLN_ENTRY SubordinateTo;
|
|
FTCache::TLN_KEY TlnKey;
|
|
FTCache::DNS_NAME_KEY DnsKey;
|
|
FTCache::NETBIOS_NAME_KEY NetbiosKey;
|
|
SECURITY_STRING sLocal;
|
|
|
|
DebuggerOut( "DomainInfoEntry: %p\n", EntryAddr );
|
|
DebuggerOut( "TdoListEntry: %p %p", EntryData->TdoListEntry.Flink, EntryData->TdoListEntry.Blink );
|
|
DebuggerOut( "SidAvlListEntry: %p\n", EntryData->SidAvlListEntry.Flink, EntryData->SidAvlListEntry.Blink );
|
|
DebuggerOut( "DnsAvlListEntry: %p\n", EntryData->DnsAvlListEntry.Flink, EntryData->DnsAvlListEntry.Blink );
|
|
DebuggerOut( "NetbiosAvlListEntry: %p\n", EntryData->NetbiosAvlListEntry.Flink, EntryData->NetbiosAvlListEntry.Blink );
|
|
DebuggerOut( "Flags: %d\n", EntryData->m_Flags );
|
|
DebuggerOut( "Time: %x-%x\n", EntryData->Time.HighPart, EntryData->Time.LowPart );
|
|
DebuggerOut( "Sid: " );
|
|
LocalDumpSid( EntryData->Sid );
|
|
DebuggerOut( "\n" );
|
|
|
|
LsaReadMemory(
|
|
EntryData->TdoEntry,
|
|
sizeof( FTCache::TDO_ENTRY ),
|
|
&TdoEntry
|
|
);
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &TdoEntry.TrustedDomainName, &sLocal );
|
|
DebuggerOut( "TdoEntry: %p (%ws)\n", EntryData->TdoEntry, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
LsaReadMemory(
|
|
EntryData->SubordinateTo,
|
|
sizeof( FTCache::TLN_ENTRY ),
|
|
&SubordinateTo
|
|
);
|
|
|
|
LsaReadMemory(
|
|
SubordinateTo.TlnKey,
|
|
sizeof( FTCache::TLN_KEY ),
|
|
&TlnKey
|
|
);
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &TlnKey.TopLevelName, &sLocal );
|
|
DebuggerOut( "SubordinateTo: %p (%ws)\n", EntryData->SubordinateTo, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
DebuggerOut( "SidKey: %p\n", EntryData->SidKey );
|
|
|
|
LsaReadMemory(
|
|
EntryData->SidKey,
|
|
sizeof( FTCache::DNS_NAME_KEY ),
|
|
&DnsKey
|
|
);
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &DnsKey.DnsName, &sLocal );
|
|
DebuggerOut( "DnsKey: %p (%ws)\n", EntryData->DnsKey, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
if ( EntryData->NetbiosKey ) {
|
|
|
|
LsaReadMemory(
|
|
EntryData->NetbiosKey,
|
|
sizeof( FTCache::NETBIOS_NAME_KEY ),
|
|
&NetbiosKey
|
|
);
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &NetbiosKey.NetbiosName, &sLocal );
|
|
DebuggerOut( "NetbiosKey: %p (%ws)\n", EntryData->NetbiosKey, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "NetbiosKey: NULL\n" );
|
|
}
|
|
|
|
DebuggerOut( "\n" );
|
|
}
|
|
|
|
VOID
|
|
ShowFtcTdoEntry(
|
|
IN PVOID TdoEntryAddr,
|
|
IN FTCache::TDO_ENTRY * TdoEntryData
|
|
)
|
|
{
|
|
ULONG Displayed;
|
|
PUCHAR ListEnd;
|
|
SECURITY_STRING sLocal;
|
|
|
|
DebuggerOut( "<------------------->\n" );
|
|
|
|
sLocal.Buffer = NULL;
|
|
MapString( &TdoEntryData->TrustedDomainName, &sLocal );
|
|
DebuggerOut( "TrustedDomainName: %ws\n", &TdoEntryData->TrustedDomainName, sLocal.Buffer );
|
|
FreeHeap( sLocal.Buffer );
|
|
|
|
DebuggerOut( "Record count: %lu\n\n", TdoEntryData->RecordCount );
|
|
|
|
DebuggerOut( "\n===> Top Level Name Entries <===\n\n" );
|
|
Displayed = 0;
|
|
|
|
ListEnd = ( PUCHAR )TdoEntryAddr + FIELD_OFFSET( FTCache::TDO_ENTRY, TlnList );
|
|
if ( TdoEntryData->TlnList.Flink == ( PLIST_ENTRY )ListEnd ) {
|
|
|
|
DebuggerOut( "<none>\n" );
|
|
|
|
} else {
|
|
|
|
FTCache::TLN_ENTRY TlnEntryData;
|
|
FTCache::TLN_ENTRY * TlnEntryAddr;
|
|
|
|
TlnEntryAddr = FTCache::TLN_ENTRY::EntryFromTdoEntry( TdoEntryData->TlnList.Flink );
|
|
|
|
do {
|
|
|
|
LsaReadMemory(
|
|
TlnEntryAddr,
|
|
sizeof( FTCache::TLN_ENTRY ),
|
|
&TlnEntryData
|
|
);
|
|
|
|
Displayed += 1;
|
|
DebuggerOut( "Entry #%lu\n", Displayed );
|
|
ShowTopLevelNameEntry( TlnEntryAddr, &TlnEntryData );
|
|
|
|
TlnEntryAddr = FTCache::TLN_ENTRY::EntryFromTdoEntry( TlnEntryData.TdoListEntry.Flink );
|
|
|
|
} while ( TlnEntryAddr != FTCache::TLN_ENTRY::EntryFromTdoEntry(( PLIST_ENTRY )ListEnd ));
|
|
}
|
|
|
|
DebuggerOut( "\n===> Domain Info Entries <===\n\n" );
|
|
Displayed = 0;
|
|
|
|
ListEnd = ( PUCHAR )TdoEntryAddr + FIELD_OFFSET( FTCache::TDO_ENTRY, DomainInfoList );
|
|
if ( TdoEntryData->DomainInfoList.Flink == ( PLIST_ENTRY )ListEnd ) {
|
|
|
|
DebuggerOut( "<none>\n" );
|
|
|
|
} else {
|
|
|
|
FTCache::DOMAIN_INFO_ENTRY DomainInfoData;
|
|
FTCache::DOMAIN_INFO_ENTRY * DomainInfoAddr;
|
|
|
|
DomainInfoAddr = FTCache::DOMAIN_INFO_ENTRY::EntryFromTdoEntry( TdoEntryData->DomainInfoList.Flink );
|
|
|
|
do {
|
|
|
|
LsaReadMemory(
|
|
DomainInfoAddr,
|
|
sizeof( FTCache::DOMAIN_INFO_ENTRY ),
|
|
&DomainInfoData
|
|
);
|
|
|
|
Displayed += 1;
|
|
DebuggerOut( "Entry #%lu\n", Displayed );
|
|
ShowDomainInfoEntry( DomainInfoAddr, &DomainInfoData );
|
|
|
|
DomainInfoAddr = FTCache::DOMAIN_INFO_ENTRY::EntryFromTdoEntry( DomainInfoData.TdoListEntry.Flink );
|
|
|
|
} while ( DomainInfoAddr != FTCache::DOMAIN_INFO_ENTRY::EntryFromTdoEntry(( PLIST_ENTRY )ListEnd ));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
ShowForestTrustCache(
|
|
IN FTCache * Ftc
|
|
)
|
|
{
|
|
DebuggerOut( "Forest Trust Cache si %s\n",
|
|
( Ftc->m_Initialized ? "valid" : "invalid" ));
|
|
|
|
DebuggerOut( "Forest Trust Cache is %s\n",
|
|
( Ftc->m_Valid ? "valid" : "invalid" ));
|
|
|
|
if ( !Ftc->m_Initialized || !Ftc->m_Valid ) {
|
|
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpFtcTdoEntry(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID TdoEntryAddr;
|
|
FTCache::TDO_ENTRY TdoEntryData;
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
TdoEntryAddr = GetExpr( pszCommand );
|
|
|
|
if ( TdoEntryAddr == NULL ) {
|
|
|
|
return;
|
|
}
|
|
|
|
LsaReadMemory( TdoEntryAddr,
|
|
sizeof( FTCache::TDO_ENTRY ),
|
|
&TdoEntryData );
|
|
|
|
ShowFtcTdoEntry( TdoEntryAddr, &TdoEntryData );
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpForestTrustCache(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
BYTE Ftc[sizeof(FTCache)];
|
|
PVOID Cache;
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
Cache = GetExpr( pszCommand );
|
|
|
|
if ( Cache == NULL ) {
|
|
|
|
return;
|
|
}
|
|
|
|
LsaReadMemory( Cache,
|
|
sizeof( FTCache ),
|
|
&Ftc );
|
|
|
|
ShowForestTrustCache( ( FTCache * )Ftc );
|
|
}
|
|
|
|
|
|
VOID
|
|
LocalPrintGuid(
|
|
GUID *Guid
|
|
)
|
|
{
|
|
if ( Guid ) {
|
|
|
|
DebuggerOut( "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
Guid->Data1, Guid->Data2, Guid->Data3, Guid->Data4[0],
|
|
Guid->Data4[1], Guid->Data4[2], Guid->Data4[3], Guid->Data4[4],
|
|
Guid->Data4[5], Guid->Data4[6], Guid->Data4[7] );
|
|
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ReadAndDumpSid(
|
|
IN PVOID SidPtr
|
|
)
|
|
{
|
|
UNICODE_STRING StringSid;
|
|
SID Sid;
|
|
PSID ReadSid;
|
|
|
|
LsaReadMemory( SidPtr, sizeof( SID ), &Sid );
|
|
|
|
ReadSid = AllocHeap( RtlLengthRequiredSid( Sid.SubAuthorityCount ) );
|
|
|
|
if ( ReadSid ) {
|
|
|
|
LsaReadMemory( SidPtr, RtlLengthRequiredSid( Sid.SubAuthorityCount ), ReadSid );
|
|
RtlConvertSidToUnicodeString( &StringSid, ReadSid, TRUE );
|
|
DebuggerOut( "%wZ", &StringSid );
|
|
RtlFreeUnicodeString( &StringSid );
|
|
FreeHeap( ReadSid );
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
ShowAcl(
|
|
IN PVOID AclPtr
|
|
)
|
|
{
|
|
ULONG i, SkipSize;
|
|
PVOID AcePtr;
|
|
ACE_HEADER Ace;
|
|
KNOWN_ACE KnownAce;
|
|
KNOWN_OBJECT_ACE KnownObjectAce;
|
|
PSID SidStart = NULL, ReadSid;
|
|
SID Sid;
|
|
UNICODE_STRING StringSid;
|
|
GUID *DisplayGuid;
|
|
ACL ReadAcl;
|
|
PACL Acl = &ReadAcl;
|
|
|
|
LsaReadMemory( AclPtr, sizeof( ACL ), &ReadAcl );
|
|
|
|
DebuggerOut( "AclRevision %lu\n", ReadAcl.AclRevision );
|
|
DebuggerOut( "Sbz1 %lu\n", ReadAcl.Sbz1 );
|
|
DebuggerOut( "AclSize %lu\n", ReadAcl.AclSize );
|
|
DebuggerOut( "AceCount %lu\n", ReadAcl.AceCount );
|
|
DebuggerOut( "Sbz2 %lu\n", ReadAcl.Sbz2 );
|
|
|
|
AcePtr = ( PUCHAR )AclPtr + sizeof( ACL );
|
|
for ( i = 0; i < ReadAcl.AceCount; i++ ) {
|
|
|
|
//
|
|
// First, we need to read the Size/Type of the ace
|
|
//
|
|
LsaReadMemory( AcePtr, sizeof( ACE_HEADER ), &Ace );
|
|
|
|
DebuggerOut( "Ace[ %lu ]\n", i );
|
|
DebuggerOut( "\tAceType %lu\n", Ace.AceType );
|
|
DebuggerOut( "\tAceFlags %lu\n", Ace.AceFlags );
|
|
DebuggerOut( "\tAceSize %lu\n", Ace.AceSize );
|
|
|
|
switch ( Ace.AceType ) {
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
case SYSTEM_ALARM_ACE_TYPE:
|
|
LsaReadMemory( AcePtr, sizeof( KNOWN_ACE ), &KnownAce );
|
|
DebuggerOut( "\tAccessMask 0x%lx\n", KnownAce.Mask );
|
|
SidStart = ( PSID )( ( PUCHAR )AcePtr + sizeof( KNOWN_ACE ) - sizeof( ULONG ) );
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
|
|
SkipSize = sizeof( KNOWN_OBJECT_ACE );
|
|
LsaReadMemory( AcePtr, sizeof( KNOWN_OBJECT_ACE ) + 2 * sizeof( GUID ), &KnownObjectAce );
|
|
DebuggerOut( "\tAccessMask 0x%lx\n", KnownObjectAce.Mask );
|
|
DisplayGuid = RtlObjectAceObjectType( &KnownObjectAce );
|
|
if ( DisplayGuid ) {
|
|
|
|
DebuggerOut( "\tObjectGuid ");
|
|
LocalPrintGuid( DisplayGuid );
|
|
DebuggerOut( "\n");
|
|
SkipSize += sizeof( GUID );
|
|
}
|
|
|
|
DisplayGuid = RtlObjectAceInheritedObjectType( &KnownObjectAce );
|
|
if ( DisplayGuid ) {
|
|
|
|
DebuggerOut( "\tObjectGuid ");
|
|
LocalPrintGuid( DisplayGuid );
|
|
DebuggerOut( "\n");
|
|
SkipSize += sizeof( GUID );
|
|
}
|
|
|
|
SidStart = ( PSID )( ( PUCHAR )AcePtr + SkipSize - sizeof( ULONG ) );
|
|
break;
|
|
|
|
|
|
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
|
|
default:
|
|
DebuggerOut( "Unsupported AceType %lu encountered... skipping\n", Ace.AceType );
|
|
break;
|
|
}
|
|
|
|
|
|
AcePtr = ( PUCHAR )AcePtr + Ace.AceSize;
|
|
|
|
LsaReadMemory( SidStart, sizeof( SID ), &Sid );
|
|
|
|
ReadSid = AllocHeap( RtlLengthRequiredSid( Sid.SubAuthorityCount ) );
|
|
|
|
if ( ReadSid ) {
|
|
|
|
LsaReadMemory( SidStart, RtlLengthRequiredSid( Sid.SubAuthorityCount ), ReadSid );
|
|
RtlConvertSidToUnicodeString( &StringSid, ReadSid, TRUE );
|
|
DebuggerOut( "\t%wZ\n", &StringSid );
|
|
RtlFreeUnicodeString( &StringSid );
|
|
FreeHeap( ReadSid );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
DumpAcl(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
ACL Acl;
|
|
PVOID AclPtr;
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
AclPtr = GetExpr( pszCommand );
|
|
|
|
if ( AclPtr == NULL ) {
|
|
|
|
return;
|
|
}
|
|
|
|
ShowAcl( AclPtr );
|
|
}
|
|
|
|
VOID
|
|
ShowSD(
|
|
IN PVOID SDPtr
|
|
)
|
|
{
|
|
SECURITY_DESCRIPTOR SD;
|
|
PSID Owner = NULL, Group = NULL;
|
|
PACL Dacl = NULL, Sacl = NULL;
|
|
|
|
LsaReadMemory( SDPtr, sizeof( SECURITY_DESCRIPTOR ), &SD );
|
|
|
|
DebuggerOut( "Revision %lu\n", SD.Revision );
|
|
DebuggerOut( "Sbz1 %lu\n", SD.Sbz1 );
|
|
DebuggerOut( "Control 0x%lx\n", SD.Control );
|
|
|
|
if ( ( SD.Control & SE_SELF_RELATIVE ) == SE_SELF_RELATIVE ) {
|
|
|
|
if ( SD.Owner != 0 ) {
|
|
|
|
Owner = ( PSID )( ( PUCHAR )SDPtr + ( ULONG_PTR )SD.Owner );
|
|
}
|
|
|
|
if ( SD.Group != 0 ) {
|
|
|
|
Group = ( PSID )( ( PUCHAR )SDPtr + ( ULONG_PTR )SD.Group );
|
|
}
|
|
|
|
if ( SD.Dacl != 0 ) {
|
|
|
|
Dacl = ( PACL )( ( PUCHAR )SDPtr + ( ULONG_PTR )SD.Dacl );
|
|
}
|
|
|
|
if ( SD.Sacl != 0 ) {
|
|
|
|
Sacl = ( PACL )( ( PUCHAR )SDPtr + ( ULONG_PTR )SD.Sacl );
|
|
}
|
|
|
|
} else {
|
|
|
|
Owner = SD.Owner;
|
|
Group = SD.Group;
|
|
Dacl = SD.Dacl;
|
|
Sacl = SD.Sacl;
|
|
}
|
|
|
|
DebuggerOut( "Owner: ");
|
|
if ( Owner ) {
|
|
|
|
ReadAndDumpSid( Owner );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "<NULL>" );
|
|
}
|
|
DebuggerOut( "\n" );
|
|
|
|
DebuggerOut( "Group: ");
|
|
if ( Group ) {
|
|
|
|
ReadAndDumpSid( Group );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "<NULL>" );
|
|
}
|
|
DebuggerOut( "\n" );
|
|
|
|
DebuggerOut( "DACL:\n");
|
|
if ( Dacl ) {
|
|
|
|
ShowAcl( Dacl );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "<NULL>" );
|
|
}
|
|
|
|
DebuggerOut( "SACL:\n");
|
|
if ( Sacl ) {
|
|
|
|
ShowAcl( Sacl );
|
|
|
|
} else {
|
|
|
|
DebuggerOut( "<NULL>" );
|
|
}
|
|
DebuggerOut( "\n" );
|
|
|
|
}
|
|
|
|
VOID
|
|
DumpSD(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
PVOID SDPtr;
|
|
|
|
InitDebugHelp( hProcess,
|
|
hThread,
|
|
lpExt);
|
|
|
|
SDPtr = GetExpr( pszCommand );
|
|
|
|
if ( SDPtr == NULL ) {
|
|
|
|
return;
|
|
}
|
|
|
|
ShowSD( SDPtr );
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
setevent(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
HANDLE h ;
|
|
HANDLE hThere ;
|
|
|
|
InitDebugHelp( hProcess, hThread, lpExt );
|
|
|
|
hThere = GetExpr( pszCommand );
|
|
|
|
if ( DuplicateHandle( hProcess,
|
|
hThere,
|
|
GetCurrentProcess(),
|
|
&h,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS ) )
|
|
{
|
|
SetEvent( h );
|
|
CloseHandle( h );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: DumpSID
|
|
|
|
FUNCTION: Prints out a SID, with the padding provided.
|
|
|
|
ARGS: pad -- Padding to print before the SID.
|
|
sid_to_dump -- Pointer to the SID to print.
|
|
Flag -- To control options.
|
|
|
|
RETURN: N/A
|
|
|
|
NOTE***: It right now, doesn't lookup the sid.
|
|
In future, you might want ot use the Flag
|
|
parameter to make that optional.
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
|
|
VOID DumpSID(
|
|
CHAR *pad,
|
|
PSID sid_to_dump,
|
|
ULONG Flag
|
|
)
|
|
{
|
|
NTSTATUS ntstatus;
|
|
UNICODE_STRING us;
|
|
|
|
if (sid_to_dump)
|
|
{
|
|
ntstatus = RtlConvertSidToUnicodeString(&us, sid_to_dump, TRUE);
|
|
|
|
if (NT_SUCCESS(ntstatus))
|
|
{
|
|
DebuggerOut("%s%wZ\n", pad, &us);
|
|
RtlFreeUnicodeString(&us);
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("0x%08lx: Can't Convert SID to UnicodeString\n", ntstatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebuggerOut("%s is NULL\n", pad);
|
|
}
|
|
}
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: DumpACL
|
|
|
|
FUNCTION: Prints out a ACL, with the padding provided.
|
|
|
|
ARGS: pad -- Padding to print before the ACL.
|
|
acl_to_dump -- Pointer to the ACL to print.
|
|
Flag -- To control options.
|
|
|
|
RETURN: N/A
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
BOOL
|
|
DumpACL (
|
|
IN char *pad,
|
|
IN ACL *pacl,
|
|
IN ULONG Flags
|
|
)
|
|
{
|
|
USHORT x;
|
|
|
|
if (pacl == NULL)
|
|
{
|
|
DebuggerOut("%s is NULL\n", pad);
|
|
return FALSE;
|
|
}
|
|
|
|
DebuggerOut("%s\n", pad);
|
|
DebuggerOut("%s->AclRevision: 0x%x\n", pad, pacl->AclRevision);
|
|
DebuggerOut("%s->Sbz1 : 0x%x\n", pad, pacl->Sbz1);
|
|
DebuggerOut("%s->AclSize : 0x%x\n", pad, pacl->AclSize);
|
|
DebuggerOut("%s->AceCount : 0x%x\n", pad, pacl->AceCount);
|
|
DebuggerOut("%s->Sbz2 : 0x%x\n", pad, pacl->Sbz2);
|
|
|
|
for (x = 0; x < pacl->AceCount; x ++)
|
|
{
|
|
PACE_HEADER ace;
|
|
CHAR temp_pad[MAX_PATH];
|
|
NTSTATUS result;
|
|
|
|
sprintf(temp_pad, "%s->Ace[%u]: ", pad, x);
|
|
|
|
result = RtlGetAce(pacl, x, (PVOID *) &ace);
|
|
if (! NT_SUCCESS(result))
|
|
{
|
|
DebuggerOut("%sCan't GetAce, 0x%08lx\n", temp_pad, result);
|
|
return FALSE;
|
|
}
|
|
|
|
DebuggerOut("%s->AceType: ", temp_pad);
|
|
|
|
#define BRANCH_AND_PRINT(x) case x: DebuggerOut(#x "\n"); break
|
|
|
|
switch (ace->AceType)
|
|
{
|
|
BRANCH_AND_PRINT(ACCESS_ALLOWED_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_DENIED_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_AUDIT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_ALARM_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_ALLOWED_COMPOUND_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_ALLOWED_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_DENIED_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_AUDIT_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_ALARM_OBJECT_ACE_TYPE);
|
|
|
|
default:
|
|
DebuggerOut("0x%08lx <-- *** Unknown AceType\n", ace->AceType);
|
|
continue; // With the next ace
|
|
}
|
|
|
|
#undef BRANCH_AND_PRINT
|
|
|
|
DebuggerOut("%s->AceFlags: 0x%x\n", temp_pad, ace->AceFlags);
|
|
|
|
#define BRANCH_AND_PRINT(x) if (ace->AceFlags & x){ DebuggerOut("%s %s\n", temp_pad, #x); }
|
|
|
|
BRANCH_AND_PRINT(OBJECT_INHERIT_ACE)
|
|
BRANCH_AND_PRINT(CONTAINER_INHERIT_ACE)
|
|
BRANCH_AND_PRINT(NO_PROPAGATE_INHERIT_ACE)
|
|
BRANCH_AND_PRINT(INHERIT_ONLY_ACE)
|
|
BRANCH_AND_PRINT(INHERITED_ACE)
|
|
BRANCH_AND_PRINT(SUCCESSFUL_ACCESS_ACE_FLAG)
|
|
BRANCH_AND_PRINT(FAILED_ACCESS_ACE_FLAG)
|
|
|
|
#undef BRANCH_AND_PRINT
|
|
|
|
DebuggerOut("%s->AceSize: 0x%x\n", temp_pad, ace->AceSize);
|
|
|
|
/*
|
|
From now on it is ace specific stuff.
|
|
Fortunately ACEs can be split into 3 groups,
|
|
with the ACE structure being the same within the group
|
|
*/
|
|
|
|
switch (ace->AceType)
|
|
{
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
case SYSTEM_ALARM_ACE_TYPE:
|
|
{
|
|
CHAR more_pad[MAX_PATH];
|
|
SYSTEM_AUDIT_ACE *tace = (SYSTEM_AUDIT_ACE *) ace;
|
|
|
|
DebuggerOut("%s->Mask : 0x%08lx\n", temp_pad, tace->Mask);
|
|
|
|
sprintf(more_pad, "%s->SID: ", temp_pad);
|
|
DumpSID(more_pad, &(tace->SidStart), Flags);
|
|
}
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
|
|
{
|
|
CHAR more_pad[MAX_PATH];
|
|
COMPOUND_ACCESS_ALLOWED_ACE *tace = (COMPOUND_ACCESS_ALLOWED_ACE *) ace;
|
|
PBYTE ptr;
|
|
|
|
DebuggerOut("%s->Mask : 0x%08lx\n", temp_pad, tace->Mask);
|
|
DebuggerOut("%s->CompoundAceType : 0x%08lx\n", temp_pad, tace->CompoundAceType);
|
|
DebuggerOut("%s->Reserved : 0x%08lx\n", temp_pad, tace->Reserved);
|
|
|
|
sprintf(more_pad, "%s->SID(1) : ", temp_pad);
|
|
DumpSID(more_pad, &(tace->SidStart), Flags);
|
|
|
|
ptr = (PBYTE)&(tace->SidStart);
|
|
ptr += RtlLengthSid((PSID)ptr); /* Skip this & get to next sid */
|
|
|
|
sprintf(more_pad, "%s->SID(2) : ", temp_pad);
|
|
DumpSID(more_pad, ptr, Flags);
|
|
}
|
|
break;
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
|
|
{
|
|
CHAR more_pad[MAX_PATH];
|
|
ACCESS_ALLOWED_OBJECT_ACE *tace = (ACCESS_ALLOWED_OBJECT_ACE *) ace;
|
|
PBYTE ptr;
|
|
GUID *obj_guid = NULL, *inh_obj_guid = NULL;
|
|
|
|
DebuggerOut("%s->Mask : 0x%08lx\n", temp_pad, tace->Mask);
|
|
DebuggerOut("%s->Flags : 0x%08lx\n", temp_pad, tace->Flags);
|
|
|
|
ptr = (PBYTE)&(tace->ObjectType);
|
|
|
|
if (tace->Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
{
|
|
DebuggerOut("%s : ACE_OBJECT_TYPE_PRESENT\n", temp_pad);
|
|
obj_guid = &(tace->ObjectType);
|
|
ptr = (PBYTE)&(tace->InheritedObjectType);
|
|
}
|
|
|
|
if (tace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
{
|
|
DebuggerOut("%s : ACE_INHERITED_OBJECT_TYPE_PRESENT\n", temp_pad);
|
|
inh_obj_guid = &(tace->InheritedObjectType);
|
|
ptr = (PBYTE)&(tace->SidStart);
|
|
}
|
|
|
|
if (obj_guid)
|
|
{
|
|
DebuggerOut("%s->ObjectType : (in HEX)", temp_pad);
|
|
DebuggerOut("(%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n",
|
|
obj_guid->Data1,
|
|
obj_guid->Data2,
|
|
obj_guid->Data3,
|
|
obj_guid->Data4[0],
|
|
obj_guid->Data4[1],
|
|
obj_guid->Data4[2],
|
|
obj_guid->Data4[3],
|
|
obj_guid->Data4[4],
|
|
obj_guid->Data4[5],
|
|
obj_guid->Data4[6],
|
|
obj_guid->Data4[7]
|
|
);
|
|
}
|
|
|
|
if (inh_obj_guid)
|
|
{
|
|
DebuggerOut("%s->InhObjTYpe : (in HEX)", temp_pad);
|
|
DebuggerOut("(%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n",
|
|
inh_obj_guid->Data1,
|
|
inh_obj_guid->Data2,
|
|
inh_obj_guid->Data3,
|
|
inh_obj_guid->Data4[0],
|
|
inh_obj_guid->Data4[1],
|
|
inh_obj_guid->Data4[2],
|
|
inh_obj_guid->Data4[3],
|
|
inh_obj_guid->Data4[4],
|
|
inh_obj_guid->Data4[5],
|
|
inh_obj_guid->Data4[6],
|
|
inh_obj_guid->Data4[7]
|
|
);
|
|
}
|
|
|
|
sprintf(more_pad, "%s->SID : ", temp_pad);
|
|
DumpSID(more_pad, ptr, Flags);
|
|
}
|
|
}
|
|
DebuggerOut("\n");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
objsec(
|
|
HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
HANDLE h ;
|
|
HANDLE hThere ;
|
|
NTSTATUS Status ;
|
|
ULONG Length ;
|
|
PVOID SecurityDescriptor ;
|
|
PACL Acl ;
|
|
|
|
InitDebugHelp( hProcess, hThread, lpExt );
|
|
|
|
hThere = GetExpr( pszCommand );
|
|
|
|
if ( DuplicateHandle( hProcess,
|
|
hThere,
|
|
GetCurrentProcess(),
|
|
&h,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS ) )
|
|
{
|
|
Status = NtQuerySecurityObject(
|
|
h,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
0,
|
|
&Length );
|
|
|
|
SecurityDescriptor = LocalAlloc( LMEM_FIXED, Length );
|
|
|
|
if ( SecurityDescriptor )
|
|
{
|
|
Status = NtQuerySecurityObject(
|
|
h,
|
|
DACL_SECURITY_INFORMATION,
|
|
SecurityDescriptor,
|
|
Length,
|
|
&Length );
|
|
|
|
if ( NT_SUCCESS( Status ) )
|
|
{
|
|
BOOLEAN Present, defaulted;
|
|
|
|
RtlGetDaclSecurityDescriptor( SecurityDescriptor,
|
|
&Present,
|
|
&Acl,
|
|
&defaulted );
|
|
|
|
DumpACL( "", Acl, 0);
|
|
|
|
}
|
|
|
|
LocalFree( SecurityDescriptor );
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
Help( HANDLE hProcess,
|
|
HANDLE hThread,
|
|
DWORD dwCurrentPc,
|
|
PNTSD_EXTENSION_APIS lpExt,
|
|
LPSTR pszCommand)
|
|
{
|
|
|
|
InitDebugHelp(hProcess, hThread, lpExt);
|
|
|
|
DebuggerOut("SPM Debug Help\n");
|
|
DebuggerOut(" DumpPackage [-v][-b]] [id | addr]\tDump Package Control\n");
|
|
DebuggerOut(" DumpSessionList <addr> \tDump Session List\n");
|
|
DebuggerOut(" DumpThreadSession \tDump Thread's session\n");
|
|
DebuggerOut(" DumpLogonSession <addr> \tDump Logon Session list\n");
|
|
DebuggerOut(" DumpSession <addr> \tDump Session\n");
|
|
DebuggerOut(" DumpHandleList <addr> \tDump a Handle List from a session\n");
|
|
DebuggerOut(" DumpBlock <addr> \tDump a memory block (DBGMEM only)\n");
|
|
DebuggerOut(" DumpScavList [<addr>[+]] \tDump the scavenger list\n");
|
|
DebuggerOut(" DumpToken <handle> \tDump a token\n");
|
|
DebuggerOut(" DumpThreadToken \tDump token of thread\n");
|
|
DebuggerOut(" DumpActives [-p|a|t] [file] \tDump active memory to file\n");
|
|
DebuggerOut(" DumpFastMem \tDump FastMem usage\n");
|
|
DebuggerOut(" Except \tShow exception for thread\n");
|
|
DebuggerOut(" DumpLpc \tDump Lpc Dispatch record\n");
|
|
DebuggerOut(" DumpLpcMessage <addr> \tDump Lpc Message at address\n");
|
|
DebuggerOut(" DumpThreadTask <addr> \tDump thread pool\n");
|
|
DebuggerOut(" DumpQueue [<addr>] \tDump Queue\n");
|
|
DebuggerOut(" DumpSecBuffer <addr> \tDump SecBuffer struct\n");
|
|
DebuggerOut(" DumpSecBufferDesc <addr> \tDump SecBufferDesc struct \n");
|
|
DebuggerOut(" DumpThreadLpc \tDump thread's LPC message\n");
|
|
DebuggerOut(" DumpNegContext <addr> \tDump NEG_CONTEXT structure\n");
|
|
DebuggerOut(" DumpNegCred <addr> \tDump NEG_CRED structure\n");
|
|
DebuggerOut(" BERDecode <addr> \tDecode BER-encoded data\n");
|
|
DebuggerOut(" GetTls <slot> \tGet the TLS value from slot\n");
|
|
DebuggerOut(" DumpHandleTable <addr> \tDump handle table at addr\n");
|
|
DebuggerOut(" DumpLsaHandle <addr> \tDump the Lsa policy handle at addr\n");
|
|
DebuggerOut(" DumpLsaHandleTable <addr> \tDump the Lsa policy handle table at addr\n");
|
|
DebuggerOut(" DumpLsaHandleTableEx <addr> \tDump the Lsa policy handle table at addr\n");
|
|
DebuggerOut(" DumpSD <addr> \tDump a security descriptor\n");
|
|
DebuggerOut(" DumpAcl <addr> \tDump the ACL at addr\n" );
|
|
DebuggerOut(" DumpSid <addr> \tDump the SID at addr\n" );
|
|
DebuggerOut(" DumpLsaSidCache [<addr>] \tDump the LSA sid cache\n" );
|
|
DebuggerOut(" DumpFtcTdoEntry <addr> \tDump the LSA FTC TDO entry\n" );
|
|
DebuggerOut(" DumpForestTrustCache <addr> \tDump the LSA forest trust cache\n");
|
|
|
|
DebuggerOut("\n\nShortcuts\n");
|
|
DebuggerOut(" sb DumpSecBuffer\n");
|
|
DebuggerOut(" sbd DumpSecBufferDesc\n");
|
|
DebuggerOut(" lpc DumpLpcMessage\n");
|
|
DebuggerOut(" sess DumpSession\n");
|
|
DebuggerOut(" ber BERDecode\n");
|
|
DebuggerOut(" q DumpQueue\n");
|
|
DebuggerOut(" task DumpThreadTask\n");
|
|
}
|