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 ................................
흠, 주제를 닫으려면 다른 게시물이 필요한 것 같습니다.