feat: add x86 support

This commit is contained in:
2026-02-27 11:26:57 +07:00
parent b679880ff4
commit 237ceb215e
4 changed files with 95 additions and 10 deletions
+2 -1
View File
@@ -1,11 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<Platforms>x64</Platforms>
<Platforms>x64;x86</Platforms>
<AssemblyName>TimeMocker.Hook</AssemblyName>
<RootNamespace>TimeMocker.Hook</RootNamespace>
<OutputType>Library</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>$(Platform)</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EasyHook" Version="2.7.7097.0"/>
+52 -5
View File
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using EasyHook;
namespace TimeMocker.UI.Core
@@ -20,8 +21,14 @@ namespace TimeMocker.UI.Core
private readonly Dictionary<int, InjectedProcess> _injected
= new Dictionary<int, InjectedProcess>();
private static readonly string HookDllPath =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TimeMocker.Hook.dll");
private static readonly string HookDllPathX64 =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TimeMocker.Hook.x64.dll");
private static readonly string HookDllPathX86 =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TimeMocker.Hook.x86.dll");
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
public event Action<string> LogMessage;
@@ -46,16 +53,19 @@ namespace TimeMocker.UI.Core
// Write initial delta (zero = real time) before hook starts reading
entry.Shm.Write(new MockTimeInfo { DeltaTicks = 0 });
// Determine which DLL to use based on target process architecture
string hookDllPath = GetHookDllPath(process);
RemoteHooking.Inject(
process.Id,
InjectionOptions.DoNotRequireStrongName,
HookDllPath,
HookDllPath,
hookDllPath,
hookDllPath,
entry.Shm.MmfName);
entry.IsInjected = true;
_injected[process.Id] = entry;
Log($"Injected into [{process.Id}] {process.ProcessName}");
Log($"Injected into [{process.Id}] {process.ProcessName} ({GetArchitectureName(process)})");
}
catch (Exception ex)
{
@@ -67,6 +77,43 @@ namespace TimeMocker.UI.Core
return entry;
}
private static string GetHookDllPath(Process process)
{
bool is64BitTarget = Is64BitProcess(process);
if (is64BitTarget)
{
if (!File.Exists(HookDllPathX64))
throw new FileNotFoundException($"x64 hook DLL not found: {HookDllPathX64}");
return HookDllPathX64;
}
else
{
if (!File.Exists(HookDllPathX86))
throw new FileNotFoundException($"x86 hook DLL not found: {HookDllPathX86}");
return HookDllPathX86;
}
}
private static bool Is64BitProcess(Process process)
{
if (!Environment.Is64BitOperatingSystem)
return false;
bool isWow64;
if (!IsWow64Process(process.Handle, out isWow64))
return false;
// If IsWow64Process returns false, it's a 64-bit process
// If it returns true, it's a 32-bit process running on 64-bit Windows
return !isWow64;
}
private static string GetArchitectureName(Process process)
{
return Is64BitProcess(process) ? "x64" : "x86";
}
// -----------------------------------------------------------------------
// Update fake time for a process
// -----------------------------------------------------------------------
+4
View File
@@ -363,6 +363,8 @@ namespace TimeMocker.UI.Forms
}
catch
{
// Skip processes we can't access
continue;
}
_allRows.Add(new ProcessRow
@@ -390,6 +392,8 @@ namespace TimeMocker.UI.Forms
dgvProcesses.ResumeLayout();
}
// =====================================================================
// Patterns Tab
// =====================================================================
// Patterns Tab
// =====================================================================
+37 -4
View File
@@ -13,8 +13,41 @@
<PackageReference Include="EasyHook" Version="2.7.7097.0"/>
<PackageReference Include="System.Text.Json" Version="8.0.5"/>
</ItemGroup>
<ItemGroup>
<!-- Ensure the hook DLL is always next to the UI exe -->
<ProjectReference Include="..\TimeMocker.Hook\TimeMocker.Hook.csproj"/>
</ItemGroup>
<!-- Build both x86 and x64 versions of the hook DLL and copy with architecture suffix -->
<Target Name="BuildAllHookDlls" AfterTargets="Build" DependsOnTargets="_BuildX64Hook;_BuildX86Hook;_CopyHookDlls">
</Target>
<Target Name="_BuildX64Hook">
<MSBuild Projects="$(SolutionDir)TimeMocker.Hook\TimeMocker.Hook.csproj"
Properties="Platform=x64;Configuration=$(Configuration)"
Targets="Build"
RunEachTargetSeparately="true" />
</Target>
<Target Name="_BuildX86Hook">
<MSBuild Projects="$(SolutionDir)TimeMocker.Hook\TimeMocker.Hook.csproj"
Properties="Platform=x86;Configuration=$(Configuration)"
Targets="Build"
RunEachTargetSeparately="true" />
</Target>
<Target Name="_CopyHookDlls" DependsOnTargets="_BuildX64Hook;_BuildX86Hook">
<PropertyGroup>
<HookBuildDir>$(SolutionDir)TimeMocker.Hook\bin\</HookBuildDir>
<X64DllPath>$(HookBuildDir)x64\$(Configuration)\net48\TimeMocker.Hook.dll</X64DllPath>
<X86DllPath>$(HookBuildDir)x86\$(Configuration)\net48\TimeMocker.Hook.dll</X86DllPath>
<X64Dest>$(OutputPath)TimeMocker.Hook.x64.dll</X64Dest>
<X86Dest>$(OutputPath)TimeMocker.Hook.x86.dll</X86Dest>
</PropertyGroup>
<!-- Copy x64 version with x64 suffix -->
<Copy SourceFiles="$(X64DllPath)"
DestinationFiles="$(X64Dest)"
SkipUnchangedFiles="true" />
<!-- Copy x86 version with x86 suffix -->
<Copy SourceFiles="$(X86DllPath)"
DestinationFiles="$(X86Dest)"
SkipUnchangedFiles="true" />
</Target>
<!-- Clean the renamed DLLs as well -->
<Target Name="CleanRenamedHookDlls" AfterTargets="Clean">
<Delete Files="$(OutputPath)TimeMocker.Hook.x64.dll" TreatErrorsAsWarnings="true" />
<Delete Files="$(OutputPath)TimeMocker.Hook.x86.dll" TreatErrorsAsWarnings="true" />
</Target>
</Project>