메모리에서 지뢰 찾기의 광산 레이아웃을 나타내는 데이터 구조를 어떻게 찾을 수 있습니까?


94

저는 Minesweeper를 샘플 애플리케이션으로 사용하여 리버스 엔지니어링에 대해 배우려고합니다. 나는 모든 광산을 드러내는 간단한 WinDbg 명령에 대한 이 MSDN 기사 를 찾았 지만 오래되었고, 자세히 설명되지 않았으며 실제로 내가 찾고있는 것이 아닙니다.

나는 IDA Pro 디스어셈블러WinDbg 디버거를 가지고 있으며 두 가지 모두에 winmine.exe를로드했습니다. 누군가 광산 필드를 나타내는 데이터 구조의 위치를 ​​찾는 측면에서 이러한 프로그램 중 하나에 대한 실용적인 팁을 제공 할 수 있습니까?

WinDbg에서는 중단 점을 설정할 수 있지만 중단 점을 설정할 지점과 메모리 위치를 상상하기가 어렵습니다. 마찬가지로 IDA Pro에서 정적 코드를 볼 때 광산 필드를 나타내는 함수 또는 데이터 구조를 어디서부터 찾을 지 확신 할 수 없습니다.

저를 올바른 방향으로 안내 할 수있는 Stackoverflow에 리버스 엔지니어가 있습니까?


27
학생들을위한 과제에 대한 훌륭한 아이디어입니다. 지뢰 찾기를 고양이로 사용하는 해부학 실험실과 같은 종류입니다.
ojblass

3
혼란 스러울 수있는 국제 독자들에게 지뢰 찾기는 Windows Vista와 함께 제공되는 행복한 꽃 찾기 게임의 미국 버전입니다. microsoft.blognewschannel.com/index.php/archives/2006/09/28/…
Kip

16
행복한 꽃 찾기 게임? O_o 정치적 정확성이 너무 멀었습니다.
Eugene

10
글쎄, 지뢰 찾기 버전은 적어도 스웨덴 비스타 버전에서는 기본값입니다. 나는 그들이 실제로 아이들을 산산조각내는 경향이있는 곳에서 행복한 꽃 버전을 기본으로한다고 생각한다.
JesperE

1
그래서 ... 그냥 임의의 사각형을 클릭하여 그들이 광산인지 확인하는 것은 이것에 도움이되지 않습니다, 응?
Smandoli

답변:


125

3 부 중 1 부


리버스 엔지니어링을 진지하게 생각한다면 트레이너와 치트 엔진은 잊으십시오.

좋은 리버스 엔지니어는 먼저 OS, 핵심 API 기능, 프로그램 일반 구조 (실행 루프, Windows 구조, 이벤트 처리 루틴), 파일 형식 (PE)을 알아야합니다. Petzold의 고전 "Programming Windows"(www.amazon.com/exec/obidos/ISBN=157231995X)와 온라인 MSDN이 도움이 될 수 있습니다.

먼저 minefield 초기화 루틴이 호출 될 수있는 위치를 생각해야합니다. 나는 다음을 생각했다 :

  • 게임을 시작할 때
  • 행복한 얼굴을 클릭하면
  • Game-> New를 클릭하거나 F2를 누르면
  • 레벨 난이도를 변경할 때

F2 가속기 명령을 확인하기로 결정했습니다.

가속기 처리 코드를 찾으려면 창 메시지 처리 절차 (WndProc)를 찾으십시오. CreateWindowEx 및 RegisterClass 호출로 추적 할 수 있습니다.

읽다:

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

두 개의 값 (dword_10056AC, uValue)이 eax 및 ecx 레지스터로 읽고 다른 두 값 (dword_1005164, dword_1005338)과 비교됩니다.

WinDBG ( 'bp 01003696'; on break '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

나는 지뢰밭 배열을 발견했다고 확신했습니다. 0xF로 360h 바이트 길이 배열 (dword_1005340)을 초기화하는주기의 원인입니다.

왜 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  ................................

흠, 주제를 닫으려면 다른 게시물이 필요한 것 같습니다.


1
@Stanislav, 좋은 대답 Stanislav. 그것에 대해 자세히 설명 할 수 있다면 그렇게하십시오. 이 길고 유익한 답변이 최고입니다. 지뢰밭 데이터 구조를 어떻게 제로화했는지에 대해 조금 더 말씀해 주시겠습니까?
KingNestor

@Stanislav, 250 회 현상금이 종료 되었기 때문에 답변을 수락했습니다. 축하합니다!
KingNestor

1
@Stanislav, 여러 부분 답변을 단일 답변으로 편집했습니다. 단일 답변의 크기 제한에 도달하지 않았으며 일반적으로 여러 개를 게시하는 것보다 하나의 답변을 갖는 것이 바람직하다고 생각합니다. 원래 답변 (이 답변)을 자유롭게 편집하고 적절하다고 판단되면 추가하십시오.
mmcdole

2
또한 서사시 대답 Stanislav. 수고 해주셔서 감사합니다!
mmcdole

15

소스를 분해하려는 것처럼 보이지만 실행중인 프로그램의 메모리 공간을 살펴 보는 것입니다. 16 진 편집기 HxD 에는이를 가능하게하는 기능이 있습니다.

http://www.freeimagehosting.net/uploads/fcc1991162.png

일단 메모리 공간에 있으면 보드를 엉망으로 만드는 동안 메모리의 스냅 샷을 찍는 문제입니다. 변경 사항과 그렇지 않은 사항을 분리합니다. 데이터 구조가 16 진 메모리에있는 위치에 대한 핸들이 있다고 생각되면 메모리에있는 동안 편집하고 결과적으로 보드가 변경되는지 확인하십시오.

당신이 원하는 과정은 비디오 게임을위한 '트레이너'를 만드는 것과 다르지 않습니다. 이는 일반적으로 건강 및 탄약과 같은 값이 기억에있는 위치를 찾아서 즉석에서 변경하는 것을 기반으로합니다. 게임 트레이너를 구축하는 방법에 대한 좋은 튜토리얼을 찾을 수있을 것입니다.


2
음, 당신은 정적 분해를 통해 메모리 위치를 찾을 수 있습니다. 광산 필드를 생성하기 위해 호출되는 rand () 함수와 같은 것을 찾는 어셈블리 지침을 따를 수 있으며, 그런 다음 거기에서 추적하여 필드가 메모리에 저장되는 위치 (및 방법)를 확인할 수 있습니다.
mmcdole

두 가지 접근 방식 모두 도전적입니다. 나는 과거에 응용 프로그램을 분해하려고 시도했지만 매우 고통 스러웠다. rand () 함수를 정확히 어떻게 발견합니까?
James McMahon

답변 nemo 감사합니다.
KingNestor

11

이 코드 프로젝트 기사를 확인하십시오. 언급 한 블로그 게시물보다 좀 더 깊이 있습니다.

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

또한 CheatEngine (Nick D.에 의해 언급 됨)을 다운로드 하고 함께 제공되는 자습서를 참조하십시오.


9

"WinDbg에서는 중단 점을 설정할 수 있지만 중단 점을 설정할 지점과 메모리 위치를 상상하기는 어렵습니다. 마찬가지로 IDA Pro에서 정적 코드를 볼 때 어디서부터 시작해야할지 모르겠습니다. 광산을 나타내는 기능이나 데이터 구조를 찾을 수 있습니다. "

바로 그거죠!

음, mines 테이블을 구성하는 동안 호출되는 random ()과 같은 루틴을 찾을 수 있습니다. 이 은 제가 리버스 엔지니어링을 실험 할 때 많은 도움 이 되었습니다. :)

일반적으로 중단 점을 설정하기에 좋은 위치는 메시지 상자 호출, 사운드 재생 호출, 타이머 및 기타 win32 API 루틴입니다.

BTW, 지금 OllyDbg로 지뢰 찾기를 스캔하고 있습니다.

업데이트 : nemo 는 Eric "Dark Byte"Heijnen 의 멋진 도구 인 치트 엔진 을 상기 시켰습니다 .

CE (Cheat Engine)는 다른 프로세스 메모리 공간을보고 수정하는 데 유용한 도구입니다. 기본 기능 외에도 CE에는 프로세스의 분해 된 메모리를보고 다른 프로세스에 코드를 삽입하는 것과 같은 더 특별한 기능이 있습니다.

( 그 프로젝트 의 진정한 가치는 소스 코드 -Delphi-를 다운로드하고 그 메커니즘이 어떻게 구현되었는지 볼 수 있다는 것입니다. 저는 몇 년 전에 그렇게했습니다. : o)


5

이 주제에 대한 꽤 좋은 기사는 Uninformed 에서 찾을 수 있습니다 . 지뢰 찾기 (Win32 앱 리버스 엔지니어링에 대한 소개)를 매우 자세하게 다루고 있으며 매우 훌륭한 리소스를 제공합니다.


4

이 웹 사이트가 더 유용 할 수 있습니다.

http://www.subversity.net/reversing/hacking-minesweeper

이를 수행하는 일반적인 방법은 다음과 같습니다.

  1. 어떻게 든 소스 코드를 얻습니다.
  2. 분해하고 남은 기호가 도움이되기를 바랍니다.
  3. 데이터 유형을 추측하고이를 조작하고 메모리 스캐너를 사용하여 가능성을 제한하십시오.

바운티에 대한 응답

글쎄, 두 번째 독서에서는 리버스 엔지니어링 방법에 대한 일반적인 질문이 아니라 WinDBG와 같은 디버거를 사용하는 방법에 대한 가이드를 원하는 것처럼 보입니다. 검색해야 할 값을 알려주는 웹 사이트를 이미 보여 드렸는데, 질문은 어떻게 검색합니까?

이 예제에서는 지뢰 찾기가 설치되어 있지 않기 때문에 메모장을 사용하고 있습니다. 그러나 아이디어는 동일합니다.

대체 텍스트

당신은 입력

s <options> <memory start> <memory end> <pattern>

도움말을 보려면 "?"를 누른 다음 "s"를 누르십시오.

원하는 메모리 패턴을 찾으면 alt + 5를 눌러 멋진 디스플레이를위한 메모리 뷰어를 불러올 수 있습니다.

대체 텍스트

WinDBG는 익숙해지는 데 약간의 시간이 걸리지 만 다른 디버거만큼 좋습니다.


1
Minesweeper가 소스없이 전송되기 때문에 "어떻게 든 소스 코드를 가져옵니다"는 어리석은 말입니다. 소스를 사용한 리버스 엔지니어링은 리버스 엔지니어링이 아닙니다. 소스 코드 분석입니다.
mrduclaw

@mrduclaw 어셈블리를 소스 언어로 디 컴파일 할 수있는 응용 프로그램이 있습니다. "소스 코드 분석"이라는 용어는 없습니다.
Unknown

1
@Unknown 주어진 컴파일 된 바이너리에서 소스 언어로 프로그램을 재구성하려는 응용 프로그램이 있습니다. 그러나 컴파일 된 바이너리에서 작성자의 주석과 인용문이있는 "소스 코드"를 얻을 수 없습니다. 물론, 이러한 "디 컴파일러"중 일부는 다른 것보다 더 나은 작업을 수행하지만 작성자가 작성한 코드를 제공하지 않습니다 (컴파일러 최적화 코드는 종종 프로그래머의 코드와 매우 다릅니다). 그리고 품질 보증 테스트를 한 적이 없습니까? PREfast 및 Sparse와 같은 도구의 기능은 무엇입니까? 정적 소스 코드 분석.
mrduclaw

PREfast와 Sparse의 정적 소스 코드 분석은 해킹을 위해 수동으로 디 컴파일 된 코드를 읽는 것과 완전히 다릅니다. 나는 누구도이 두 가지 다른 생각을 서로 혼동하지 않을 것이라고 생각합니다.
Unknown

@Unknown 저는 한 번 더 설명하고 리버스 엔지니어링 디스 어셈블리를 소스 코드를 보는 것과 혼동해서는 안된다는 데 동의합니다 (디 컴파일되거나 소스 코드 분석을 수행하는 소스가있는 경우). 그게 내 요점이었다. 그러니 두 가지를 혼동하지 마세요. :)
mrduclaw

0

디버거에서 추적을 시작하는 좋은 점은 마우스를 올리는 것입니다. 따라서 주 창 프로 시저를 찾으십시오 (spyxx와 같은 도구가 창 속성을 검사 할 수 있고 이벤트 처리기 주소가 그중 하나라고 생각합니다). 그것에 침입하여 마우스 이벤트를 처리하는 위치를 찾으십시오. 어셈블러에서 인식 할 수 있다면 스위치가있을 것입니다 (windows.h에서 마우스를 올리려면 WM_XXX 값을보십시오).

거기에 중단 점을 놓고 단계를 시작하십시오. 마우스 버튼을 놓은 시간과 화면이 업데이트되는 사이에 victum이 찾고있는 데이터 구조에 액세스합니다.

인내심을 갖고 주어진 시간에 무슨 일이 일어나고 있는지 확인하려고 노력하되 현재 목표에 관심이 없다고 의심되는 코드를 너무 깊이 들여다 보지 마십시오. 디버거에서 여러 번 실행해야 할 수 있습니다.

일반적인 win32 응용 프로그램 워크 플로에 대한 지식도 도움이됩니다.


0

광산은 아마도 일종의 2 차원 배열에 저장 될 것입니다. 이것은 포인터의 배열이거나 부울의 단일 C 스타일 배열임을 의미합니다.

양식이 mouse-up 이벤트를 수신 할 때마다이 데이터 구조가 참조됩니다. 인덱스는 아마도 정수 나누기를 사용하여 마우스 좌표를 사용하여 계산됩니다. 만약 아마도 찾아야한다는 것을 의미 cmp하거나 유사한 피연산자 중 하나는 오프셋을 사용하여 계산되는 명령어 및 x, x정수 나눗셈을 포함하는 연산의 결과이다. 오프셋은 데이터 구조의 시작 부분에 대한 포인터가됩니다.


0

광산에 대한 정보가 적어도 행 (즉, 2D 배열 또는 배열 배열)에 대해 메모리에 연속적으로 배치된다고 가정하는 것은 상당히 합리적입니다. 따라서 동일한 행에서 인접한 여러 셀을 열어서 프로세스의 메모리 덤프를 만든 다음 비교하고 동일한 메모리 영역에서 반복되는 변경 사항을 찾습니다 (즉, 첫 번째 단계에서 1 바이트가 변경되고 다음 다음 단계에서 바이트가 정확히 동일한 값으로 변경되었습니다.

패킹 된 비트 배열 일 가능성도 있습니다 (닫힘 / 개방, 내 / 아니오, 플래그 지정 / 플래그되지 않은 모든 가능한 상태를 기록하는 데 내 3 비트이면 충분해야 함). 패턴도 반복 가능하지만 발견하기는 더 어렵습니다.) 하지만 다루기에는 편리한 구조가 아니고, 메모리 사용량이 지뢰 찾기의 병목이라고 생각하지 않기 때문에 이런 종류의 것이 사용될 가능성은 거의 없습니다.


0

엄격히 "역 엔지니어의 도구"는 아니고 나 같은 바보라도 사용할 수있는 장난감이 더 많지만 Cheat Engine을 확인하십시오 . 메모리의 어떤 부분이 언제, 언제 변경되었는지 추적하기가 다소 쉬우 며 포인터를 통해 변경된 메모리 부분을 추적 할 수있는 조항도 있습니다 (아마 필요하지 않을 수도 있음). 멋진 대화 형 튜토리얼이 포함되어 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.