Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Сплайсинг

56K
17 апреля 2010 года
kamax70
7 / / 20.03.2010
Написал программу, выполняющую перехват Апи функции MessageBoxExA методом сплайсинга:
Код внедряемой длл:
Код:
type
 OldCode = packed record
  One: dword;
  two: word;
 end;
 
far_jmp = packed record
  PuhsOp: byte;
  PushArg: pointer;
  RetOp: byte;
 end;
 
var
 JmpMba: far_jmp;
 OldMba: OldCode;
 MbaAdr: pointer;
 
 
function NewMessageBox: Integer; stdcall;
var
  Bytes: dword;
begin
WriteProcessMemory(INVALID_HANDLE_VALUE, MbaAdr, @OldMba, SizeOf(OldCode), Bytes);
asm
mov eax, dword ptr MbaAdr
add eax, 5
jmp eax
end;
end;
     
Procedure SetHook();
var
 hUser32: dword;
 Bytes,OldProtect: dword;
begin
  hUser32 := GetModuleHandle('user32.dll');
  MbaAdr  := GetProcAddress(hUser32, 'MessageBoxExA');
  ReadProcessMemory(INVALID_HANDLE_VALUE, MbaAdr, @OldMba, SizeOf(OldCode), Bytes);
  VirtualProtect(MbaAdr,6,PAGE_EXECUTE_READWRITE,OldProtect);
  JmpMba.PuhsOp  :=$68;
  JmpMba.PushArg := @NewMessageBox;
  JmpMba.RetOp   := $C3;
  WriteProcessMemory(INVALID_HANDLE_VALUE, MbaAdr, @JmpMba, SizeOf(far_jmp), Bytes);
end;
.........

В идеале при перехвате происходит джамп на мою функцию NewMessageBox, затем восстанавливается затертый джампом участок памяти и джамп обратно.. и как следствие правильное выполнение функции MessageBoxExA. Фукция выполняется правильно, но после закрытия MessadgeBox'a закрывается почему-то и программа, его вызвавшая...
Кто-нибудь может подсказать, в чем проблема? Вобзможно в этом коде
 
Код:
mov eax, dword ptr MbaAdr
add eax, 5
jmp eax
8.2K
17 апреля 2010 года
bagie2
299 / / 26.10.2008
У меня есть старый пример. Может быть поможет.

По коду у вас не восстанавливаются байты, после того, как MessageBox отработает и еще возможно, что компилятор вставляет фрейм в процедуру и выход из MsgBox будет не туда, куда надо. В дизасме или отладчике поглядите и поймете почему ошибка.
56K
17 апреля 2010 года
kamax70
7 / / 20.03.2010
Этот пример не подходит, ибо там немного иначе делается, чем мне надо.

Цитата: bagie2
По коду у вас не восстанавливаются байты, после того, как MessageBox отработает



Почему не восстанавливаются? Я записываю созраненные 6 байт в начало перехватываемой функции. После этого выполняю на неё джамп. По-хорошему первоначальный вид перехватываемой функции в памяти не должен был измениться, разве не так?

8.2K
17 апреля 2010 года
bagie2
299 / / 26.10.2008
а как вам надо? что именно иначе и почему?

вы восстановили ориг. байты функции, она отработала и после этого обычно снова патчат начало функции (конечно если не надо, чтобы хук только один раз отработал). к тому же у вас скорее всего в стеке лежат еще данные, например локальные переменные (var Bytes: dword), поэтому может стать так, что адрес возврата будет неправильный и приложение "упадет"

кстати сплайсинг плох тем, что потоконебозопасный. может быть имеет смысл юзать критические секции.
56K
17 апреля 2010 года
kamax70
7 / / 20.03.2010
Я привел не весь код проги.. Я дальше использую мьютекс для синхронизации.

Иначе - это значит я не знаю, какую функцию перехватываю, а считываю её название из файла. Поэтому не могу написать что-то типо result:=MessageBoxExA (...);
Я должен совершить джамп обратно,чтобы вынкция выполнилась.
Цитата:

к тому же у вас скорее всего в стеке лежат еще данные, например локальные переменные (var Bytes: dword), поэтому может стать так, что адрес возврата будет неправильный и приложение "упадет"


А как решить эту проблему? Удалить Bytes из стека?

8.2K
17 апреля 2010 года
bagie2
299 / / 26.10.2008
Попробуйте это.
56K
18 апреля 2010 года
kamax70
7 / / 20.03.2010
Спасибо за интересный пример :) Возьму на вооружение.
Только если заменить user32.dll на kernel32.dll, а MessageBoxA на CreateFileA, то вылетает ошибка :(
У меня главная задача - возможность перехвата любой функции...
И вам не кажется, что вы это сделали как-то сложно? Неужели нельзя проще?
Например вот так http://hellknights.void.ru/articles/cch-hotpatching.txt
56K
18 апреля 2010 года
kamax70
7 / / 20.03.2010
Спасибо, интересный пример :) Возьму на вооружение.
Вот только если я заменяю MessageBoxA на CreateFileA,а user32 на kernel32,
то программа выдает ошибку.. У меня главная задача, чтобы прога могла перехватывать любые АПИ функции по их названию и названию библиотеки.

И вам не кажется, что вы сделали слишком сложно? Разве нельзя было проще? Например вот так ?
282
01 мая 2010 года
Bard
481 / / 26.02.2006
Цитата: kamax70

 
Код:
mov eax, dword ptr MbaAdr
add eax, 5
jmp eax



Не, ну вообще забавно. Из NewMessageBox, где стек уже искажен локальной переменной Bytes, и может быть, прочей чепухой сразу брать тай переходить джампом на адрес в другой функции... аяяй. Нехорошо. Ну а смысл записать оригинальные байты и перейти на +5 байт вперед - ето что шутка? Если подумать, то 0x68 + DWORD + 0xc3 == 6 байт, ну может я чего не понял. 5 или 6 - какая разница. Главное что ети байты что-то в оригинальной функции делают, а ты их просто взял и пропустил. То что ор. функция отрабатывает правильно - ето чудо.

Короче. Как надо делать :):

1) Читаем оригинальные байты (чтобы не прогадать с количеством нужен дисассемблер длин инструкций).

2) Строим код перехода:

 
Код:
push НовыйОбработчик
ret


3) Строим мост:

 
Код:
Ор. байты
push АдресФункции
add [esp],ДлинаЗатертыхИнструкций
ret



4) На место оригинальных байт ставим код перехода на новый обработчик.

 
Код:
НовыйОбработчик (args) {
   
    // шото делаем...
   
    push args
    call мост

}


Следует сказать о многопоточности. Приведенный мною метод вроде безопасен в етом плане (сам не проверял).
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог