(本文系转载,原文地址:http://blog.youkuaiyun.com/prsniper/article/details/16953403)
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();
- }
至于是干嘛的,看得懂就懂,不懂也就这样了,至于你懂不懂,反正我懂了.
无图有真相...
本文介绍了一种针对蜘蛛纸牌游戏的内存破解方法,通过读取和修改游戏进程中的内存数据来实现游戏的自动胜利。该方法涉及查找游戏窗口、获取进程句柄、读取游戏全局数据及牌组信息等步骤。
1755





