Search notes:
Windows: set date in process (faketime for Windows)
This is the source code for a simple Windows tool that uses
Detours to start a
process and hook the
WinAPI functions
GetLocalTime
and
GetSystemTime
in order to make the started process run under a given time.
Thus, this utility is a an approximation of the shell command
faketime
that is found in
Linux distributions.
C:\Users\rene> setDate 2001-02-03 04:05:06 path-and-or-name-of.exe
For example, if
path-and-or-name-of.exe
is
cmd.exe
, the time or date is now changed to the given values:
C:\Users\rene> echo %TIME%
4:05:06.00
C:\Users\rene> echo %DATE%
2001-02-03
TODO
There are a number of other WinAPI functions that return a date or time that also should be hooked:
GetSystemTimePreciseAsFileTime
GetSystemTimeAsFileTime
time
(undocumented and not exposed through <windows.h>
or an import library, found in KernelBase.dll
)
NtQuerySystemTime
GetTimeFormat
(?)
If this tool is used to start a process that in turn starts another (child-) process, the child process does not «inherit» the time. Therefore, the tool should probably also hook
CreateProcess
so that the started process injects the hooking
DLL also into the child-process.
setDate.c
#include <windows.h>
#include <stdio.h>
#include "detours.h"
#include "setDate.h"
int main(int argc, char* argv[]) {
if (argc < 2) {
printf("specify executable\n");
return 1;
}
STARTUPINFO si; ZeroMemory(&si, sizeof(si));
PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
char* dllPath = malloc(MAX_PATH);
char* cp = dllPath + GetModuleFileName(NULL, dllPath, MAX_PATH);
while (*--cp != '\\');
memcpy (cp+1, "setDate.dll\x00", 12);
char* lpCommandLine = GetCommandLine();
lpCommandLine += strlen(argv[0]) + 2; // Skip program name plus 2 apostrophes in which it is enclosed.
printf(lpCommandLine);
printf("\n");
while (*++lpCommandLine == ' ');
SYSTEMTIME fake_SYSTEMTIME;
*(lpCommandLine + 4) = 0; fake_SYSTEMTIME.wYear = atoi(lpCommandLine); lpCommandLine += 5;
*(lpCommandLine + 2) = 0; fake_SYSTEMTIME.wMonth = atoi(lpCommandLine); lpCommandLine += 3;
*(lpCommandLine + 2) = 0; fake_SYSTEMTIME.wDay = atoi(lpCommandLine); lpCommandLine += 3;
*(lpCommandLine + 2) = 0; fake_SYSTEMTIME.wHour = atoi(lpCommandLine); lpCommandLine += 3;
*(lpCommandLine + 2) = 0; fake_SYSTEMTIME.wMinute = atoi(lpCommandLine); lpCommandLine += 3;
*(lpCommandLine + 2) = 0; fake_SYSTEMTIME.wSecond = atoi(lpCommandLine); lpCommandLine += 3;
fake_SYSTEMTIME.wDayOfWeek = 0; // Hah. How am I supposed to know?
fake_SYSTEMTIME.wMilliseconds = 0; // Granularity of one second is enough for everyone...
while (*lpCommandLine == ' ') lpCommandLine++;
if (! DetourCreateProcessWithDllEx (
0 , // LPCTSTR appName
lpCommandLine , // LPTSTR lpCommandLine,
0 , // LPSECURITY_ATTRIBUTES lpProcessAttributes,
0 , // LPSECURITY_ATTRIBUTES lpThreadAttributes,
0 , // BOOL bInheritHandles,
CREATE_DEFAULT_ERROR_MODE |
CREATE_SUSPENDED , // DWORD dwCreationFlags,
0 , // LPVOID lpEnvironment,
0 , // LPCTSTR lpCurrentDirectory,
&si , // LPSTARTUPINFOW lpStartupInfo,
&pi , // LPPROCESS_INFORMATION lpProcessInformation,
dllPath , // LPCSTR lpDllName
0 // PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW
)) {
printf("Failed.\n");
exit(-1);
}
free(dllPath);
// https://github.com/microsoft/Detours/blob/master/samples/tracebld/tracebld.cpp
if (!DetourCopyPayloadToProcess(
pi.hProcess,
&payload,
&fake_SYSTEMTIME,
sizeof(SYSTEMTIME))
) {
printf("failed copy payload\n");
return 1;
}
ResumeThread(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(&si);
CloseHandle(&pi);
return 0;
}
hooks.c
#include <windows.h>
#include "detours.h"
#include "setDate.h"
typedef void (WINAPI *GetSystemTime_func )(LPSYSTEMTIME );
typedef void (WINAPI *GetLocalTime_func )(LPSYSTEMTIME );
GetSystemTime_func GetSystemTime_real;
GetLocalTime_func GetLocalTime_real ;
LPSYSTEMTIME pFakeLocalTime = 0;
SYSTEMTIME fakeUniversalTime;
void WINAPI GetSystemTime_hook (LPSYSTEMTIME t) {
CopyMemory(t, &fakeUniversalTime, sizeof(SYSTEMTIME));
}
void WINAPI GetLocalTime_hook (LPSYSTEMTIME t) {
CopyMemory(t, pFakeLocalTime, sizeof(SYSTEMTIME));
}
int attach(PVOID func, PVOID* real, PVOID hook) {
*real = func;
LONG dar;
if ( (dar = DetourAttach(real, hook)) != NO_ERROR ) {
return 0;
}
return 1;
}
BOOL WINAPI DllMain(HINSTANCE i, DWORD dwReason, LPVOID l) {
switch ( dwReason ) {
case DLL_PROCESS_ATTACH: {
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
ULONG cbData;
PVOID pvData = DetourFindPayload(hMod, &payload, &cbData);
if (pvData != NULL) {
pFakeLocalTime = (LPSYSTEMTIME) pvData;
TzSpecificLocalTimeToSystemTime(0, pFakeLocalTime , &fakeUniversalTime);
//
// MSDN: Do not cast a pointer to a FILETIME structure to either a
// ULARGE_INTEGER* or __int64* value because it can cause alignment
// faults on 64-bit Windows.
//
// fakeLargeIntger.LowPart = fakeFiletime.dwLowDateTime;
// fakeLargeIntger.HighPart = fakeFiletime.dwHighDateTime;
}
}
if (DetourTransactionBegin() != NO_ERROR) {
return FALSE;
}
if ( DetourUpdateThread( GetCurrentThread()) != NO_ERROR ) {
return FALSE;
}
HMODULE kernelBase = GetModuleHandle("kernelbase.dll");
GetSystemTime_func GetSystemTime_ = (GetSystemTime_func) GetProcAddress(kernelBase, "GetSystemTime");
GetLocalTime_func GetLocalTime_ = (GetLocalTime_func ) GetProcAddress(kernelBase, "GetLocalTime" );
attach((PVOID) GetSystemTime_ , (PVOID*) &GetSystemTime_real , (PVOID) GetSystemTime_hook );
attach((PVOID) GetLocalTime_ , (PVOID*) &GetLocalTime_real , (PVOID) GetLocalTime_hook );
if ( DetourTransactionCommit() != NO_ERROR) {
return FALSE;
}
break;
}
case DLL_PROCESS_DETACH: {
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourTransactionCommit();
}
break;
}
return TRUE;
}
setDate.h
const GUID payload = {
0xcb190af8, 0x5dc7, 0x461d, {0xb9, 0x07, 0x87, 0x6a, 0x8d, 0x15, 0x61, 0x42}
};
Makefile
DETOURS_SRC=Detours/src
all: setDate.dll setDate.exe
setDate.dll: hooks.o Detours.o disasm.o modules.o
g++ -shared hooks.o Detours.o disasm.o modules.o -lntdll -o setDate.dll
setDate.exe: setDate.o creatwth.o Detours.o disasm.o modules.o
g++ setDate.o creatwth.o Detours.o disasm.o modules.o -o setDate.exe
hooks.o : hooks.c setDate.h
gcc -I$(DETOURS_SRC) -std=c99 -c hooks.c
Detours.o : $(DETOURS_SRC)/Detours.cpp
g++ -I$(DETOURS_SRC) -c $(DETOURS_SRC)/Detours.cpp
disasm.o : $(DETOURS_SRC)/disasm.cpp
g++ -I$(DETOURS_SRC) -c $(DETOURS_SRC)/disasm.cpp
modules.o : $(DETOURS_SRC)/modules.cpp
g++ -I$(DETOURS_SRC) -c $(DETOURS_SRC)/modules.cpp
creatwth.o : $(DETOURS_SRC)/creatwth.cpp
g++ -I$(DETOURS_SRC) -c $(DETOURS_SRC)/creatwth.cpp
setDate.o: setDate.c setDate.h
gcc -I$(DETOURS_SRC) -c setDate.c
# test-target.exe: test-target.o
# gcc target.o -o test-target.exe
History
2021-11-30 Makefile
: Add compiler option -std=c99
to compile hooks.c
in order to be able to compile it with g++ 4.6.3
Links
The source code is hosted on
github .