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
#include "dump.h"
#include
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();
}
至于是干嘛的,看得懂就懂,不懂也就这样了,至于你懂不懂,反正我懂了.
无图有真相...