|
|
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <tlhelp32.h>
#include "profiler.h"
#include "inject.h"
#include "view.h"
#include "except.h"
#include "thread.h"
#include "dump.h"
#include "shimdb.h"
#include "shim2.h"
#include "hooks.h"
#include "memory.h"
#include "filter.h"
#include "clevel.h"
#include "cap.h"
extern CHAR g_fnFinalizeInjection[MAX_PATH]; extern HINSTANCE g_hProfileDLL; extern FIXUPRETURN g_fnFixupReturn[1]; extern DWORD g_dwCallArray[2]; extern CAPFILTER g_execFilter;
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR lpszCmd, int swShow) { HANDLE hFile = 0; BOOL bResult = FALSE; STARTUPINFO sInfo; PCHAR pszToken; PCHAR pszEnd; PROCESS_INFORMATION pInfo; DWORD dwEntry = 0; OSVERSIONINFO verInfo; BOOL bIsWin9X = FALSE; HANDLE hDevice = INVALID_HANDLE_VALUE;
//
// Get the OS information
//
ZeroMemory(&verInfo, sizeof(OSVERSIONINFO)); verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); bResult = GetVersionExA(&verInfo); if (FALSE == bResult) { return -1; }
if (VER_PLATFORM_WIN32_NT == verInfo.dwPlatformId) { bIsWin9X = FALSE; } else if (VER_PLATFORM_WIN32_WINDOWS == verInfo.dwPlatformId) { bIsWin9X = TRUE; }
//
// Initialize my working heap
//
bResult = InitializeHeap(); if (FALSE == bResult) { return -1; }
//
// Parse the command line
//
pszToken = strstr(lpszCmd, "\""); if (pszToken) { pszToken++;
pszEnd = strstr(pszToken, "\""); *pszEnd = '\0'; }
if (0 == pszToken) { pszToken = strstr(lpszCmd, " "); if (0 == pszToken) { pszToken = strstr(lpszCmd, "\t"); if (0 == pszToken) { pszToken = lpszCmd; } } }
//
// Initialize our process information struct
//
ZeroMemory(&sInfo, sizeof(STARTUPINFO)); ZeroMemory(&pInfo, sizeof(PROCESS_INFORMATION)); sInfo.cb = sizeof(STARTUPINFO);
dwEntry = GetExeEntryPoint(pszToken); if (0 == dwEntry) { return -1; }
//
// Get our exe ready for DLL injection
//
bResult = CreateProcessA(0, pszToken, 0, 0, FALSE, CREATE_SUSPENDED, 0, 0, //should make this a setable param sooner rather than later
&sInfo, &pInfo); if (FALSE == bResult) { return -1; }
//
// If we're 9x - bring in the VxD
//
if (TRUE == bIsWin9X) { hDevice = AttachToEXVectorVXD(); if (INVALID_HANDLE_VALUE == hDevice) { return -1; } }
//
// Inject our dll into the target
//
hFile = InjectDLL(dwEntry, pInfo.hProcess, NAME_OF_DLL_TO_INJECT); if (0 == hFile) { return -1; }
//
// Turn the process loose
//
bResult = ResumeThread(pInfo.hThread); if (FALSE == bResult) { return -1; }
//
// Wait for target termination
//
WaitForSingleObject(pInfo.hThread, INFINITE);
//
// If we're 9x - close our handle to the vxd (this will unload the vxd from memory)
//
if (TRUE == bIsWin9X) { if (INVALID_HANDLE_VALUE != hDevice) { DetachFromEXVectorVXD(hDevice); } }
return 0; }
DWORD GetExeEntryPoint(LPSTR pszExePath) { PIMAGE_NT_HEADERS pHeaders; BOOL bResult; PCHAR pEXEBits = 0; DWORD dwEntry = 0; DWORD dwNumberBytesRead; HANDLE hFile = INVALID_HANDLE_VALUE;
pEXEBits = (PCHAR)AllocMem(4096 * 1); //allocate a page for reading the PE entry point
if (0 == pEXEBits) { return dwEntry; }
hFile = CreateFileA(pszExePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (INVALID_HANDLE_VALUE == hFile) { goto handleerror; }
bResult = ReadFile(hFile, pEXEBits, 4096, //read one page
&dwNumberBytesRead, 0); if (FALSE == bResult) { goto handleerror; }
//
// Dig out the PE information
//
pHeaders = ImageNtHeader2((PVOID)pEXEBits); if (0 == pHeaders) { goto handleerror; }
dwEntry = pHeaders->OptionalHeader.ImageBase + pHeaders->OptionalHeader.AddressOfEntryPoint; handleerror:
if (pEXEBits) { FreeMem(pEXEBits); }
if (INVALID_HANDLE_VALUE != hFile) { CloseHandle(hFile); } return dwEntry; }
PIMAGE_NT_HEADERS ImageNtHeader2 (PVOID Base) { PIMAGE_NT_HEADERS NtHeaders = NULL;
if (Base != NULL && Base != (PVOID)-1) { if (((PIMAGE_DOS_HEADER)Base)->e_magic == IMAGE_DOS_SIGNATURE) { NtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)Base + ((PIMAGE_DOS_HEADER)Base)->e_lfanew);
if (NtHeaders->Signature != IMAGE_NT_SIGNATURE) { NtHeaders = NULL; } } }
return NtHeaders; }
BOOL WINAPI DllMain ( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { PIMAGE_NT_HEADERS pHeaders; PVOID pBase = 0; DWORD dwEntryPoint; BOOL bResult = FALSE;
//
// Return true for everything coming through here
//
if (DLL_PROCESS_ATTACH == fdwReason) { //
// Initialize my working heap
//
bResult = InitializeHeap(); if (FALSE == bResult) { return FALSE; }
//
// Initialize the asm for the fixup return
//
//
// Get the entry point from the headers
//
pBase = (PVOID)GetModuleHandle(0); if (0 == pBase) { return FALSE; }
//
// Dig out the PE information
//
pHeaders = ImageNtHeader2(pBase); if (0 == pHeaders) { return FALSE; }
dwEntryPoint = pHeaders->OptionalHeader.ImageBase + pHeaders->OptionalHeader.AddressOfEntryPoint;
//
// Initialize stub asm for cleanup
//
g_fnFinalizeInjection[0] = 0x90; // int 3
g_fnFinalizeInjection[1] = 0xff; // call dword ptr [xxxxxxxx] - RestoreImageFromInjection
g_fnFinalizeInjection[2] = 0x15; *(DWORD *)(&(g_fnFinalizeInjection[3])) = (DWORD)g_fnFinalizeInjection + 50; g_fnFinalizeInjection[7] = 0x83; g_fnFinalizeInjection[8] = 0xc4; g_fnFinalizeInjection[9] = 0x04; g_fnFinalizeInjection[10] = 0x61; g_fnFinalizeInjection[11] = 0xa1; *(DWORD *)(&(g_fnFinalizeInjection[12])) = (DWORD)g_fnFinalizeInjection + 54; g_fnFinalizeInjection[16] = 0xff; g_fnFinalizeInjection[17] = 0xe0;
*(DWORD *)(&(g_fnFinalizeInjection[50])) = (DWORD)RestoreImageFromInjection; *(DWORD *)(&(g_fnFinalizeInjection[54])) = dwEntryPoint;
//
// Initialize the call return code
//
g_dwCallArray[0] = (DWORD)PopCaller; g_dwCallArray[1] = (DWORD)g_fnFixupReturn;
g_fnFixupReturn->PUSHAD = 0x60; //pushad (60)
g_fnFixupReturn->PUSHFD = 0x9c; //pushfd (9c)
g_fnFixupReturn->PUSHDWORDESPPLUS24[0] = 0xff; //push dword ptr [esp+24] (ff 74 24 24)
g_fnFixupReturn->PUSHDWORDESPPLUS24[1] = 0x74; g_fnFixupReturn->PUSHDWORDESPPLUS24[2] = 0x24; g_fnFixupReturn->PUSHDWORDESPPLUS24[3] = 0x24; g_fnFixupReturn->CALLROUTINE[0] = 0xff; //call [address] (ff15 dword address)
g_fnFixupReturn->CALLROUTINE[1] = 0x15; *(DWORD *)(&(g_fnFixupReturn->CALLROUTINE[2])) = (DWORD)&(g_dwCallArray[0]); g_fnFixupReturn->MOVESPPLUS24EAX[0] = 0x89; //mov [esp+0x24],eax (89 44 24 24)
g_fnFixupReturn->MOVESPPLUS24EAX[1] = 0x44; g_fnFixupReturn->MOVESPPLUS24EAX[2] = 0x24; g_fnFixupReturn->MOVESPPLUS24EAX[3] = 0x24; g_fnFixupReturn->POPFD = 0x9d; //popfd (9d)
g_fnFixupReturn->POPAD = 0x61; //popad (61)
g_fnFixupReturn->RET = 0xc3; //ret (c3)
//
// Store the DLL base address
//
g_hProfileDLL = hinstDLL; } return TRUE; }
BOOL InitializeProfiler(VOID) { BOOL bResult = TRUE; PIMAGE_NT_HEADERS pHeaders; PVOID pBase = 0; DWORD dwEntryPoint; PVIEWCHAIN pvTemp;
//
// Get the entry point from the headers
//
pBase = (PVOID)GetModuleHandle(0); if (0 == pBase) { return FALSE; }
//
// Dig out the PE information
//
pHeaders = ImageNtHeader2(pBase); if (0 == pHeaders) { return FALSE; }
dwEntryPoint = pHeaders->OptionalHeader.ImageBase + pHeaders->OptionalHeader.AddressOfEntryPoint;
//
// Tag the entry point so it'll start profiling with the initial view
//
bResult = InitializeViewData(); if (FALSE == bResult) { //
// Something unexpected happened
//
ExitProcess(-1); }
//
// Initialize execution filter data
//
ZeroMemory(&g_execFilter, sizeof(CAPFILTER));
//
// Initialize thread context data
//
InitializeThreadData();
//
// Get the debug logging setup
//
bResult = InitializeDumpData(); if (FALSE == bResult) { //
// Something unexpected happened
//
ExitProcess(-1); }
//
// Initialize the module filtering
//
bResult = InitializeFilterList(); if (FALSE == bResult) { //
// Something unexpected happened
//
ExitProcess(-1); }
//
// Set up exception trap mechanism
//
bResult = HookUnchainableExceptionFilter(); if (FALSE == bResult) { //
// Something unexpected happened while chaining exception filter
//
ExitProcess(-1); }
//
// Fixup the module list now that everything is restored
//
//
InitializeBaseHooks(g_hProfileDLL);
//
// Write out import table base info
//
bResult = WriteImportDLLTableInfo(); if (FALSE == bResult) { ExitProcess(-1); }
//
// Add our entrypoint to the view monitor
//
pvTemp = AddViewToMonitor(dwEntryPoint, ThreadStart); if (0 == pvTemp) { ExitProcess(-1); }
//
// We're done
//
return TRUE; }
BOOL WriteImportDLLTableInfo(VOID) { HANDLE hSnapshot = INVALID_HANDLE_VALUE; MODULEENTRY32 ModuleEntry32; BOOL bResult;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); if (INVALID_HANDLE_VALUE == hSnapshot) { return FALSE; }
//
// Walk the DLL imports
//
ModuleEntry32.dwSize = sizeof(ModuleEntry32);
bResult = Module32First(hSnapshot, &ModuleEntry32); if (FALSE == bResult) { return bResult; }
while(bResult) { //
// Dump the module information to disk
//
if ((DWORD)(ModuleEntry32.modBaseAddr) != (DWORD)g_hProfileDLL) { bResult = WriteDllInfo(ModuleEntry32.szModule, (DWORD)(ModuleEntry32.modBaseAddr), (DWORD)(ModuleEntry32.modBaseSize)); if (FALSE == bResult) { CloseHandle(hSnapshot);
return FALSE; } }
bResult = Module32Next(hSnapshot, &ModuleEntry32); }
if (INVALID_HANDLE_VALUE != hSnapshot) { CloseHandle(hSnapshot); }
return TRUE; }
HANDLE AttachToEXVectorVXD(VOID) { HANDLE hFile;
hFile = CreateFileA(NAME_OF_EXCEPTION_VXD, 0, 0, 0, 0, FILE_FLAG_DELETE_ON_CLOSE, 0);
return hFile; }
VOID DetachFromEXVectorVXD(HANDLE hDevice) { CloseHandle(hDevice); }
|