Раскрашиваем файлы в ДИСКо Командире

от автора

Из всех файловых менеджеров ДИСКо Командир мне нравится больше всего. Вопрос «почему?» к данному посту не имеет отношения, так что останавливаться на этом я не буду. К сожалению, у этого файлового менеджера отсутствует некоторая функциональность, которая бы мне очень не помешала. Например, он не умеет подсвечивать файлы разных типов разными цветами. Попробуем это исправить!

Исходного кода, разумеется, у меня нет, поэтому придется действовать иначе — найти участок кода, который отвечает за отрисовку имён файлов, и соответствующим образом его поправить. Поправлять будем очевидным образом — запишем в нужное место call на нашу функцию, которая будет проверять имена файлов, устанавливать соответствующий цвет и затем возвращать управление в исходную точку.

Найти нужный участок кода легко — достаточно открыть dc32.exe в IDA и поискать вызовы функций типа ExtTextOutA. Незадолго перед ней находится SetTextColor, которая, собственно, и устанавливает цвет текста. Нужный нам фрагмент выглядит так:

.text:00435372                 mov     edx, [esp+0B4h+var_70] .text:00435376                 mov     edi, [eax] .text:00435378                 add     esp, 8 .text:0043537B                 mov     ecx, [esi+4] .text:0043537E                 and     edx, 0FFFFFFh .text:00435384                 push    edx             ; COLORREF .text:00435385                 mov     eax, [ecx+4] .text:00435388                 push    eax             ; HDC .text:00435389                 call    ds:SetTextColor 

В edx, очевидно, содержится цвет. Имя файла в виде null-terminated строки лежит по адресу [ebx]. Точнее, там лежит строчка, соответствующая тому, что будет отображаться на экране: пространство между именем и расширением заполнено пробелами, само имя, если оно слишком длинное, обрезается многоточием. В принципе, можно было бы вытащить и настоящее имя, но для наших целей это не потребуется.

Внедряться будем следующим образом: запишем по адресу 0043537E две команды: mov eax, &Hook_FNDisplay; call eax, где &Hook_FNDisplay — адрес функции, которая будет заниматься дополнительной работой (регистр eax мы в данном месте можем смело «портить»).

HANDLE phandle = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, 0, pid); if (phandle == NULL) return FALSE;  int addr = 0x43537E; BYTE hook_code[7] = {0xb8, 0, 0, 0, 0, 0xff, 0xd0}; LPVOID hook_addr = &Hook_FNDisplay; memcpy(&hook_code[1], &hook_addr, 4); WriteProcessMemory(phandle, (LPVOID)addr, &hook_code, sizeof(hook_code), 0); 

Семибайтный массив hook_code содержит коды указанных выше инструкций.

Теперь обратимся к самой процедуре Hook_FNDisplay. Объявим её как __declspec(naked), чтобы компилятор не сгенерировал ненужный нам код («пролог» и «эпилог»). В самом начале настроим стек, сохраним в стеке регистры и запомним в локальных переменных имя файла и его цвет:

__asm { 	pop eax 	push ebp 	mov ebp, esp 	sub esp, __LOCAL_SIZE 	mov filename, ebx 	and edx, 0xffffff 	mov color, edx 	pushad } 

Перед выходом, соответственно, восстановим регистры и указатель стека. Кроме того, надо позаботиться о том, чтобы на вершине стека после ret остался заданный нами цвет, ведь при внедрении нашего кода мы «затёрли» команду push edx:

__asm{ 	popad 	mov edx, color 	mov esp, ebp 	pop ebp 	push edx 	push eax 	ret } 

Основная логика — между этими двумя ассемблерными вставками. Идея очевидна:

filename_len = strlen((char*)filename); if (_strcmpi((char*)((size_t)filename + filename_len - 4), "djvu") == 0) 	color = 0xFF00FF; 

Код оформляется в виде обычной DLL, которая затем инжектируется маленькой утилиткой CLI DLL-Injector (спасибо Glowfall за наводку).

Здесь я описал основную идею. Полный код не выкладываю, поскольку он ещё требует работы: как минимум надо сделать удобную возможность конфигурирования раскрасок. Благодарю за внимание и буду рад конструктивной критике. 😉

ссылка на оригинал статьи http://habrahabr.ru/post/176663/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *