Никак не могу понять. Предположим у нас есть процесс в котором тысячи структур и переменных. Предположим я любым доступным способом нашел актуальный оффсет к переменной для текущей сессии. Но ведь после перезапуска программы данные записываются по другим адресам, разве нет? Перелопатил кучу литературы на эту тему. Все, что нашел - статьи про поиск паттерна в оперативной памяти. Но что делать, если паттерн слишком простой и встречается часто и не позволяет однозначно идентифицировать объект в памяти?
Никак не могу понять. Предположим у нас есть процесс в котором тысячи структур и переменных. Предположим я любым доступным способом нашел актуальный оффсет к переменной для текущей сессии. Но ведь после перезапуска программы данные записываются по другим адресам, разве нет? Перелопатил кучу литературы на эту тему. Все, что нашел - статьи про поиск паттерна в оперативной памяти. Но что делать, если паттерн слишком простой и встречается часто и не позволяет однозначно идентифицировать объект в памяти?
Ты плохо искал. В большинстве процессов приминяется штука под названием - ASLR (address space layout randomization), эт технология заставляет распологать данные в радомном месте, в памяти. *бтв, ее может и не быть, и тогда все намного проще xD*.
Из-за этого после каждого рестарта (или выделения дин. памяти) у тебя данные находятся по разным адресам, чтобы решить эту "проблему" тебе нужно найти цепочку указателей, которые приведут тебя к значению. Приложение в любом случае как-то работает с данными, которые тебе нужны, так что поиск нужной цепочки - это лишь вопрос времени, а она, ЗА ИСКЛЮЧЕНИЯМИ, всегда есть.
Ты плохо искал. В большинстве процессов приминяется штука под названием - ASLR (address space layout randomization), эт технология заставляет распологать данные в радомном месте, в памяти. *бтв, ее может и не быть, и тогда все намного проще xD*.
Из-за этого после каждого рестарта (или выделения дин. памяти) у тебя данные находятся по разным адресам, чтобы решить эту "проблему" тебе нужно найти цепочку указателей, которые приведут тебя к значению. Приложение в любом случае как-то работает с данными, которые тебе нужны, так что поиск нужной цепочки - это лишь вопрос времени, а она, ЗА ИСКЛЮЧЕНИЯМИ, всегда есть.
Спасибо за ответ, это, думаю, то что нужно. Я уже слышал про ASLR, но не увидел, что там используются цепочки указателей. Если сможете привести какую-нибудь литературу или еще что-то, что можно покурить, то буду крайне благодарен :)
Посткодинг не интересует. Если есть конкретная теория - говорите, я удовольствием приму ответ. Размазанные же ответы или ответы в стиле "Вот сюда ткни, а зачем - не знаю" мне не нужны, извините
P.S. Если под позицией байтов вы имели ввиду определенное характерное расположение статичных байт, то это и есть паттерн. Он же шаблон
Чего не знаю, я как-бы читы создавал свои. И я определяю адрес по позиции байтов (не шаблоны). Не знаю, почему так, информацию нигде не нашел. Но все работает.
Если патерен не уникален, то можно получать нужный стат адрес по ссылке. По ссылке это то место ,где вызывается нужная тебе функция.
Допустим есть Н функция которая расположена в файле по смещению program.exe+12345; И если не получается сделать патерн на саму функцию (мало уникальных байт).
Нужно найти места где она вызвается и делать Паттерн уже на то место , где вызывается . Найти можно в ida через xref перейдя на адрес функции и нажав X.
Либо сделать самому xref, я так раньше делал , до того как понял как идой пользоваться -_-, Я искал байты начала Call'ов и проверял Смещение инструкции + ее байты куда собственно идет call ( В x64), Гет Абсолют адрес называют получение такого адреса. (мб немного ошибся как он получается ,я уже точно не помню ,так примерно)
Собственно после того ты нашел , где вызывается нужная тебе функция, то ты уже делаешь патерн на call program.exe+12345 и берешь от туда уже адрес. А если тебе потом уже нужно брать адресс из этой функции, то ты уже берешь смещение относительно нее типо вот полный пример пвсевдокода :
Код:
xrefinstructionadr = findpatter("program.exe","48 ? ? ff 25 90 90 90 ?");
Fooadr = getabsAddr(xrefinstructionadr); // там вроде надо от адреса инструкции прибавлять число, что бы не брать байты call, а брать байты который нужны для вычилсения адреса .
VeryCoolInstructionadr = Fooadr+0x1C;
engineadr = getAbsAddress(VeryCoolInstruction);
Programengine* engine = (Programengine*)engineadr;
std::cout <<engine->Version<<"\n" ;
// п.с само смещение от базового адресса в таком случаее не нужно, но если тебе вруг все же для чего-то надо, то то просто из Абсадресса вычитай базовый так и получишь смещение от базового, главное что бы это было смещение относительно одного модуля .
Еще можно найти vtable, я с ними особо не работал так, что хз так видел пару примеров примерно понимаю ,но мне обычно нужна 1 опр функция , а др мне не нужны так ,что я на прямую делаю.
И да так чисто на всякий Патерны на .data / динам память, ОБЫЧНО нет смысла делать , нужно патрен на код делать. (просто я одному челу пытался сказать, но мне кажется ему пофиг, он находит значение и сразу в дизасемблере открывает , а не в отладчике и не ищит инструкцию которая читает / пишит и вот на нее уже патерн надо делать. )
Если патерен не уникален, то можно получать нужный стат адрес по ссылке. По ссылке это то место ,где вызывается нужная тебе функция.
Допустим есть Н функция которая расположена в файле по смещению program.exe+12345; И если не получается сделать патерн на саму функцию (мало уникальных байт).
Нужно найти места где она вызвается и делать Паттерн уже на то место , где вызывается . Найти можно в ida через xref перейдя на адрес функции и нажав X.
Либо сделать самому xref, я так раньше делал , до того как понял как идой пользоваться -_-, Я искал байты начала Call'ов и проверял Смещение инструкции + ее байты куда собственно идет call ( В x64), Гет Абсолют адрес называют получение такого адреса. (мб немного ошибся как он получается ,я уже точно не помню ,так примерно)
Собственно после того ты нашел , где вызывается нужная тебе функция, то ты уже делаешь патерн на call program.exe+12345 и берешь от туда уже адрес. А если тебе потом уже нужно брать адресс из этой функции, то ты уже берешь смещение относительно нее типо вот полный пример пвсевдокода :
Код:
xrefinstructionadr = findpatter("program.exe","48 ? ? ff 25 90 90 90 ?");
Fooadr = getabsAddr(xrefinstructionadr); // там вроде надо от адреса инструкции прибавлять число, что бы не брать байты call, а брать байты который нужны для вычилсения адреса .
VeryCoolInstructionadr = Fooadr+0x1C;
engineadr = getAbsAddress(VeryCoolInstruction);
Programengine* engine = (Programengine*)engineadr;
std::cout <<engine->Version<<"\n" ;
// п.с само смещение от базового адресса в таком случаее не нужно, но если тебе вруг все же для чего-то надо, то то просто из Абсадресса вычитай базовый так и получишь смещение от базового, главное что бы это было смещение относительно одного модуля .
Еще можно найти vtable, я с ними особо не работал так, что хз так видел пару примеров примерно понимаю ,но мне обычно нужна 1 опр функция , а др мне не нужны так ,что я на прямую делаю.
И да так чисто на всякий Патерны на .data / динам память, ОБЫЧНО нет смысла делать , нужно патрен на код делать. (просто я одному челу пытался сказать, но мне кажется ему пофиг, он находит значение и сразу в дизасемблере открывает , а не в отладчике и не ищит инструкцию которая читает / пишит и вот на нее уже патерн надо делать. )