207 lines
4.9 KiB
C++
207 lines
4.9 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 2001 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
NetManageViewNow.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
|
||
|
The app doesnt follow stdcall conventions for the ServiceMain function
|
||
|
it registers with SCM. This is resulting in an AV as the ServiceMain
|
||
|
is not cleaning up the stack on return, after being called by SCM.
|
||
|
We clean up the stack for the app registered ServiceMain by hooking
|
||
|
StartServiceCtrlDispatcher and registering our own ServiceMain routine,
|
||
|
which makes the actual call to the app registered servicemain and then
|
||
|
pop 8 bytes of the stack before returning.
|
||
|
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
This is an app specific shim.
|
||
|
|
||
|
History:
|
||
|
|
||
|
03/08/2001 a-leelat Created
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
IMPLEMENT_SHIM_BEGIN(NetManageViewNow)
|
||
|
#include "ShimHookMacro.h"
|
||
|
|
||
|
APIHOOK_ENUM_BEGIN
|
||
|
APIHOOK_ENUM_ENTRY(StartServiceCtrlDispatcherA)
|
||
|
APIHOOK_ENUM_ENTRY(StartServiceCtrlDispatcherW)
|
||
|
APIHOOK_ENUM_END
|
||
|
|
||
|
|
||
|
|
||
|
//last entry of the service table are supposed to be NULL entries
|
||
|
SERVICE_TABLE_ENTRYA g_SvcTableA[] = { {NULL,NULL},{NULL,NULL} };
|
||
|
SERVICE_TABLE_ENTRYW g_SvcTableW[] = { {NULL,NULL},{NULL,NULL} };
|
||
|
|
||
|
LPSERVICE_MAIN_FUNCTIONA g_pfnActualMainA = NULL;
|
||
|
LPSERVICE_MAIN_FUNCTIONW g_pfnActualMainW = NULL;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
VOID WINAPI ServiceMainA(
|
||
|
DWORD dwArgc, // number of arguments
|
||
|
LPSTR *lpszArgv // array of arguments
|
||
|
)
|
||
|
{
|
||
|
|
||
|
//call the actual routine
|
||
|
(g_pfnActualMainA)(dwArgc,lpszArgv);
|
||
|
|
||
|
//pop 8 bytes of stack to compensate for
|
||
|
//the app not following stdcall convention
|
||
|
__asm
|
||
|
{
|
||
|
add esp,8
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID WINAPI ServiceMainW(
|
||
|
DWORD dwArgc, // number of arguments
|
||
|
LPWSTR *lpszArgv // array of arguments
|
||
|
)
|
||
|
{
|
||
|
|
||
|
//call the actual routine
|
||
|
(g_pfnActualMainW)(dwArgc,lpszArgv);
|
||
|
|
||
|
//pop 8 bytes of stack to compensate for
|
||
|
//the app not following stdcall convention
|
||
|
__asm
|
||
|
{
|
||
|
add esp, 8
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL APIHOOK(StartServiceCtrlDispatcherA)(
|
||
|
CONST LPSERVICE_TABLE_ENTRYA lpServiceTable // service table
|
||
|
)
|
||
|
{
|
||
|
BOOL bRet = false;
|
||
|
|
||
|
LPSERVICE_TABLE_ENTRYA lpSvcTblToPass = lpServiceTable;
|
||
|
|
||
|
DWORD ccbServiceName = (strlen(lpServiceTable->lpServiceName) + 1) * sizeof(*lpServiceTable->lpServiceName);
|
||
|
LPSTR serviceName = (LPSTR) malloc(ccbServiceName);
|
||
|
|
||
|
if (serviceName == NULL)
|
||
|
{
|
||
|
DPFN( eDbgLevelError,
|
||
|
"[StartServiceCtrlDispatcherA] Buffer allocation failure");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Setup our service table to register with SCM
|
||
|
|
||
|
//Copy the service name as defined by the app
|
||
|
HRESULT hr = StringCbCopyA(serviceName, ccbServiceName, lpServiceTable->lpServiceName);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
g_SvcTableA[0].lpServiceName = serviceName;
|
||
|
|
||
|
//Now put our service routine
|
||
|
g_SvcTableA[0].lpServiceProc = ServiceMainA;
|
||
|
|
||
|
//Save the old servicemain func ptr
|
||
|
g_pfnActualMainA = lpServiceTable->lpServiceProc;
|
||
|
|
||
|
//Set the service table to our table
|
||
|
lpSvcTblToPass = &g_SvcTableA[0];
|
||
|
|
||
|
DPFN( eDbgLevelInfo,
|
||
|
"[StartServiceCtrlDispatcherA] Hooked ServiceMainA");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Call the Original API
|
||
|
bRet = StartServiceCtrlDispatcherA(lpSvcTblToPass);
|
||
|
|
||
|
return bRet;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL APIHOOK(StartServiceCtrlDispatcherW)(
|
||
|
CONST LPSERVICE_TABLE_ENTRYW lpServiceTable // service table
|
||
|
)
|
||
|
{
|
||
|
BOOL bRet = false;
|
||
|
|
||
|
LPSERVICE_TABLE_ENTRYW lpSvcTblToPass = lpServiceTable;
|
||
|
|
||
|
DWORD ccbServiceName = (wcslen(lpServiceTable->lpServiceName) + 1) * sizeof(*lpServiceTable->lpServiceName);
|
||
|
LPWSTR serviceName = (LPWSTR) malloc(ccbServiceName);
|
||
|
|
||
|
if (serviceName == NULL)
|
||
|
{
|
||
|
DPFN( eDbgLevelError,
|
||
|
"[StartServiceCtrlDispatcherW] Buffer allocation failure");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Setup our service table to register with SCM
|
||
|
|
||
|
//Copy the service name as defined by the app
|
||
|
HRESULT hr = StringCbCopyW(serviceName, ccbServiceName, lpServiceTable->lpServiceName);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
g_SvcTableW[0].lpServiceName = serviceName;
|
||
|
|
||
|
//Now put our service routine
|
||
|
g_SvcTableW[0].lpServiceProc = ServiceMainW;
|
||
|
|
||
|
//Save the old servicemain func ptr
|
||
|
g_pfnActualMainW = lpServiceTable->lpServiceProc;
|
||
|
|
||
|
//Set the service table to our table
|
||
|
lpSvcTblToPass = &g_SvcTableW[0];
|
||
|
|
||
|
DPFN( eDbgLevelInfo,
|
||
|
"[StartServiceCtrlDispatcherW] Hooked ServiceMainW");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//Call the Original API
|
||
|
bRet = StartServiceCtrlDispatcherW(lpSvcTblToPass);
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Register hooked functions
|
||
|
|
||
|
--*/
|
||
|
|
||
|
HOOK_BEGIN
|
||
|
|
||
|
APIHOOK_ENTRY(ADVAPI32.DLL, StartServiceCtrlDispatcherA)
|
||
|
APIHOOK_ENTRY(ADVAPI32.DLL, StartServiceCtrlDispatcherW)
|
||
|
|
||
|
HOOK_END
|
||
|
|
||
|
|
||
|
IMPLEMENT_SHIM_END
|
||
|
|