
Time to reverse ...

I, inspired by the article about hidden opportunities customization of the process explorer.exe, also decided to do something funny.
Let my second hand clock in Windows go back today! Not the most useful mod in the economy, of course, but for academic and recreational purposes it’s quite suitable :)
I left the hour and minute hands in the right direction. Sometimes you still have to half-eat up the clock in the tray - let them show the time with an accuracy of at least a minute ...
Training
The sequence of actions seems to be approximately the following:
- Explore explorer.exe and understand how it counts time
- Something to change something in the logic so that the clock goes back
Changing the logic of some 32-bit usermode process is not difficult: for a long time there is a debugger OllyDbg that many people have loved, there are plenty of tutorials on it even in Russian. Therefore, to give a twist to it, it was decided to implement the task on my 64-bit Windows 7 - I wanted to find out how processes with double-digit capacity live there for a long time ...
In the 64-bit world, at the disassembler level, unfortunately, it’s not very sweet yet: you don’t feel comfortable for debugging, you do n’t need the most convenient Detours , for which they ask you to pay no less than $ 9,999.95 (well, thank you for not $ 10k - marketers know how to make the price more attractive). Even old 32-bit injectorscannot be used to implement 64-bit dlls. Apparently, my default search engine will have to work hard ...
Yes, fans of static analysis will forgive me, I didn’t have a relationship with IDA Pro, so I had almost no choice - the old WinDbg was waiting in the wings.
In matters of working with WinDbg, the most valuable source of information is the windbg.info resource .
Explore explorer.exe
We are connected to the process and are looking for something related to the word " clock ":

Having looked better at the list of functions given out, you can notice an inconspicuous function
explorer!CClockCtl::_RecalcCurTime
. Is the first shot right at the target? Let's see what is inside it: 
That's right, immediately after the function prologue we see a GetLocalTime call , which, as you know, returns the local time and date. If we can influence the return result of this function, we can also change the direction of the second hand - it remains only to put a hook on this function.
To implement our plans, we need to somehow get into the address space of the process explorer.exe. And the CLI DLL-Injector command-line utility will help us in the best way possible.. Not only does it support 32 and 64 bits, it also knows how to implement dll in two ways: through the LoadLibrary injection, and by directly writing the code through WriteProcessMemory and then transferring the relocs.
Directly to install hooks inside the explorer.exe process, we will use the simple and reliable MinHook library .
It is worth noting that behind the apparent simplicity of the library, there is a very thought-out logic inside that works even in fairly complex cases. So, the Powerful x86 / x64 Mini Hook-Engine library , which I tried to use at first, led to Access Violation due to the fact that the first GetLocalTime function instruction is a relative JMP transition. In this case, the task is complicated by the need to recalculate the offset.
Implementation
We decided on the tools. Now it remains to write a dll, which with DLL_PROCESS_ATTACH will put a hook on the GetLocalTime function:
#include
#include "MinHook.h"
// Статически линкуемся с libMinHook.dll
#pragma comment(lib, "libMinHook.x64.lib")
// Указатель на оригинальный GetLocalTime
static void (WINAPI *GetLocalTime_)(LPSYSTEMTIME lpSystemTime);
void WINAPI MyGetLocalTime(LPSYSTEMTIME lpSystemTime)
{
// Вызываем оригинальный GetLocalTime
GetLocalTime_(lpSystemTime);
// Инвертируем количество секунд: 59 -> 0, 0 -> 59
lpSystemTime->wSecond = 59 - lpSystemTime->wSecond;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
// Не повторяйте этого в продакшене!
// Во избежание неприятных дедлоков, внутри DllMain() нужно оставлять только самый необходимый функционал
// Инициализируем библиотеку libMinHook
if (MH_Initialize() != MH_OK) {
return FALSE;
}
// Создаём хук (пока что он будет в выключенном состоянии)
if (MH_CreateHook(&GetLocalTime, &MyGetLocalTime, reinterpret_cast(&GetLocalTime_)) != MH_OK) {
return FALSE;
}
// Активизируем хук
if (MH_EnableHook(&GetLocalTime) != MH_OK) {
return FALSE;
}
}
return TRUE;
}
We use the received dll
Now you can implement the dll. We launch the injector in the console with the following command:

In the --lib key, it is important to pass the full path to the dll, for more details why this is done see comment
Everything, you can enjoy the results! (carefully, hypnotizing)
Sources (projects for VS2010) and binaries for self-picking can be found here .