2015-02-09 2 views
0

Я не так хорошо знаком с C++, но у меня возникают проблемы с проверкой строки в моей собственной памяти.Поиск строки в памяти вызывает сбой

Вот небольшой пример моего кода:

for (unsigned int i = 0x400000; i < 0xFFFFFFFFFF; i++) { 
    string s = (char *) i; 
    if (s[0] == 'H') { 
     if (s == "Hello") { 
      cout << "Found at address: " << i << endl; 
     } 
    } 
} 

Он продолжает сканирование, пока не доходит до определенной «позиции», где происходит сбой приложения. Я предполагаю, что он достигает нераспределенной памяти и рушится из-за неопределенного поведения.

Но вопрос в том, что это лучший способ сделать это? Я стараюсь держаться подальше от ReadProcessMemory и WriteProcessMemory.

В целом: Каков наилучший способ поиска строки в рамках ее собственного процесса?

Заранее спасибо.

+1

Эта строка 's = (char *) i;' уже приведет к неопределенному поведению. 'i' не является строкой с нулевым завершением. – juanchopanza

+0

Да, я понял это, но вопрос в том, как я могу это исправить? Или любой другой способ предотвратить его сбой? – John

+4

'VirtualQuery' может сказать вам, какие области адресного пространства поддерживаются фактической памятью. Или вы можете исследовать с помощью 'IsBadReadPtr'. Или вы можете продолжить работу и получить доступ к памяти под блоком '__try/__ except' и соответствующим образом обрабатывать исключения SEH. –

ответ

1

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

Crashing является одним из многих неопределенных поведений.

+0

Я уже говорил, что в оригинальном вопросе мне просто интересно, можно ли предотвратить крах или хотя бы еще один способ сделать это. – John

+0

Это зависит от платформы и операционной системы, нет универсального способа. – StenSoft

1

Хотя это не упоминается в тегах, на основании упоминания ReadProcessMemory, я собираюсь предположить, что вы хотите это для Windows.

Для этого достаточно использовать VirtualQuery, чтобы выяснить, какие части вашего адресного пространства можно использовать (особенно важно в 64-битных системах, где допустимые адреса намного реже, чем в 32-разрядных системах) ,

кода с использованием VirtualQuery, чтобы найти доступные для поиска блоков может выглядеть примерно так:

#include <iostream> 
#include <vector> 
#include <string> 
#include <windows.h> 
#include <algorithm> 
#include <iterator> 

template <class InIter1, class InIter2, class OutIter> 
void find_all(InIter1 buf_begin, InIter1 buf_end, InIter2 pat_begin, InIter2 pat_end, OutIter output) { 
    for (auto pos = buf_begin; 
     buf_end != (pos = std::search(pos, buf_end, pat_begin, pat_end)); 
     ++pos) 
    { 
     *output++ = (void *)pos; 
    } 
} 

template <class outIter> 
void find_locs(std::string const &pat, outIter output) { 

    unsigned char *p; 
    MEMORY_BASIC_INFORMATION info; 

    for (p = nullptr; 
     VirtualQuery(p, &info, sizeof(info)) == sizeof(info); 
     p += info.RegionSize) 
    { 
     if (info.State == MEM_COMMIT && 
      (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE)) 
     { 
      find_all(p, p + info.RegionSize, pat.begin(), pat.end(), output); 
     } 
    } 
} 

int main(int argc, char **argv) { 
    if (argc != 2) { 
     fprintf(stderr, "Usage: %s <pattern>", argv[0]); 
     return 1; 
    } 

    find_locs(argv[1], std::ostream_iterator<void *>(std::cout, "\n")); 
} 

Ожидать этого оказаться несколько «ложных» матчей. В частности, даже если строка, которую вы ищете, не встречается нигде в пространстве памяти процесса, будет одна копия как часть argv и (по крайней мере) еще одна для временного std::string, которая передается в find_locs, так что ожидайте голый минимум двух совпадений для любой строки, которую вы можете передать.

Возможно, вы также захотите прочитать документы за MEMORY_BASIC_INFORMATION. Я выбрал подмножество блоков, которые (я уверен) безопасен для чтения (т. Е. Те, которые были зафиксированы и сопоставлены или закрыты), но в зависимости от того, что вы ищете, вы можете изменить это на ограничивать его поиском только через текст программы, а не текст и данные.

+0

Каковы параметры, которые необходимо пройти? Я вижу, что там есть «шаблон»? – John

+0

@John: Поскольку он стоит прямо сейчас, вы запускаете его так: 'search 'my_string". Несмотря на «шаблон», он действительно ищет только литературные совпадения. –

Смежные вопросы