185 lines
4.8 KiB
C
185 lines
4.8 KiB
C
|
#include "loader.h"
|
||
|
#include "ps.h"
|
||
|
#include "session.h"
|
||
|
#include "inject.h"
|
||
|
|
||
|
/*
|
||
|
* Get the arch type (either x86 or x64) for a given PE (either PE32 or PE64) DLL image.
|
||
|
*/
|
||
|
DWORD ps_getarch_dll( LPVOID lpDllBuffer )
|
||
|
{
|
||
|
DWORD dwDllArch = PROCESS_ARCH_UNKNOWN;
|
||
|
PIMAGE_NT_HEADERS pNtHeader = NULL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if( !lpDllBuffer )
|
||
|
break;
|
||
|
|
||
|
// get the File Offset of the modules NT Header
|
||
|
pNtHeader = (PIMAGE_NT_HEADERS)( ((UINT_PTR)lpDllBuffer) + ((PIMAGE_DOS_HEADER)lpDllBuffer)->e_lfanew );
|
||
|
|
||
|
if( pNtHeader->OptionalHeader.Magic == 0x010B ) // PE32
|
||
|
dwDllArch = PROCESS_ARCH_X86;
|
||
|
else if( pNtHeader->OptionalHeader.Magic == 0x020B ) // PE64
|
||
|
dwDllArch = PROCESS_ARCH_X64;
|
||
|
|
||
|
} while( 0 );
|
||
|
|
||
|
return dwDllArch;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Inject a DLL into another process via Reflective DLL Injection.
|
||
|
*/
|
||
|
DWORD ps_inject( DWORD dwPid, DLL_BUFFER * pDllBuffer )
|
||
|
{
|
||
|
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||
|
DWORD dwPidArch = PROCESS_ARCH_UNKNOWN;
|
||
|
DWORD dwDllArch = PROCESS_ARCH_UNKNOWN;
|
||
|
LPVOID lpDllBuffer = NULL;
|
||
|
DWORD dwDllLenght = 0;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if( !pDllBuffer )
|
||
|
BREAK_WITH_ERROR( "[PS] ps_inject_dll. No Dll buffer specified", ERROR_INVALID_PARAMETER );
|
||
|
|
||
|
dwPidArch = ps_getarch( dwPid );
|
||
|
|
||
|
if( dwPidArch == PROCESS_ARCH_X86 )
|
||
|
{
|
||
|
lpDllBuffer = pDllBuffer->lpPE32DllBuffer;
|
||
|
dwDllLenght = pDllBuffer->dwPE32DllLenght;
|
||
|
}
|
||
|
else if( dwPidArch == PROCESS_ARCH_X64 )
|
||
|
{
|
||
|
lpDllBuffer = pDllBuffer->lpPE64DllBuffer;
|
||
|
dwDllLenght = pDllBuffer->dwPE64DllLenght;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BREAK_WITH_ERROR( "[PS] ps_inject_dll. Unable to determine target pid arhitecture", ERROR_INVALID_DATA );
|
||
|
}
|
||
|
|
||
|
dwDllArch = ps_getarch_dll( lpDllBuffer );
|
||
|
if( dwDllArch == PROCESS_ARCH_UNKNOWN )
|
||
|
BREAK_WITH_ERROR( "[PS] ps_inject_dll. Unable to determine DLL arhitecture", ERROR_BAD_FORMAT );
|
||
|
|
||
|
if( dwDllArch != dwPidArch )
|
||
|
BREAK_WITH_ERROR( "[PS] ps_inject_dll. pid/dll architecture mixup", ERROR_BAD_ENVIRONMENT );
|
||
|
|
||
|
dwResult = inject_dll( dwPid, lpDllBuffer, dwDllLenght );
|
||
|
|
||
|
} while( 0 );
|
||
|
|
||
|
return dwResult;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Get the architecture of the given process.
|
||
|
*/
|
||
|
DWORD ps_getarch( DWORD dwPid )
|
||
|
{
|
||
|
DWORD result = PROCESS_ARCH_UNKNOWN;
|
||
|
static DWORD dwNativeArch = PROCESS_ARCH_UNKNOWN;
|
||
|
HANDLE hKernel = NULL;
|
||
|
HANDLE hProcess = NULL;
|
||
|
ISWOW64PROCESS pIsWow64Process = NULL;
|
||
|
BOOL bIsWow64 = FALSE;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// grab the native systems architecture the first time we use this function...
|
||
|
if( dwNativeArch == PROCESS_ARCH_UNKNOWN )
|
||
|
dwNativeArch = ps_getnativearch();
|
||
|
|
||
|
// first we default to 'x86' as if kernel32!IsWow64Process is not present then we are on an older x86 system.
|
||
|
result = PROCESS_ARCH_X86;
|
||
|
|
||
|
hKernel = LoadLibraryA( "kernel32.dll" );
|
||
|
if( !hKernel )
|
||
|
break;
|
||
|
|
||
|
pIsWow64Process = (ISWOW64PROCESS)GetProcAddress( hKernel, "IsWow64Process" );
|
||
|
if( !pIsWow64Process )
|
||
|
break;
|
||
|
|
||
|
// now we must default to an unknown architecture as the process may be either x86/x64 and we may not have the rights to open it
|
||
|
result = PROCESS_ARCH_UNKNOWN;
|
||
|
|
||
|
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwPid );
|
||
|
if( !hProcess )
|
||
|
{
|
||
|
hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPid );
|
||
|
if( !hProcess )
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if( !pIsWow64Process( hProcess, &bIsWow64 ) )
|
||
|
break;
|
||
|
|
||
|
if( bIsWow64 )
|
||
|
result = PROCESS_ARCH_X86;
|
||
|
else
|
||
|
result = dwNativeArch;
|
||
|
|
||
|
} while( 0 );
|
||
|
|
||
|
if( hProcess )
|
||
|
CloseHandle( hProcess );
|
||
|
|
||
|
if( hKernel )
|
||
|
FreeLibrary( hKernel );
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Get the native architecture of the system we are running on.
|
||
|
*/
|
||
|
DWORD ps_getnativearch( VOID )
|
||
|
{
|
||
|
HANDLE hKernel = NULL;
|
||
|
GETNATIVESYSTEMINFO pGetNativeSystemInfo = NULL;
|
||
|
DWORD dwNativeArch = PROCESS_ARCH_UNKNOWN;
|
||
|
SYSTEM_INFO SystemInfo = {0};
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// default to 'x86' as if kernel32!GetNativeSystemInfo is not present then we are on an old x86 system.
|
||
|
dwNativeArch = PROCESS_ARCH_X86;
|
||
|
|
||
|
hKernel = LoadLibraryA( "kernel32.dll" );
|
||
|
if( !hKernel )
|
||
|
break;
|
||
|
|
||
|
pGetNativeSystemInfo = (GETNATIVESYSTEMINFO)GetProcAddress( hKernel, "GetNativeSystemInfo" );
|
||
|
if( !pGetNativeSystemInfo )
|
||
|
break;
|
||
|
|
||
|
pGetNativeSystemInfo( &SystemInfo );
|
||
|
switch( SystemInfo.wProcessorArchitecture )
|
||
|
{
|
||
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
||
|
dwNativeArch = PROCESS_ARCH_X64;
|
||
|
break;
|
||
|
case PROCESSOR_ARCHITECTURE_IA64:
|
||
|
dwNativeArch = PROCESS_ARCH_IA64;
|
||
|
break;
|
||
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
||
|
dwNativeArch = PROCESS_ARCH_X86;
|
||
|
break;
|
||
|
default:
|
||
|
dwNativeArch = PROCESS_ARCH_UNKNOWN;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while( 0 );
|
||
|
|
||
|
if( hKernel )
|
||
|
FreeLibrary( hKernel );
|
||
|
|
||
|
return dwNativeArch;
|
||
|
}
|