메모리에서 지뢰찾기의 광산 레이아웃을 나타내는 데이터 구조를 어떻게 찾을 수 있나요?
-
06-09-2019 - |
문제
지뢰 찾기를 샘플 애플리케이션으로 사용하여 리버스 엔지니어링에 대해 배우려고 합니다.나는 이것을 발견했다 MSDN 기사 모든 광산을 표시하는 간단한 WinDbg 명령은 오래되었지만 자세히 설명되지 않았으며 실제로 내가 찾고 있는 것이 아닙니다.
나는 가지고있다 IDA Pro 디스어셈블러 그리고 WinDbg 디버거 그리고 나는 둘 다에 winmine.exe를 로드했습니다.지뢰밭을 나타내는 데이터 구조의 위치를 찾는 측면에서 이러한 프로그램 중 하나에 대한 실용적인 팁을 제공할 수 있는 사람이 있습니까?
WinDbg에서는 중단점을 설정할 수 있지만 중단점을 설정할 지점과 메모리 위치를 상상하기 어렵습니다.마찬가지로, IDA Pro에서 정적 코드를 볼 때 지뢰밭을 나타내는 함수나 데이터 구조를 어디서 찾아야 할지 잘 모르겠습니다.
나에게 올바른 방향을 알려줄 수 있는 리버스 엔지니어가 Stackoverflow에 있습니까?
해결책
3부 중 1부
리버스 엔지니어링에 진지하게 관심이 있다면 트레이너와 치트 엔진은 잊어버리세요.
좋은 리버스 엔지니어는 먼저 OS, 핵심 API 기능, 프로그램 일반 구조(런 루프, Windows 구조, 이벤트 처리 루틴이 무엇인지), 파일 형식(PE)을 알아야 합니다.Petzold의 고전적인 "Windows 프로그래밍"(www.amazon.com/exec/obidos/ISBN=157231995X)과 온라인 MSDN이 도움이 될 수 있습니다.
먼저 지뢰밭 초기화 루틴을 어디에서 호출할 수 있는지 생각해야 합니다.나는 다음을 생각했다:
- 게임을 실행하면
- 행복한 얼굴을 클릭하면
- Game->New를 클릭하거나 F2를 누르면
- 레벨 난이도를 변경할 때
F2 가속기 명령을 확인하기로 결정했습니다.
가속기 처리 코드를 찾으려면 창 메시지 처리 절차(WndProc)를 찾아야 합니다.CreateWindowEx 및 RegisterClass 호출을 통해 추적할 수 있습니다.
읽다:
- CreateWindowEx http://msdn.microsoft.com/en-us/library/ms632680%28VS.85%29.aspx
- 클래스 등록 http://msdn.microsoft.com/en-us/library/ms633586%28VS.85%29.aspx
- Petzold의 3장 "창과 메시지"
IDA, Imports 창을 열고 "CreateWindow*"를 찾아서 점프한 다음 "Jump xref to Operand (X)" 명령을 사용하여 호출되는 위치를 확인합니다.전화는 한 번만 하면 됩니다.
이제 위에서 RegisterClass 함수와 WndClass.lpfnWndProc 매개변수를 살펴보세요.내 경우에는 이미 mainWndProc 함수 이름을 지정했습니다.
.text:0100225D mov [ebp+WndClass.lpfnWndProc], offset mainWndProc
.text:01002264 mov [ebp+WndClass.cbClsExtra], edi
.text:01002267 mov [ebp+WndClass.cbWndExtra], edi
.text:0100226A mov [ebp+WndClass.hInstance], ecx
.text:0100226D mov [ebp+WndClass.hIcon], eax
.text:01002292 call ds:RegisterClassW
함수 이름에서 Enter 키를 누르세요. (더 나은 이름으로 바꾸려면 'N'을 사용하세요.)
이제 살펴보세요
.text:01001BCF mov edx, [ebp+Msg]
이는 F2 버튼을 누를 경우 WM_COMMAND 값을 포함해야 하는 메시지 ID입니다.111h와 비교되는 곳을 찾으시면 됩니다.IDA에서 edx를 추적하거나 다음을 통해 수행할 수 있습니다. 조건부 중단점 설정 WinDbg에서 게임에서 F2를 누르세요.
어느 쪽이든 다음과 같은 결과로 이어집니다.
.text:01001D5B sub eax, 111h
.text:01001D60 jz short loc_1001DBC
111h를 마우스 오른쪽 버튼으로 클릭하고 "기호 상수" -> "표준 기호 상수 사용"을 선택한 후 WM_을 입력하고 Enter를 누르세요.이제 당신은
.text:01001D5B sub eax, WM_COMMAND
.text:01001D60 jz short loc_1001DBC
메시지 ID 값을 찾는 쉬운 방법입니다.
가속기 처리를 이해하려면 다음을 확인하세요.
단일 답변에 비해 텍스트가 꽤 많습니다.관심이 있으시면 두 개의 게시물을 더 작성해 드릴 수 있습니다.바이트 [24x36] 배열로 저장된 긴 이야기의 짧은 지뢰밭, 0x0F는 바이트가 사용되지 않음을 나타냅니다(더 작은 필드 재생), 0x10 - 빈 필드, 0x80 - 광산.
3부 중 2부
좋아, 계속해서 F2 버튼을 눌러보자.
에 따르면 키보드 가속기 사용 F2 버튼을 눌렀을 때 wndProc 함수
...는 WM_COMMAND 또는 WM_SYSCOMMAND를 수신합니다 메시지입니다.의 저차 단어 wParam 매개변수에는 가속기의 식별자입니다.
좋아, 우리는 이미 WM_COMMAND가 처리되는 위치를 찾았지만 해당 wParam 매개변수 값을 어떻게 결정합니까?이곳은 리소스 해커 작용합니다.바이너리를 입력하면 모든 것이 표시됩니다.나에게는 액셀러레이터 테이블과 같습니다.
대체 텍스트 http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg
여기서 볼 수 있듯이 F2 버튼은 wParam의 510에 해당합니다.
이제 WM_COMMAND를 처리하는 코드로 돌아가겠습니다.wParam을 다른 상수와 비교합니다.
.text:01001DBC HandleWM_COMMAND: ; CODE XREF: mainWndProc+197j
.text:01001DBC movzx eax, word ptr [ebp+wParam]
.text:01001DC0 mov ecx, 210h
.text:01001DC5 cmp eax, ecx
.text:01001DC7 jg loc_1001EDC
.text:01001DC7
.text:01001DCD jz loc_1001ED2
.text:01001DCD
.text:01001DD3 cmp eax, 1FEh
.text:01001DD8 jz loc_1001EC8
상황에 맞는 메뉴 또는 'H' 키보드 단축키를 사용하여 소수 값을 표시하면 점프하는 모습을 볼 수 있습니다.
.text:01001DBC HandleWM_COMMAND: ; CODE XREF: mainWndProc+197j
.text:01001DBC movzx eax, word ptr [ebp+wParam]
.text:01001DC0 mov ecx, 528
.text:01001DC5 cmp eax, ecx
.text:01001DC7 jg loc_1001EDC
.text:01001DC7
.text:01001DCD jz loc_1001ED2
.text:01001DCD
.text:01001DD3 cmp eax, 510
.text:01001DD8 jz loc_1001EC8 ; here is our jump
이는 일부 proc을 호출하고 wndProc를 종료하는 코드 청크로 이어집니다.
.text:01001EC8 loc_1001EC8: ; CODE XREF: mainWndProc+20Fj
.text:01001EC8 call sub_100367A ; startNewGame ?
.text:01001EC8
.text:01001ECD jmp callDefAndExit ; default
그게 새로운 게임을 시작하는 기능인가요?마지막 부분에서 알아보세요!계속 지켜봐 주시기 바랍니다.
3부 중 3부
해당 함수의 첫 번째 부분을 살펴보겠습니다.
.text:0100367A sub_100367A proc near ; CODE XREF: sub_100140C+CAp
.text:0100367A ; sub_1001B49+33j ...
.text:0100367A mov eax, dword_10056AC
.text:0100367F mov ecx, uValue
.text:01003685 push ebx
.text:01003686 push esi
.text:01003687 push edi
.text:01003688 xor edi, edi
.text:0100368A cmp eax, dword_1005334
.text:01003690 mov dword_1005164, edi
.text:01003696 jnz short loc_10036A4
.text:01003696
.text:01003698 cmp ecx, dword_1005338
.text:0100369E jnz short loc_10036A4
eax 및 ecx 레지스터에 읽혀진 두 개의 값(dword_10056AC, uValue)이 있으며 다른 두 값(dword_1005164, dword_1005338)과 비교됩니다.
WinDBG('bp 01003696';)를 이용하여 실제 값을 살펴보세요.휴식 시간에 'p eax;p ecx') - 그것은 나에게 지뢰밭 크기처럼 보였습니다.사용자 정의 지뢰밭 크기를 가지고 플레이하면 첫 번째 쌍이 새로운 차원이고 두 번째 쌍이 현재 차원인 것으로 나타났습니다.새로운 이름을 설정해 봅시다.
.text:0100367A startNewGame proc near ; CODE XREF: handleButtonPress+CAp
.text:0100367A ; sub_1001B49+33j ...
.text:0100367A mov eax, newMineFieldWidth
.text:0100367F mov ecx, newMineFieldHeight
.text:01003685 push ebx
.text:01003686 push esi
.text:01003687 push edi
.text:01003688 xor edi, edi
.text:0100368A cmp eax, currentMineFieldWidth
.text:01003690 mov dword_1005164, edi
.text:01003696 jnz short loc_10036A4
.text:01003696
.text:01003698 cmp ecx, currentMineFieldHeight
.text:0100369E jnz short loc_10036A4
조금 후에 새로운 값이 현재를 덮어쓰고 서브루틴이 호출됩니다.
.text:010036A7 mov currentMineFieldWidth, eax
.text:010036AC mov currentMineFieldHeight, ecx
.text:010036B2 call sub_1002ED5
그리고 그걸 봤을 때
.text:01002ED5 sub_1002ED5 proc near ; CODE XREF: sub_1002B14:loc_1002B1Ep
.text:01002ED5 ; sub_100367A+38p
.text:01002ED5 mov eax, 360h
.text:01002ED5
.text:01002EDA
.text:01002EDA loc_1002EDA: ; CODE XREF: sub_1002ED5+Dj
.text:01002EDA dec eax
.text:01002EDB mov byte ptr dword_1005340[eax], 0Fh
.text:01002EE2 jnz short loc_1002EDA
나는 지뢰밭 배열을 발견했다고 확신했습니다.360h 바이트 길이의 배열(dword_1005340 )을 0xF로 초기화하는 주기의 원인입니다.
왜 360h = 864인가요?아래에는 행이 32바이트를 차지하고 864를 32로 나눌 수 있으므로 배열이 27*32 셀을 보유할 수 있다는 몇 가지 단서가 있습니다(UI에서는 최대 24*30 필드를 허용하지만 배열 주위에 테두리 패딩이 1바이트 있습니다).
다음 코드는 지뢰밭 상단 및 하단 테두리(0x10바이트)를 생성합니다.그 혼란 속에서 루프 반복을 볼 수 있기를 바랍니다 ;) 저는 종이와 펜을 사용해야 했습니다
.text:01002EE4 mov ecx, currentMineFieldWidth
.text:01002EEA mov edx, currentMineFieldHeight
.text:01002EF0 lea eax, [ecx+2]
.text:01002EF3 test eax, eax
.text:01002EF5 push esi
.text:01002EF6 jz short loc_1002F11 ;
.text:01002EF6
.text:01002EF8 mov esi, edx
.text:01002EFA shl esi, 5
.text:01002EFD lea esi, dword_1005360[esi]
.text:01002EFD
.text:01002F03 draws top and bottom borders
.text:01002F03
.text:01002F03 loc_1002F03: ; CODE XREF: sub_1002ED5+3Aj
.text:01002F03 dec eax
.text:01002F04 mov byte ptr MineField?[eax], 10h ; top border
.text:01002F0B mov byte ptr [esi+eax], 10h ; bottom border
.text:01002F0F jnz short loc_1002F03
.text:01002F0F
.text:01002F11
.text:01002F11 loc_1002F11: ; CODE XREF: sub_1002ED5+21j
.text:01002F11 lea esi, [edx+2]
.text:01002F14 test esi, esi
.text:01002F16 jz short loc_1002F39
나머지 서브루틴에서는 왼쪽과 오른쪽 테두리를 그립니다.
.text:01002F18 mov eax, esi
.text:01002F1A shl eax, 5
.text:01002F1D lea edx, MineField?[eax]
.text:01002F23 lea eax, (MineField?+1)[eax+ecx]
.text:01002F23
.text:01002F2A
.text:01002F2A loc_1002F2A: ; CODE XREF: sub_1002ED5+62j
.text:01002F2A sub edx, 20h
.text:01002F2D sub eax, 20h
.text:01002F30 dec esi
.text:01002F31 mov byte ptr [edx], 10h
.text:01002F34 mov byte ptr [eax], 10h
.text:01002F37 jnz short loc_1002F2A
.text:01002F37
.text:01002F39
.text:01002F39 loc_1002F39: ; CODE XREF: sub_1002ED5+41j
.text:01002F39 pop esi
.text:01002F3A retn
WinDBG 명령을 현명하게 사용하면 멋진 지뢰밭 덤프(사용자 정의 크기 9x9)를 제공할 수 있습니다.테두리를 확인해보세요!
0:000> db /c 20 01005340 L360
01005340 10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005360 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005380 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053a0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053c0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053e0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005400 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005420 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005440 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005460 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005480 10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054a0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054c0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054e0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
흠, 주제를 마무리하려면 다른 게시물이 필요할 것 같습니다
다른 팁
소스를 디스어셈블하려는 것처럼 보이지만 해야 할 일은 실행 중인 프로그램의 메모리 공간을 살펴보는 것입니다.16진수 편집기 HxD 그렇게 할 수 있는 기능이 있습니다.
메모리 공간에 들어가면 보드를 만지작거리면서 메모리의 스냅샷을 찍는 것이 중요합니다.변화하는 것과 변하지 않는 것을 분리하세요.데이터 구조가 16진수 메모리에 있는 위치를 파악했다고 생각되면 메모리에 있는 동안 편집을 시도하고 결과적으로 보드가 변경되는지 확인하세요.
원하는 프로세스는 비디오 게임용 '트레이너'를 구축하는 것과 다르지 않습니다.이는 일반적으로 체력 및 탄약과 같은 값이 메모리에 있는 위치를 찾아 즉시 변경하는 것을 기반으로 합니다.게임 트레이너를 구축하는 방법에 대한 좋은 튜토리얼을 찾을 수 있습니다.
이 코드 프로젝트 기사를 확인하세요. 언급한 블로그 게시물보다 조금 더 심층적입니다.
http://www.codeproject.com/KB/trace/minememoryreader.aspx
편집하다
지뢰 찾기에 대한 직접적인 내용은 아니지만 이 기사에서는 WinDbg를 사용하여 메모리를 검색하는 방법에 대한 좋은 단계별 가이드를 제공합니다.
http://www.codingthewheel.com/archives/extracting-hidden-text-with-windbg
편집 2
다시 말하지만, 이것은 지뢰 찾기에 관한 것이 아니지만 확실히 내 메모리 디버깅에 대해 생각할 거리를 제공했습니다. 여기에는 풍부한 튜토리얼이 있습니다.
http://memoryhacking.com/forums/index.php
또한, 다운로드 치트 엔진 (Nick D.가 언급함) 함께 제공되는 튜토리얼을 진행하세요.
"WinDbg에서는 중단점을 설정할 수 있지만 에서 상상하기 어렵습니다 중단점을 설정할 시점과 메모리 위치.마찬가지로 다음과 같은 경우 IDA Pro에서 정적 코드를 확인합니다 어디서부터 찾아야 할지 모르겠습니다 함수 또는 데이터 구조 는 지뢰밭을 상징합니다."
정확히!
광산 테이블을 구성하는 동안 호출될 random()과 같은 루틴을 찾아볼 수 있습니다.이것 책 리버스엔지니어링을 실험할 때 많은 도움이 되었습니다.:)
일반적으로 중단점을 설정하기에 좋은 위치는 메시지 상자 호출, 사운드 재생 호출, 타이머 및 기타 win32 API 루틴입니다.
그런데 지금 지뢰찾기를 스캔하고 있어요 올리Dbg.
업데이트: 니모 훌륭한 도구가 생각났어요. 치트 엔진 작성자: Eric "Dark Byte" Heijnen.
치트 엔진(CE)은 다른 프로세스의 메모리 공간을 관찰하고 수정하는 데 유용한 도구입니다.그 너머 기초적인 CE에는 프로세스의 분해된 메모리를 확인하고 다른 프로세스에 코드를 삽입하는 것과 같은 더 많은 특수 기능이 있습니다.
(그만큼 진짜 해당 프로젝트의 가치는 소스 코드인 Delphi를 다운로드하여 이러한 메커니즘이 어떻게 구현되었는지 확인할 수 있다는 것입니다. 저는 몇 년 전에 그렇게 했습니다.
바로 이 주제에 관한 아주 좋은 기사를 다음에서 찾을 수 있습니다. 정보가 없음.지뢰 찾기 반전(Win32 앱 리버스 엔지니어링에 대한 소개)을 매우 자세하게 다루고 있으며 매우 유용한 리소스입니다.
다음 웹사이트가 더 도움이 될 수 있습니다.
http://www.subversity.net/reversing/hacking-minesweeper
이를 수행하는 일반적인 방법은 다음과 같습니다.
- 어떻게 든 소스 코드를 얻으십시오.
- 분해하고 남은 기호가 도움이 되기를 바랍니다.
- 데이터 유형을 추측하고 이를 조작한 후 메모리 스캐너를 사용하여 가능성을 제한해 보세요.
바운티에 대한 응답으로
글쎄, 두 번째 읽으면 리버스 엔지니어링 방법에 대한 일반적인 질문보다는 WinDBG와 같은 디버거를 사용하는 방법에 대한 가이드를 원하는 것처럼 보입니다.검색해야 하는 값을 알려주는 웹사이트를 이미 보여 드렸으므로 질문은 어떻게 검색합니까?
이 예에서는 지뢰찾기가 설치되어 있지 않기 때문에 메모장을 사용하고 있습니다.그러나 아이디어는 동일합니다.
당신은 입력
s <options> <memory start> <memory end> <pattern>
누르다 "?"를 누른 다음 "s "를 클릭하면 도움말을 볼 수 있습니다.
원하는 메모리 패턴을 찾았으면 Alt+5를 눌러 멋진 디스플레이를 위한 메모리 뷰어를 불러올 수 있습니다.
WinDBG는 익숙해지는 데 시간이 좀 걸리지만 다른 디버거만큼 훌륭합니다.
디버거에서 추적을 시작하는 좋은 지점은 마우스를 올려놓는 것입니다.따라서 기본 창 절차를 찾으세요(spyxx와 같은 도구는 창 속성을 검사할 수 있으며 이벤트 처리기 주소도 그 중 하나입니다).그것에 침입하여 마우스 이벤트를 처리하는 위치를 찾으십시오. 어셈블러에서 인식할 수 있는 경우 스위치가 있을 것입니다(windows.h에서 마우스 업에 대한 WM_XXX 값 참조).
거기에 중단점을 놓고 한 단계씩 실행을 시작하세요.마우스 버튼을 놓은 시점과 화면이 업데이트되는 시점 사이에 피해자는 찾고 있는 데이터 구조에 액세스하게 됩니다.
인내심을 갖고 주어진 시간에 무슨 일이 일어나고 있는지 확인하려고 노력하십시오. 하지만 현재 목표에 흥미롭지 않다고 의심되는 코드를 너무 깊이 조사하는 데 신경쓰지 마십시오.문제를 해결하려면 디버거를 여러 번 실행해야 할 수도 있습니다.
일반적인 win32 응용 프로그램 작업 흐름에 대한 지식도 도움이 됩니다.
광산은 아마도 일종의 2차원 배열로 저장될 것입니다.이는 포인터 배열이거나 단일 C 스타일 부울 배열임을 의미합니다.
양식이 마우스업 이벤트를 수신할 때마다 이 데이터 구조가 참조됩니다.인덱스는 아마도 정수 나누기를 사용하여 마우스 좌표를 사용하여 계산됩니다.이는 아마도 당신이 다음을 찾아야 한다는 것을 의미합니다. cmp
또는 유사한 명령어로 피연산자 중 하나가 오프셋을 사용하여 계산되고 x
, 어디 x
정수 나누기와 관련된 계산의 결과입니다.그러면 오프셋은 데이터 구조의 시작 부분에 대한 포인터가 됩니다.
광산에 관한 정보가 적어도 한 행(예:2D 배열 또는 배열의 배열입니다).따라서 동일한 행에서 여러 개의 인접한 셀을 열어서 프로세스의 메모리 덤프를 만든 다음 차이점을 비교하고 동일한 메모리 영역에서 반복되는 변경 사항을 찾습니다(예:첫 번째 단계에서 1바이트가 변경되고, 다음 단계에서 다음 바이트가 정확히 동일한 값으로 변경되는 등).
또한 압축된 비트 배열일 가능성도 있습니다(폐쇄됨/개방, 광산/광산 없음, 플래그 지정/플래그 없음 등 가능한 모든 상태를 기록하려면 광산당 3비트이면 충분합니다). 패턴은 반복 가능하지만 발견하기는 더 어렵습니다.)하지만 다루기 편리한 구조도 아니고, 메모리 사용량이 지뢰 찾기의 병목 현상도 아니라고 생각해서 이런 식으로 활용될 가능성은 거의 없습니다.
엄밀히 말하면 "리버스 엔지니어의 도구"는 아니고 나 같은 바보도 사용할 수 있는 장난감에 가깝지만 확인해 보세요. 치트 엔진.메모리의 어떤 부분이 언제 변경되었는지 추적하는 것이 어느 정도 쉬우며 심지어 포인터를 통해 변경된 메모리 부분을 추적하는 기능도 있습니다(아마도 그럴 필요는 없을 것입니다).멋진 대화형 튜토리얼이 포함되어 있습니다.