- PVSM.RU - https://www.pvsm.ru -
Вот и отгремело первое апреля. Кто-то в этот день нюхал свои девайсы в новом сервисе Google Нос [1], кто-то играл в «Поле чудес» [2], а кто-то, позабыв о роковой дате, просто угрюмо отряхивал спину от мела…
Я же, воодушевлённый статьёй [3] про скрытые возможности кастомизации процесса explorer.exe, тоже решил сделать что-нибудь забавное.
Пусть сегодня моя секундная стрелка часов в Windows идёт в обратную сторону! Не самый, конечно, полезный в хозяйстве мод, но в академических и рекреационных целях вполне сгодится :)
Часовую и минутную стрелки я оставил в правильном направлении. Иногда всё же приходится полгядывать на часы в трее — пусть они показывают время с точностью хотя бы до минуты...
Последовательность действий представляется примерно следующей:
Немного поменять логику какого-нибудь 32-битного usermode-процесса не представляет сложностей: давно есть полюбившийся многим отладчик OllyDbg [4], туториалов по которому предостаточно даже на русском языке. Поэтому, для придания изюминки было решено реализовывать задачу на моей 64-битной Windows 7 — давно хотел узнать каково́ там живётся процессам с удвоенной разрядностью…
В 64-битном мире на уровне дизассемблера пока, к сожалению, живется не очень сладко: ни тебе комфортного Olly для отладки, ни тебе удобнейшего поисковику по умолчанию [5] придётся неслабо поработать…
Да простят меня любители статического анализа, с IDA Pro у меня отношения не сложились, так что выбора у меня почти не осталось — старичок WinDbg дождался своего часа.
В вопросах работы с WinDbg ценнейшим источником информации является ресурс windbg.info [6]
Подключаемся к процессу и ищем что-нибудь связанное со словом "clock":
Присмотревшись получше к выданному списку функций, можно заметить неприметную функцию explorer!CClockCtl::_RecalcCurTime
. Неужели первый выстрел сразу в цель? Посмотрим что у неё внутри:
Всё верно, сразу за прологом функции видим вызов GetLocalTime [7], которая, как известно, возвращает местное время и дату. Если мы сможем влиять на возвращаемый результат этой функции, то сможем также и изменять направление секундной стрелки — осталось только поставить хук на эту функцию.
Чтобы реализовать задуманное, нам нужно как-то попасть в адресное пространство процесса explorer.exe. И в этом как нельзя лучше нам поможет утилита командной строки CLI DLL-Injector [8]. Она мало того что поддерживает 32 и 64 бита, так еще и умеет внедрять dll двумя способами: через инжект LoadLibrary, и с помощью прямой записи кода через WriteProcessMemory с последующим переносом reloc'ов.
Непосредственно для установки хуков внутри процесса explorer.exe воспользуемся простой и надёжной библиотекой MinHook [9].
Стоит обратить внимание, что за кажущейся простотой библиотеки, внутри скрывается очень продуманная логика, которая работает даже в достаточно сложных случаях. Так, библиотека Powerful x86/x64 Mini Hook-Engine [10], которую я пытался использовать поначалу, приводила к Access Violention всвязи с тем, что первая же инструкция функции GetLocalTime — это относительный переход JMP. В этом случае задача усложняется необходимостью перерасчёта смещения.
С инструментами определились. Теперь осталось написать dll, которая при DLL_PROCESS_ATTACH будет ставить хук на функцию GetLocalTime:
#include <windows.h>
#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<void**>(&GetLocalTime_)) != MH_OK) {
return FALSE;
}
// Активизируем хук
if (MH_EnableHook(&GetLocalTime) != MH_OK) {
return FALSE;
}
}
return TRUE;
}
Теперь можно внедрять dll. Запускаем в консоли инжектор следующей командой:
Всё, можно наслаждаться результатами! (осторожно, гипнотизирует)
Автор: Glowfall
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/windows/30938
Ссылки в тексте:
[1] Google Нос: https://www.google.ru/intl/ru/landing/nose/
[2] «Поле чудес»: http://www.yandex.ru/
[3] статьёй: http://habrahabr.ru/post/174593
[4] OllyDbg: http://www.ollydbg.de/
[5] поисковику по умолчанию: http://www.google.com/
[6] windbg.info: http://www.windbg.info/doc/1-common-cmds.html
[7] GetLocalTime: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724338%28v=vs.85%29.aspx
[8] CLI DLL-Injector: http://code.google.com/p/injector/
[9] MinHook: http://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x86-x64-API-Hooking-Libra
[10] Powerful x86/x64 Mini Hook-Engine: http://www.codeproject.com/Articles/21414/Powerful-x86-x64-Mini-Hook-Engine
[11] Источник: http://habrahabr.ru/post/175025/
Нажмите здесь для печати.