Отследить изменение в памяти процесса по определённым адресам
Адрес на начало строки я научился получать.
Вопрос в том что нужно считывать эту строку если она изменилась. То есть нужны события когда меняются значения в определённом диапазоне адресов
Что посоветуете на эту тему?
Сразу попрошу не советовать считывать по таймеру(да бы не захломлять), в общем любые варианты кроме таймера
Но если я правильно понял она возвращает инфу об изменениях, но не порождает событий. А мне нужно событие, считаю я потом сам
Искал в функциях для работы с памятью, если не там искал или не увидел очевидного подтолкните в нужном направлении.
Забыл указать что работа идёт из под самого процесса, поэтому огроничений связанных с адресными пространствами процессов на выбор функций нету.
Прочитал список memory management functions — действительно, только твою и увидел. Из того, что приходит в голову — ставить protected на область памяти, и этой самой GetWriteWatch (хотя почитай внимательно описание к VirtualAlloc) отлавливать изменения, а потом сравнивать
MEM_WRITE_WATCH
Этот флаг заставляет систему отслеживать факт записи в выделенные страницы. Указание этого флага требует обязательного наличия флага MEM_RESERVE. Для получения адресов страниц, в которые производилась запись после их резервирования или сброса состояния отслеживания записи, используется функция.
DWORD dwFlags,
PVOID lpBaseAddress,
SIZE_T dwRegionSize,
PVOID* lpAddresses,
PULONG_PTR lpdwCount,
PULONG lpdwGranularity
);
LPVOID lpBaseAddress,
SIZE_T dwRegionSize
);
Вот функция GetWriteWatch принимала бы хендл на событие, ну или другая может есть просто я не найду никак
Протектед, чтоб вызывать исключения при записи в этот регион? Ну типа это и будет событием? А потом обрабатывать их самому чтоб программа не накрылась медным тазом?
Или это гонево? И я совершенно ничего не понял
...
Этого я не могу сказать. Есть адрес начала строки, а какая там структура мне не известно.
Может тут отладка как нибудь может помоч?
Воспользоваться дебаг апи, какие нибудь точки останова поставить или ещё что?
Да, как-то так. Правда, через SEH придётся перехватывать, если мне память не изменяет
(но после того, как я не смог вспомнить функцию или хотя бы контекст, в котором я на неё наткнулся, меня терзают смутные сомнения)
Но чёто нихрена не выходит:
begin
if DebugActiveProcess(GetCurrentProcessId) = TRUE then ShowMessage('O ya, baby') else
ShowMessage(IntToStr(GetLastError));
...
ERROR_ACCESS_DENIED
5 (0x5)
Access is denied.
Ну и как я понял(из мсдн) ни о каких точках останова не может быть и речи в такой ситуации.
По умолчанию у процесса отключенна привелегия - SeDebugPrivilege. Использовал самопальную функцию которая включает эту привелегию. С помощью ProcessExplorer вижу что когда грузится моя DLL SeDebugPrivilege - Enabled.
Но DebugActiveProcess всё равно возвращает ту же самую ошибку(ну в смысле не возвращает, а выполняется с ошибкой)
Не могу поверить что у системы нет средств для наблюдения за памятью
А ты привилегию в DLL включаешь?
SeDebugPrivilege? Да, когда она грузится в память процесса то выполняется вот такой код:
begin
if EnableDebugPrivilege = TRUE then ShowMessage('EnableDebugPrivilege') else
ShowMessage(IntToStr(GetLastError));
if DebugActiveProcess(GetCurrentProcessId) = TRUE then ShowMessage('DebugActiveProcess') else
ShowMessage(IntToStr(GetLastError));
Вообще теоретически процесс может отлаживать сам себя?
Насчёт SEH тоже почитал, но видимо пока не достаточно. ни один сишный пример не заставил работать в делфи
Вот как пример попыток, это я пишу при создании формы:
handler := CARDINAL(ExceptAddr);
// ShowMessage(IntToStr(CARDINAL(Addr(_except_handler)))); // Вот так получается тот же самый адрес
asm
push handler
push FS:[0]
mov FS:[0],ESP
end;
var
I: CARDINAL;
begin
ContextRecord.Eax := CARDINAL(MemAddr) - 1000; // MemAddr - это начало региона в который нельзя писать
ShowMessage('Похоже что произошло исключение!');
result := EXCEPTION_CONTINUE_EXECUTION;
end;
Сам процессы не отлаживал, да и с SEH давно работал. А что случается вообще при нажатии той самой кнопки? По идее, если SEH не отлавливает, должна RTL Багдадовская отловить
Обратите внимание! на то, что, если процессу отладки предоставили привилегию SE_DEBUG_NAME и включили в работу, он может отладить любой процесс.
Вот чтото такое пишут в примечаниях. Я чесно хз где там его открывать с PROCESS_ALL_ACCESS. Функция DebugActiveProcess требует идентификатор процесса, а не хендл.
Коль на то пошло я эту прогу открываю с PROCESS_ALL_ACCESS и из под своей проги, и из под эксплорера(ну из внедрённой в него DLL). Так что в чём напряги я если честно понять не могу.
Кстати я запускаю прогу через CreateProcessW, но там всё по умолчанию(цель была запустить и всё).
Может нужно заполнить какие структуры перед запуском, для подготовки к отладке?
Интересно "любой процесс" можно воспринимать буквально?
Кто нибудь отлаживал процесс из под себя?
При нажатии на кнопку появляется сообщение AccessViolation(ну как обычно сначала студийное).
При создании формы:
// Вот выделение 10-и страниц в которые нельзя писать
var
A: PAnsiChar;
begin
A := MemAddr;
A^ := 'S';
// Memo1.Lines.Add(IntToHex(CARDINAL(GetStrAddr('TeSt sTrinG')), 8));
end;
Вот здесь и надо всё править — тот самый флаг ставить. Хотя я что-то запутался, распиши ещё раз, что откуда надо отладить и что откуда запускается
Могу предложить освежить воспоминания о SEH (вдруг что-то не так сделал; а я свой проект, где с этим работал, найти не могу). И кстати, брякается ли отладчик в этом месте, если точку останова поставить?
Теперь мне нужно отлаживать "жертву" из под самой себя. Вот и всех делов :-)
Мля, вот я время убил, отладкой не пользуюсь(но про базовые вещи читал). (((
Поставил безусловную точку останова но программа работала как ни в чём не бывало.
Потом я вспомнил что собирал проект в релиз конфигураци, поменял(там где отображается группа проектов) на дебаг.
Но не тут то было. Программа работала как ни в чём не бывало.
Начал читать, может чё не так делаю(хотя там сложно не так делать).
В итоге на одном форуме нашлось решение. Оказывается просто поменять конфигурацию не достаточно, нужно заново собрать проект. А я думал что это сделается автоматом при таких серьёзных изменениях, но автоматической оказалась только компиляция.
Точка останова вот на этой строке:
Проект собирал в разных режимах, запускал из под студии и отдельно, открывал процесс с полным доступом, но всегда ошибка 5 при выполнении DebugActiveProcess
Создал тестовый проект, сам для себя процесс тоже не хочет становитьтся отладчиком.
Но при этом в лёгкую(без всяких настроек) работает вот такой код
var
SI: STARTUPINFO;
PI: PROCESS_INFORMATION;
begin
CreateProcess('D:\PROJEKTS\CPP\CHANGE RESOLUTION\Release\ChangeResolution.exe', NIL, NIL, NIL, FALSE, NORMAL_PRIORITY_CLASS, NIL, 'D:\PROJEKTS\CPP\CHANGE RESOLUTION\Release', SI, PI);
if DebugActiveProcess(PI.dwProcessId) = TRUE then ShowMessage('DebugActiveProcess') else
ShowMessage(IntToStr(GetLastError));
end;
По ходу придётся по серьёзному разбираться кто там доступ запрещает, и по какой причине
При присоединении отладчика все потоки ставятся на паузу(и при срабатывании точки останова как я понял тоже)
, и я не смогу обработать событие и запустить процесс.
Программа не может узнать если её отлаживают из под ядра(это я гдето читал давно).
Может ли программа заметить(получить об этом информацию) что её отлаживают из под пользовательского уровня? Прокоментируйте пожалуйста кто нибудь кто владеет темой и достаточно опытен.
Хотелось с отладчиком, но теперь видимо придётся разбираться с SEH. Хотя если отладчик пользовательского уровня не "палится" то можно и поотлаживать из под эксплорера.
Если у кого появились идеи, выкладывайте, не стесняйтесь
По прежнему интересует метод получить событие при записи в определённый адрес(желательно из под самого процесса)
Кстати, вполне логичное поведение же :) Я немного потерял нить обсуждения, но что у тебя случалось при самоотладке? ЕМНИП, ошибка, которая просто не допускала самоподвешивания
Может ли программа заметить(получить об этом информацию) что её отлаживают из под пользовательского уровня?
1-е — скорее всего, точно. А насчёт 2-го — в той же секции есть такая функция IsDebuggerPresent, вот благодаря ей и можно узнать. А вообще, если почитать про антиотладочные приёмы, ещё кучу всего узнать можно
И кстати, твоя же прога вряд ли палит отладчик, так что можно смело отлаживать её хоть до укладки ☺
Может и логичное, я не знал как это работает. Понятно что любой поток может изменить значение по определённому адресу, и этого не должно случиться в момент срабатывания(и после) точки останова. Но я думал может оставляют работающим отлаживающий поток. Видимо инженерам из нашей любимой корпорации показалось что это вовсе ни к чему.
Да и что происходит с памятью самому процессу знать не обязательно.
Я не знаю "палит" программа или нет, по этому по умолчанию для меня как "палит".
Если не "палит" тогда отладка из под эксплорера. Фунька как я вижу есть, и ничто не мешает этой проге её вызвать.
Видимо придётся подменить эту фуньку, и возвращать всегда FALSE.
Хотя мне уже больше SEH нравится, с отладкой пошла какая то порнуха.