· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.WIN32 —› Перехвать функций (глобальный)

. 1 . 2 . 3 . >>

Посл.отвђт Сообщенiе


Дата: Ноя 28, 2003 03:17:45

Добрый день, господа.
Интересует каким образом можно глобально перехватить вызовы функций. Т.е. имеется ввиду к примеру - перехватывать вызов MessageBoxA во всех процессах. При этом естественно знать какой это процесс и т.д. Причем перехватывать безопасно - т.е. чтоб при возможности можно было продолжить выполнение функции.
Собственно у меня единственный вариант, который пришел в голову - это инжектировать код, и патчить импорты у каждого модуля. Но здесь возникает резонный вопрос - как загрузиться _ДО_ всех юзерских либ? т.е. сразу после kernel32 (Даже в случае, если либы грузятся из импортов).

Собственно вот.Если у кого есть что сказат по этой теме - буду весьма признателен.


Дата: Ноя 28, 2003 09:27:10

Я листал процессы с помощью Process32First/Process32Next и в каждом процессе первые 6 байт функции заменял на
push offset hook
ret
а из хука менял их обратно и вызывал настоящую функцию

Вот кусок моего user mode сниффера. Здесь хукается send и весь исходящий траффик пишется в c:\send_log

_1974133046__sniffer.asm


Дата: Ноя 28, 2003 17:39:54

Есть другая методика, но будет работать только в случае функций, проходящих через шлюз sysenter/int 2E. Надо патчить SDT.


Дата: Ноя 28, 2003 23:30:43

Володя: Функции из winapi, к ядру отношения мало имеющие.
А что по поводу патча функции _ДО_ загрузки библиотек и старта программы?


Дата: Ноя 28, 2003 23:37:16

rst
ИМХО единственный способ это сделать - пропатчить сами дллки. Еще можно хукнуть CreateProcess, но это будет не _ДО_ а _СРАЗУ_ПОСЛЕ_ :) Можешь подробнее описать задачу?


Дата: Ноя 29, 2003 00:11:16

Посмотри у Рихтера. Там целая глава этому посвящена "DLL Injection and API Hooking". Все основные методы расписаны. Всё для третьего кольца. И в конце главы как раз есть пример хуканья MessageBox. А грузиться до не имеет смысла, в этом случае, т.к. хучить то ещё нечего :-) В общем, почитай. Там всё грамотно написано.


Дата: Ноя 29, 2003 00:18:55

А существует ли метод где не надо каждый прцесс отдельно хукать?


Дата: Ноя 29, 2003 00:42:28

comrade
в win9x можно все хукнуть 1 раз. Там все библиотеки общие для всех процессов. Еще можно длл пропатчить.
Вот пара ссылок:
http://www.wasm.ru/article.php?article=1021007
http://z0mbie.host.sk/api_hook.txt


Дата: Ноя 29, 2003 03:12:26

FFFF - я читал рихтера. Там описана методика хука самого по себе (путем патчинга IAT - я это умею и делаю.. собственно это единственный момент, который не вызывает вопросов - я это уже делал). Меня больше интересует следующий момент - глобальный хук. Т.е. преследую следующие 2 вещи:
1) чтоб ни один процесс не мог вызвать определенные функции без моей сатисфакции
2) чтоб ни коим образом нельзя было вызвать функции без моей сатисфакции (LoadLibrary && GetProcAddress и Imorts)
Т.е. нужно:
а) следить создание процессов и сразу же делать перехват GetProcAddress после загрузки процесса.
б) в каждом процессе так же делать патчинг IAT во всех модулях.
Да, кстати есть метод, не описанный у Рихтера - через отладку. Можно ведь бряку поставить туда. Но это ИМХО так же некрасиво, как и подменять код самих DLL.
Собственно остается два вопроса на повеске дня:
1) отслеживать создание процессов.
2) получать доступ сразу же после CreateProcess..


Дата: Ноя 29, 2003 03:52:26

2 all
Прочитал Рихтера и ничего не понял. Почему он рекомендует патчить IAT вместо того чтобы патчить первые 6 байт функции?
Цитата из книги:
На замену кода в начале функции уходит какое-то время, а в этот момент перехватываемая функция может понадобиться другому потоку. Результаты могут быть просто катастрофическими!
Какая разница сколько байт менять 6 или 4 ???
И еще если патчить IAT то придется писать писать функцию для ее поиска и ставить хук на GetProcAdress.
Может я чего-то не понимаю?


Дата: Ноя 29, 2003 04:13:44

rst
Тут один вариант (если хочешь чтобы хук был глобальным) и
volodya прав в том плане, что надо писать перехватчик на уровне ядра системы, поскольку для каждого процесса в Win используется своя память, т.е. один процесс не может залезть в память другого процесса (хотя это не совсем так, но для текущего объяснения пойдет), а вот ядро для всех процессов одинаково. Хочешь пример реализациии такого хука - это отладчик SoftIce.


Дата: Ноя 29, 2003 06:04:13

PROFi :
1) не все функции уходят в ядро.
2) ReadProcessMemory\WriteProcessMemory\CreateRemoteThread - так что я имею доступ ко всему, что надо -)
hello_world: - а ты уверен. что сможешь восстановить алгоритм работы функции после замены этих 6-х байт? Дело в том, что это весьма "кривой" и "грязный" метод патчинга (имхо) Уж лучше int 3 туда поставить , или drx регистры юзать.
2 all: а что скажете по поводу перехвата userspace функций, используя драйвер? (Я не особо знаком с написанием драйверов. Посему у самого идеи на этот счет не появятся). Я думаю что с помощью драйверов можно реализовать перехват выполнения кода после запуска процесса ( до каких-либо initialization routines )

Ещё были мысли по поводу замены либы ( т.е. создание т.н. прокси-либы ), но это не вариант по той причине, что я не могу гарантировать такое же количество экспортов, как в оригинале. Да и мне кажется это есть _СЛИШКОМ_ радикальное решение. Хотя Symantec использует подобное, но там proxy com-библиотека. Там все проще намного.


Дата: Ноя 29, 2003 10:15:50 · Поправил: zen333

если менять первые 6 байт функций
то их надо менять постоянно при каждой подгрузке длл
а еще нужно чтоб функция была восстановленна для продолжения выполнения...
мне нужно было перехватить что посылает ТХе БАТ...
в таблицах импорта он несодержит сенд вообще
писал через хук длл ку которая постоянно меняет 6 байт а потом обратно , когда принимаешь почту с 10 ящиков то БАТ вместе с Эксплорером вылетают с Эксцепшином потому как постоянно меняются байтики в начале функции туда сюда...
выход нашел такой например для всех НТ систем:
исходник дллки

;goto make
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib

filsav proto STDCALL :dword,:dword
includef proto STDCALL inclfile:dword,result:dword
myfunc PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
getwindir proto STDCALL :dword
.data?
oldseh db 10 dup (?)
buflen dd ?
SizeWrite dd ?
SizeWritten dd ?
hHook dd ?
hWnd dd ?
ws2lib dd ?
hFileWrite dd ?
buffer db 255 dup (?)
tmpstr db 255 dup (?)
txtbuf db 255 dup (?)
windir db 255 dup (?)
adress dd ?
adress1 dd ?
dwOldProtect dd ?


.data
offmy equ offset myfunc
me equ 13,10,0

_1310end db 96,13,10,'end',13,10,'.',me
_1310begin db 13,10,13,10,'begin 600 _1310 db me
flag db 0
senen db 13,10,'.',13,10,0
szLib db 'ws2_32',0
szProc db 'send',0
oldapi db 6 dup (0)
newseh db 068h
dd offmy
db 0c3h
hhook1 dd 0
hhook dd 0
hInstance dd 0
cnt dd 0
nil dd 0

.code
DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
push hInst
pop hInstance
assume fs: nothing
mov eax,fs:[0]
mov [eax+4],offset ErrorHandler
mov eax,1
ret
DllEntry Endp


DebugProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD

cmp cnt,0
jnz @F
invoke GetModuleHandle, ADDR szLib
cmp eax,NULL
jz @F
mov ws2lib,eax
invoke GetProcAddress, eax, ADDR szProc
mov adress,eax
invoke VirtualProtect,eax, 10, PAGE_EXECUTE_READWRITE, ADDR dwOldProtect
call conv
@@:
invoke CallNextHookEx,hhook1,nCode,wParam,lParam
ret
DebugProc endp

InstallHook proc
invoke SetWindowsHookEx,WH_CBT,addr DebugProc,hInstance,NULL
mov hhook1,eax
ret
InstallHook endp

UninstallHook proc
invoke UnhookWindowsHookEx,hhook1
pusha
mov edi,adress
mov esi,offset oldseh
movsw
movsd
popa
ret
UninstallHook endp
;--------------------------------------------------------------------- --------

conv: inc cnt
pusha
mov esi,adress
mov edi,offset oldseh
movsw
movsd

mov esi,offset newseh
mov edi,adress
movsw
movsd
popa
retn
;------------------

_send: push ebp ;вот здесь очень важно
mov ebp,esp ;так как нам нельзя постоянно крутить байтики мы восстанавливаем значения всех регистров как должно быть и отдаем управление оригинальной функции точнее ее продолжению после 6 байт...
sub esp,10h
mov eax,adress
add eax,6
mov adress1,eax
jmp [adress1]

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@myfunc PROC mysock:DWORD,myvar:DWORD,mycount:DWORD,myflag:DWORD
local dlina:dword
local buf:dword
local res:dword
local mesto:dword
push myflag
push mycount
push myvar
push mysock
call _send
@@: ret
myfunc endp

;---------=-=-=-=-=--=---------------------------------------


ErrorHandler proc C lpExcept:DWORD, lpFrame:DWORD, lpContext:DWORD, lpDispatch:DWORD
invoke ExitProcess,0
xor eax, eax ; continue execution
ret
ErrorHandler endp

End DllEntry
:make
echo LIBRARY ahook>mhook.def
echo EXPORTS >>mhook.def
echo InstallHook>>mhook.def
echo UninstallHook>>mhook.def
\masm32\bin\ml /c /coff /Cp %0
\masm32\bin\Link /SECTION:.bss,S /DLL /DEF:mhook.def /SUBSYSTEM:WINDOWS /LIBPATH:\masm32\lib bhook.obj
del *.obj
del *.exp
del *.lib


Дата: Ноя 29, 2003 11:28:27

[ rst: FFFF - я читал рихтера. ]

Извини, своих не признал.


[ rst: Собственно остается два вопроса на повеске дня:
1) отслеживать создание процессов.
2) получать доступ сразу же после CreateProcess.
]

Из драйвера это просто. Есть документированные PsSetCreateProcessNotifyRoutine, PsSetCreateThreadNotifyRoutine, PsSetLoadImageNotifyRoutine.

"PsSetCreateProcessNotifyRoutine adds a driver-supplied callback routine to, or removes it from, a list of routines to be called whenever a process is created or deleted.

After a driver-supplied routine is registered, it is called with Create set to TRUE just after the initial thread is created within the newly created process designated by the input ProcessId handle.

A driver's process-notify routine is also called with Create set to FALSE, usually when the last thread within a process has terminated and the process address space is about to be deleted."


Дата: Ноя 29, 2003 13:41:55

rst
а ты уверен. что сможешь восстановить алгоритм работы функции после замены этих 6-х байт?
а в чем может быть проблема?
zen333
мне нужно было перехватить что посылает ТХе БАТ...
в таблицах импорта он несодержит сенд вообще

он делает GetModuleHandle/GetProcAdress
mov eax,adress
add eax,6
mov adress1,eax
jmp [adress1]

а зачем add eax,6 ?

. 1 . 2 . 3 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.112