diff options
Diffstat (limited to 'Hunted')
-rw-r--r-- | Hunted/Hunted.cpp | 400 | ||||
-rw-r--r-- | Hunted/Hunted.vcxproj | 194 | ||||
-rw-r--r-- | Hunted/Hunted.vcxproj.filters | 39 | ||||
-rw-r--r-- | Hunted/KInterface.cpp | 326 | ||||
-rw-r--r-- | Hunted/pch.cpp | 5 | ||||
-rw-r--r-- | Hunted/pch.h | 14 |
6 files changed, 978 insertions, 0 deletions
diff --git a/Hunted/Hunted.cpp b/Hunted/Hunted.cpp new file mode 100644 index 0000000..b4cbda5 --- /dev/null +++ b/Hunted/Hunted.cpp @@ -0,0 +1,400 @@ +#include "pch.h" +#include "KMemDriver.h" +#include "KInterface.h" + +#include <iostream> +#include <iomanip> +#include <windows.h> + +#pragma comment(lib, "User32.lib") + +#define WHEXOUT std::setfill(L'0') << std::setw(16) << std::hex + +BOOL running = false; +const wchar_t *wName = L"HUNT"; + +typedef struct SSystemGlobalEnvironment +{ + PVOID pDialogSystem; + PVOID p3DEngine; + PVOID pNetwork; + PVOID pNetContext; + PVOID pLobby; + PVOID pScriptSystem; + PVOID pPhysicalWorld; + PVOID pFlowSystem; + PVOID pInput; + PVOID pStatoscope; + PVOID pCryPak; + PVOID pFileChangeMonitor; + PVOID pProfileLogSystem; + PVOID pParticleManager; + PVOID pOpticsManager; + PVOID pFrameProfileSystem; + PVOID pTimer; + PVOID pCryFont; + PVOID pGameFramework; + PVOID pLocalMemoryUsage; + PVOID pEntitySystem; + PVOID pConsole; + PVOID pAudioSystem; + PVOID pSystem; + PVOID pCharacterManager; + PVOID pAISystem; + PVOID pLog; + PVOID pCodeCheckpointMgr; + PVOID pMovieSystem; + PVOID pNameTable; + PVOID pRenderer; + PVOID pAuxGeomRenderer; + PVOID pHardwareMouse; + PVOID pMaterialEffects; + PVOID pJobManager; + PVOID pOverloadSceneManager; + PVOID pFlashUI; + PVOID pUIFramework; + PVOID pServiceNetwork; + PVOID pRemoteCommandManager; + PVOID pDynamicResponseSystem; + PVOID pThreadManager; + PVOID pScaleformHelper; // nullptr when Scaleform support is not enabled + PVOID pSchematyc; + PVOID pSchematyc2; + PVOID pReflection; + + PVOID pLiveCreateManager; + PVOID pLiveCreateHost; + PVOID pMonoRuntime; + UINT32 mMainThreadId; //!< The main thread ID is used in multiple systems so should be stored globally. + UINT32 nMainFrameID; + const char* szCmdLine = ""; //!< Startup command line. + + //! Generic debug string which can be easily updated by any system and output by the debug handler + enum { MAX_DEBUG_STRING_LENGTH = 128 }; + char szDebugStatus[MAX_DEBUG_STRING_LENGTH]; + + //! Used to tell if this is a server/multiplayer instance + bool bServer; + bool bMultiplayer; + bool bHostMigrating; + int bDeepProfiling; + bool bBootProfilerEnabledFrames; + PVOID callbackStartSection; + PVOID callbackEndSection; + ////////////////////////////////////////////////////////////////////////// + + //! Whether we are running unattended, disallows message boxes and other blocking events that require human intervention + bool bUnattendedMode; + //! Whether we are unit testing + bool bTesting; + + bool bNoRandomSeed; +} SSystemGlobalEnvironment; + + + +bool consoleHandler(int signal) { + if (signal == CTRL_C_EVENT) { + if (!running) + exit(EXIT_FAILURE); + running = false; + std::wcout << L"Waiting for graceful shutdown .." << std::endl; + } + return true; +} + +void printBuf(UCHAR *buf, SIZE_T siz, SIZE_T bytesBeforeNewline) { + unsigned int i, j; + const unsigned char colors[] = { 10,11,12,13,14,15 }; + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + for (i = 0, j = 0; i < siz; ++i) { + if (i % bytesBeforeNewline == 0) { + SetConsoleTextAttribute(hConsole, colors[j++ % (sizeof colors)]); + wprintf(L"\n0x%04X: ", i); + } + wprintf(L"%02X ", buf[i]); + } + wprintf(L"\n"); + SetConsoleTextAttribute(hConsole, 15); +} + +BOOL CALLBACK enumWindowsProc(HWND hWnd, LPARAM lParam) +{ + int length = GetWindowTextLength(hWnd); + TCHAR* buffer; + buffer = new TCHAR[length + 1]; + memset(buffer, 0, (length + 1) * sizeof(TCHAR)); + GetWindowText(hWnd, buffer, length + 1); + if (!wcscmp(buffer, wName)) + *(HWND *)lParam = hWnd; + delete[] buffer; + return TRUE; +} + +int wmain(int argc, wchar_t **argv) +{ + HANDLE targetPID = 0; + PVOID buf; + HANDLE kevent; + HANDLE uevent; + + KInterface &ki = KInterface::getInstance(); + std::vector<MEMORY_BASIC_INFORMATION> pages; + std::vector<MODULE_DATA> modules; + + if (argc > 1 && !wcscmp(argv[1], L"test")) { + return 0; + } + + if (argc > 1 && !wcscmp(argv[1], L"wnd")) { + if (argc < 3) { + std::wcout << L"Window title required!" << std::endl; + return 1; + } + wName = argv[2]; + std::wcout << L"Waiting for window title: '" << wName << L"'" << std::endl; + + HWND targetHWND = NULL; + while (1) { + if (!EnumWindows(enumWindowsProc, (LPARAM)&targetHWND)) { + return 1; + } + if (targetHWND) { + std::wcout << L"Found window '" << wName << L"' with Handle 0x" + << std::hex << targetHWND << std::endl; + break; + } + Sleep(1000); + } + GetWindowThreadProcessId(targetHWND, (LPDWORD)&targetPID); + } + + SetConsoleCtrlHandler((PHANDLER_ROUTINE)consoleHandler, TRUE); + + if (!ki.Init()) { + std::wcout << L"Kernel Interface Init() failed" << std::endl; + return 1; + } + + try { + buf = ki.getBuffer(); + kevent = ki.getKHandle(); + uevent = ki.getUHandle(); + } + catch (std::runtime_error& err) { + std::wcout << err.what() << std::endl; + return 1; + } + + std::wcout << L"Buffer.: " << buf << std::endl; + std::wcout << L"KHandle: " << kevent << std::endl; + std::wcout << L"UHandle: " << uevent << std::endl; + + if (!ki.Handshake()) { + std::wcout << L"Kernel Interface Handshake() failed" << std::endl; + return 1; + } + if (targetPID) { + if (!ki.Modules(targetPID, modules)) + std::wcout << L"Kernel Interface Modules() failed with 0x" + << std::hex << ki.getLastNtStatus() << std::endl; + else std::wcout << L"Got " << std::dec << modules.size() << L" modules for pid 0x" + << std::hex << targetPID << std::endl; + if (!ki.Pages(targetPID, pages)) + std::wcout << L"Kernel Interface Pages() failed with 0x" + << std::hex << ki.getLastNtStatus() << std::endl; + else std::wcout << L"Got " << std::dec << pages.size() << L" mapped pages for pid 0x" + << std::hex << targetPID << std::endl; + } + + running = TRUE; + do { + if (ki.RecvWait() == SRR_TIMEOUT) { + std::wcout << L"Ping -> "; + if (!ki.Ping()) { + std::wcout << L"Got no valid PONG, abort!" << std::endl; + running = FALSE; + } + else std::wcout << L"PONG!" << std::endl; + } + + if (!running) + break; + + try { + if (targetPID) { + for (MODULE_DATA& md : modules) { + if (!strncmp(md.BaseDllName, "CrySystem.dll", + sizeof md.BaseDllName)) + { + std::wcout << L"CrySystem.dll......: 0x" << WHEXOUT << md.DllBase << std::endl; + UINT64 g_pEnv = KMemory::Rpm<UINT64>(targetPID, + (PVOID)((UINT64)md.DllBase + 0xA37708)); + + std::wcout << L"g_pEnv.............: 0x" << WHEXOUT << g_pEnv << std::endl; + } + else + if (!strncmp(md.BaseDllName, "CryEntitySystem.dll", + sizeof md.BaseDllName)) + { + std::wcout << L"CryEntitySystem.dll: 0x" << std::hex << md.DllBase << std::endl; +#if 1 + /* Found: void CEntitySystem::LoadInternalState(IDataReadStream& reader) */ + UINT64 g_pEnv = KMemory::Rpm<UINT64>(targetPID, + (PVOID)((UINT64)md.DllBase + 0x28C400)); + + std::wcout << L"g_pEnv.............: 0x" << WHEXOUT << g_pEnv << std::endl; +#if 1 + BYTE tmp[sizeof SSystemGlobalEnvironment * 2] = { 0 }; + SSIZE_T siz = KMemoryBuf::Rpm<sizeof tmp>(targetPID, (PVOID)(g_pEnv), tmp); + + SSystemGlobalEnvironment *gEnv = (SSystemGlobalEnvironment *)&tmp[0]; + std::wcout << std::hex + << gEnv->p3DEngine << ", " + << gEnv->pEntitySystem << ", " + << gEnv->bMultiplayer << ", " + << gEnv->mMainThreadId << ", " + << gEnv->nMainFrameID << ", " + << gEnv->szDebugStatus << ", " + << gEnv->pMonoRuntime << ", " + << gEnv->callbackStartSection << ", " + << gEnv->callbackEndSection << ", " + << gEnv->bUnattendedMode << ", " + << gEnv->bTesting << ", " + << gEnv->bNoRandomSeed << ", " + << gEnv->bDeepProfiling << ", " + << std::endl; + + /* Found: void CEntitySystem::LoadInternalState(IDataReadStream& reader) + * search for String "ExistingEntity: '%s' '%s'" + */ + UINT64 m_EntityArray = KMemory::Rpm<UINT64>(targetPID, + (PVOID)((UINT64)gEnv->pEntitySystem + 0x40078)); + //m_EntityArray += 0x40078; + std::wcout << WHEXOUT + << m_EntityArray + << std::endl; + + USHORT nops; + nops = KMemory::Rpm<USHORT>(targetPID, + (PVOID)((UINT64)md.DllBase + 0x12C3C7)); + std::wcout << std::hex << "+++ " << nops << std::endl; + nops = 0x9090; + KMemory::Wpm<USHORT>(targetPID, + (PVOID)((UINT64)md.DllBase + 0x12C3C7), &nops); +#if 0 + UINT64 tmp2[1024]; + SSIZE_T siz2 = KMemoryBuf::Rpm<sizeof tmp2>(targetPID, (PVOID)(m_EntityArray), (PBYTE)tmp2); + SIZE_T i = 0; + for (UINT64 val : tmp2) { + if (val) + std::wcout << WHEXOUT << val << ", "; + if (++i % 16 == 0) + std::wcout << std::endl; + } + /* + if (siz2 > 0) + printBuf(tmp2, sizeof tmp2, 64); + */ +#endif +#endif +#if 0 + SSIZE_T siz3; + static Diff<65535> diff = { 0 }; + siz3 = KScan::BinDiffSimple(targetPID, (PVOID)(m_EntityArray), &diff); + if (siz3 > 0) { + std::wcout << L"Got " << std::dec << diff.diffs.size() << L" diffs" << std::endl; + for (auto& e : diff.diffs) { + std::wcout << std::dec << L"0x" + << std::hex << (PVOID)(/*(ULONG_PTR)(m_EntityArray)+*/e.first) + << " - " << std::hex << e.second + << L": "; + printBuf((UCHAR *)((ULONG_PTR)(diff.current_buffer) + e.first), e.second, e.second); + } + } +#endif +#if 0 +#if 1 + //UCHAR scan[1024] = { 0 }; + UCHAR scan[] = "anti_alles"; + SSIZE_T found = KScan::ScanSimple<UCHAR, sizeof scan>(targetPID, + (PVOID)(m_EntityArray), 65535, scan); +#else + SSIZE_T found = (SSIZE_T)(pIEntitySystem)+8192; +#endif + if (found >= 0) { + std::wcout << "FOUND: 0x" << std::hex << (PVOID)found << std::endl; + UCHAR tmp[4096] = { 0 }; + SSIZE_T siz = KMemoryBuf::Rpm<UCHAR, sizeof tmp>(targetPID, (PVOID)found, tmp); + if (siz > 0) { + printBuf(tmp, sizeof tmp, 64); +#if 0 + UINT64 i; + for (i = 0; i < sizeof tmp; i += 8) { + UINT64 value = *(UINT64 *)&tmp[i]; + if (value) + printf("0x%p ", (PVOID)value); + } + printf("\nGot %llu entities ..\n", i); +#endif + } + } +#endif +#endif + } +#if 0 + else if (!strncmp(md.BaseDllName, "CryRenderD3D11.dll", + sizeof md.BaseDllName)) + { + UINT32 displayWidth = KMemory::Rpm<UINT32>(targetPID, + (PVOID)((ULONGLONG)md.DllBase + /* 0x19F0FE */ 0x5EA870)); + UINT32 displayHeight = KMemory::Rpm<UINT32>(targetPID, + (PVOID)((ULONGLONG)md.DllBase + /* 0x19F0F0 */ 0x5EA9DC)); + std::wcout << L"Display.........: " << std::dec << displayWidth + << " x " << displayHeight << std::endl; + } +#endif +#if 0 + else if (!strncmp(md.BaseDllName, "ntdll.dll", + sizeof md.BaseDllName)) + { + UCHAR tmp[8192] = { 0 }; + SSIZE_T siz = KMemoryBuf::Rpm<UCHAR, sizeof tmp>(targetPID, (PVOID)((ULONGLONG)md.DllBase), tmp); + /* + if (siz > 0) + printBuf(tmp, sizeof tmp, 64); + + UCHAR scan[] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; + SSIZE_T found = KScan::ScanSimple<UCHAR, sizeof scan>(targetPID, + (PVOID)((ULONGLONG)md.DllBase), sizeof tmp, scan); + std::wcout << "FOUND: 0x" << std::hex << (found - (ULONGLONG)md.DllBase) << std::endl; + */ + static Diff<10> diff = { 0 }; + siz = KScan::BinDiffSimple(targetPID, (PVOID)((ULONGLONG)md.DllBase), &diff); + if (siz > 0) { + std::wcout << L"Got " << std::dec << diff.diffs.size() << L" diffs" << std::endl; + for (auto& e : diff.diffs) { + printBuf((UCHAR *)((ULONGLONG)md.DllBase + e.first), e.second, e.second); + /* + std::wcout << std::dec << L" addr: " << e.first + << std::endl << L" size: " << e.second + << std::endl; + */ + } + } + } +#endif + } + } + } + catch (std::runtime_error& err) { + std::wcout << err.what() << std::endl; + } + } while (running); + + std::wcout << L"Driver shutdown .." << std::endl; + ki.Exit(); + + return 0; +}
\ No newline at end of file diff --git a/Hunted/Hunted.vcxproj b/Hunted/Hunted.vcxproj new file mode 100644 index 0000000..a87c397 --- /dev/null +++ b/Hunted/Hunted.vcxproj @@ -0,0 +1,194 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>15.0</VCProjectVersion> + <ProjectGuid>{8661069D-CE09-4A70-8C75-8F33E77732E6}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>Hunted</RootNamespace> + <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion> + <ProjectName>Hunted</ProjectName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <SpectreMitigation>false</SpectreMitigation> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <SpectreMitigation>false</SpectreMitigation> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + <SpectreMitigation>false</SpectreMitigation> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <SpectreMitigation>false</SpectreMitigation> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <ExceptionHandling>SyncCThrow</ExceptionHandling> + <BufferSecurityCheck>true</BufferSecurityCheck> + <AdditionalIncludeDirectories>$(SolutionDir)include</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>$(VCToolsInstallDir)lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <ExceptionHandling>SyncCThrow</ExceptionHandling> + <BufferSecurityCheck>false</BufferSecurityCheck> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <ExceptionHandling>Sync</ExceptionHandling> + <BufferSecurityCheck>false</BufferSecurityCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <ExceptionHandling>Sync</ExceptionHandling> + <BufferSecurityCheck>false</BufferSecurityCheck> + <AdditionalIncludeDirectories>$(SolutionDir)include</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>$(VCToolsInstallDir)lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\include\KInterface.h" /> + <ClInclude Include="..\include\KMemDriver.h" /> + <ClInclude Include="pch.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="KInterface.cpp" /> + <ClCompile Include="Hunted.cpp" /> + <ClCompile Include="pch.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> + </ClCompile> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/Hunted/Hunted.vcxproj.filters b/Hunted/Hunted.vcxproj.filters new file mode 100644 index 0000000..6961c18 --- /dev/null +++ b/Hunted/Hunted.vcxproj.filters @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="pch.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\KInterface.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\KMemDriver.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="pch.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Hunted.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="KInterface.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/Hunted/KInterface.cpp b/Hunted/KInterface.cpp new file mode 100644 index 0000000..62859a4 --- /dev/null +++ b/Hunted/KInterface.cpp @@ -0,0 +1,326 @@ +#include "pch.h" +#include "KInterface.h" +#include "KMemDriver.h" + +#include <sstream> +#include <ctime> +#include <stdexcept> + + +KInterface::KInterface() +{ +} + +bool KInterface::Init() +{ + std::srand((unsigned int)std::time(nullptr)); + m_shmem = VirtualAlloc((PVOID)SHMEM_ADDR, SHMEM_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + m_kevent = CreateEvent(NULL, FALSE, FALSE, NULL); + m_uevent = CreateEvent(NULL, FALSE, FALSE, NULL); + return m_shmem && m_kevent != INVALID_HANDLE_VALUE && m_uevent != INVALID_HANDLE_VALUE; +} + +bool KInterface::Handshake() +{ + PKERNEL_HANDSHAKE hnds = (PKERNEL_HANDSHAKE)getBuffer(); + hnds->kevent = m_kevent; + hnds->uevent = m_uevent; + m_last_ntstatus = INVALID_NTSTATUS; + return SendRecvWait(MEM_HANDSHAKE) == SRR_SIGNALED; +} + +bool KInterface::Ping() +{ + SendRecvReturn srr; + PKERNEL_PING ping = (PKERNEL_PING)getBuffer(); + m_last_ping_value = ping->rnd_user = (std::rand() << 16) | std::rand(); + std::srand(m_last_ping_value); + m_last_ntstatus = INVALID_NTSTATUS; + srr = SendRecvWait(MEM_PING); + if (ping->rnd_kern != getLastPingValue()) + return false; + return srr == SRR_SIGNALED; +} + +bool KInterface::Pages(HANDLE targetPID, + std::vector<MEMORY_BASIC_INFORMATION>& dest, + PVOID start_address) +{ + PKERNEL_PAGE pages = (PKERNEL_PAGE)getBuffer(); + const ULONGLONG max_pages = (SHMEM_SIZE - sizeof *pages + + sizeof pages->pages_start) / sizeof pages->pages_start; + SendRecvReturn srr; + bool success = false; + + do { + m_last_ntstatus = INVALID_NTSTATUS; + pages->pages = 0; + pages->ProcessId = targetPID; + pages->StartAddress = start_address; + srr = SendRecvWait(MEM_PAGES); + if (srr == SRR_SIGNALED) { + m_last_ntstatus = pages->StatusRes; + if (validateRespone(getBuffer()) == MEM_PAGES && + !pages->StatusRes && + pages->pages * sizeof(pages->pages_start) <= SHMEM_SIZE) + { + for (SIZE_T i = 0; i < pages->pages; ++i) { + dest.push_back((&pages->pages_start)[i]); + start_address = (PVOID) + ((ULONG_PTR)((&pages->pages_start)[i].BaseAddress) + + (&pages->pages_start)[i].RegionSize); + } + success = true; + } + else { + success = false; + break; + } + } + } while (srr == SRR_SIGNALED && pages->pages == max_pages && pages->pages); + return success && srr == SRR_SIGNALED;; +} + +bool KInterface::Modules(HANDLE targetPID, + std::vector<MODULE_DATA>& dest) +{ + PKERNEL_MODULES mods = (PKERNEL_MODULES)getBuffer(); + SIZE_T start_index = 0; + const ULONGLONG max_mods = (SHMEM_SIZE - sizeof *mods + + sizeof mods->modules_start) / sizeof mods->modules_start; + SendRecvReturn srr; + bool success = false; + + do { + m_last_ntstatus = INVALID_NTSTATUS; + mods->modules = 0; + mods->ProcessId = targetPID; + mods->StartIndex = start_index; + srr = SendRecvWait(MEM_MODULES); + if (srr == SRR_SIGNALED) { + m_last_ntstatus = mods->StatusRes; + if (validateRespone(getBuffer()) == MEM_MODULES && + !mods->StatusRes && + mods->modules * sizeof(mods->modules_start) <= SHMEM_SIZE) + { + for (SIZE_T i = 0; i < mods->modules; ++i) { + dest.push_back((&mods->modules_start)[i]); + start_index++; + } + success = true; + } + else { + success = false; + break; + } + } + } while (srr == SRR_SIGNALED && mods->modules == max_mods && mods->modules); + return success && srr == SRR_SIGNALED; +} + +bool KInterface::Exit() +{ + m_last_ntstatus = INVALID_NTSTATUS; + return SendRecvWait(MEM_EXIT, INFINITE) == SRR_SIGNALED; +} + +bool KInterface::RPM(HANDLE targetPID, PVOID address, BYTE *buf, SIZE_T size, + PKERNEL_READ_REQUEST result) +{ + PKERNEL_READ_REQUEST rr = (PKERNEL_READ_REQUEST)getBuffer(); + m_last_ntstatus = INVALID_NTSTATUS; + if (size > SHMEM_SIZE - sizeof *rr) + return false; + rr->ProcessId = targetPID; + rr->Address = address; + rr->SizeReq = size; + rr->SizeRes = (SIZE_T)-1; + rr->StatusRes = (NTSTATUS)-1; + if (SendRecvWait(MEM_RPM) == SRR_SIGNALED) { + m_last_ntstatus = rr->StatusRes; + if (rr->StatusRes || + rr->SizeRes != size) + { + std::stringstream err_str; + err_str << "Call RPM(0x" << std::hex << address + << "," << std::dec << size + << ") failed with 0x" + << std::hex << rr->StatusRes + << " (Size Req/Res: " + << std::dec << rr->SizeReq << "/" << (SSIZE_T)rr->SizeRes + << ")"; + throw std::runtime_error(err_str.str()); + } + memcpy(buf, (BYTE *)rr + sizeof *rr, size); + if (result) + *result = *rr; + return true; + } + return false; +} + +bool KInterface::WPM(HANDLE targetPID, PVOID address, BYTE *buf, SIZE_T size, + PKERNEL_WRITE_REQUEST result) +{ + PKERNEL_WRITE_REQUEST wr = (PKERNEL_WRITE_REQUEST)getBuffer(); + m_last_ntstatus = INVALID_NTSTATUS; + if (size > SHMEM_SIZE - sizeof *wr) + return false; + wr->ProcessId = targetPID; + wr->Address = address; + wr->SizeReq = size; + wr->SizeRes = (SIZE_T)-1; + wr->StatusRes = (NTSTATUS)-1; + memcpy((BYTE *)wr + sizeof *wr, buf, size); + if (SendRecvWait(MEM_WPM) == SRR_SIGNALED) { + m_last_ntstatus = wr->StatusRes; + if (wr->StatusRes || + wr->SizeRes != size) + { + std::stringstream err_str; + err_str << "Call WPM(0x" << std::hex << address + << "," << std::dec << size + << ") failed with 0x" + << std::hex << wr->StatusRes + << " (Size Req/Res: " + << std::dec << wr->SizeReq << "/" << (SSIZE_T)wr->SizeRes + << ")"; + throw std::runtime_error(err_str.str()); + } + if (result) + *result = *wr; + return true; + } + return false; +} + +PVOID KInterface::getBuffer() { + if (!m_shmem) + throw std::runtime_error("Call Init() before.."); + return m_shmem; +} + +HANDLE KInterface::getKHandle() { + if (!m_kevent) + throw std::runtime_error("Call Init() before.."); + return m_kevent; +} + +HANDLE KInterface::getUHandle() { + if (!m_uevent) + throw std::runtime_error("Call Init() before.."); + return m_uevent; +} + +UINT32 KInterface::getLastPingValue() { + return m_last_ping_value; +} + +UINT32 KInterface::getLastNtStatus() { + return m_last_ntstatus; +} + +SendRecvReturn KInterface::SendRecvWait(UINT32 type, DWORD timeout) +{ + prepareRequest(getBuffer(), type); + if (!SetEvent(m_kevent)) + return SRR_ERR_KEVENT; + return RecvWait(timeout); +} + +SendRecvReturn KInterface::RecvWait(DWORD timeout) +{ + switch (WaitForSingleObject(m_uevent, timeout)) { + case WAIT_OBJECT_0: + return validateRespone(getBuffer()) != INVALID_REQUEST ? SRR_SIGNALED : SRR_ERR_HEADER; + case WAIT_TIMEOUT: + return SRR_TIMEOUT; + } + return SRR_ERR_UEVENT; +} + +SSIZE_T KScan::KScanSimple(HANDLE targetPID, PVOID start_address, SIZE_T max_scansize, + PVOID scanbuf, SIZE_T scanbuf_size) +{ + ULONG_PTR max_addr; + ULONG_PTR cur_addr = (ULONG_PTR)start_address; + BYTE tmp_rpmbuf[SHMEM_SIZE]; + SIZE_T scan_index, processed, real_size, diff_size; + std::vector<MEMORY_BASIC_INFORMATION> mbis; + KERNEL_READ_REQUEST rr = { 0 }; + + if (max_scansize < scanbuf_size) + return -1; + if (!KInterface::getInstance().Pages(targetPID, mbis, start_address)) + return -1; + + diff_size = (ULONG_PTR)start_address - (ULONG_PTR)mbis.at(0).BaseAddress; + real_size = (mbis.at(0).RegionSize - diff_size > max_scansize ? + max_scansize : (ULONG_PTR)mbis.at(0).RegionSize - diff_size); + max_addr = (ULONG_PTR)start_address + real_size; + + while (cur_addr < max_addr) { + if (!KInterface::getInstance().RPM(targetPID, (PVOID)cur_addr, + tmp_rpmbuf, (sizeof tmp_rpmbuf > real_size ? real_size : sizeof tmp_rpmbuf), &rr)) + { + break; + } + + if (rr.StatusRes || rr.SizeRes < scanbuf_size) + break; + + for (processed = 0, scan_index = 0; processed < rr.SizeRes; ++processed) { + if (tmp_rpmbuf[processed] != *((BYTE*)scanbuf + scan_index)) { + scan_index = 0; + } + else { + scan_index++; + if (scan_index == scanbuf_size) { + return cur_addr + processed - scanbuf_size + 1; + } + } + } + cur_addr += processed; + real_size -= processed; + } + return -1; +} + +SSIZE_T KScan::KBinDiffSimple(HANDLE targetPID, PVOID start_address, + BYTE *curbuf, BYTE *oldbuf, SIZE_T siz, std::vector<std::pair<SIZE_T, SIZE_T>> *diffs) +{ + SSIZE_T scanned, diff_start; + SIZE_T diff_size; + KERNEL_READ_REQUEST rr = { 0 }; + + if (!KInterface::getInstance().RPM(targetPID, start_address, + curbuf, siz, &rr)) + { + scanned = -1; + } + else scanned = rr.SizeRes; + + if (scanned > 0) { + diffs->clear(); + diff_start = -1; + diff_size = 0; + for (SIZE_T i = 0; i < (SIZE_T)scanned; ++i) { + if (curbuf[i] != oldbuf[i]) { + if (diff_start < 0) + diff_start = i; + diff_size++; + } + else if (diff_start >= 0) { + diffs->push_back(std::pair<SIZE_T, SIZE_T> + (diff_start, diff_size)); + diff_start = -1; + diff_size = 0; + } + } + memcpy(oldbuf, curbuf, scanned); + if ((SIZE_T)scanned < siz) + memset(oldbuf + scanned, 0, siz - scanned); + } + + return scanned; +}
\ No newline at end of file diff --git a/Hunted/pch.cpp b/Hunted/pch.cpp new file mode 100644 index 0000000..3a3d12b --- /dev/null +++ b/Hunted/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed + +#include "pch.h" + +// In general, ignore this file, but keep it around if you are using pre-compiled headers. diff --git a/Hunted/pch.h b/Hunted/pch.h new file mode 100644 index 0000000..b04e71e --- /dev/null +++ b/Hunted/pch.h @@ -0,0 +1,14 @@ +// Tips for Getting Started: +// 1. Use the Solution Explorer window to add/manage files +// 2. Use the Team Explorer window to connect to source control +// 3. Use the Output window to see build output and other messages +// 4. Use the Error List window to view errors +// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project +// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file + +#ifndef PCH_H +#define PCH_H + +// TODO: add headers that you want to pre-compile here + +#endif //PCH_H |