#include <windows.h>
#include <stdio.h>
/*
半年前看Moon大师的蜘蛛纸牌教程后,想自己也跟着做。到最后发现,原理XP SP2后的
版本已经大不相同,深受打击。前段时间重要搞定它了,呵呵。代码和一些数据如下,语言
视频教程过两天录好再首发断点论坛。
感谢看雪Moon大师在百忙中给予的邮件支持和指导。
作者:Jerson Ju(Zhujian198)
*/
typedef struct _ListEntry //双向链表节点的数据结构
{
DWORD dwPaiSeqNo; //牌序号,从0到103
struct _ListEntry *prior;//指向链表的上一个节点
struct _ListEntry *next;//指向链表的下一个节点
}ListEntry;
typedef struct _Pai //牌的数据结构
{
DWORD dwHua; //该牌是什么花,梅 方 红 黑分别为0,1,2,3
DWORD dwPaiNo; //牌号码,从0开始,0表示A
DWORD dwOpenedOrNot;//0表示牌未翻开,1表示已翻开
}Pai;
//环境:操作系统winxp sp3 英文版
//分析程序:蜘蛛纸牌
//经过分析app程序对象偏移地址是 1012008
//[1012008 + 4] + 8 等于牌总数
//[1012008 + 4] + c 牌结构数组的开始地址
//[1012008+8] 等于 10个链表存放 的数组首地址
#define BASEADDR 0x1012008
int main()
{
DWORD dwProcessId;
HWND hwnd;
HANDLE hProcess;
DWORD dwPaiAddr;
DWORD dwReadedBytes;
Pai structPai[13*8];//牌的结构数组104张
DWORD dwListAddr[10];//10个双向链表头存放的数组首地址
DWORD dwFistListAddr;
if(NULL==(hwnd=FindWindow(NULL,"Spider")))
{
MessageBox(NULL,"你没有在玩蜘蛛纸牌吧?","Error",MB_OK|MB_ICONQUESTION);
return 0;
}
GetWindowThreadProcessId(hwnd,&dwProcessId);
if(NULL==(hProcess=OpenProcess(PROCESS_VM_READ,false,dwProcessId)))//打开进程
{
MessageBox(NULL,"OpenProcess Error!","Error",MB_OK);
return 0;
}
ReadProcessMemory(hProcess,(PVOID)(BASEADDR+0x04),&dwPaiAddr,4,NULL);
ReadProcessMemory(hProcess,(PVOID)(dwPaiAddr+0x0c),&dwPaiAddr,4,NULL);
if((!ReadProcessMemory(hProcess,(LPCVOID)dwPaiAddr,structPai,13*8*sizeof(Pai),
&dwReadedBytes))||(dwReadedBytes!=13*8*sizeof(Pai)))
{
MessageBox(NULL,"ReadProcess Pai Error!","Error",MB_OK);
return 0;
}
//读取链表数组首地址
ReadProcessMemory(hProcess,(PVOID)(BASEADDR+0x08),&dwFistListAddr,4,NULL);
if ((!ReadProcessMemory(hProcess,(PVOID)(dwFistListAddr),&dwListAddr,10*4,&dwReadedBytes))||(dwReadedBytes!=10*4))
{
MessageBox(NULL,"ReadProcess List Error!","Error",MB_OK);
return 0;
}
//测试打印牌
// for (int i = 0; i < 104;i++)
// {
// printf("%d/t%d/t%d/t/t",structPai.dwHua,structPai.dwPaiNo,structPai.dwOpenedOrNot);
//
// }
DWORD dwTemp;
ListEntry structListEntry;//节点
int j = 0;
for (int i = 0;i<10;i++)
{
printf("第%d列: ",i+1);
if (dwListAddr==NULL)
{
printf("/n");
continue;
}
//printf("%d/n",dwListAddr);
ReadProcessMemory(hProcess,(LPCVOID)dwListAddr,&dwTemp,4,NULL);
if (dwTemp==NULL)
{
printf("/n");
continue;
}
ReadProcessMemory(hProcess,(LPCVOID)dwTemp,&structListEntry,sizeof(ListEntry),NULL);
j++;
do
{
switch(structPai[structListEntry.dwPaiSeqNo].dwHua)
{
case 0:printf("梅");break;
case 1:printf("方");break;
case 2:printf("红");break;
case 3:printf("黑");break;
default:printf("unkown");break;
}
printf("%d ",structPai[structListEntry.dwPaiSeqNo].dwPaiNo+1);
if(structListEntry.next==NULL)
break;
ReadProcessMemory(hProcess,(LPCVOID)structListEntry.next ,&structListEntry,sizeof(ListEntry),NULL);
j++;
}while(true);
printf("/n");
}
getchar();
return 0;
}