Показать сообщение отдельно

Эмуляция VirtualProtect
  #1  
Старый 25.09.2007, 18:56
0x0c0de
Постоянный
Регистрация: 25.05.2007
Сообщений: 448
Провел на форуме:
4226446

Репутация: 1564
По умолчанию Эмуляция VirtualProtect

Итак.... Представим ситуацию. Есть фаер/антитварь, ставящее хуки на нужные зловредному коду функции. И все бы ничего...
Возьмем да и снимем поставленые хуки... а нет... на функции ZwProtectVirtualMemory тоже стоит перехват=\ что тогда? с утра сегодня пришла идея сэмулировать нужную функцию... мож кому-то будет интересно. Если не будет -тему дельнете. делов-то

Посидела немного за дизасмом VirtualProtectEx и ZwProtectVirtualMemory. Я их обе сэмулирую. Значит с первой проблем вообще не возникло. Просто проследила за содержанием стека, чтобы узнать где какой параметр. Далее... Далее вызов ntdll функции, на начале которой стоит наш воображаемый хук. Пять байт затерто. А нам надо узнать номер функции

Код:
  
7C90DE77 n>/$  B8 86000000               MOV EAX,86
7C90DE7C   |.  BA 0003FE7F               MOV EDX,7FFE0300
7C90DE81   |.  FF12                      CALL DWORD PTR DS:[EDX]
7C90DE83   \.  C2 0C00                   RETN 0C
7C90DE86       90                        NOP
7C90DE87       90                        NOP
7C90DE88       90                        NOP
7C90DE89       90                        NOP
7C90DE8A       90                        NOP
7C90DE8B       90                        NOP
7C90DE8C n>/$  B8 87000000               MOV EAX,87
7C90DE91   |.  BA 0003FE7F               MOV EDX,7FFE0300
7C90DE96   |.  FF12                      CALL DWORD PTR DS:[EDX]
7C90DE98   \.  C2 1800                   RETN 18
7C90DE9B       90                        NOP
7C90DE9C       90                        NOP
7C90DE9D       90                        NOP
7C90DE9E       90                        NOP
7C90DE9F       90                        NOP
7C90DEA0       90                        NOP
7C90DEA1 n>/$  B8 88000000               MOV EAX,88
7C90DEA6   |.  BA 0003FE7F               MOV EDX,7FFE0300
7C90DEAB   |.  FF12                      CALL DWORD PTR DS:[EDX]
7C90DEAD   \.  C2 1400                   RETN 14
Мы видим, что номера функций идут строго по порядку. Это означает, что чтобы нам вычислить адрес ZwProtectVirtualMemory надо просто посмотреть номер предыдущей функции и прибавить 1 или последующей (но тогда надо вычитать 1). Второй вариант мне больше понравился.

а тот же аутпост (в пример привожу его - это модный пример) ставит хук так

Код:
7C90EA32 n> $- E9 71DE7393               JMP wl_hook.1004C8A8 ; это поясняет мои стова относительно пяти байт
7C90EA37    .  BA 0003FE7F               MOV EDX,7FFE0300
7C90EA3C    .  FF12                      CALL DWORD PTR DS:[EDX]
7C90EA3E    .  C2 1400                   RETN 14
Значит нам потребуется вычислить номер функции. Теперь подробнее. Ищем байт 0B8, забираем двойное слово- номер функции декрементируем, вписываем значение в наш код.... Потом ищем 0BA, поступаем так же. По поводу записи непосредственно в секцию кода. VirtualProtect тут вызывать тоже не надо. Я установила характеристики секции в 0E0000020H, поэтому все в порядке=)

Код:
.386
.model flat, stdcall
include kernel32.inc
include windows.inc
includelib kernel32.lib
.data
ntdl_ db "ntdll.dll",0 
vprotect db "ZwProtectVirtualMemory",0
func_ dword ?
.const
.code

system_call proc
mov eax,0 ; сюда мы запишем номер функции
mov edx,0 
call dword ptr [edx] ;  KiFastSystemCall
retn 14h ; количество передаваемых параметров я знаю точно
system_call endp

emulator_ proc  ; эмуляция VirtualProtectEx
local old_protect:dword
local size_c:dword
local address:dword
lea eax,old_protect
push eax
push 40h ; тип протекта запись-чтение-исполнение
mov size_c,10
lea eax,size_c
push eax
push func_ ; на ней же и протестим=)
pop address
lea eax,address
push eax
push -1 ; пишем в своем процессе, поэтому -1
call system_call
mov esi,func_
mov byte ptr[esi],8 ; проверяем на запись. ошибки нет=) 
ret
emulator_ endp

Main:
invoke GetModuleHandleA,offset ntdl_
invoke GetProcAddress,eax,offset vprotect 
test eax,eax
je ext_
mov func_,eax
add eax,4 ; пять байт мы смело пропускаем. тут четыре, да ниже inc - итого 5)
loo:
inc eax
cmp byte ptr [eax],0b8h ; начало инструкции mov eax,xxxx. для надежности можно проверять длину инструкции. должно быть 5 байт. в этом нам поможет
; дизассемблер длин, его прикрутить вообще не проблема
jnz loo
inc eax
mov edx,dword ptr[eax]
mov edi,offset system_call
dec edx
inc edi
mov dword ptr[edi],edx
add eax,5
add edi,5
mov edx,dword ptr[eax]
mov dword ptr[edi],edx
call emulator_
ext_:
invoke ExitProcess, NULL
end Main
Не забудьте установить характеристики секции кода данной проги в 0E0000020H!
Вообще наверняка есть способ лучше..

Последний раз редактировалось 0x0c0de; 25.09.2007 в 20:13..
 
Ответить с цитированием