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

в 22:45, , рубрики: dll injection, ida, windows, метки: ,

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

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

Исходного кода, разумеется, у меня нет, поэтому придется действовать иначе — найти участок кода, который отвечает за отрисовку имён файлов, и соответствующим образом его поправить. Поправлять будем очевидным образом — запишем в нужное место 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 за наводку).

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

Автор: EvgeshaS

Источник

Поделиться

* - обязательные к заполнению поля