Delphi | Работа с памятью чужого процесса, перехват API
Вопрос в PM пришел:
Цитата:
Цитата:
|
Savant
Ну,тогда я сдаюсь :( . Дело в том,что мне необходимо изменить защитные атрибуты определённой страницы чужого процесса,к примеру: поменять на PAGE_EXECUTE_READWRITE ,но теперь я совсем запутался... |
DillerInc
Не могу не спросить - каковы причины? Может есть другое решение? Кстати, нужные адреса можно и через VirtualQueryEx() получить. Ща попробуем.... =) |
Savant
Цитата:
Мне необходимо поймать на крючок вызов функции LoadLibraryA из библиотеки Kernel32.dll в чужом процессе, иными словами,иметь возможность поместить в нужное место в нужное время два байта ( EB FE ), если я вообще правильно понял всю эту катавасию. Цитата:
Код:
var |
Когда мне надо посмотреть или проверить как работает та или иная функция, то обычно я пишу небольшую программку, которая эту самую функцию активно использует
Итак, представленная ниже программа (если я все правильно сделал) должна: 1) найти все запущенные процессы 2) в области виртуальной памяти каждого процесса найти используемые им части (регионы/блоки) и вывести по ним информацию Если выводить в файл, то он получается размером в 2,37 мб :))) Код:
program vpe; Цитата:
Цитата:
|
Вот на Делфи - http://forum.sources.ru/index.php?sh...=43286&hl=hook
Добавлено: В этой статье (ближе к концу) тоже есть полезности (на асме). Перехват APi функций в WinNT+ Добавлено: Статьи о перехвате вызовов API, используя Delphi: Перехват API функций в Windows NT (часть 1). Основы перехвата. Перехват API функций в Windows NT (часть 2). Методы внедрения кода. Перехват API функций в Windows NT (часть 3). Нулевое кольцо. |
Savant
Спасибо за ссылки - будем разбираться. Если что, буду тогда сюда постить,если ты не против. Цитата:
|
Вообще,как то странно это...к примеру:
Код:
var Код:
var Вопрос: почему первый вариант работает,а второй нет ? Как можно поправить ситуацию ? |
Нет,ну это просто проказа какая-то :angry: :
беру любое смещение из адресного простанства чужого процесса,вставляю его как второй параметр в функцию VirtualProtectEx - всё работает без каких-либо проблем! Как только использую адрес начала системной функции - всё идёт крахом, из-за чего рушится и вся остальная конструкция. Может быть проблема заключается именно в попытке обращения к импортируемой библиотеке,но в указанных примерах (по ссылкам) предлагали же непосредственное внедрение своих команд в начало системной функции :blink: ... |
Ну,неужели ни у кого нету никаких соображений по этому поводу,никаких советов ?
Может причина "недосягаемости" адресного пространтсва импортируемых библиотек заключается где-то в атрибутах,свойствах открытия файла или создания процесса из последнего... :help: |
hasherfrog
Темы разбил... DillerInc Цитата:
Цитата:
Цитата:
Кстати говоря, а Вы не из под 9x/Me случайно работаете?! Там область применения VirtualProtectEx() ограничена 2 Гб, а область загрузки системных DLL как раз идет дальше (т.н. shared virtual address space). p.s.: получать адрес из числа (Integer->Pointer) в Delphi лучше функцией ptr(), например ptr($4FFF). |
Savant
Цитата:
Цитата:
Цитата:
Код:
var |
В общем,почитав всякого и наковырявшись с кодом "по полной программе",я к сожалению так конкретно и не понял почему возникает вышеописанная ошибка - ну,да бог с ним...
Во большинстве материалов,которые я читал,преподавалась следующая техника т.н. "сплайсинга" системных функций: в адресном пространстве чужого процесса создаётся удалённый поток с помощью CreateRemoteThread,в который потом подгружается библиотека,ответственная за перехват системных функций (размещение своих команд в начале таких функций,перенаправление управления на свой код-перехватчик)... Причём такой вариант трактуется именно как наиболее предпочтительный и эффективный. Но теперь я здесь по иному вопросу. Функция GetModuleHandle возвращает дескриптор указанного модуля,который,как я понял,является ни чем иным как базовым адрестом загрузки этого самого модуля.Проблема заключается походу в следующем: Цитата:
А как можно получить такой дескриптор какого-нибудь модуля в чужом процессе ? |
Я почти достиг того,чего я хотел,а именно:
Код:
var Соответственно,кто-нибудь может сказать в чём могут быть причины ? Можно,конечно,пытаться использовать поле dEvent.LoadDll.lpImageName структуры _DEBUG_EVENT, которое,как я понял,должно содержать указатель на имя загруженной библиотеки,но там какие-то трудности,о которых как-то размыто пишут на MSDN...и сколько я не пробЫвал использовать эту возможность - ничего путного не выходило.Хотя это был бы наверное самый идеальный вариант получения имени загруженной библиотеки. |
хм...неужели я задаю такие сложные вопросы,что никто не хочет на них отвечать... :huh:
Иными словами,либо я чего-то не допонимаю,либо библиотека psapi.dll, в которой объявлены такие функции как GetModuleFileNameEx, GetModuleBaseName, криво написана... Тем не менее мне удалось создать работающий код(точнее взять его основу на MSDN),который будет динамически получать имя загружаемой в чужом процессе библиотеки,хотя,по-моему,всё это скорее напоминает какие-то танцы с бубном. Код:
function GetFileNameFromHandle(hFile : Cardinal) : Boolean; |
В общем,подумал,что может кому-то будет интересно,каким образом можно всё-таки поймать вызов какой-нибудь API-функции,заменив первые команды последней банальным EB FE,то есть попросту зациклив эту функцию.
Случай относится к тому варианту,когда вы запускаете подопытный процесс в режиме CREATE_SUSPENDED. Причина,из-за которой у меня в своё время не получалось поймать функцию,заключалась в следующем. При подобной технике необходимо,чтобы процесс был разморожен и как бы начал физически выполняться,если так можно выразиться. Достигается это с помощью предварительного зацикливания процесса на точке входа,а именно: Код:
var Под конец стоит заметить,что зацикливание библиотечных функций не будет работать на 9х-ой линейке Windows,т.к. если я не ошибаюсь,библиотеки там отображаются в некую общую область памяти,а не в каждый процесс отдельно. |
Вижу тема давнишняя, но наверняка сюда заходят.
Была аналогичная проблема с получением хендла длл в чужом процессе. Честно говоря был удивлен не найдя простой функции для этого. Пришлось делать через тулхелп32. В юзес подключаем Tlhelp32 и перечисляем модули в конкретном процессе(или если не ошибаюсь во всех когда вместо PId передаётся 0): {Code} // HLibrary := GetModuleHandle(PWideChar('ИмяМодуля.Dll')); Вот так разумеется не проканывает // HLibrary разумеется глобальная переменная procedure TForm1.Button2Click(Sender: TObject); var SnapModule: CARDINAL; ModuleEntry: ModuleEntry32; NextModule: BOOL; begin HLibrary := 0; SnapModule := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PId); // Не забываем предварительно получить пид ModuleEntry.dwSize := SizeOf(ModuleEntry); NextModule := Module32First(SnapModule, ModuleEntry); while NextModule do begin if ModuleEntry.szModule = 'ИмяМодуля.Dll' then begin HLibrary := ModuleEntry.hModule; Exit; end; NextModule := Module32Next(SnapModule, ModuleEntry); end; CloseHandle(SnapModule); end; {/Code} Ну там можно поиграть структурой ModuleEntry под свои потребности. Там много интересных полей. |
DillerInc
"var ProcAddress : LPDWORD; Temp_Protect : Cardinal; begin ProcAddress := LPDWORD(GetProcAddress(GetModuleHandle('Kernel32.dll'), 'LoadLibraryA'));" Зачем ProcAddress какого то непонятного типа? var ProcAddress: POINTER; begin ProcAddress := GetProcAddress(GetModuleHandle('Kernel32.dll'), 'LoadLibraryA');" Функция VirtualProtectEx судя из описания в моей студии требует lpAddress (System.Pointer), так надо понимать lp перед переменной означает что нам нужен LONG POINTER, т.е. указатель на функцию, а не указатель на параметр DWORD. Зачем там все эти выкрутасы? Поймать то вызов легко. Создаётся удалённый поток в процессе "жертве", и поток загружает нашу длл в адресное пространство. А в длл разумеется код который выполняет перехват(затирает первые 5 байт перехватываемой функции и записывает адрес нашей функции), и в зависимости от задачи можно восстановить искомую функцию, вызвать её, и опять переписать 5 байт до следующего вызова. А вот самому вызвать свою функцию из своей же длл(закинутой в сторонний процесс) не понятно пока как. Я понимаю что моя длл теперь в виртуальном пространстве стороннего процесса. Непонятно почему .modBaseAddr(как я понимаю адрес загрузки) совпадает с хендлом модуля. Допустим можно вычислить адрес функции, но ведь это виртуальный адрес в том процессе, и как вызвать функцию по виртуальному адресу? |
Время: 16:08. |
Время: 16:08.
© OSzone.net 2001-