📄 hdstub.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
hdstub.c : HDStub layer
Abstract:
HDStub is a small kernel dll that accepts and filters notifications from
the kernel. These notifications include (and are not limited to)
exceptions, virtual memory paging, module load, and module unload.
Environment:
CE kernel
History:
--*/
#include "hdstub_p.h"
// BEGIN OsAxsHCe50.dll parameters
// Global stopping event structure.
HDSTUB_EVENT g_Event;
// Hardware event filter.
static ULONG s_ulFakeHDEventFilter = 0;
static ULONG* s_pulHDEventFilter = &s_ulFakeHDEventFilter;
// Taint flag for modules. Indicates the number of module events that OsAccess
// has missed.
static BOOL s_dwTaintedModuleCount = 0;
// END parameters
// Pointer to kdata
struct KDataStruct *g_pKData;
// Current Hdstub event handlers
HDSTUB_CLIENT *pClientListHead;
// KITL Ioctl
DWORD (*g_pfnKitlIoctl) (DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD) = 0;
// Sprintf
void (WINAPIV* g_pfnNKvsprintfW)(LPWSTR, LPCWSTR, va_list, int) = 0;
void (*g_pfnOutputDebugString)(const char *sz, ...) = 0;
static void PageInModule (DWORD dwVmBaseAddr);
#ifdef MIPS
/* Interlocked functions for mips */
LONG (*g_pfnInterlockedDecrement)(LPLONG);
LONG (*g_pfnInterlockedIncrement)(LPLONG);
#endif
CRITICAL_SECTION csModLoad;
CRITICAL_SECTION csHdStubEventRecord;
HDSTUB_INIT g_HdStubData = {0};
static ULONG s_ulOldHDEventFilter = 0;
// During boot, allow 2 load events to go through without altering the event flags.
// This is for performance reasons, because 2 load events would guarantee the hardware debugger starting up.
DWORD g_dwModInitCount = 2;
/*++
Routine Name:
HdstubCallClientIoctl
Routine Description:
Call any of hdstub's clients. This is used for inter Kdstub - Osaccess communication.
Arguments:
szClientName - name of the client ("kdstub", "osaxst0", "osaxst1", etc.)
dwFunction - Which function to call.
dwArg1,2,3,4 - Arguments 1 - 4. Size of a machine word and should be castable to pointers
if necessary.
Return Value:
E_FAIL - Unable to find client (Must Change.)
--*/
HRESULT HdstubCallClientIoctl (const char *szClientName, DWORD dwFunction, DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
{
HDSTUB_CLIENT *pClient;
HRESULT hr = HDSTUB_E_NOCLIENT;
DEBUGGERMSG (HDZONE_CLIENT, (L"++HdstubCallClientIoctl, %S, %d, %d, %d, %d, %d\r\n", szClientName,
dwFunction, dwArg1, dwArg2, dwArg3, dwArg4));
pClient = pClientListHead;
while (pClient)
{
if (!strcmp (pClient->szClientName, szClientName))
{
DEBUGGERMSG (HDZONE_CLIENT, (L" HdstubCallClientIoctl: Found and calling.\r\n"));
if (pClient->pfnIoctl)
{
hr = pClient->pfnIoctl (dwFunction, dwArg1, dwArg2, dwArg3, dwArg4);
DEBUGGERMSG (HDZONE_CLIENT, (L" HdstubCallClientIoctl: returned 0x%.08x\r\n", hr));
}
break;
}
pClient = pClient->pCliNext;
}
DEBUGGERMSG (HDZONE_CLIENT, (L"--HdstubCallClientIoctl: 0x%.08x\r\n", hr));
return hr;
}
/*++
Routine Name:
HdstubConnectKdstub
Routine Description:
Hook KDStub to HDStub. Assume that the Kernel debugger dll is already
loaded.
Arguments:
pfnCliInit - in, Pointer to Client init function
pvExtra - in, Pointer to Extra Data to pass through to Client
Return Value:
TRUE : Load successful
FALSE : Failure
--*/
BOOL HdstubConnectClient (HDSTUB_CLINIT_FUNC pfnCliInit, void *pvExtra)
{
BOOL fReturn;
HDSTUB_DATA HdstubData =
{
HdstubRegisterClient,
HdstubUnregisterClient,
HdstubCallClientIoctl
};
DEBUGGERMSG (HDZONE_INIT, (L"++HdstubConnectKdstub: CliInit=0x%.8x, pvExtra=0x%.8x\r\n", pfnCliInit, pvExtra));
fReturn = pfnCliInit (&HdstubData, pvExtra);
DEBUGGERMSG (HDZONE_INIT, (L"--HdstubConnectKdstub: return %d\r\n", fReturn));
return fReturn;
}
/*++
Routine Name:
HdstubDLLEntry
Routine Description:
Attach to nk.exe. Provide nk.exe with a pointer to HdstubInit
Arguments:
hInstance -
ulReason -
pvReserved -
Return Value:
TRUE - Loaded
FALSE - Error during entry.
--*/
BOOL WINAPI HdstubDLLEntry (HINSTANCE hInstance, ULONG ulReason,
LPVOID pvReserved)
{
BOOL bResult;
FARPROC pfnKernelLibIoctl;
FARPROC pfnInit;
pfnKernelLibIoctl = (FARPROC)pvReserved;
pfnInit = (FARPROC)HdstubInit;
bResult = TRUE;
DEBUGREGISTER(hInstance);
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
bResult = pfnKernelLibIoctl
&& pfnKernelLibIoctl ((HANDLE)KMOD_DBG,
IOCTL_DBG_HDSTUB_INIT,
(void *) &pfnInit,
sizeof (pfnInit),
NULL,
0,
NULL);
break;
case DLL_PROCESS_DETACH:
break;
}
return bResult;
}
/*++
Routine Name:
HdstubInit
Routine Description:
Initialize Hdstub.
Arguments:
pHdInit - out, export event notification functions.
Return Value:
TRUE : success.
--*/
BOOL HdstubInit(HDSTUB_INIT *pHdInit)
{
BOOL fResult = FALSE;
if (pHdInit && (pHdInit->cbSize == sizeof(*pHdInit)))
{
g_HdStubData = *pHdInit;
g_HdStubData.pfnInitializeCriticalSection(&csModLoad);
#ifdef MIPS
g_pfnInterlockedDecrement = pHdInit->pfnInterlockedDecrement;
g_pfnInterlockedIncrement = pHdInit->pfnInterlockedIncrement;
#endif
// Get existing imported functions and data
g_pfnNKvsprintfW = pHdInit->pNKSprintfW;
g_pfnKitlIoctl = pHdInit->pKITLIoCtl;
g_pKData = pHdInit->pKData;
s_pulHDEventFilter = pHdInit->pulHDEventFilter;
// Obtain KITLOutputDebugString
if (g_pfnKitlIoctl)
{
g_pfnKitlIoctl(IOCTL_EDBG_GET_OUTPUT_DEBUG_FN, NULL, 0, (VOID*)&g_pfnOutputDebugString,
sizeof(g_pfnOutputDebugString), NULL);
}
// Export trap functions
pHdInit->pfnException = HdstubTrapException;
pHdInit->pfnVmPageIn = HdstubTrapVmPageIn;
pHdInit->pfnModLoad = HdstubTrapModuleLoad;
pHdInit->pfnModUnload = HdstubTrapModuleUnload;
pHdInit->pfnConnectClient = HdstubConnectClient;
// Export hw debug notification function and structure.
pHdInit->pEvent = &g_Event;
pHdInit->pdwTaintedModuleCount = &s_dwTaintedModuleCount;
fResult = TRUE;
}
return fResult;
}
/*++
Routine Name:
HdstubRegisterClient
Routine Description:
Add a client structure into the linked list. Does not copy.
Arguments:
pClient - Client Structure, must be either allocated or static data from client..
Disposition - Position to insert the element, either at head or at tail.
Return Value:
TRUE - successfully added client.
FALSE - unable to add the client.
--*/
BOOL HdstubRegisterClient (HDSTUB_CLIENT *pClient, int Disposition)
{
HDSTUB_CLIENT *pClientCur = NULL;
HDSTUB_CLIENT *pClientLast = NULL;
BOOL fResult = FALSE;
DEBUGGERMSG (HDZONE_CLIENT, (L"++HdstubRegisterClient: 0x%.08x, %d\r\n", pClient, Disposition));
pClientCur = pClientListHead;
while (pClientCur)
{
if (pClientCur == pClient)
{
DEBUGGERMSG (HDZONE_CLIENT, (L" HdstubRegisterClient: Already registered.\r\n"));
fResult = TRUE;
goto Done;
}
pClientLast = pClientCur;
pClientCur = pClientCur->pCliNext;
}
pClient->pCliNext = NULL;
switch (Disposition)
{
case HdstubClientFirst:
DEBUGGERMSG (HDZONE_CLIENT, (L" HdstubRegisterClient: Insert at head.\r\n"));
pClient->pCliNext = pClientListHead;
pClientListHead = pClient;
fResult = TRUE;
break;
case HdstubClientLast:
if (pClientLast)
{
DEBUGGERMSG (HDZONE_CLIENT, (L" HdstubRegisterClient: Insert at tail after 0x%.08x\r\n", pClientLast));
pClientLast->pCliNext = pClient;
}
else
{
DEBUGGERMSG (HDZONE_CLIENT, (L" HdstubRegisterClient: Tail, Insert at head because no other clients.\r\n"));
pClientListHead = pClient;
}
fResult = TRUE;
break;
default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -