xp扫雷简单逆向
掃雷是從xp里拷出來的,是一個win32程序,用IDA分析,找到它的主函數 WinMain,這個函數是很明顯的,只要學過windows編程都能很快找到。
注冊窗口類時需要給出窗口函數,所以就找到窗口函數了。進去F5,我們關心鼠標左鍵事件:
注意23行,點擊左鍵后調用的函數,關鍵代碼就在里面,參數是點擊時鼠標在client區的坐標,進去繼續看:
注意54行調用的 sub_100367A 函數,進去看,發現有一個疑似遍歷全局二維數組的操作:
動態調試發現這里就是雷區的二維數組,怎么確定呢?很簡單,右鍵點擊,標記為旗子和問號,內存里面的東西會變,找找規律就會發現 0x8F 表示地雷。后面的操作就是找到不是地雷的格子,然后鼠標點擊即可。
#include <windows.h> #include <stdio.h> #include <TlHelp32.h>#define MAP_MAX_SIZE 32 * 32 BYTE GameMap[32][32]; int MapSize[2];// 提權函數:提升為DEBUG權限 BOOL EnableDebugPrivilege() {HANDLE hToken;BOOL fOk = FALSE;if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)){TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);fOk = (GetLastError() == ERROR_SUCCESS);CloseHandle(hToken);}return fOk; }HANDLE OpenProcessWithName(const WCHAR *szProcessName) {HANDLE hSnapshot;hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (INVALID_HANDLE_VALUE == hSnapshot){printf("CreateToolhelp32Snapshot failed.\n");exit(1);}PROCESSENTRY32W process;process.dwSize = sizeof(PROCESSENTRY32W);BOOL first = Process32First(hSnapshot, &process);while (first){if (!wcscmp(szProcessName, process.szExeFile)){HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);if (hProcess != NULL){return hProcess;}}first = Process32NextW(hSnapshot, &process);}CloseHandle(hSnapshot);return NULL; }void LeftClickBlock(HWND hWnd, int i, int j) {POINT p;p.x = j * 16 + 20;p.y = i * 16 + 60;ClientToScreen(hWnd, &p);SetCursorPos(p.x, p.y);INPUT input = { 0 };input.type = INPUT_MOUSE;input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;SendInput(1, &input, sizeof(input));if (GetFocus() != hWnd){SendInput(1, &input, sizeof(input));}ZeroMemory(&input, sizeof(input));Sleep(10);input.type = INPUT_MOUSE;input.mi.dwFlags = MOUSEEVENTF_LEFTUP;SendInput(1, &input, sizeof(input));Sleep(10); }void Go() {HANDLE hWinmine = OpenProcessWithName(L"winmine.exe");HWND hWnd = FindWindowW(NULL, L"掃雷");if (INVALID_HANDLE_VALUE == hWinmine){printf("打開進程失敗 %d.\n", GetLastError());system("pause");exit(1);}SIZE_T nRead = 0;ReadProcessMemory(hWinmine, (LPCVOID)0x01005361, GameMap, MAP_MAX_SIZE, &nRead);if (MAP_MAX_SIZE != nRead){printf("讀取地圖失敗 %d.\n", GetLastError());printf("實際讀取字節 %d.\n", nRead);system("pause");exit(1);}ReadProcessMemory(hWinmine, (LPCVOID)0x01005334, MapSize, 8, &nRead);if (8 != nRead){printf("讀取地圖尺寸失敗 %d.\n", GetLastError());printf("實際讀取字節 %d.\n", nRead);system("pause");exit(1);}LeftClickBlock(hWnd, 0, 0);for (int i = 0; i < MapSize[1]; i++){for (int j = 0; j < MapSize[0]; j++){if (0x8F != GameMap[i][j]) // 8F 是雷{//printf("%d %d\n", i + 1, j + 1);LeftClickBlock(hWnd, i, j);}}}CloseHandle(hWinmine);CloseHandle(hWnd); }int main() {if (!EnableDebugPrivilege()){printf("請以管理員權限運行.\n");system("pause");exit(1);}printf("點擊 [M] 開始掃雷.\n");while (1){if (GetAsyncKeyState('M')){Go();}Sleep(10);}system("pause");return 0; }總結
- 上一篇: Prison Architect 64位
- 下一篇: 使用 detours 框架 hook 函