BOOL SpyWriteFilter (PSPY_PROTOCOL psp,
PBYTE pbFormat,
PVOID pParameters,
DWORD dParameters)
{
PHANDLE phObject = NULL;
HANDLE hObject = NULL;
POBJECT_ATTRIBUTES poa = NULL;
PDWORD pdNext;
DWORD i, j;
pdNext = pParameters;
i = j = 0;
while (pbFormat [i])
{
while (pbFormat [i] && (pbFormat [i] != '%')) i++;
if (pbFormat [i] && pbFormat [++i])
{
j++;
switch (pbFormat [i++])
{
case 'b':
case 'a':
case 'w':
case 'u':
case 'n':
case 'l':
case 's':
case 'i':
case 'c':
case 'd':
case 'p':
{
break;
}
case 'o':
{
if (poa == NULL)
{
poa = (POBJECT_ATTRIBUTES) *pdNext;
}
break;
}
case '+':
{
if (phObject == NULL)
{
phObject = (PHANDLE) *pdNext;
}
break;
}
case '!':
case '-':
{
if (hObject == NULL)
{
hObject = (HANDLE) *pdNext;
}
break;
}
default:
{
j--;
break;
}
}
pdNext++;
}
}
return // number of arguments ok
(j == dParameters)
&&
// no handles involved
(((phObject == NULL) && (hObject == NULL))
||
// new handle, successfully registered
((phObject != NULL) &&
SpyHandleRegister (psp, PsGetCurrentProcessId (),
*phObject, OBJECT_NAME (poa)))
||
// registered handle
SpyHandleSlot (psp, PsGetCurrentProcessId (), hObject)
||
// filter disabled
(!gfSpyHookFilter));
}
#define SPY_HANDLES 0x00001000 // max number of handles
#define SPY_NAME_BUFFER 0x00100000 // object name buffer size
#define SPY_DATA_BUFFER 0x00100000 // protocol data buffer size
// -----------------------------------------------------------------
typedef struct _SPY_HEADER
{
LARGE_INTEGER liStart; // start time
DWORD dRead; // read data index
DWORD dWrite; // write data index
DWORD dCalls; // api usage count
DWORD dHandles; // handle count
DWORD dName; // object name index
}
SPY_HEADER, *PSPY_HEADER, **PPSPY_HEADER;
#define SPY_HEADER_ sizeof (SPY_HEADER)
// -----------------------------------------------------------------
typedef struct _SPY_PROTOCOL
{
SPY_HEADER sh; // protocol header
HANDLE ahProcesses [SPY_HANDLES]; // process id array
HANDLE ahObjects [SPY_HANDLES]; // handle array
DWORD adNames [SPY_HANDLES]; // name offsets
WORD awNames [SPY_NAME_BUFFER]; // name strings
BYTE abData [SPY_DATA_BUFFER]; // protocol data
}
SPY_PROTOCOL, *PSPY_PROTOCOL, **PPSPY_PROTOCOL;
#define SPY_PROTOCOL_ sizeof (SPY_PROTOCOL)
// =================================================================
// HANDLE MANAGEMENT
// =================================================================
DWORD SpyHandleSlot (PSPY_PROTOCOL psp,
HANDLE hProcess,
HANDLE hObject)
{
DWORD dSlot = 0;
if (hObject != NULL)
{
while ((dSlot < psp->sh.dHandles)
&&
((psp->ahProcesses [dSlot] != hProcess) ||
(psp->ahObjects [dSlot] != hObject ))) dSlot++;
dSlot = (dSlot < psp->sh.dHandles ? dSlot+1 : 0);
}
return dSlot;
}
// -----------------------------------------------------------------
DWORD SpyHandleName (PSPY_PROTOCOL psp,
HANDLE hProcess,
HANDLE hObject,
PWORD pwName,
DWORD dName)
{
WORD w;
DWORD i;
DWORD dSlot = SpyHandleSlot (psp, hProcess, hObject);
if ((pwName != NULL) && dName)
{
i = 0;
if (dSlot)
{
while ((i+1 < dName) &&
(w = psp->awNames [psp->adNames [dSlot-1] + i]))
{
pwName [i++] = w;
}
}
pwName [i] = 0;
}
return dSlot;
}
// -----------------------------------------------------------------
DWORD SpyHandleUnregister (PSPY_PROTOCOL psp,
HANDLE hProcess,
HANDLE hObject,
PWORD pwName,
DWORD dName)
{
DWORD i, j;
DWORD dSlot = SpyHandleName (psp, hProcess, hObject,
pwName, dName);
if (dSlot)
{
if (dSlot == psp->sh.dHandles)
{
// remove last name entry
psp->sh.dName = psp->adNames [dSlot-1];
}
else
{
i = psp->adNames [dSlot-1];
j = psp->adNames [dSlot ];
// shift left all remaining name entries
while (j < psp->sh.dName)
{
psp->awNames [i++] = psp->awNames [j++];
}
j -= (psp->sh.dName = i);
// shift left all remaining handles and name offsets
for (i = dSlot; i < psp->sh.dHandles; i++)
{
psp->ahProcesses [i-1] = psp->ahProcesses [i];
psp->ahObjects [i-1] = psp->ahObjects [i];
psp->adNames [i-1] = psp->adNames [i] - j;
}
}
psp->sh.dHandles--;
}
return dSlot;
}
// -----------------------------------------------------------------
DWORD SpyHandleRegister (PSPY_PROTOCOL psp,
HANDLE hProcess,
HANDLE hObject,
PUNICODE_STRING puName)
{
PWORD pwName;
DWORD dName;
DWORD i;
DWORD dSlot = 0;
if (hObject != NULL)
{
// unregister old handle with same value
SpyHandleUnregister (psp, hProcess, hObject, NULL, 0);
if (psp->sh.dHandles == SPY_HANDLES)
{
// unregister oldest handle if overflow
SpyHandleUnregister (psp, psp->ahProcesses [0],
psp->ahObjects [0], NULL, 0);
}
pwName = ((puName != NULL) && SpyMemoryTestAddress (puName)
? puName->Buffer
: NULL);
dName = ((pwName != NULL) && SpyMemoryTestAddress (pwName)
? puName->Length / WORD_
: 0);
if (dName + 1 <= SPY_NAME_BUFFER - psp->sh.dName)
{
// append object to end of list
psp->ahProcesses [psp->sh.dHandles] = hProcess;
psp->ahObjects [psp->sh.dHandles] = hObject;
psp->adNames [psp->sh.dHandles] = psp->sh.dName;
for (i = 0; i < dName; i++)
{
psp->awNames [psp->sh.dName++] = pwName [i];
}
psp->awNames [psp->sh.dName++] = 0;
psp->sh.dHandles++;
dSlot = psp->sh.dHandles;
}
}
return dSlot;
}