Skip to content

Commit eaefb20

Browse files
1.8.4
- Fixed offline patcher architecture conflicts - Now all builds of offline patcher can patch all kernel images - Previously it was same patcher/kernel due to preprocessor definitions and a bug in code. - Fixed build errors caused by freestanding memset.
1 parent 221fbe2 commit eaefb20

12 files changed

Lines changed: 67 additions & 11 deletions

.vs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.vs

.vs/Offline-VS2026.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@
112112
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
113113
<ConformanceMode>true</ConformanceMode>
114114
<LanguageStandard>Default</LanguageStandard>
115+
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
116+
<DebugInformationFormat>None</DebugInformationFormat>
115117
</ClCompile>
116118
<Link>
117119
<SubSystem>Console</SubSystem>
@@ -140,6 +142,8 @@
140142
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
141143
<ConformanceMode>true</ConformanceMode>
142144
<LanguageStandard>Default</LanguageStandard>
145+
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
146+
<DebugInformationFormat>None</DebugInformationFormat>
143147
</ClCompile>
144148
<Link>
145149
<SubSystem>Console</SubSystem>

.vs/TimeDefuser-VS2013.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
<ExceptionHandling>false</ExceptionHandling>
168168
<BufferSecurityCheck>false</BufferSecurityCheck>
169169
<CreateHotpatchableImage>false</CreateHotpatchableImage>
170+
<WholeProgramOptimization>false</WholeProgramOptimization>
170171
</ClCompile>
171172
<Link>
172173
<SubSystem>Native</SubSystem>
@@ -179,6 +180,7 @@
179180
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
180181
<BaseAddress>0x10000</BaseAddress>
181182
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
183+
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
182184
</Link>
183185
</ItemDefinitionGroup>
184186
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -195,6 +197,7 @@
195197
<ExceptionHandling>false</ExceptionHandling>
196198
<BufferSecurityCheck>false</BufferSecurityCheck>
197199
<CreateHotpatchableImage>false</CreateHotpatchableImage>
200+
<WholeProgramOptimization>false</WholeProgramOptimization>
198201
</ClCompile>
199202
<Link>
200203
<SubSystem>Native</SubSystem>
@@ -207,6 +210,7 @@
207210
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
208211
<BaseAddress>0x10000</BaseAddress>
209212
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
213+
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
210214
</Link>
211215
</ItemDefinitionGroup>
212216
<ItemGroup>

.vs/TimeDefuser-VS2022.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
<ExceptionHandling>false</ExceptionHandling>
139139
<BufferSecurityCheck>false</BufferSecurityCheck>
140140
<ControlFlowGuard>false</ControlFlowGuard>
141+
<WholeProgramOptimization>false</WholeProgramOptimization>
141142
</ClCompile>
142143
<Link>
143144
<SubSystem>Native</SubSystem>
@@ -148,6 +149,7 @@
148149
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
149150
<BaseAddress>0x10000</BaseAddress>
150151
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
152+
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
151153
</Link>
152154
</ItemDefinitionGroup>
153155
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -188,6 +190,7 @@
188190
<ExceptionHandling>false</ExceptionHandling>
189191
<BufferSecurityCheck>false</BufferSecurityCheck>
190192
<ControlFlowGuard>false</ControlFlowGuard>
193+
<WholeProgramOptimization>false</WholeProgramOptimization>
191194
</ClCompile>
192195
<Link>
193196
<SubSystem>Native</SubSystem>
@@ -198,6 +201,7 @@
198201
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
199202
<BaseAddress>0x10000</BaseAddress>
200203
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
204+
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
201205
</Link>
202206
</ItemDefinitionGroup>
203207
<ItemGroup>

.vs/TimeDefuser-VS2026.vcxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@
148148
<ExceptionHandling>false</ExceptionHandling>
149149
<BufferSecurityCheck>false</BufferSecurityCheck>
150150
<ControlFlowGuard>false</ControlFlowGuard>
151+
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
152+
<WholeProgramOptimization>false</WholeProgramOptimization>
151153
</ClCompile>
152154
<Link>
153155
<SubSystem>Native</SubSystem>
@@ -160,6 +162,7 @@
160162
<RandomizedBaseAddress>true</RandomizedBaseAddress>
161163
<DataExecutionPrevention>true</DataExecutionPrevention>
162164
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
165+
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
163166
</Link>
164167
</ItemDefinitionGroup>
165168
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -205,6 +208,8 @@
205208
<ExceptionHandling>false</ExceptionHandling>
206209
<BufferSecurityCheck>false</BufferSecurityCheck>
207210
<ControlFlowGuard>false</ControlFlowGuard>
211+
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
212+
<WholeProgramOptimization>false</WholeProgramOptimization>
208213
</ClCompile>
209214
<Link>
210215
<SubSystem>Native</SubSystem>
@@ -217,6 +222,7 @@
217222
<RandomizedBaseAddress>true</RandomizedBaseAddress>
218223
<DataExecutionPrevention>true</DataExecutionPrevention>
219224
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
225+
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
220226
</Link>
221227
</ItemDefinitionGroup>
222228
<ItemGroup>

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,14 @@ Getting over it will weaponize this already versatile patch, so disabling PatchG
3232
- Patch the kernel image itself with offline patcher, instead of runtime patching with driver.
3333
- This patch can technically be ported to ARM, ARM64 and Itanium hosts but due to lack of an environment to run and debug Windows on these platforms, this is not possible at the moment.
3434

35+
## Notes for Offline Patcher
36+
- Do not use kernel driver with offline patched systems, as the driver is nonfunctional with patched kernels (as there is nothing to remove).
37+
- Windows XP and earlier builds are not supported, usage of kernel driver is required for those builds.
38+
3539
## Notes Per Version
3640

3741
### Windows 2000/XP
42+
- As written above, these builds does not support offline patching.
3843
- **I KNOW there are "easier" methods, so don't come to say me "muh set GracePeriod to 0" or "muh use TweakNT"**. This tweak for NT 5.x exists more as proof of concept, and both this patch or other tweaks will do the work.
3944
### Post-reset Windows Vista & Early 7
4045
- They suck. Avoid using these versions at all. After build expires, buggy WPA breaks the timebomb which makes this patch not get applied anyway, and shows the "Activate Windows" dialog which logs you off if you say no; considering that those builds can successfully finish the windeploy and boot to OOBE/desktop at all in the first place (https://github.com/NevermindExpress/TimeDefuser/issues/3). See https://github.com/NevermindExpress/TimeDefuser/issues/2 and https://github.com/NevermindExpress/TimeDefuser/issues/2#issuecomment-2970226626 for more info.

offline/Main.c

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ int main(int argc, char* argv[]) {
4848
DWORD sz = 0; // File size
4949
wchar_t* dupFilePath = tdGetDupFilePath(); // Name for duplicated file.
5050
wchar_t* openFilePath; // Path of kernel image to open.
51+
PVOID unusedOldVal = NULL;
52+
53+
// Disable filesystem redirection if running under WoW64
54+
Wow64DisableWow64FsRedirection(&unusedOldVal);
5155

5256
// Enable proper Unicode output
5357
SetConsoleOutputCP(CP_UTF8);
@@ -122,31 +126,49 @@ int main(int argc, char* argv[]) {
122126

123127
// Check version.
124128
if (nt->OptionalHeader.MajorSubsystemVersion < 6) {
125-
puts("[-] Windows XP builds are not supported. For those, you have to use the Legacy kernel driver.");
129+
puts("[-] Windows XP builds are not supported. For those, you have to use the kernel driver.");
126130
failed = 1; goto _Return;
127131
}
128132

129133
// All check and stuff are done, now actual patching work begins. First we'll need to find where to patch.
130-
IMAGE_SECTION_HEADER* PAGELK = tdFindSection("PAGELK\0", (IMAGE_SECTION_HEADER*)(nt + 1));
134+
IMAGE_SECTION_HEADER* PAGELK;
135+
if (mach->is64)
136+
PAGELK = tdFindSection("PAGELK\0", (IMAGE_SECTION_HEADER*)((IMAGE_NT_HEADERS64*)nt + 1));
137+
else
138+
PAGELK = tdFindSection("PAGELK\0", (IMAGE_SECTION_HEADER*)((IMAGE_NT_HEADERS32*)nt + 1));
139+
131140
if (!PAGELK) {
132141
puts("[-] PAGELK section not found.");
133142
failed = 1; goto _Return;
134143
} // Search onwards it until end of the file.
135144
printf("[+] Searching at 0x%x within 0x%x bytes...\n", PAGELK->PointerToRawData, (int)sz - PAGELK->PointerToRawData);
136145
data += PAGELK->PointerToRawData;
137146
for (size_t i = 0; i < sz - PAGELK->PointerToRawData; i++) {
138-
if ((mach->w64 && *(__int64*)&data[i] == mach->SharedData)
139-
|| (!mach->w64 && *(int*)&data[i] == mach->SharedData)) {
147+
if ((mach->is64 && *(__int64*)&data[i] == mach->SharedData)
148+
|| (!mach->is64 && *(int*)&data[i] == (int)mach->SharedData)) {
140149
// We found the time refresh work, search backwards for a CALL instruction
150+
#ifdef _WIN64
141151
printf("[+] ExGetExpirationDate found at 0x%llx\n", &data[i]-data0);
152+
#else
153+
printf("[+] ExGetExpirationDate found at 0x%lx\n", &data[i] - data0);
154+
#endif
142155
for (unsigned char k = 0; k < 100; k++) {
143156
if ((unsigned char)data[i - k] == mach->callOp) { // CALL instruction found.
157+
#ifdef _WIN64
144158
printf("[+] CALL instruction found at file: 0x%llx ", &data[i - k] - data0);
159+
#else
160+
printf("[+] CALL instruction found at file: 0x%lx ", &data[i - k] - data0);
161+
#endif
145162
int pCall = &data[i - k] - data0;
146163
unsigned int Offset = *(unsigned int*)&data[i - k + 1] + 5; // Next 4 bytes are relative address to our current location.
147164

148165
// Convert file offset to RVA
149-
IMAGE_SECTION_HEADER* currentSect = tdFindSectionByAddress((unsigned int)pCall, (IMAGE_SECTION_HEADER*)(nt + 1));
166+
IMAGE_SECTION_HEADER* currentSect = NULL;
167+
if(mach->is64)
168+
currentSect = tdFindSectionByAddress((unsigned int)pCall, (IMAGE_SECTION_HEADER*)((IMAGE_NT_HEADERS64*)nt + 1));
169+
else
170+
currentSect = tdFindSectionByAddress((unsigned int)pCall, (IMAGE_SECTION_HEADER*)((IMAGE_NT_HEADERS32*)nt + 1));
171+
150172
if (!currentSect) {
151173
puts("\n[*] Invalid address, skipping this one...");
152174
continue;
@@ -160,6 +182,11 @@ int main(int argc, char* argv[]) {
160182

161183
// Convert this new RVA back to file offset.
162184
currentSect = tdFindSectionByRVA(pCallRVA, (IMAGE_SECTION_HEADER*)(nt + 1));
185+
if (mach->is64)
186+
currentSect = tdFindSectionByRVA(pCallRVA, (IMAGE_SECTION_HEADER*)((IMAGE_NT_HEADERS64*)nt + 1));
187+
else
188+
currentSect = tdFindSectionByRVA(pCallRVA, (IMAGE_SECTION_HEADER*)((IMAGE_NT_HEADERS32*)nt + 1));
189+
163190
if (!currentSect) {
164191
puts("\n[*] Invalid address, skipping this one...");
165192
continue;

offline/SanityChecks.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ bool tdSanityCheck(char* data, IMAGE_NT_HEADERS** nt) {
5050
}
5151
// Has resources. Now we gotta find where they are in image.
5252
// Find the .rsrc section
53-
IMAGE_SECTION_HEADER* sect = tdFindSection(".rsrc\0\0", (IMAGE_SECTION_HEADER*)(*nt + 1));
53+
IMAGE_SECTION_HEADER* sect = NULL;
54+
55+
if ((*nt)->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
56+
sect = tdFindSection(".rsrc\0\0", (IMAGE_SECTION_HEADER*)((IMAGE_NT_HEADERS64*)*nt + 1));
57+
else
58+
sect = tdFindSection(".rsrc\0\0", (IMAGE_SECTION_HEADER*)((IMAGE_NT_HEADERS32*)*nt + 1));
59+
5460
if (!sect) {
5561
printf("[-] Not a kernel image (no resources).\n");
5662
return 0;

offline/TimeDefuserOffline.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#error You are not supposed to use this header in the kernel driver.
55
#endif // !TD_OFFLINE
66

7-
#define td_version "1.8"
7+
#define td_version "1.8.4"
88

99
// Includes
1010
#include <stdio.h>
@@ -20,7 +20,7 @@ typedef struct TD_MACHINE {
2020
const char* FriendlyName;
2121
unsigned int ShellCode; // Shell code for "return 0" that will be patched to the function.
2222
__int64 SharedData; // Where "ExpirationDate" on KUSER_SHARED_DATA is
23-
bool w64; unsigned char callOp;
23+
bool is64; unsigned char callOp;
2424
} TDMachine;
2525

2626
typedef struct {

src/Driver.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
#include "TimeDefuser.h"
22

3-
#ifdef _M_IX86
3+
#pragma function(memset)
44
void* __cdecl memset(void* dest, int c, size_t count) {
55
unsigned char* p = (unsigned char*)dest;
66
while (count--) {
77
*p++ = (unsigned char)c;
88
}
99
return dest;
1010
}
11-
#endif // _M_IX86
1211

1312
BOOLEAN PatchExGetExpirationDate(void* pExGetExpirationDate) {
1413
PMDL mdl = NULL;

0 commit comments

Comments
 (0)