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

Ваш аккаунт

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

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

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

Отследить изменение в памяти процесса по определённым адресам

465
23 января 2013 года
QWERYTY
595 / / 25.03.2012
Есть програмка в памяти которой в процессе работы создаётся строка. Так же в процессе работы она дополняется, ну или стирается и туда пишется более длинная.
Адрес на начало строки я научился получать.

Вопрос в том что нужно считывать эту строку если она изменилась. То есть нужны события когда меняются значения в определённом диапазоне адресов
Что посоветуете на эту тему?

Сразу попрошу не советовать считывать по таймеру(да бы не захломлять), в общем любые варианты кроме таймера
465
23 января 2013 года
QWERYTY
595 / / 25.03.2012
Разумеется был в мсдн, и увидел только одну функцию которая хоть каким то боком относится к теме - GetWriteWatch
Но если я правильно понял она возвращает инфу об изменениях, но не порождает событий. А мне нужно событие, считаю я потом сам

Искал в функциях для работы с памятью, если не там искал или не увидел очевидного подтолкните в нужном направлении.

Забыл указать что работа идёт из под самого процесса, поэтому огроничений связанных с адресными пространствами процессов на выбор функций нету.
7
23 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Вот знаешь, совершенно недавно натыкался на подобную функцию — прочёл описание и удивился, нужна ли такая. Но совершенно забыл её название
Прочитал список memory management functions — действительно, только твою и увидел. Из того, что приходит в голову — ставить protected на область памяти, и этой самой GetWriteWatch (хотя почитай внимательно описание к VirtualAlloc) отлавливать изменения, а потом сравнивать
465
23 января 2013 года
QWERYTY
595 / / 25.03.2012
Да блин, читал я про VirtualAlloc. Там третьим параметром можно указывать совокупность флагов, в том числе - MEM_WRITE_WATCH.


MEM_WRITE_WATCH
Этот флаг заставляет систему отслеживать факт записи в выделенные страницы. Указание этого флага требует обязательного наличия флага MEM_RESERVE. Для получения адресов страниц, в которые производилась запись после их резервирования или сброса состояния отслеживания записи, используется функция.

 
Код:
UINT GetWriteWatch(
  DWORD dwFlags,
  PVOID lpBaseAddress,
  SIZE_T dwRegionSize,
  PVOID* lpAddresses,
  PULONG_PTR lpdwCount,
  PULONG lpdwGranularity
);
Сбросить состояние отслеживания записи можно этой же функцией, указав WRITE_WATCH_FLAG_RESET в параметре dwFlags или вызвав функцию

 
Код:
UINT ResetWriteWatch(
  LPVOID lpBaseAddress,
  SIZE_T dwRegionSize
);
Только не улавливаю где тут события по которым бы я мог считывать.
Вот функция GetWriteWatch принимала бы хендл на событие, ну или другая может есть просто я не найду никак
465
23 января 2013 года
QWERYTY
595 / / 25.03.2012
Цитата: @pixo $oft
Из того, что приходит в голову — ставить protected на область памяти, и этой самой GetWriteWatch (хотя почитай внимательно описание к VirtualAlloc) отлавливать изменения, а потом сравнивать



Протектед, чтоб вызывать исключения при записи в этот регион? Ну типа это и будет событием? А потом обрабатывать их самому чтоб программа не накрылась медным тазом?

Или это гонево? И я совершенно ничего не понял

20K
24 января 2013 года
ellor!
198 / / 24.05.2012
Речь идёт о глобальной переменной, в которую одни функции записывают значения, а другие считывают? Не лучшее решение, но можно в записывающих методах генерировать события SendMessage, SendMessageCallback, а в каком-нибудь классе, скажем, обрабатывать эти сообщения.
465
24 января 2013 года
QWERYTY
595 / / 25.03.2012
Цитата: ellor!
Речь идёт о глобальной переменной, в которую одни функции записывают значения, а другие считывают?
...


Этого я не могу сказать. Есть адрес начала строки, а какая там структура мне не известно.

465
24 января 2013 года
QWERYTY
595 / / 25.03.2012
Например в с++ пишем(не важно, просто для примера глобальная переменная )
 
Код:
AnsiString str = "VASYA"
Тут как я понял нечего перехватывать, никаких апи не вызывается.


Может тут отладка как нибудь может помоч?
Воспользоваться дебаг апи, какие нибудь точки останова поставить или ещё что?
7
24 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Цитата: QWERYTY
Протектед, чтоб вызывать исключения при записи в этот регион?

Да, как-то так. Правда, через SEH придётся перехватывать, если мне память не изменяет
(но после того, как я не смог вспомнить функцию или хотя бы контекст, в котором я на неё наткнулся, меня терзают смутные сомнения)

465
25 января 2013 года
QWERYTY
595 / / 25.03.2012
На другом порталле программистов посоветовали попытаться стать отладчиком, и поставить точки останова.

Но чёто нихрена не выходит:
 
Код:
procedure DllProcessAttach(); stdcall;
begin
  if DebugActiveProcess(GetCurrentProcessId) = TRUE then ShowMessage('O ya, baby') else
  ShowMessage(IntToStr(GetLastError));
...
Но получаю ошибку под номером 5.
ERROR_ACCESS_DENIED
5 (0x5)
Access is denied.

Ну и как я понял(из мсдн) ни о каких точках останова не может быть и речи в такой ситуации.


По умолчанию у процесса отключенна привелегия - SeDebugPrivilege. Использовал самопальную функцию которая включает эту привелегию. С помощью ProcessExplorer вижу что когда грузится моя DLL SeDebugPrivilege - Enabled.

Но DebugActiveProcess всё равно возвращает ту же самую ошибку(ну в смысле не возвращает, а выполняется с ошибкой)

Не могу поверить что у системы нет средств для наблюдения за памятью
7
25 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
ОС какая? Быть может, если спермёрка, то надо принудительно запускать из-под админа
А ты привилегию в DLL включаешь?
465
26 января 2013 года
QWERYTY
595 / / 25.03.2012
XP SP3. Работаю под администраторской учётной записью. Но не под встроенной(которая не отображается в учётных записях), хотя если это может облегчить жизнь можно и под ней входить.

SeDebugPrivilege? Да, когда она грузится в память процесса то выполняется вот такой код:
 
Код:
procedure DllProcessAttach(); stdcall;
begin
  if EnableDebugPrivilege = TRUE then ShowMessage('EnableDebugPrivilege') else
  ShowMessage(IntToStr(GetLastError));
  if DebugActiveProcess(GetCurrentProcessId) = TRUE then ShowMessage('DebugActiveProcess') else
  ShowMessage(IntToStr(GetLastError));
EnableDebugPrivilege - самописанная, но работает как часы. Проверенно сто раз.

Вообще теоретически процесс может отлаживать сам себя?


Насчёт SEH тоже почитал, но видимо пока не достаточно. ни один сишный пример не заставил работать в делфи

Вот как пример попыток, это я пишу при создании формы:
 
Код:
ExceptAddr := GetProcAddress(GetModuleHandle(0), PAnsiChar('_except_handler')); // Это я так начал по тому что не работало, думал может адрес не тот получаю
   handler := CARDINAL(ExceptAddr);
  // ShowMessage(IntToStr(CARDINAL(Addr(_except_handler))));  // Вот так получается тот же самый адрес
asm
   push    handler
   push    FS:[0]
   mov     FS:[0],ESP
   end;
Ну и соответственно в этом же модуле вот такая функция:
 
Код:
function _except_handler(ExceptionRecord: EXCEPTION_RECORD; EstablisherFrame: POINTER; ContextRecord: CONTEXT; DispatcherContext: POINTER): INTEGER; stdcall; export;
var
I: CARDINAL;
begin
   ContextRecord.Eax := CARDINAL(MemAddr) - 1000; // MemAddr - это начало региона в который нельзя писать

   ShowMessage('Похоже что произошло исключение!');

   result := EXCEPTION_CONTINUE_EXECUTION;
end;
По кнопке написан код который вызывает исключение, но после всех манипуляций изменений никаких
7
26 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Внимательно читал про DebugActiveProcess? Там написано, что должны быть все права
Сам процессы не отлаживал, да и с SEH давно работал. А что случается вообще при нажатии той самой кнопки? По идее, если SEH не отлавливает, должна RTL Багдадовская отловить
465
26 января 2013 года
QWERYTY
595 / / 25.03.2012
Отладчик должен иметь соответствующий доступ к целевому процессу; он должен быть в состоянии открыть процесс для доступа PROCESS_ALL_ACCESS. В среде Windows Me/98/95, отладчик имеет соответствующий доступ, если идентификатор процесса допустим. На других версиях Windows, DebugActiveProcess может завершиться ошибкой, если целевой процесс создавался с дескриптором безопасности, который предоставляет отладчику что-то меньшее чем полный доступ.

Обратите внимание! на то, что, если процессу отладки предоставили привилегию SE_DEBUG_NAME и включили в работу, он может отладить любой процесс.

Вот чтото такое пишут в примечаниях. Я чесно хз где там его открывать с PROCESS_ALL_ACCESS. Функция DebugActiveProcess требует идентификатор процесса, а не хендл.
Коль на то пошло я эту прогу открываю с PROCESS_ALL_ACCESS и из под своей проги, и из под эксплорера(ну из внедрённой в него DLL). Так что в чём напряги я если честно понять не могу.

Кстати я запускаю прогу через CreateProcessW, но там всё по умолчанию(цель была запустить и всё).
Может нужно заполнить какие структуры перед запуском, для подготовки к отладке?

Интересно "любой процесс" можно воспринимать буквально?
Кто нибудь отлаживал процесс из под себя?


При нажатии на кнопку появляется сообщение AccessViolation(ну как обычно сначала студийное).
При создании формы:
 
Код:
MemAddr := VirtualAlloc(NIL, SI.dwPageSize * 10, MEM_COMMIT + MEM_RESERVE + MEM_WRITE_WATCH, PAGE_NOACCESS);
// Вот выделение 10-и страниц в которые нельзя писать
Ну и кнопка вызывающая исключение:
 
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
A: PAnsiChar;
begin
   A := MemAddr;
   A^ := 'S';

  // Memo1.Lines.Add(IntToHex(CARDINAL(GetStrAddr('TeSt sTrinG')), 8));
end;
465
26 января 2013 года
QWERYTY
595 / / 25.03.2012
Никаких антивирусов(и прочего софта смежного функционала) не установлено.
7
26 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Цитата: QWERYTY
Кстати я запускаю прогу через CreateProcessW, но там всё по умолчанию

Вот здесь и надо всё править — тот самый флаг ставить. Хотя я что-то запутался, распиши ещё раз, что откуда надо отладить и что откуда запускается
Могу предложить освежить воспоминания о SEH (вдруг что-то не так сделал; а я свой проект, где с этим работал, найти не могу). И кстати, брякается ли отладчик в этом месте, если точку останова поставить?

465
27 января 2013 года
QWERYTY
595 / / 25.03.2012
Моя программа при запуске внедряет длл в эксплорер. Длл при загрузке запускает программу "жертву", и внедряет туда ещё одну длл. Весь этот гемор был сделан для того чтобы "жертва" думала что процесс родитель - эксплорер.
Теперь мне нужно отлаживать "жертву" из под самой себя. Вот и всех делов :-)

Мля, вот я время убил, отладкой не пользуюсь(но про базовые вещи читал). (((
Поставил безусловную точку останова но программа работала как ни в чём не бывало.
Потом я вспомнил что собирал проект в релиз конфигураци, поменял(там где отображается группа проектов) на дебаг.
Но не тут то было. Программа работала как ни в чём не бывало.
Начал читать, может чё не так делаю(хотя там сложно не так делать).
В итоге на одном форуме нашлось решение. Оказывается просто поменять конфигурацию не достаточно, нужно заново собрать проект. А я думал что это сделается автоматом при таких серьёзных изменениях, но автоматической оказалась только компиляция.

Точка останова вот на этой строке:
 
Код:
A^ := 'S';
срабатывает до появления всяких сообщений об ошибках.


Проект собирал в разных режимах, запускал из под студии и отдельно, открывал процесс с полным доступом, но всегда ошибка 5 при выполнении DebugActiveProcess
465
27 января 2013 года
QWERYTY
595 / / 25.03.2012
У пациента состояние тяжёлое, но стабильное :-)


Создал тестовый проект, сам для себя процесс тоже не хочет становитьтся отладчиком.

Но при этом в лёгкую(без всяких настроек) работает вот такой код
Код:
procedure TForm1.Button2Click(Sender: TObject);
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;
И отлаживаемый процесс тутже становится на паузу(видимо ждёт команды от отладчика)

По ходу придётся по серьёзному разбираться кто там доступ запрещает, и по какой причине
465
28 января 2013 года
QWERYTY
595 / / 25.03.2012
Программа не может отлаживать сама себя. И никто из опытных форумчан не подсказал, ну да ладно.
При присоединении отладчика все потоки ставятся на паузу(и при срабатывании точки останова как я понял тоже)
, и я не смогу обработать событие и запустить процесс.

Программа не может узнать если её отлаживают из под ядра(это я гдето читал давно).
Может ли программа заметить(получить об этом информацию) что её отлаживают из под пользовательского уровня? Прокоментируйте пожалуйста кто нибудь кто владеет темой и достаточно опытен.


Хотелось с отладчиком, но теперь видимо придётся разбираться с SEH. Хотя если отладчик пользовательского уровня не "палится" то можно и поотлаживать из под эксплорера.

Если у кого появились идеи, выкладывайте, не стесняйтесь
По прежнему интересует метод получить событие при записи в определённый адрес(желательно из под самого процесса)
7
29 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Цитата: QWERYTY
Программа не может отлаживать сама себя. И никто из опытных форумчан не подсказал, ну да ладно

Кстати, вполне логичное поведение же :) Я немного потерял нить обсуждения, но что у тебя случалось при самоотладке? ЕМНИП, ошибка, которая просто не допускала самоподвешивания

Цитата: QWERYTY
Программа не может узнать если её отлаживают из под ядра(это я гдето читал давно).
Может ли программа заметить(получить об этом информацию) что её отлаживают из под пользовательского уровня?

1-е — скорее всего, точно. А насчёт 2-го — в той же секции есть такая функция IsDebuggerPresent, вот благодаря ей и можно узнать. А вообще, если почитать про антиотладочные приёмы, ещё кучу всего узнать можно
И кстати, твоя же прога вряд ли палит отладчик, так что можно смело отлаживать её хоть до укладки ☺

465
29 января 2013 года
QWERYTY
595 / / 25.03.2012
При самоотладке ничего не происходит. :-) Её вообще не происходит. Функция DebugActiveProcess выполняется с ошибкой 5.
Может и логичное, я не знал как это работает. Понятно что любой поток может изменить значение по определённому адресу, и этого не должно случиться в момент срабатывания(и после) точки останова. Но я думал может оставляют работающим отлаживающий поток. Видимо инженерам из нашей любимой корпорации показалось что это вовсе ни к чему.
Да и что происходит с памятью самому процессу знать не обязательно.


Я не знаю "палит" программа или нет, по этому по умолчанию для меня как "палит".
Если не "палит" тогда отладка из под эксплорера. Фунька как я вижу есть, и ничто не мешает этой проге её вызвать.
Видимо придётся подменить эту фуньку, и возвращать всегда FALSE.
Хотя мне уже больше SEH нравится, с отладкой пошла какая то порнуха.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог