Làm cách nào tôi có thể tìm thấy cấu trúc dữ liệu đại diện cho bố cục của tôi của Minesweeper trong bộ nhớ?


94

Tôi đang cố gắng tìm hiểu về kỹ thuật đảo ngược, sử dụng Minesweeper làm ứng dụng mẫu. Tôi đã tìm thấy bài viết MSDN này trên một lệnh WinDbg đơn giản tiết lộ tất cả các mỏ nhưng nó đã cũ, không được giải thích chi tiết và thực sự không phải là thứ tôi đang tìm kiếm.

Tôi có trình tháo gỡ IDA Protrình gỡ lỗi WinDbg và tôi đã tải winmine.exe vào cả hai. Ai đó có thể cung cấp một số mẹo thiết thực cho một trong hai chương trình này về việc tìm vị trí của cấu trúc dữ liệu đại diện cho mỏ không?

Trong WinDbg, tôi có thể thiết lập các điểm ngắt, nhưng tôi rất khó hình dung nên đặt điểm ngắt ở điểm nào và ở vị trí bộ nhớ nào. Tương tự, khi tôi xem mã tĩnh trong IDA Pro, tôi không chắc nên bắt đầu tìm hàm hoặc cấu trúc dữ liệu đại diện cho trường của tôi ở đâu.

Có bất kỳ Kỹ sư đảo ngược nào trên Stackoverflow có thể chỉ tôi đi đúng hướng không?


27
Thật là một ý tưởng tuyệt vời cho một bài tập cho học sinh. Nó giống như phòng thí nghiệm giải phẫu với tàu quét mìn là con mèo.
ojblass,

3
đối với độc giả quốc tế của chúng tôi có thể nhầm lẫn, tàu quét mìn là phiên bản Mỹ của trò chơi tìm bông hoa hạnh phúc được phát hành với windows vista. microsoft.blognewschannel.com/index.php/archives/2006/09/28/…
Kip

16
Trò chơi tìm hoa vui không? O_o Sự đúng đắn về chính trị đã đi quá xa.
Eugene

10
Vâng, phiên bản quét mìn ít nhất là mặc định trong phiên bản Vista của Thụy Điển. Tôi cho rằng họ mặc định phiên bản bông hoa hạnh phúc ở những nơi mà mỏ thực sự có xu hướng thổi trẻ em ra từng mảnh.
JesperE

1
Vì vậy ... chỉ cần nhấp vào một số ô vuông ngẫu nhiên để xem chúng có phải là mỏ không cũng không hữu ích cho việc này, phải không?
Smandoli

Câu trả lời:


125

Phần 1 của 3


Nếu bạn nghiêm túc với kỹ thuật đảo ngược - hãy quên các trình đào tạo và động cơ gian lận.

Kỹ sư đảo ngược giỏi trước tiên nên biết hệ điều hành, các chức năng API cốt lõi, cấu trúc chung của chương trình (vòng lặp chạy là gì, cấu trúc cửa sổ, quy trình xử lý sự kiện), định dạng tệp (PE). Tác phẩm kinh điển "Lập trình Windows" của Petzold có thể giúp ích (www.amazon.com/exec/obidos/ISBN=157231995X) cũng như MSDN trực tuyến.

Trước tiên, bạn nên nghĩ về nơi có thể gọi quy trình khởi tạo bãi mìn. Tôi đã nghĩ đến những điều sau:

  • Khi bạn khởi chạy trò chơi
  • Khi bạn nhấp vào khuôn mặt hạnh phúc
  • Khi bạn nhấp vào Trò chơi-> Mới hoặc nhấn F2
  • Khi bạn thay đổi mức độ khó

Tôi quyết định kiểm tra lệnh tăng tốc F2.

Để tìm mã xử lý bộ tăng tốc, bạn phải tìm quy trình xử lý thông báo cửa sổ (WndProc). Nó có thể được truy tìm bằng các cuộc gọi CreateWindowEx và RegisterClass.

Đọc:

Mở cửa sổ IDA, Imports, tìm "CreateWindow *", chuyển đến nó và sử dụng lệnh "Jump xref to operand (X)" để xem nó được gọi ở đâu. Chỉ nên có một cuộc gọi.

Bây giờ, hãy tìm ở trên cho hàm RegisterClass và nó là tham số WndClass.lpfnWndProc. Tôi đã đặt tên cho hàm mainWndProc trong trường hợp của mình.

.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

Nhấn Enter trên tên hàm (sử dụng 'N' để đổi tên nó thành tên khác tốt hơn)

Bây giờ hãy xem

.text:01001BCF                 mov     edx, [ebp+Msg]

Đây là id thông báo, trong trường hợp nhấn nút F2 phải chứa giá trị WM_COMMAND. Bạn phải tìm nó ở đâu so với 111h. Nó có thể được thực hiện bằng cách truy tìm edx trong IDA hoặc bằng cách thiết lập điểm ngắt có điều kiện trong WinDbg và nhấn F2 trong trò chơi.

Dù bằng cách nào cũng dẫn đến một cái gì đó như

.text:01001D5B                 sub     eax, 111h
.text:01001D60                 jz      short loc_1001DBC

Nhấp chuột phải vào 111h và sử dụng "Hằng số ký hiệu" -> "Sử dụng hằng số ký hiệu tiêu chuẩn", gõ WM_ và Enter. Bây giờ bạn nên có

.text:01001D5B                 sub     eax, WM_COMMAND
.text:01001D60                 jz      short loc_1001DBC

Đây là một cách dễ dàng để tìm ra các giá trị id tin nhắn.

Để hiểu cách xử lý máy gia tốc, hãy kiểm tra:

Có khá nhiều văn bản cho một câu trả lời duy nhất. Nếu bạn quan tâm, tôi có thể viết một vài bài viết khác. Bãi mìn ngắn câu chuyện dài được lưu trữ dưới dạng một mảng byte [24x36], 0x0F cho biết byte đó không được sử dụng (chơi trường nhỏ hơn), 0x10 - trường trống, 0x80 - của tôi.

Phần 2 của 3


Ok, hãy tiếp tục với nút F2.

Theo Sử dụng bộ tăng tốc bàn phím khi nhấn nút F2, chức năng wndProc

... nhận được thông báo WM_COMMAND hoặc WM_SYSCOMMAND. Từ bậc thấp của tham số wParam chứa mã định danh của bộ gia tốc.

Ok, chúng tôi đã tìm thấy nơi WM_COMMAND được xử lý, nhưng làm thế nào để xác định giá trị tham số wParam tương ứng? Đây là lúc Resource hacker vào cuộc. Nuôi nó bằng nhị phân và nó hiển thị cho bạn mọi thứ. Giống như bảng gia tốc cho tôi.

văn bản thay thế http://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg

Bạn có thể thấy ở đây, nút F2 đó tương ứng với 510 trong wParam.

Bây giờ chúng ta hãy quay lại mã, xử lý WM_COMMAND. Nó so sánh wParam với các hằng số khác nhau.

.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

Sử dụng menu ngữ cảnh hoặc phím tắt 'H' để hiển thị các giá trị thập phân và bạn có thể thấy bước nhảy của chúng tôi

.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

Nó dẫn đến đoạn mã gọi một số proc và thoát khỏi wndProc.

.text:01001EC8 loc_1001EC8:                            ; CODE XREF: mainWndProc+20Fj
.text:01001EC8                 call    sub_100367A     ; startNewGame ?
.text:01001EC8
.text:01001ECD                 jmp     callDefAndExit  ; default

Đó có phải là chức năng bắt đầu trò chơi mới không? Tìm hiểu điều đó trong phần cuối cùng! Giữ nguyên.

Phần 3 của 3

Chúng ta hãy xem phần đầu tiên của hàm đó

.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

Có hai giá trị (dword_10056AC, uValue) được đọc vào thanh ghi eax và ecx và được so sánh với hai giá trị khác (dword_1005164, dword_1005338).

Hãy xem các giá trị thực tế bằng WinDBG ('bp 01003696'; on break 'p eax; p ecx') - đối với tôi chúng giống như kích thước bãi mìn. Chơi với kích thước bãi mìn tùy chỉnh cho thấy rằng cặp thứ nhất là thứ nguyên mới và thứ hai - thứ nguyên hiện tại. Hãy đặt tên mới.

.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

Một chút sau các giá trị mới sẽ ghi đè lên chương trình con hiện tại và chương trình con được gọi là

.text:010036A7                 mov     currentMineFieldWidth, eax
.text:010036AC                 mov     currentMineFieldHeight, ecx
.text:010036B2                 call    sub_1002ED5

Và khi tôi nhìn thấy nó

.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

Tôi hoàn toàn chắc chắn rằng tôi đã tìm thấy mảng bãi mìn. Nguyên nhân do chu kỳ chiếm mảng độ dài 360h byte (dword_1005340) với 0xF.

Tại sao 360h = 864? Có một số gợi ý bên dưới rằng hàng có 32 byte và 864 có thể được chia cho 32, vì vậy mảng có thể chứa 27 * 32 ô (mặc dù giao diện người dùng cho phép trường tối đa 24 * 30, có một phần đệm byte xung quanh mảng cho đường viền).

Mã sau tạo đường viền trên và dưới của bãi mìn (byte 0x10). Tôi hy vọng bạn có thể thấy sự lặp lại vòng lặp trong mớ hỗn độn đó;) Tôi đã phải sử dụng giấy và bút

.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

Và phần còn lại của chương trình con vẽ các đường viền trái và phải

.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

Việc sử dụng thông minh các lệnh WinDBG có thể cung cấp cho bạn kết xuất bãi mìn thú vị (kích thước tùy chỉnh 9x9). Kiểm tra các đường biên giới!

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

Rất tiếc, có vẻ như tôi sẽ cần một bài đăng khác để đóng chủ đề


1
@Stanislav, câu trả lời hay đấy Stanislav. Nếu bạn có thể giải thích chi tiết về nó, vui lòng làm như vậy. Những câu trả lời dài, nhiều thông tin này là tốt nhất. Có lẽ thêm một chút về cách bạn khai thác cấu trúc dữ liệu bãi mìn?
KingNestor

@Stanislav, tôi đã chấp nhận câu trả lời của bạn vì tiền thưởng 250 đại diện đã kết thúc. Xin chúc mừng!
KingNestor

1
@Stanislav, tôi đã chỉnh sửa câu trả lời có phần khó hiểu của bạn thành một câu trả lời duy nhất. Bạn chưa đạt đến giới hạn kích thước của câu trả lời duy nhất của mình và tôi nghĩ rằng bạn nên có một câu trả lời hơn là đăng nhiều câu trả lời. Vui lòng chỉnh sửa câu trả lời ban đầu của bạn (câu này) và thêm vào câu trả lời khi bạn thấy phù hợp.
mmcdole

2
Ngoài ra, câu trả lời sử thi Stanislav. Cảm ơn rất nhiều vì sự chăm chỉ của bạn!
mmcdole

15

Có vẻ như bạn đang cố gắng tháo rời nguồn nhưng những gì bạn cần làm là nhìn vào không gian bộ nhớ của chương trình đang chạy. Trình chỉnh sửa hex HxD có một tính năng cho phép bạn thực hiện điều đó.

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

Khi bạn đang ở trong không gian bộ nhớ, vấn đề là chụp ảnh nhanh bộ nhớ trong khi bạn lộn xộn với bảng. Cô lập những gì thay đổi so với những gì không. Khi bạn nghĩ rằng bạn có khả năng xử lý vị trí cấu trúc dữ liệu nằm trong bộ nhớ hex, hãy thử chỉnh sửa nó khi nó ở trong bộ nhớ và xem kết quả là bảng có thay đổi hay không.

Quá trình bạn muốn không khác gì xây dựng 'huấn luyện viên' cho trò chơi điện tử. Chúng thường dựa trên việc tìm ra nơi các giá trị như sức khỏe và đạn dược sống trong bộ nhớ và thay đổi chúng nhanh chóng. Bạn có thể tìm thấy một số hướng dẫn tốt về cách xây dựng trình huấn luyện trò chơi.


2
Chà, bạn có thể ~ xác định vị trí bộ nhớ thông qua chức năng tháo gỡ tĩnh. Bạn có thể làm theo hướng dẫn lắp ráp để tìm kiếm những thứ như hàm rand () đang được gọi để tạo trường mỏ và sau đó theo dõi từ đó để xem trường được lưu trữ ở vị trí nào trong bộ nhớ (và cách thức).
mmcdole

Cả hai cách tiếp cận đều đầy thách thức. Tôi đã cố gắng tháo gỡ các ứng dụng trong quá khứ và tôi thấy nó rất đau. Làm thế nào để bạn phát hiện chính xác một hàm rand ()?
James McMahon

Cảm ơn bạn đã trả lời nemo.
KingNestor

11

Hãy xem bài viết dự án mã này, nó chuyên sâu hơn một chút so với bài đăng trên blog mà bạn đã đề cập.

http://www.codeproject.com/KB/trace/minememoryreader.aspx

Biên tập

Và bài viết này, mặc dù không trực tiếp về máy quét mìn, nhưng sẽ cung cấp cho bạn hướng dẫn từng bước tốt về cách săn tìm qua bộ nhớ bằng WinDbg:

http://www.codingthewheel.com/archives/extract-hiested-text-with-windbg

Chỉnh sửa 2

Một lần nữa, đây không phải là về máy quét mìn, nhưng nó chắc chắn đã mang lại cho tôi một số thức ăn để suy nghĩ cho việc gỡ lỗi bộ nhớ của tôi, có rất nhiều hướng dẫn ở đây:

http://memoryhacking.com/forums/index.php

Ngoài ra, hãy tải xuống CheatEngine (do Nick D. đề cập) và thực hiện theo hướng dẫn đi kèm.


9

"Trong WinDbg, tôi có thể thiết lập các điểm ngắt, nhưng tôi rất khó hình dung nên đặt điểm ngắt ở điểm nào và tại vị trí bộ nhớ nào. Tương tự, khi tôi xem mã tĩnh trong IDA Pro, tôi không chắc nên bắt đầu từ đâu. để tìm chức năng hoặc cơ cấu dữ liệu đại diện cho trường mỏ. "

Chính xác!

Chà, bạn có thể tìm các thói quen như random () sẽ được gọi trong quá trình xây dựng bảng mìn. Cuốn sách này đã giúp tôi rất nhiều khi tôi đang thử nghiệm thiết kế ngược. :)

Nói chung, những nơi tốt để thiết lập các điểm ngắt là các lệnh gọi đến hộp tin nhắn, lệnh gọi để phát âm thanh, bộ hẹn giờ và các quy trình API win32 khác.

BTW, tôi đang quét tàu quét mìn bằng OllyDbg .

Cập nhật: nemo đã nhắc nhở tôi một công cụ tuyệt vời, Cheat Engine của Eric "Dark Byte" Heijnen.

Cheat Engine (CE) là một công cụ tuyệt vời để xem và sửa đổi không gian bộ nhớ các quy trình khác. Ngoài sở cơ bản đó , CE có nhiều tính năng đặc biệt hơn như xem bộ nhớ đã tháo rời của một quy trình và đưa mã vào các quy trình khác.

( giá trị thực của dự án đó là bạn có thể tải xuống mã nguồn -Delphi- và xem các cơ chế đó được triển khai như thế nào - Tôi đã làm điều đó nhiều năm trước: o)


5

Bạn có thể tìm thấy một bài viết khá hay về chủ đề này tại Uninformed . Nó bao gồm việc đảo ngược Minesweeper (như một phần giới thiệu về các ứng dụng Win32 thiết kế ngược) khá chi tiết và là một nguồn tài nguyên khá tuyệt vời.


4

Trang web này có thể hữu ích hơn:

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

Cách chung để làm điều này là:

  1. Bằng cách nào đó lấy mã nguồn.
  2. Hãy tháo rời và hy vọng những biểu tượng còn sót lại có thể giúp ích cho bạn.
  3. Đoán kiểu dữ liệu và cố gắng thao tác và sử dụng máy quét bộ nhớ để hạn chế khả năng xảy ra.

Đáp lại Bounty

Chà, trong bài đọc thứ hai, có vẻ như bạn muốn có một hướng dẫn về cách sử dụng trình gỡ lỗi như WinDBG hơn là câu hỏi thông thường về cách thiết kế ngược. Tôi đã chỉ cho bạn trang web cho bạn biết các giá trị bạn cần tìm kiếm, vậy câu hỏi đặt ra là, bạn tìm kiếm nó như thế nào?

Tôi đang sử dụng Notepad trong ví dụ này vì tôi chưa cài đặt Minesweeper. Nhưng ý tưởng là như nhau.

văn bản thay thế

Bạn gõ

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

Nhấn "?" Rồi nhấn "s" để xem trợ giúp.

Khi bạn đã tìm thấy mẫu bộ nhớ mình muốn, sau đó bạn có thể nhấn alt + 5 để hiển thị trình xem bộ nhớ để hiển thị đẹp.

văn bản thay thế

WinDBG mất một số thời gian để làm quen, nhưng nó tốt như bất kỳ trình gỡ lỗi nào khác.


1
"Bằng cách nào đó lấy mã nguồn" là một tuyên bố ngớ ngẩn vì Minesweeper được gửi mà không có nguồn. Và kỹ thuật đảo ngược với nguồn không phải là kỹ thuật đảo ngược ... đó là phân tích mã nguồn.
mrduclaw 22-07-09

@mrduclaw có những ứng dụng có thể dịch ngược cụm từ sang ngôn ngữ nguồn. Không có thuật ngữ nào được gọi là "phân tích mã nguồn".
Không xác định

1
@Unknown Có những ứng dụng cố gắng tạo lại một chương trình bằng ngôn ngữ nguồn từ một tệp nhị phân đã biên dịch nhất định. Nhưng bạn không thể lấy "mã nguồn" với các nhận xét và trích dẫn của tác giả từ một tệp nhị phân đã biên dịch. Chắc chắn, một số "trình dịch ngược" làm công việc tốt hơn những người khác nhưng họ không cung cấp cho bạn mã mà tác giả đã viết (mã tối ưu hóa trình biên dịch thường rất khác với mã của lập trình viên). Và bạn chưa bao giờ thực hiện kiểm tra đảm bảo chất lượng? Các công cụ như PREfast và Sparse làm gì? Phân tích mã nguồn tĩnh.
mrduclaw 22-07-09

Phân tích mã nguồn tĩnh trong PREfast and Sparse hoàn toàn khác với việc đọc mã dịch ngược theo cách thủ công để hack nó. Tôi không nghĩ có ai lại nhầm lẫn hai ý tưởng khác nhau đó với nhau.
Không xác định

@Unknown Tôi nói thêm về vấn đề này và đồng ý rằng bạn không nên nhầm lẫn giữa việc tháo gỡ kỹ thuật đảo ngược với việc xem xét mã nguồn (được dịch ngược hoặc cách khác, nếu bạn có nguồn mà bạn đang thực hiện phân tích mã nguồn). Đó là toàn bộ quan điểm của tôi. Vì vậy, xin đừng nhầm lẫn giữa hai người. :)
mrduclaw

0

Một điểm tốt để bắt đầu truy tìm trong trình gỡ lỗi là di chuột lên. Vì vậy, hãy tìm thủ tục cửa sổ chính (tôi nghĩ các công cụ như spyxx có thể kiểm tra các thuộc tính của cửa sổ và địa chỉ xử lý sự kiện là một trong số đó). Hãy đột nhập vào nó và tìm nơi nó xử lý các sự kiện chuột - sẽ có một công tắc, nếu bạn có thể nhận ra nó trong trình hợp dịch (hãy xem giá trị của WM_XXX để di chuột lên trong windows.h).

Đặt một điểm dừng ở đó và bắt đầu bước vào. Khoảng thời gian giữa thời gian bạn nhả nút chuột và màn hình được cập nhật, thức ăn sẽ truy cập vào cơ cấu dữ liệu bạn đang tìm kiếm.

Hãy kiên nhẫn, cố gắng xác định những gì đang được thực hiện vào bất kỳ thời điểm nào, nhưng đừng bận tâm quá sâu vào đoạn mã mà bạn nghi ngờ là không thú vị cho mục tiêu hiện tại của bạn. Có thể mất vài lần chạy trình gỡ lỗi để gỡ rối.

Kiến thức về quy trình làm việc của các ứng dụng win32 thông thường cũng giúp ích cho bạn.


0

Các mỏ có thể sẽ được lưu trữ trong một số loại mảng hai chiều. Điều này có nghĩa là nó là một mảng con trỏ hoặc một mảng kiểu C đơn lẻ của các boolean.

Bất cứ khi nào biểu mẫu nhận được sự kiện di chuột lên, cấu trúc dữ liệu này sẽ được tham chiếu. Chỉ số sẽ được tính toán bằng cách sử dụng tọa độ chuột, có thể sử dụng phép chia số nguyên. Điều đó có nghĩa là bạn có thể nên tìm kiếm một cmphoặc một lệnh tương tự, trong đó một trong các toán hạng được tính bằng cách sử dụng bù và x, đâu xlà kết quả của một phép tính liên quan đến phép chia số nguyên. Phần bù sau đó sẽ là con trỏ đến phần đầu của cấu trúc dữ liệu.


0

Khá hợp lý khi giả định rằng thông tin về các mỏ được sắp xếp liền kề trong bộ nhớ ít nhất là đối với các hàng (tức là đó là mảng 2D hoặc mảng của các mảng). Vì vậy, tôi sẽ thử mở một số ô liền kề trong cùng một hàng, tạo kết xuất bộ nhớ của quá trình khi tôi bắt đầu, sau đó khác biệt chúng và tìm kiếm bất kỳ thay đổi lặp lại nào trong cùng một vùng bộ nhớ (tức là 1 byte đã thay đổi ở bước đầu tiên, bước tiếp theo byte được thay đổi thành cùng một giá trị trong bước tiếp theo, v.v.).

Cũng có khả năng đó là một mảng bit được đóng gói (3 bit cho mỗi mỏ phải đủ để ghi lại tất cả các trạng thái có thể xảy ra - đóng / mở, của tôi / không của tôi, được gắn cờ / không được gắn cờ), vì vậy tôi cũng sẽ chú ý đến điều đó ( các mẫu cũng sẽ có thể lặp lại, mặc dù khó phát hiện hơn). Nhưng nó không phải là một cấu trúc thuận tiện để giải quyết và tôi không nghĩ rằng việc sử dụng bộ nhớ là một nút thắt cổ chai cho Minesweeper, vì vậy không chắc rằng loại thứ này sẽ được sử dụng.


0

Mặc dù không hoàn toàn là một "công cụ của kỹ sư đảo ngược", và nhiều thứ đồ chơi mà ngay cả một kẻ ngốc như tôi cũng có thể sử dụng, hãy xem Cheat Engine . Nó giúp bạn dễ dàng theo dõi phần nào của bộ nhớ đã thay đổi, khi nào, và thậm chí có các quy định để theo dõi các phần bộ nhớ đã thay đổi thông qua con trỏ (mặc dù bạn có thể không cần điều đó). Một hướng dẫn tương tác tốt đẹp được bao gồm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.