1. dump.h
#ifndef __SPIDER_DUMP_H_ #define __SPIDER_DUMP_H_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 typedef struct _CARDINFO{ DWORD dwIndex; // 牌的序号 _CARDINFO *pPrev; // 前一张指针(NULL为第一张) _CARDINFO *pNext; // 下一张指针(NULL最后一张) } CARDINFO, *PCARDINFO; typedef struct _CARDPROP{ DWORD Class; // 花色: 梅花=0, 方块=1, 红桃=2, 黑桃=3 DWORD Order; // 序列: A-K, A=0 DWORD Opened; // 状态: 未翻开=0 } CARDPROP, *PCARDPROP; typedef struct _GAMEPROP{ LPVOID lpCardList[10]; // 链表指针数组 DWORD dwCardCount[10]; // 每列牌数数组 DWORD dwHideCount[10]; // 未翻牌数数组 } GAMEPROP, *PGAMEPROP; typedef struct _GAMEDATA{ HWND hWnd; LPVOID lpDifficulty; LPVOID lppTrainList; } GAMEDATA, *PGAMEDATA; #endif
2.dump.cpp
#include <windows.h> #include "dump.h" #include <stdio.h> const char *szClass[] = { "梅花", "方块", "红桃", "黑桃" }; const char *szOrder[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" }; const char *szOpened[] = { "未翻开", "已翻开" }; LPVOID lpBaseAddress = (LPVOID)0x01012008; // 全局指针 //LPVOID lpPropAddress = (LPVOID)0x01012008; //LPVOID lpViewAddress = (LPVOID)0x01012008; //LPVOID lpShowAddress = (LPVOID)0x01012008; //LPVOID lpHideAddress = (LPVOID)0x01012008; GAMEDATA g_Data; GAMEPROP g_Prop; CARDPROP lpCards[104]; CARDINFO ci; int fnDump() { HWND hWnd; DWORD dwProcessId; HANDLE hProcess; LPVOID lpAddress; DWORD dwValue; DWORD dwLoop; DWORD dwOrder; // 12-0循环 DWORD dwClass; // 7-0黑桃*2, 红桃*2, 梅花*2, 方块*2 int dwRet; hWnd = FindWindow(NULL, "蜘蛛"); if(hWnd == NULL) { printf("Can not find the spider window!\n"); return 0; } GetWindowThreadProcessId(hWnd, &dwProcessId); // return thread id hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if(hProcess == NULL) { printf("Can not open process! code: %d.\n", GetLastError()); return 0; } dwRet = ReadProcessMemory(hProcess, lpBaseAddress, &g_Data, sizeof(GAMEDATA), NULL); if(dwRet == 0) { printf("Can not read global data! code: %d.\n", GetLastError()); CloseHandle(hProcess); return 0; } if(g_Data.hWnd != hWnd) { printf("Global data mismatch!\n"); CloseHandle(hProcess); return 0; } lpAddress = (LPVOID)((DWORD)lpBaseAddress + 0xF1C); dwRet = ReadProcessMemory(hProcess, lpAddress, &dwValue, sizeof(DWORD), NULL); if(dwRet == 0) { printf("Can not determine whether partially completed or not! code: %d.\n", GetLastError()); CloseHandle(hProcess); return 0; } if(dwValue != 0) { printf("Game is partially completed!\n"); CloseHandle(hProcess); return 0; } lpAddress = (LPVOID)((DWORD)lpBaseAddress + 0x58); dwRet = ReadProcessMemory(hProcess, lpAddress, &dwValue, sizeof(DWORD), NULL); if(dwRet == 0) { printf("Can not read remaining card count! code: %d.\n", GetLastError()); CloseHandle(hProcess); return 0; } dwValue = 5 - dwValue; // 发完是5次 printf("There are(is) %d time(s) remaining.\n", dwValue); if(dwValue > 0) { SetForegroundWindow(hWnd); for(dwLoop = 0; dwLoop < dwValue; dwLoop++) { // 把所有的牌发完 -> 发送点击发牌菜单的命令 dwRet = SendMessage(hWnd, WM_COMMAND, 40016, 0); } } dwRet = ReadProcessMemory(hProcess, g_Data.lpDifficulty, &dwValue, sizeof(DWORD), NULL); if(dwRet == 0) { printf("Can not read difficulty data! code: %d.\n", GetLastError()); CloseHandle(hProcess); return 0; } if((dwValue != 1) && (dwValue != 2) && (dwValue != 4)) { printf("Difficulty data mismatch!\n"); CloseHandle(hProcess); return 0; } dwValue = (DWORD)g_Data.lpDifficulty; dwValue += 0xC; lpAddress = (LPVOID)dwValue; // 牌属性指针地址 dwRet = ReadProcessMemory(hProcess, lpAddress, &dwValue, sizeof(DWORD), NULL); if(dwRet == 0) { printf("Can not read card property pointer! code: %d.\n", GetLastError()); CloseHandle(hProcess); return 0; } lpAddress = (LPVOID)dwValue; // 牌属性指针 dwRet = ReadProcessMemory(hProcess, lpAddress, lpCards, sizeof(CARDPROP) * 104, NULL); if(dwRet == 0) { printf("Can not read card property array! code: %d.\n", GetLastError()); CloseHandle(hProcess); return 0; } dwRet = ReadProcessMemory(hProcess, g_Data.lppTrainList, &g_Prop, sizeof(GAMEPROP), NULL); if(dwRet == 0) { printf("Can not read train list data! code: %d.\n", GetLastError()); CloseHandle(hProcess); return 0; } printf("======== begin dumping card data ========\n"); dwOrder = 12; // .. dwClass = 7; // .. for(dwLoop = 0; dwLoop < 10; dwLoop++) { // 遍历每一列 dwRet = ReadProcessMemory(hProcess, g_Prop.lpCardList[dwLoop], &dwValue, sizeof(DWORD), NULL); if(dwRet == 0) { // 此次是根据元素(链表指针读取链表地址) printf("Can not read train %d pointer! code: %d.\n", dwLoop, GetLastError()); CloseHandle(hProcess); return 0; } //lpAddress = (LPVOID)dwValue; //dwRet = ReadProcessMemory(hProcess, lpAddress, &dwValue, sizeof(DWORD), NULL); //if(dwRet == 0) //{ // printf("Can not read train %d data! code: %d.\n", dwLoop, GetLastError()); // CloseHandle(hProcess); // return 0; //} lpAddress = (LPVOID)dwValue; dwRet = ReadProcessMemory(hProcess, lpAddress, &ci, sizeof(CARDINFO), NULL); if(dwRet == 0) { // 此次读取链表第一个元素(要求游戏一行都没有收起, 也没有空行) printf("Can not read train %d data! code: %d.\n", dwLoop, GetLastError()); CloseHandle(hProcess); return 0; } dwValue = 0; // 显示当前实际的卡片属性 printf("第 %d 张牌序号为: %d(%s 的 %s%s).\n", dwValue, ci.dwIndex, szOpened[lpCards[ci.dwIndex].Opened], szClass[lpCards[ci.dwIndex].Class], szOrder[lpCards[ci.dwIndex].Order]); // 修改为我们想要的属性值 lpCards[ci.dwIndex].Opened = 1; // 已经翻开 lpCards[ci.dwIndex].Class = dwClass / 2; // 花色 lpCards[ci.dwIndex].Order = dwOrder; // 序号 if(dwOrder == 0) { // 已经排到A了 if(dwClass == 0) break; // 尽头了 dwOrder = 12; dwClass--; }else dwOrder--; while(ci.pNext != 0) { lpAddress = (LPVOID)ci.pNext; dwRet = ReadProcessMemory(hProcess, lpAddress, &ci, sizeof(CARDINFO), NULL); if(dwRet == 0) { printf("Can not read train %d data!! code: %d.\n", dwLoop, GetLastError()); CloseHandle(hProcess); return 0; } dwValue++; // 显示当前实际的卡片属性 printf("第 %d 张牌序号为: %d(%s 的 %s%s).\n", dwValue, ci.dwIndex, szOpened[lpCards[ci.dwIndex].Opened], szClass[lpCards[ci.dwIndex].Class], szOrder[lpCards[ci.dwIndex].Order]); // 修改为我们想要的属性值 lpCards[ci.dwIndex].Opened = 1; // 已经翻开 lpCards[ci.dwIndex].Class = dwClass / 2; // 花色 lpCards[ci.dwIndex].Order = dwOrder; // 序号 if(dwOrder == 0) { // 已经排到A了 if(dwClass == 0) break; // 尽头了 dwOrder = 12; dwClass--; }else dwOrder--; } if(ci.pNext) break; // 中断跳出的while循环 if(dwLoop < 9) printf("\n"); } if(dwLoop < 10) { printf("Card count mismatch.\n"); CloseHandle(hProcess); return 0; } printf("======== Cracking game memory ========\n"); dwValue = (DWORD)g_Data.lpDifficulty; dwValue += 0xC; lpAddress = (LPVOID)dwValue; // 牌属性指针地址 dwRet = ReadProcessMemory(hProcess, lpAddress, &dwValue, sizeof(DWORD), NULL); lpAddress = (LPVOID)dwValue; // 牌属性指针 dwRet = WriteProcessMemory(hProcess, lpAddress, lpCards, sizeof(CARDPROP) * 104, NULL); // 修改已翻开的牌数 for(dwLoop = 0; dwLoop < 10; dwLoop++) { g_Prop.dwHideCount[dwLoop] = 0; } dwValue = (DWORD)g_Data.lppTrainList; dwValue += (sizeof(DWORD) * 20); lpAddress = (LPVOID)dwValue; dwRet = WriteProcessMemory(hProcess, lpAddress, g_Prop.dwHideCount, sizeof(DWORD) * 10, NULL); if(dwRet == 0) { printf("Can not crack card view property! code: %d.\n", GetLastError()); CloseHandle(hProcess); return 0; } InvalidateRect(hWnd, NULL, TRUE); printf("======== finish dumping card data ========\n"); CloseHandle(hProcess); return 1; } int main(int argc, char* argv[]) { printf("============================================\n"); printf("======== 游侠技术研究,请勿非法使用 ========\n"); printf("============================================\n"); return fnDump(); }
至于是干嘛的,看得懂就懂,不懂也就这样了,至于你懂不懂,反正我懂了.
无图有真相...