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.
328 lines
7.8 KiB
328 lines
7.8 KiB
//+-----------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (c) Microsoft Corporation 2000
|
|
//
|
|
// File: N E W E X T . C
|
|
//
|
|
// Contents: LSA debugger extensions that use the new style
|
|
// extension API.
|
|
//
|
|
//
|
|
// History:
|
|
// 07-January-2000 kumarp created
|
|
//
|
|
// Note:
|
|
//
|
|
// If you want to add extensions to this file, read the following
|
|
// guidelines from andreva first:
|
|
//
|
|
// Everyone who debugs or runs stress will expect debugger extensions
|
|
// to work on both 32 bit and 64 bit TARGETS. The Debugger extensions must
|
|
// therefore be TARGET independent. We the only viable solution to this is to
|
|
// get structure definitions from the symbol information, instead of
|
|
// from the header file. So the way we solve this problem is:
|
|
//
|
|
// - A debugger extension can only include windows.h and wdbgexts.h
|
|
// - A debugger extensions NEVER includes header files from
|
|
// the component it tries to analyze\debug.
|
|
// - Debugger extensions use the new routines we provide to query
|
|
// type information.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <dbghelp.h>
|
|
#define KDEXT_64BIT
|
|
#include <wdbgexts.h>
|
|
#include <ntverp.h>
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// globals
|
|
//
|
|
WINDBG_EXTENSION_APIS ExtensionApis;
|
|
EXT_API_VERSION ApiVersion =
|
|
{
|
|
(VER_PRODUCTVERSION_W >> 8),
|
|
(VER_PRODUCTVERSION_W & 0xff),
|
|
EXT_API_VERSION_NUMBER64,
|
|
0
|
|
};
|
|
USHORT SavedMajorVersion;
|
|
USHORT SavedMinorVersion;
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// The following 3 functions must be present in the extension dll.
|
|
// They were lifted straight from base\tools\kdexts\kdexts.c
|
|
//
|
|
VOID
|
|
WinDbgExtensionDllInit(
|
|
PWINDBG_EXTENSION_APIS64 lpExtensionApis, // 64Bit Change
|
|
USHORT MajorVersion,
|
|
USHORT MinorVersion
|
|
)
|
|
{
|
|
ExtensionApis = *lpExtensionApis;
|
|
|
|
SavedMajorVersion = MajorVersion;
|
|
SavedMinorVersion = MinorVersion;
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
CheckVersion(
|
|
VOID
|
|
)
|
|
{
|
|
}
|
|
|
|
LPEXT_API_VERSION
|
|
ExtensionApiVersion(
|
|
VOID
|
|
)
|
|
{
|
|
return &ApiVersion;
|
|
}
|
|
// ----------------------------------------------------------------------
|
|
|
|
|
|
BOOL
|
|
GetGlobalVar (
|
|
IN PUCHAR Name,
|
|
IN USHORT Size,
|
|
OUT PVOID pOutValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get value of global vars of primitive type OR
|
|
Get the address instead for non-primitive global vars.
|
|
|
|
Primitive type is defined as the one not-involving any struct/union
|
|
in its type definition. Pointer to struct/unions are ok.
|
|
for example: USHORT, ULONG, PVOID etc.
|
|
|
|
Arguments:
|
|
|
|
Name - global var name
|
|
(for example: "lsasrv!LsapAdtContextList")
|
|
|
|
Size - size in bytes for primitive types, 0 otherwise
|
|
|
|
pOutValue - pointer to return val.
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE otherwise
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
ULONG64 Temp=0;
|
|
|
|
SYM_DUMP_PARAM Sym =
|
|
{
|
|
sizeof (SYM_DUMP_PARAM),
|
|
Name,
|
|
DBG_DUMP_NO_PRINT | DBG_DUMP_COPY_TYPE_DATA,
|
|
0,
|
|
NULL,
|
|
&Temp,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
};
|
|
|
|
ULONG RetVal;
|
|
|
|
RetVal = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
|
|
|
|
//
|
|
// store only the correct number of bytes from the value read
|
|
//
|
|
switch(Size)
|
|
{
|
|
default:
|
|
case 0:
|
|
*((PUCHAR*) pOutValue) = (PUCHAR) Sym.addr;
|
|
break;
|
|
|
|
case 1:
|
|
*((UCHAR*) pOutValue) = (UCHAR) Temp;
|
|
break;
|
|
|
|
case 2:
|
|
*((USHORT*) pOutValue) = (USHORT) Temp;
|
|
break;
|
|
|
|
case 4:
|
|
*((DWORD*) pOutValue) = (DWORD) Temp;
|
|
break;
|
|
|
|
case 8:
|
|
*((ULONG64*) pOutValue) = Temp;
|
|
break;
|
|
}
|
|
|
|
return (RetVal == NO_ERROR);
|
|
}
|
|
|
|
//
|
|
// helper macro to get field of AUDIT_CONTEXT struct
|
|
//
|
|
#define GetAuditContextField(addr,f) \
|
|
GetFieldData( (ULONG64) addr, \
|
|
"AUDIT_CONTEXT",\
|
|
#f, \
|
|
sizeof(f), \
|
|
&f )
|
|
|
|
//
|
|
// helper macro to get LIST_ENTRY.Flink
|
|
//
|
|
#define GetFlink(addr,pflink) \
|
|
GetFieldData( addr,\
|
|
"LIST_ENTRY", \
|
|
"Flink",\
|
|
sizeof(ULONG64),\
|
|
pflink )
|
|
void
|
|
DumpAuditContextList(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump the audit context list.
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Notes:
|
|
It appears that there is a built in support for dumping
|
|
lists using SYM_DUMP_PARAM.listLink but I came to know about it too late.
|
|
|
|
--*/
|
|
{
|
|
LIST_ENTRY LsapAdtContextList = { (PLIST_ENTRY) 22, (PLIST_ENTRY) 33 };
|
|
ULONG64 pLsapAdtContextList=0;
|
|
ULONG LsapAdtContextListCount=0;
|
|
ULONG64 Temp=0;
|
|
ULONG64 Scan=0;
|
|
ULONG64 Link=0;
|
|
USHORT CategoryId;
|
|
USHORT AuditId;
|
|
USHORT ParameterCount;
|
|
|
|
ULONG Status=NO_ERROR;
|
|
ULONG i;
|
|
|
|
if (!GetGlobalVar( "lsasrv!LsapAdtContextListCount",
|
|
sizeof(LsapAdtContextListCount),
|
|
&LsapAdtContextListCount ))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
dprintf( "# contexts: %ld\n", LsapAdtContextListCount );
|
|
|
|
if ( ((LONG) LsapAdtContextListCount) < 0 )
|
|
{
|
|
dprintf("...List/ListCount may be corrupt\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( LsapAdtContextListCount == 0 )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!GetGlobalVar( "lsasrv!LsapAdtContextList",
|
|
0,
|
|
&pLsapAdtContextList ))
|
|
{
|
|
dprintf("...error reading lsasrv!LsapAdtContextList\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = GetFlink( pLsapAdtContextList, &Scan );
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
dprintf("...error reading lsasrv!LsapAdtContextList.Flink\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
dprintf("LsapAdtContextList @ %p\n", pLsapAdtContextList);
|
|
|
|
for (i=0; i < LsapAdtContextListCount; i++)
|
|
{
|
|
dprintf("%02d) [%p]: ", i, Scan);
|
|
|
|
if ( Scan == pLsapAdtContextList )
|
|
{
|
|
dprintf("...pre-mature end of list\nList/ListCount may be corrupt\n");
|
|
break;
|
|
}
|
|
else if ( Scan == 0 )
|
|
{
|
|
dprintf("...NULL list element found!\nList/ListCount may be corrupt\n");
|
|
break;
|
|
}
|
|
|
|
Status = GetAuditContextField( Scan, CategoryId );
|
|
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
dprintf("...error reading AUDIT_CONTEXT.CategoryId\n");
|
|
break;
|
|
}
|
|
|
|
dprintf("Category: %03x\t", CategoryId);
|
|
|
|
Status = GetAuditContextField( Scan, AuditId );
|
|
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
dprintf("...error reading AUDIT_CONTEXT.AuditId\n");
|
|
break;
|
|
}
|
|
|
|
dprintf("AuditId: %03x\t", AuditId);
|
|
|
|
Status = GetAuditContextField( Scan, Link );
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
dprintf("...error reading AUDIT_CONTEXT.Link\n");
|
|
break;
|
|
}
|
|
|
|
Status = GetFlink( Link, &Scan );
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
dprintf("\n");
|
|
}
|
|
|
|
Cleanup:
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
dprintf("...failed\n");
|
|
}
|
|
}
|
|
|
|
DECLARE_API(AuditContexts)
|
|
{
|
|
DumpAuditContextList();
|
|
}
|