2012-04-29 4 views
3

타사 응용 프로그램의 메모리를 검사하려고합니다. 나는 주소를 이미 알아 냈다. 지금은 0x0643FB78입니다. 문제는, 내가 LPMODULEENTRY32->modBaseAddr0x00400000이고, LPMODULEENTRY32->modBaseSize0x006FF000 일 때까지 결코 올라갈 수 없다는 것입니다. 따라서이 모듈을 스캔 할 수있는 최대 주소는 0x00AFF000입니다.프로세스의 프로세스 메모리 읽기가 모든 것을 반환하지 않습니다.

내가 찾는 주소가 다른 프로세스/module/thread/something 내부에 있다는 것을 의미합니까? 나는 그 과정에 주소가 들어 있다고 확신한다. 그러면 메모리에 어떻게 액세스해야합니까? 고맙습니다.

+1

MODULEENTRY 당신에게 * 코드의 주소를 제공합니다 *. 확실히 당신은 데이터에 더 관심이 있습니까? 이는 Windows가 힙을 할당 한 위치에 따라 어디에서나 나타날 수 있습니다. 데이터 섹션, 실제로는 힙에있는 경우 해당 주소를 반복적으로 가져올 수있는 희망이 없기 때문에 가능합니다. VirtualQueryEx()를 사용하여 주소 공간에서 할당을 열거하십시오. –

답변

7

내 생각에 적어도 LPMODULEENTRY이있는 경우 잘못된 방향으로 시작했을 가능성이 큽니다. 대신 VirtualQueryEx을 사용하여 대상 프로세스의 메모리 블록을 살펴볼 것입니다. 그러면 해당 프로세스의 각 블록에 대해 MEMORY_BASIC_INFORMATION이 표시됩니다. 그런 다음 ReadProcessMemory을 사용하고 블록을 스캔하여 원하는 것을 찾을 수 있습니다.

는 여기에 내가 거의 같은 일을 쓴 오래된 코드이지만, 포인터가 아닌 문자열을 찾고 :

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

template <class InIter1, class InIter2, class OutIter> 
void find_all(unsigned char *base, InIter1 buf_start, InIter1 buf_end, InIter2 pat_start, InIter2 pat_end, OutIter res) { 
    for (InIter1 pos = buf_start; 
     buf_end!=(pos=std::search(pos, buf_end, pat_start, pat_end)); 
     ++pos) 
    { 
     *res++ = base+(pos-buf_start); 
    } 
} 

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

    unsigned char *p = NULL; 
    MEMORY_BASIC_INFORMATION info; 

    for (p = NULL; 
     VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info); 
     p += info.RegionSize) 
    { 
     std::vector<char> buffer; 
     std::vector<char>::iterator pos; 

     if (info.State == MEM_COMMIT && 
      (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE)) 
     { 
      SIZE_T bytes_read; 
      buffer.resize(info.RegionSize); 
      ReadProcessMemory(process, p, &buffer[0], info.RegionSize, &bytes_read); 
      buffer.resize(bytes_read); 
      find_all(p, buffer.begin(), buffer.end(), pattern.begin(), pattern.end(), output); 
     } 
    } 
} 

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

    int pid; 
    sscanf(argv[1], "%i", &pid); 

    std::string pattern(argv[2]); 

    HANDLE process = OpenProcess( 
     PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 
     false, 
     pid); 

    find_locs(process, pattern, 
     std::ostream_iterator<void *>(std::cout, "\n")); 

    return 0; 
} 
+1

멋지고, 이것은 확실히 올바른 길에 나를 놓을 것입니다. 고맙습니다. –

+0

@ Jerry Coffin - 훌륭한 답변입니다. 두 가지 더 묻고 싶습니다 : 1) 페이지의 내용을 char 벡터'std :: vector 버퍼 '로 읽은 후에 어떻게 처리해야합니까? ASCII 문자 또는 UTF-8/UTF-16으로 인코딩 된 문자가 포함되어 있습니까? 메모리에 ASCII 문자가 들어있는 경우 유니 코드로 변환하려면 어떻게해야합니까 (UTF-16이어야 함)? 2) 정확히'std :: vector :: iterator pos'가 무엇을 위해 사용 되었습니까? 귀하의 도움을 많이 주시면 감사하겠습니다! –

2

프로세스는 특정 보호 기능과 매핑되는 메모리 페이지로 구성됩니다. 이 페이지는 모듈로 캡슐화됩니다. 각 모듈에는 기준과 크기가 있습니다. 그러나 ReadProcessMemory는이를 완전히 추상화합니다. 어떤 모듈이든 상관없이 메모리를 읽을 수 있어야합니다.

이 경우 메모리는보고있는 모듈에 없습니다. 모듈이 속한 위치를 찾으려면 CreateToolHelp32Snapshot, Module32First 및 Module32Next를 사용하여 기본 및 크기를 확인하는 모듈을 반복 할 수 있습니다.

일부 코드를 게시하면 잘못 된 부분을 찾을 수 있도록 도와 드리겠습니다. 왜 당신이 찾고있는 주소가 당신이 말하는 주소인지 확신합니까? 주소는 종종 ASLR 때문에 기본 모듈 + 오프셋으로 지정됩니다. 목표 프로세스를 어떻게 처리하고 있습니까? ReadProcessMemory를 사용하려면 특정 액세스 권한이 있어야합니다.

+1

감사합니다. 이것이 제가 부족한 통찰력입니다. 그가 코드 샘플을 가지고 있기 때문에 나는 Jerry의 대답을 받아 들였다. –

관련 문제