메모리 스캐너 관련질문입니다.

홈 > 커뮤니티 > 질문 게시판
질문 게시판

메모리 스캐너 관련질문입니다.

메모리 스캐너를 만들어보고싶어서 외국커뮤니티와 각종 구글 자료를 찾아보았더니
아래와 같은순서로 메모리 스캐너를 작성하라고 되어있었습니다.
1- Get the process address range.
2- We query info about the memory page.
3- Check if we can access this part of memory
4- Check if can we write to the memory
5- dump
6- RPM
7- Check for value in bytes

그래서 저는 아래의 CPP 코드로 코드를 작성하여보았지만 메모리 스캐닝은 잘 되지않는것같습니다.
메모리스캐너를 제작하는데있어서 참고할만한 자료가있다면 알려주시면 감사하겠습니다.
(소스코드 읽기힘드실까봐 따로 cpp파일 첨부합니다.)

void ScanMem(LPCSTR _name)
{
DWORD pid;
HWND hwnd = FindWindowA(NULL, _name);
if (!hwnd)
{
cout << "Window Not Found!" << endl;
return;
}

cout << "hwnd :" << hwnd << endl;

GetWindowThreadProcessId(hwnd, &pid);
if (!pid)
{
cout << "Could not get process ID" << endl;
return;
}

cout << "pid :" << pid << endl;

phandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, 0, pid);

if (!phandle)
{
cout << "Could not get handle!" << endl;
return;
}

SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);

DWORD MemoryStart = (long)sysInfo.lpMinimumApplicationAddress;
DWORD MemoryEnd = (long)sysInfo.lpMaximumApplicationAddress;
DWORD PageSize = sysInfo.dwPageSize;


cout << "MemoryStart : " << MemoryStart << endl;
cout << "MemoryEnd : " << MemoryEnd << endl;
cout << "PageSize : " << PageSize << endl;

MEMORY_BASIC_INFORMATION mbi;

while (MemoryStart < MemoryEnd)
{
VirtualQuery((LPCVOID)MemoryStart, &mbi, sizeof(mbi));

if (mbi.State == MEM_COMMIT && (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_WRITECOPY || mbi.Protect == PAGE_EXECUTE_READWRITE || mbi.Protect == PAGE_EXECUTE_WRITECOPY))
{
DWORD value;
cout << "BaseAddress : " << mbi.BaseAddress << endl;
ReadProcessMemory(phandle, mbi.AllocationBase, &value, mbi.RegionSize, NULL);

cout << "value : " << value << endl;
}

MemoryStart += PageSize;
}
}
7 Comments
6 지존 2019.10.29 23:44  
메모리 스캔 부분은 구현 안하신것 같고 단순 메모리 정보 읽어오는 부분만 보았을때 난잡해보인다는것 말고는 큰 문제가 없어보입니다..
어떤 부분이 안된다는 거죠?
1 MAJG 2019.10.30 07:53  
할당되어있는 메모리를 모두 찾아서 각 메모리주소가 가지고있는 값 들을 출력시키려고하는데
ReadProcessMemory를 통해 얻은 값을 출력시키면 모든 주소의 값이 0 으로 출력됩니다.
치트엔진의 FirstScan 기능을 만들고싶습니다.
6 지존 2019.10.30 09:54  
ReadProcessMemory 오류로 보입니다
예상가능한 이유가 몇가지 있긴한데 일단 GetLastError 를 이용해서 에러코드를 확인 해보시는게 먼저일듯합니다
관리자 권한으로 프로그램을 실행해보시고 그래도 안된다면 AdjustTokenPrivileges 함수를 이용하여 권한을 상승시킨 후에 관리자 권한으로 실행시켜보세요
1 MAJG 2019.10.30 22:30  
위의 코드를 실행시켯을때 아래와 같이 다른 주소임에도 불구하고 모두 같은 value값을 출력시킵니다.
hwnd :00020418
pid :4336
MemoryStart : 65536
MemoryEnd : 2147418111
PageSize : 4096
BaseAddress : 008D1000
value : 3435973836
BaseAddress : 008D2000
value : 3435973836
. . .
BaseAddress : 7FF30000
value : 3435973836
BaseAddress : 7FF41000
value : 3435973836

그리고 말씀해주신것처럼 GetLastError 함수로 에러코드를 확인했을때 299 가 출력되는것으로 보아
RPM 함수가 일부만 실행되는것같습니다.
또한 관리자 권한으로 실행시켯을때도 위와 같은 결과를 출력시킵니다.
6 지존 2019.10.31 02:23  
어젠 없었던것 같은데 ReadProcessMemory 부분을 이제서야 적어주셨군요 ㅋㅋ
문제는 명확합니다
value변수에 어처구니 없이 많은 양의 데이터를 집어넣으려고 하니 생기는 문제입니다;;
value 선언된부분이 글에서는 안보여서 무슨 자료형인지 모르겠지만 char[] 형식으로 mbi.RegionSize만큼의 크기를 주셔야합니다 그냥 일반적인 uint로 받으려고 하신거 같은데 ㅋㅋ 이건 4바이트짜리라서 고작 4개 바이트밖에 저장 못합니다
근데 페이지 크기를 쑤셔박는 지역변수들을 만든다면 프로그램에따라 스택이 터질수도있겠네요 ㅋㅋ
재밌는일 해보는것,시도하는것은 좋은데 기본기 한번 다져보는것도 괜찮아보입니다..
1 MAJG 2019.11.02 09:18  
Value는 DWORD 형으로 선언되어있고 말씀해주신것처럼 char 배열을 사용해 데이터를
받았을때는 모든Value값들이 0이출력됩니다.
마찬가지로 299에러가 출력되구요.
특정값의 메모리주소를 알고있을때 값을 받아오는건 DWORD형으로 잘됫었습니다.
3 하이큐 2019.10.31 09:29  
c언어를 공부합시다