Доступ к прямым адресам памяти и получение значений в C++

Мне было интересно, можно ли получить доступ к прямому блоку памяти с помощью C/C++ и получить значение. Например:

int i = 15;
int *p = &i;
cout << &i;

Если бы я взял напечатанное значение здесь, это дало бы мне адрес переменной i, которая содержит значение 15. Я просто скажу, что для этого примера было напечатано 0x0ff9c1. Если у меня есть отдельная программа, которая объявляет такой указатель...

int *p = 0x0ff9c1;
cout << *p;

Можно ли распечатать те 15, которые другое приложение поместило в блок памяти 0x0ff9c1? Я знаю, что мое объявление указателя с адресом памяти неверно, я не знаю, как это сделать иначе. Я пытался использовать memcopy, но мне тоже не удалось заставить его работать. Я знаю, что это каким-то образом возможно, поскольку у меня есть программа под названием Cheat Engine, которая изменяет значения адресов игровой памяти, чтобы получить несправедливые преимущества. Мне удалось разместить распечатанную ячейку памяти и получить значение (15) через Cheat Engine. Моя цель - сделать это с помощью C++. Если это слишком запутанно, в основном я хотел бы получить доступ к переменной, которую другое приложение сохранило, используя свой адрес памяти, и распечатать значение. Я использую Windows 7 x64 с компилятором MinGW, если это имеет значение. Спасибо!

PS: Я опубликую изображение того, что делает Cheat Engine, чтобы дать лучшее представление. введите здесь описание изображения


person llk    schedule 01.09.2011    source источник
comment
+1 за такие эксперименты.   -  person Nawaz    schedule 01.09.2011
comment
прочитайте книгу о виртуальной памяти. В качестве дополнительного примечания: Linux и некоторые новые версии Windows используют рандомизацию стека, поэтому адреса локальных переменных будут различаться между запусками программы.   -  person unkulunkulu    schedule 01.09.2011
comment
Да хоть опытным путем я это обнаружил. Я думал об экспорте адреса через аргумент выполнения во вторую программу. Поищу виртуальную память, спасибо за подсказку.   -  person llk    schedule 01.09.2011
comment
Вы смогли в этом разобраться? Я пытаюсь сделать что-то подобное. Я смог прочитать область памяти из другой программы, используя программу чтения системной памяти, похожую на Cheat Engine. Я хотел иметь возможность считывать это место в памяти из созданной мной программы, и я также хотел бы знать, как предсказать, где это будет в будущих перезапусках приложения.   -  person Jeff82    schedule 26.08.2013
comment
В Linux есть системный вызов ptrace(), который может это сделать, но не уверен в Windows.   -  person aditya    schedule 12.03.2020


Ответы (5)


Два процесса имеют отдельные адресные пространства. Один процесс не может получить доступ к памяти другого процесса, если это явно не разделяемая память.

person Ed Heal    schedule 01.09.2011
comment
@Shadowalker Основываясь на ответе Эда, адрес внутри указателя не является фактическим физическим адресом внутри вашей оперативной памяти, это просто адрес, локальный для приложения (в некотором смысле, виртуальный адрес). - person Paul Manta; 01.09.2011
comment
Как тогда отладчики и другие программы, такие как Cheat Engine, получают к ним доступ? Насколько я понимаю, OLLYDbg и Cheat Engine не устанавливают драйверы ядра или какие-либо серьезные хуки. Хотя я могу ошибаться. - person llk; 01.09.2011
comment
Что под Windows будет использовать ReadProcessMemory() и WriteProcessMemory(). - person trojanfoe; 01.09.2011
comment
Спасибо за даунбот. Такие вещи, как отладчики, присоединяются к процессу и, следовательно, могут получить доступ ко всей памяти для этого процесса. @paul - я думаю, что кто-то должен прочитать о подкачке, виртуальной памяти, сегментации и адресном пространстве процесса. - person Ed Heal; 01.09.2011
comment
@Shadowalker, каждая приличная ОС имеет поддержку отладчика для упрощения этих задач (обратите внимание, что отладчики не только получают доступ к внешней памяти, но и могут устанавливать точки останова и даже просматривать регистры в контексте другого процесса). - person unkulunkulu; 01.09.2011
comment
@ Эд Хил, хорошо, последний вопрос, ха-ха. Можно ли подключиться к процессу с помощью С++? Должен ли я использовать ассемблер x86? Если я могу сделать это на С++, есть идеи, с чего начать? Спасибо! - person llk; 01.09.2011
comment
@unkulunkulu Не может ли кто-нибудь обмануть ОС, что их программа является отладчиком, и воспользоваться этим? - person Paul Manta; 01.09.2011
comment
@Shadowalker, комментарии не для того, чтобы задавать дополнительные вопросы, начните новый - person unkulunkulu; 01.09.2011
comment
@Paul, я не знаю точного ответа, но я думаю, что какая-то система прав, встроенная в операционные системы, контролирует программы, которым разрешено использовать функции отладки. - person unkulunkulu; 01.09.2011
comment
@Paul В Windows вы должны указать права доступа при открытии дескриптора процесса. Я почти уверен, что в Linux у вас должен быть root-доступ, чтобы использовать API. - person Ze Blob; 01.09.2011
comment
@EdHeal: -1 за ответ через несколько секунд после того, как был задан вопрос, с рефлекторным ответом, который категорически отрицал опыт ОП о существовании этой программы (я не беспокоюсь о том, чтобы отрицать такие вещи, если только я не думаю, что за них проголосовали по плохим причинам ). +1 к вашему комментарию, который исправляет это там, но, по-моему, лучше исправить это в своем ответе. В любом случае, добро пожаловать. - person HostileFork says dont trust SE; 01.09.2011
comment
@Hostile Вы действительно не должны голосовать против или против в ответ или на мнения других. - person Paul Manta; 01.09.2011
comment
@Paul Небольшая поправка (не могу редактировать). ptrace требует, чтобы процесс, выполняющий трассировку, был родителем трассируемого процесса. Вы также можете прикрепить себя, но для этого требуется root-доступ. В Windows чтение (PROCESS_VM_READ) памяти других процессов не требует отладки или прав администратора. Другое дело написать. О, и чего бы это ни стоило, я согласен с Враждебным. - person Ze Blob; 01.09.2011
comment
@Paul: Uhhh ... Один процесс не может получить доступ к памяти другого процесса, если это явно не разделяемая память. это не мнение. Это верно в полностью обобщенном случае с точки зрения языкового стандарта, но не объясняет существование этой программы. Должно быть объяснение того, как работает эта программа, иначе это не полный ответ. - person HostileFork says dont trust SE; 01.09.2011
comment
@Hostile Вы сказали, что проголосовали против, потому что [вы] думаете, что за него проголосовали по плохим причинам. Отмена голосования другого человека - это не то, как вы должны использовать эту функцию SO. - person Paul Manta; 01.09.2011
comment
@Пол: Расслабься. Я просто говорю, что не думаю, что это был хороший ответ, и хотя ответ распространяется на какофонию комментариев к этому ответу, мы голосуем вверх/вниз по тексту самого ответа. Я проголосую за него, если он будет реорганизован, чтобы текст ответа давал полную историю, но до тех пор я довольно разочарован текстом ответа «нет», это невозможно принять. Моя привычка не отрицать ответы с нулем — это отдельная проблема, и это больше связано с ощущением, что я не вижу смысла в штрафе за чистую репутацию для того, кто просто пытался помочь, даже если плохо. - person HostileFork says dont trust SE; 01.09.2011

Вы не можете сделать это независимо от платформы на С++. Хотя я специально не использовал этот «читерский движок», он почти наверняка использует тот же специальный API, что и отладчик. Код будет специфичен для Windows, и вам потребуется определенный уровень привилегий для запущенного процесса.

(Например, если вы используете Visual Studio и запускаете программу в режиме отладки, Visual Studio может просматривать и изменять значения в этой программе.)

Я давно не писал отладчик, поэтому не знаю, с чего начать работу с Debug API, но вы можете поискать в Интернете такие вещи, как эта статья:

http://www.woodmann.com/fravia/iceman1.htm

person HostileFork says dont trust SE    schedule 01.09.2011
comment
Примечание. Как отмечают другие, API-интерфейс отладчика — не единственный привилегированный API, который определенные платформы могут предлагать для использования в других процессах. (На самом деле, некоторые встраиваемые системы вообще не заморачиваются отдельными адресными пространствами и по-прежнему позволяют компилировать исходный код C и C++, так что ваш наивный пример может действительно работать на этих очень простых платформах.) Я просто предположил, что шансы были отладочными. API был тем, что он использовал — в отличие от ловушек, которые использует SpyXX или что-то в этом роде. - person HostileFork says dont trust SE; 01.09.2011

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

Найдите создание удаленного потока или перехват. Здесь есть несколько вопросов по этому поводу (и здесь, для начала) .

person eran    schedule 01.09.2011

Как правило, одна программа не может модифицировать память другой. Система делает все возможное, чтобы обеспечить это. Если бы это было не так, ни одна программа не была бы безопасной. Это особенно верно для всех вариантов Unix, над которыми я работал, хотя и не для всех проприетарных ОС, которые я видел.

Обратите внимание, что ни одно из этих правил не применяется к ядру...

Существует также парадигма программирования, называемая разделяемой памятью, но вы должны настроить ее явно.

Краткий ответ: обычно вы не можете этого сделать. Я полагаю, что вы упомянули окна. Я ничего не знаю о Windows, поэтому ваш пробег может отличаться.

person Lee-Man    schedule 01.09.2011
comment
Ответ сфокусирован немного неправильно и строго не совсем правильно, потому что ОС предоставляют процессам средства для изменения памяти друг друга. Ответ должен сосредоточиться на том факте, что области памяти различны, поэтому указатели с одинаковыми значениями ссылаются на разные области физической памяти в разных процессах. - person unkulunkulu; 01.09.2011
comment
Я не чувствовал, что полный урок виртуальной памяти оправдан, хотя, возможно, и необходим. - person Lee-Man; 01.09.2011

Немного поздно, но вы все равно можете это сделать через DLL-инъекцию. Вот ссылка на руководство: http://resources.infosecinstitute.com/using-createmotethread-for-dll-injection-on-windows/

person user3771655    schedule 01.11.2015