На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
  
> ReadProcessMemory... code error 299 , Помогите справиться с кодом 299
    Пытаюсь прочитать память процесса по заранее известному адресу.....
    ExpandedWrap disabled
      HANDLE hQip=0;
          HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
          PROCESSENTRY32 ProcEntry;
          ProcEntry.dwSize = sizeof(PROCESSENTRY32);
       
          Process32First(hSnapShot,&ProcEntry);
          do
          {
              if(lstrcmp("qip.exe",ProcEntry.szExeFile)==0)
              {
                  hQip = OpenProcess(PROCESS_ALL_ACCESS,TRUE,ProcEntry.th32ProcessID);
                  if(hQip==0) return 0;
              }
          }
          while(Process32Next(hSnapShot,&ProcEntry));
       
          if(ReadProcessMemory(hQip,(PVOID)0x006A3AC,n,1000,&d) == 0)
          {
              d = GetLastError();
          sprintf(n,"%d",d);
       
          MessageBox(HWND_DESKTOP,n,"pass:",0);
          }
          else
          {
              MessageBox(HWND_DESKTOP,n,"",0);
       
          }


    GetLastError() всегда говорит о 299 ошибке: Read\WriteProcessMemory запрос выполнен не полнустью.
    Чего это может быть ?
      barberan
      во первых надо проверять

      ExpandedWrap disabled
        if (hQip)
        {
           if(ReadProcessMemory(hQip,(PVOID)0x006A3AC,n,1000,&d) == 0)
            {
                d = GetLastError();
                sprintf(n,"%d",d);
         
                MessageBox(HWND_DESKTOP,n,"pass:",0);
            }
            else
            {
                MessageBox(HWND_DESKTOP,n,"",0);
         
            }
         
        }


      во вторых адрес 0x006A3AC на разных платформах, системах, при разных условиях может быть разным.
      И в третьих, кто тебе сказал что там можно считать 1000 байт?

      Добавлено
      и в четверых посмотри чему равно d после вызова ReadProcessMemory.

      Добавлено
      и вообще код ОЧЕНЬ плохой, т.к. используешь одни и те же переменные для разных целей (n, d)
        Цитата Мальчиш @
        во вторых адрес 0x006A3AC на разных платформах, системах, при разных условиях может быть разным.
        И в третьих, кто тебе сказал что там можно считать 1000 байт?

        Во-вторых - верно, а в-третьих - Майкрософт ;)
        Т.к. память выделяется страницами не менее 4К, то либо адрес 0x06A3AC вообше не доступен, либо доступна вся страница до 0x06B000, т.е. 3156 байт

        А вот хватает ли размера переменной n для 1000 байт - из приведенного кода не видно
          if (hQip)
          { }

          это проверено заранее.
          адрес - заранее известен... из отладчика.
          а ошибка 299 - есть.
            Ошибка 299 вылезает и в том случае, когда память по адресу вообще не доступна. Проверь число прочитанных байт d - если 0, значит память по данному адресу вообще не выделена - можешь проверить по VirtualQueryEx
              С этим разобрался, спасибо. А еще вопрос.. как в памяти процесса найти что-то определнное, и узнать по какому адресу оно лежит ?
                Цитата barberan @
                как в памяти процесса найти что-то определнное, и узнать по какому адресу оно лежит ?

                Сам понимаешь, вопрос не только не новый, но и достаточно "популярный" ;)
                Краткий ответ: VirtualQueryEx + SetLength(s,pmi.RegionSize) + ReadProcessMemory(..,pointer(s),..) + Pos(..,s)
                Конкретные примеры найдешь поиском, например VirtualQueryEx и ReadProcessMemory
                  Подскажите, как найти границы адресов процесса? Делаю так:
                  ExpandedWrap disabled
                    MEMORY_BASIC_INFORMATION mbi;
                    SIZE_T mbi_size = sizeof(mbi);
                     
                    DWORD startaddr=0,     //начальный адрес
                    lowaddr,             //нижняя граница
                    highaddr;            //верхняя граница
                     
                     
                    do
                        {
                            if( VirtualQueryEx(hQip,(LPCVOID)startaddr,&mbi,mbi_size) != sizeof(mbi))
                            {
                                         return 0;
                            }
                            startaddr+=(DWORD)mbi.RegionSize;
                        }while(mbi.State != MEM_COMMIT);
                    lowaddr = mbi.BaseAddress; //типа нашли нижнюю границу процесса.


                  Через отладчик смарел... startaddr сначала +=65536 потом еще +=4096... Получается всего 2 страницы MEM_COMMIT чего быть то и не может.
                  Сам вопрос вообще в том, что я не понимаю %) С какого адресса начинать VirtualQueryEx-ить... т.е. 2 арг. ф-ции - что туда передавать ?
                      Цитата barberan @
                      как найти границы адресов процесса?
                      Получается всего 2 страницы MEM_COMMIT чего быть то и не может

                      Еще как может ;) Похоже ты не понимаешь главного - память процесса это не только образ загруженного экзешника, но и образы подключенных длл (системных и "личных"), стек(и) потока(ов), динамическая память (виндовая куча, собственная куча, отдельные блоки VirtualAlloc), плюс множество служебных регионов памяти типа переменных окружения, списка загруженных модулей (куча загрузчика) и т.д. и т.п. Каждая из этих "сущностей" занимает непрерывные регионы памяти, но между собой эти регионы не "склеены" и как правило разделены "дырами", хотя бы потому что в винде адреса резервируются с шагом 64К, а физ.память выделяется (commit) страницами по 4К.
                      Поэтому если ты точно знаешь, что твое искомое значение принадлежит секции данных образа или виндовой кучи, то можно определить соотв.диапазон адресов через ToolHelp АПИ и структуру PE-заголовка. Но определить диапазон адресов стека и тем более не виндовой кучи (например, борландовской) и уж тем более отдельно выделенных блоков - не так то просто. Поэтому проще просто просканировать всю память VirtualQueryEx с шагом 4 (или 64К), читая commited блоки и искать в них нужное значение
                        Хм.. РАзобрался. А вот еще вопрос... ведь каждый адресс, если верить карте памяти состояит из 16 байт(или как это... - секций чтоли). В каждом байте(секции) хранится 1 символ. Иногда у меня странно считываетются не все 16(я точно не знаю что происходит), но знаючи, что например по данному адрессу "hello,world" я вижу чёта типа "lo,world" или "hello,wor". Что есть что? :wacko:
                          Цитата barberan @
                          ведь каждый адресс, если верить карте памяти состояит из 16 байт

                          Не верь глазам своим :) Это делается просто для удобства отображения - в каждой строке выводится по 16 байт\символов по адресам кратным 0x10. Поэтому если ты вместо "hello,world" видишь чёта типа "lo,world" по адресу X, значит действительный адрес начала текста = X-3 и ничего более :)
                            а как бы это корректировать по ходу ??? ведь не знаю что увижу, толи леву половинку, толи правую. КАк быть?
                              Никак.
                              Не пойму, чего ты хочешь. Если нужно найти заданную строку, например, "hello,world" то и ищи ее в регионе памяти.
                              Если же не знаешь, чего искать, и хочешь сам вывести карту памяти, то тебе по любому нужно будет как-то ограничивать длину выводимых строк, разбивая их по 8, 16 или 32 символа. При этом ес-но текст "hello,world" может оказаться в любом месте

                              PS: В дельфи\BCB поиск подстроки реализуется легко - выделяем память под AnsiString через SetLength(s,mbi.RegionSize), читаем в строку весь регион и затем ищем подстроку функцией Pos. Такой поиск работает для любых бинарных данных, т.к. диапазон поиска ограничивается явно заданной длиной строки, а не нулевыми символами, которые могут встречаться в произвольных данных. Есть ли нечто подобное в C\C++ не знаю. Если нет, то придется организовать ручками: юзать в цикле strstr и перескакивать нулевые символы, пока не дойдем до конца региона
                              1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                              0 пользователей:


                              Рейтинг@Mail.ru
                              [ Script execution time: 0,1242 ]   [ 15 queries used ]   [ Generated: 18.07.25, 00:59 GMT ]