Leaked source code of windows server 2003
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.
 
 
 
 
 
 

709 lines
16 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
injecter.cxx
Abstract:
Injecter
Author:
Larry Zhu (LZhu) December 1, 2001 Created
Environment:
User Mode
Revision History:
--*/
#include "precomp.hxx"
#pragma hdrstop
#include "injecter.hxx"
DWORD
AdjustDebugPriv(
VOID
)
{
HANDLE hToken = NULL;
DWORD dwErr = 0;
TOKEN_PRIVILEGES newPrivs = {0};
if (!OpenProcessToken(
GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&hToken))
{
dwErr = GetLastError();
goto Cleanup;
}
if (!LookupPrivilegeValue(
NULL,
SE_DEBUG_NAME,
&newPrivs.Privileges[0].Luid
))
{
dwErr = GetLastError();
goto Cleanup;
}
newPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
newPrivs.PrivilegeCount = 1;
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&newPrivs,
0,
NULL,
NULL
))
{
dwErr = GetLastError();
goto Cleanup;
}
Cleanup:
if (hToken)
{
CloseHandle(hToken);
}
return dwErr;
}
static DWORD
WorkerFunc(
IN REMOTE_INFO* pInfo
)
{
HINSTANCE hDll = NULL;
PFuncRunIt_t pFuncRunit = NULL;
DWORD dwErr = -1;
hDll = pInfo->pFuncLoadLibrary(pInfo->szDllName);
if (hDll != NULL)
{
pFuncRunit = (PFuncRunIt_t) pInfo->pFuncGetProcAddress(
hDll,
pInfo->szProcName
);
if (pFuncRunit != NULL)
{
dwErr = pFuncRunit(
pInfo->cbParameters,
pInfo->Parameters
);
}
else
{
dwErr = -3;
}
//
// ERROR_NO_MORE_USER_HANDLES unload repeatedly
// ERROR_SERVER_HAS_OPEN_HANDLES no unload at all
// others unload once
//
if (ERROR_SERVER_HAS_OPEN_HANDLES != dwErr)
{
pInfo->pFuncFreeLibrary(hDll);
//
// unload abandoned dll
//
if (ERROR_NO_MORE_USER_HANDLES == dwErr)
{
while (pInfo->pFuncFreeLibrary(hDll))
{
// repeat FreeLibrary unit it fails
}
}
}
}
else
{
dwErr = -2;
}
return dwErr;
}
static VOID
MarkerFunc(
VOID
)
{
// empty
}
DWORD
InjectDllToProcess(
IN HANDLE hProc,
IN PCSTR pszDllFileName,
IN ULONG cbParameters,
IN VOID* pvParameters
)
{
DWORD dwErr = ERROR_SUCCESS;
VOID* pRemoteAlloc = NULL;
HANDLE hRemoteThread = NULL;
HINSTANCE hKernel32 = NULL;
HINSTANCE hDll = NULL;
REMOTE_INFO* pRemInfo = NULL;
ULONG cbRemInfo = 0;
ULONG ulFuncSize = 0;
ULONG ulBytesToAlloc = 0;
CHAR szDllPath[MAX_PATH] = {0};
SIZE_T dwBytesWritten = 0;
DWORD dwIgnored;
ULONG cbPadding = sizeof(ULONG);
cbRemInfo = sizeof(REMOTE_INFO) + cbParameters | sizeof(VOID*); // add a safe zone
pRemInfo = (REMOTE_INFO*) new CHAR [cbRemInfo];
if (!pRemInfo)
{
dwErr = ERROR_OUTOFMEMORY;
}
RtlZeroMemory(pRemInfo, cbRemInfo);
pRemInfo->cbParameters = cbParameters;
hKernel32 = LoadLibraryA("Kernel32");
if (!hKernel32)
{
dwErr = GetLastError();
goto Cleanup;
}
pRemInfo->pFuncLoadLibrary = (PFuncLoadLib_t) GetProcAddress(hKernel32, "LoadLibraryA");
if (!pRemInfo->pFuncLoadLibrary)
{
dwErr = GetLastError();
goto Cleanup;
}
pRemInfo->pFuncGetProcAddress = (PFuncGetProcAddr_t) GetProcAddress(hKernel32, "GetProcAddress");
if (!pRemInfo->pFuncGetProcAddress)
{
dwErr = GetLastError();
goto Cleanup;
}
pRemInfo->pFuncFreeLibrary = (PFuncFreeLib_t) GetProcAddress(hKernel32, "FreeLibrary");
if (!pRemInfo->pFuncFreeLibrary)
{
dwErr = GetLastError();
goto Cleanup;
}
if (0 == GetModuleFileNameA(NULL, szDllPath, sizeof (szDllPath)))
{
dwErr = GetLastError();
goto Cleanup;
}
strcpy(strrchr (szDllPath, '\\') + 1, pszDllFileName);
strncpy(pRemInfo->szDllName, szDllPath, sizeof(pRemInfo->szDllName));
strncpy(pRemInfo->szProcName, REMOTE_DLL_ENTRY, sizeof(pRemInfo->szProcName));
pRemInfo->cbParameters = cbParameters;
memcpy(&pRemInfo->Parameters, pvParameters, pRemInfo->cbParameters);
ulFuncSize = (ULONG) ((ULONG_PTR) MarkerFunc - (ULONG_PTR) WorkerFunc);
cbPadding = sizeof(void*) - ulFuncSize % sizeof(void*);
ulBytesToAlloc = ulFuncSize + cbPadding + cbRemInfo;
DebugPrintf(SSPI_LOG, "InjectDllToProcess dllname %s, ulBytesToAlloc %#x, cbRemInfo %#x\n",
pszDllFileName, ulBytesToAlloc, cbRemInfo);
DebugPrintf(SSPI_LOG, "pInfo->pFuncLoadLibrary %p\n", pRemInfo->pFuncLoadLibrary);
DebugPrintf(SSPI_LOG, "pInfo->pFuncGetProcAddress %p\n", pRemInfo->pFuncGetProcAddress);
DebugPrintf(SSPI_LOG, "pInfo->pFuncFreeLibrary %p\n", pRemInfo->pFuncFreeLibrary);
DebugPrintf(SSPI_LOG, "pInfo->szDllName %s\n", pRemInfo->szDllName);
DebugPrintf(SSPI_LOG, "pInfo->szProcName %s\n", pRemInfo->szProcName);
DebugPrintf(SSPI_LOG, "pInfo->cbParameters %#x, pInfo->Parameters %p\n",
pRemInfo->cbParameters, pRemInfo->Parameters);
DebugPrintHex(SSPI_LOG, "Parameters", pRemInfo->cbParameters, pRemInfo->Parameters);
pRemoteAlloc = VirtualAllocEx(
hProc,
NULL,
ulBytesToAlloc,
MEM_COMMIT,
PAGE_READWRITE
);
if (pRemoteAlloc == NULL)
{
dwErr = GetLastError();
goto Cleanup;
}
if (!WriteProcessMemory(
hProc,
pRemoteAlloc,
(PVOID) WorkerFunc,
ulFuncSize + cbPadding,
&dwBytesWritten
))
{
dwErr = GetLastError();
goto Cleanup;
}
if (!WriteProcessMemory(
hProc,
((UCHAR*) pRemoteAlloc) + ulFuncSize + cbPadding,
pRemInfo,
cbRemInfo,
&dwBytesWritten
))
{
dwErr = GetLastError();
goto Cleanup;
}
DebugPrintf(SSPI_LOG,
"InjectDllToProcess pRemoteAlloc %p, pRemInfo %p\n",
pRemoteAlloc, ((UCHAR*) pRemoteAlloc) + ulFuncSize + cbPadding);
hRemoteThread = CreateRemoteThread(
hProc,
NULL,
0,
(PTHREAD_START_ROUTINE) pRemoteAlloc, // start address
((UCHAR*) pRemoteAlloc) + ulFuncSize + cbPadding, // parameter
0, // creation flags
&dwIgnored
);
if (!hRemoteThread)
{
dwErr = GetLastError();
goto Cleanup;
}
//
// run Init()
//
dwErr = WaitForSingleObject(hRemoteThread, INFINITE);
if (dwErr != ERROR_SUCCESS)
{
DebugPrintf(SSPI_ERROR, "WaitForSingleObject failed with %#x\n", dwErr);
dwErr = GetLastError();
}
Cleanup:
if (hKernel32)
{
FreeLibrary(hKernel32);
}
if (hRemoteThread)
{
CloseHandle(hRemoteThread);
}
if (pRemoteAlloc)
{
VirtualFreeEx(hProc, pRemoteAlloc, 0, MEM_RELEASE);
}
if (pRemInfo)
{
delete [] pRemInfo;
}
return dwErr;
}
DWORD
FindPid(
IN PCSTR pszImageFileName
)
{
NTSTATUS Status ;
PSYSTEM_PROCESS_INFORMATION pSystemInfo = NULL;
PSYSTEM_PROCESS_INFORMATION pWalk = NULL;
ANSI_STRING AnsiProcessName = {0};
UNICODE_STRING ProcessName = {0};
DWORD ulPid = 0;
DebugPrintf(SSPI_LOG, "FindPid looking for %s\n", pszImageFileName);
pSystemInfo = new SYSTEM_PROCESS_INFORMATION[1024];
if ( !pSystemInfo )
{
DebugPrintf(SSPI_ERROR, "FindPid out of memory\n");
return ERROR_SUCCESS;
}
Status = NtQuerySystemInformation(
SystemProcessInformation,
pSystemInfo,
sizeof( SYSTEM_PROCESS_INFORMATION ) * 1024,
NULL
);
if ( !NT_SUCCESS( Status ) )
{
DebugPrintf(SSPI_ERROR, "NtQuerySystemInformation failed with %#x\n", Status);
return ERROR_SUCCESS;
}
RtlInitAnsiString(&AnsiProcessName, pszImageFileName);
Status = RtlAnsiStringToUnicodeString(&ProcessName, &AnsiProcessName, TRUE);
if ( !NT_SUCCESS( Status ) )
{
DebugPrintf(SSPI_ERROR, "RtlAnsiStringToUnicodeString failed with %#x\n", Status);
return ERROR_SUCCESS;
}
pWalk = pSystemInfo ;
while ( RtlCompareUnicodeString( &pWalk->ImageName, &ProcessName, TRUE ) != 0 )
{
if ( pWalk->NextEntryOffset == 0 )
{
pWalk = NULL ;
break;
}
pWalk = (PSYSTEM_PROCESS_INFORMATION) ((PUCHAR) pWalk + pWalk->NextEntryOffset );
}
if ( !pWalk )
{
delete [] pSystemInfo;
return ERROR_SUCCESS;
}
ulPid = PtrToUlong( pWalk->UniqueProcessId );
delete [] pSystemInfo;
return ulPid;
}
void
DisplayUsage(
IN PCSTR pszApp,
IN OPTIONAL PCSTR pszArgs
)
{
DebugPrintf(SSPI_ERROR, "\n\nUsage: %s <injectee.dll> [-p<PID>|-n<process name>] %s\n\n\n", pszApp, pszArgs ? pszArgs : "");
}
DWORD
Init(
IN PCSTR pszFileName,
IN ULONG argc,
IN PCSTR* argv,
IN PCSTR pszDllName,
IN PCSTR pszRunItProcName,
IN PCSTR pszInitProcName,
OUT ULONG* pcbParameters,
OUT VOID** ppvParameters
)
{
DWORD dwErr = ERROR_SUCCESS;
HINSTANCE hDll = NULL;
PFuncRunIt_t pFuncRunIt = NULL;
PFuncInit_t pFuncInit = NULL;
BOOLEAN bUseDefaulInitHandler = FALSE;
hDll = LoadLibraryA(pszDllName);
if (!hDll)
{
dwErr = GetLastError();
goto Cleanup;
}
pFuncRunIt = (PFuncRunIt_t) GetProcAddress(hDll, pszRunItProcName);
if (!pFuncRunIt)
{
dwErr = GetLastError();
goto Cleanup;
}
pFuncInit = (PFuncInit_t) GetProcAddress(hDll, pszInitProcName);
if (!pFuncInit)
{
dwErr = GetLastError();
DebugPrintf(SSPI_WARN, "Init failed to locate %s %#x\n", REMOTE_DLL_INIT, dwErr);
if (dwErr == ERROR_PROC_NOT_FOUND)
{
bUseDefaulInitHandler = TRUE;
}
else
{
goto Cleanup;
}
}
else
{
dwErr = pFuncInit(
argc,
argv,
pcbParameters,
ppvParameters
);
if (dwErr == ERROR_CONTINUE)
{
bUseDefaulInitHandler = TRUE;
}
else if (dwErr == ERROR_INVALID_PARAMETER)
{
DisplayUsage(pszFileName, (PSTR) (*ppvParameters));
goto Cleanup;
}
else if (dwErr != ERROR_SUCCESS)
{
DebugPrintf(SSPI_ERROR, "Init faield with %#x\n", dwErr);
goto Cleanup;
}
}
if (bUseDefaulInitHandler)
{
dwErr = InitDefaultHandler(argc, argv, pcbParameters, ppvParameters);
}
else
{
dwErr = ERROR_SUCCESS;
}
Cleanup:
if (hDll)
{
FreeLibrary(hDll);
}
return dwErr;
}
int
InitDefaultHandler(
IN ULONG argc,
IN PCSTR* argv,
OUT ULONG* pcbParameters,
OUT VOID** ppvParameters
)
{
DWORD dwErr = ERROR_SUCCESS;
CHAR Parameters[REMOTE_PACKET_SIZE] = {0};
ULONG cbBuffer = sizeof(Parameters);
VOID* pvParameters = NULL;
ULONG cbParameters = 0;
DebugPrintf(SSPI_LOG, "InitDefaultHandler is used\n");
*pcbParameters = 0;
*ppvParameters = NULL;
for (ULONG i = 0; i < (ULONG) argc; i++)
{
cbBuffer -= _snprintf(Parameters + sizeof(Parameters) - cbBuffer, cbBuffer, "%s", argv[i]);
cbBuffer--; // add a null
}
cbBuffer--; // the last null of multi-sz string
cbParameters = sizeof(Parameters) - cbBuffer;
pvParameters = new CHAR[cbParameters];
if (pvParameters)
{
memcpy(pvParameters, Parameters, cbParameters);
*ppvParameters = pvParameters;
pvParameters = NULL;
*pcbParameters = cbParameters;
}
else
{
dwErr = ERROR_OUTOFMEMORY;
goto Cleanup;
}
Cleanup:
if (pvParameters)
{
delete [] pvParameters;
}
return dwErr;
}
int __cdecl
main(
IN int argc,
IN CHAR* argv[]
)
{
DWORD dwErr = ERROR_SUCCESS;
DWORD dwIgnored;
HANDLE hLsassProc = NULL;
HANDLE hReceiveThread = NULL;
ULONG ulPid = 0;
VOID* pvParameters = NULL;
ULONG cbParamerter = 0;
ULONG ulStart = 2;
PSTR pszProcess = "lsass.exe";
if (argc >= 3)
{
if ((argv[2][0] == '-') || (argv[2][0] == '/'))
{
if (argv[2][1] == 'n')
{
ulStart++;
pszProcess = argv[2] + 2 * sizeof(char);
}
else if (argv[2][1] == 'p')
{
ulStart++;
ulPid = strtol(argv[2] + 2 * sizeof(char), NULL, 0);
}
}
}
#if 0
/* allow the user to override settings with command line switches */
for (i = 1; i < argc; i++)
{
if ((*argv[i] == '-') || (*argv[i] == '/'))
{
switch (tolower(*(argv[i]+1)))
{
case 'd':
fEncode = 0;
break;
case 'e':
fEncode = 1;
break;
case 'i':
fFixedStyle = 0;
break;
case 'f':
pszFileName = argv[i] + 2;
break;
case 'h':
case '?':
default:
Usage(argv[0]);
}
}
else
Usage(argv[0]);
}
#endif 0
if ((argc >= 2) && (ulPid == 0))
{
ulPid = FindPid(pszProcess);
}
if (!ulPid)
{
DisplayUsage(argv[0], NULL);
DebugPrintf(SSPI_ERROR, "%s failed: pszProcess is \"%s\", ulPid is %#x\n", argv[0], pszProcess, ulPid);
goto Cleanup;
}
DebugPrintf(SSPI_LOG, "%s is injecting %s with pid %#x(%d)\n", argv[0], pszProcess, ulPid, ulPid);
dwErr = Init(argv[0],
argc - ulStart,
(PCSTR*) reinterpret_cast<PSTR*>(argv + ulStart),
argv[1],
REMOTE_DLL_ENTRY,
REMOTE_DLL_INIT,
&cbParamerter,
&pvParameters);
if (dwErr != ERROR_SUCCESS)
{
DebugPrintf(SSPI_ERROR, "Init failed with error %#x\n", dwErr);
goto Cleanup;
}
dwErr = AdjustDebugPriv();
if (dwErr != ERROR_SUCCESS)
{
DebugPrintf(SSPI_ERROR, "EnableDebugPriv failed with error %#x\n", dwErr);
goto Cleanup;
}
hLsassProc = OpenProcess(MAXIMUM_ALLOWED, FALSE, ulPid);
if (!hLsassProc)
{
DebugPrintf(SSPI_ERROR, "OpenProcess pid %#x failed with last error %#x\n", ulPid, GetLastError());
goto Cleanup;
}
dwErr = InjectDllToProcess(
hLsassProc,
argv[1],
cbParamerter,
pvParameters
);
if (dwErr != ERROR_SUCCESS)
{
DebugPrintf(SSPI_ERROR, "InjectDllToProcess failed with status %#x, dwErr %#x\n", dwErr);
goto Cleanup;
}
Cleanup:
if (pvParameters)
{
delete [] pvParameters;
}
if (hLsassProc)
{
CloseHandle(hLsassProc);
}
if (hReceiveThread)
{
CloseHandle(hReceiveThread);
}
return ERROR_SUCCESS;
}