您的位置:首页 > 编程语言 > C语言/C++

追逐自己的梦想----------辅助制作第九课:分析怪物列表及怪物属性的封装等

2015-01-11 14:13 531 查看
本节课中我们要对怪物列表以及怪物列表属性进行分析

首先我们选中一只怪,然后攻击怪物改变血量来找到怪物血量的地址,然后通过它找到怪物列表的基址

t通过ce中的跟随访问了这个地址的代码,得到如下地址

可能的基址316B6208

+5b4 怪物血量  

316B6200

+5bc 怪物血量

再将这两个地址在ce中搜索就可以得到他的基址

然后在OD中通过dd 来查看基址中的数据,再通过下硬件访问断点就可以得到如下的基址:

45fb98c

通过查看基址中的数据可以得到如下的分析:

dc [45fb98c + 4*0]+320 //名字

007F13EC    890C85 88B95F04 MOV DWORD PTR DS:[EAX*4+0x45FB988],ECX

dc [45fb988 + 4*7]+320

+314 是否活着  活着为1

+5B4  血量

+5b8 怪物等级

+1018 X

+1020 Y

+1024 X

+102c Y

//基址的内存单元代码

007F13DE    FFD0            CALL EAX

007F13E0    83F8 01         CMP EAX,0x1

007F13E3    7F 16           JG SHORT Client.007F13FB

007F13E5    A1 A8F21E03     MOV EAX,DWORD PTR DS:[0x31EF2A8]

007F13EA    8B0B            MOV ECX,DWORD PTR DS:[EBX]

007F13EC    890C85 88B95F04 MOV DWORD PTR DS:[EAX*4+0x45FB988],ECX //基址

007F13F3    40              INC EAX

007F13F4    A3 A8F21E03     MOV DWORD PTR DS:[0x31EF2A8],EAX

007F13F9    EB 14           JMP SHORT Client.007F140F

007F13FB    8B13            MOV EDX,DWORD PTR DS:[EBX]

007F13FD    8B4A 10         MOV ECX,DWORD PTR DS:[EDX+0x10]

007F1400    C1E1 04         SHL ECX,0x4

以上代码就完成了对怪物列表基址单元的分析,下面就是对怪物列表进行封装了

封装怪物列表
typedef struct FREAK
{
char* szpName; //怪物名称
BOOL IsDead; //是否活着
int  Hp;  //怪物血量
int level;//怪物等级
float X1; //x
float Y1;//y
float X2; //x
float Y2;//y

}_FREAK;

class FreakList :public BaseData{
public:
FreakList();
~FreakList();
DWORD GetFreakNameOffset();   //获取怪物名字
DWORD GetFreakIsDeadOffset();  //获取死亡状态
DWORD GetFreapHpOffset();     //获取怪物HP
DWORD GetFreakLevelOffset();  //获取怪物等级
DWORD GetFreakX1Offset();     //获取怪物的X坐标
DWORD GetFreakY1Offset();     //获取怪物的Y坐标
DWORD GetFreakX2Offset();     //获取怪物的X坐标
DWORD GetFreakY2Offset();	    //获取怪物的Y坐标

void PrintFreak();//调试怪物数组的数据

private:
const int MaxFreakNum = 20; //最大怪物数目
FREAK freak[20]; //怪物列表数组
DWORD nameOffset = 0x320;   //名字偏移
DWORD IsDeadOffset = 0x314; //死亡状态
DWORD HpOffset = 0x5b4;     //hp偏移
DWORD LevelOffset = 0x5b8;  //等级偏移
DWORD X1offset = 0x1018;    //X偏移
DWORD Y1offset = 0x1020;    //Y偏移
DWORD X2offset = 0x1024;    //X偏移
DWORD Y2offset = 0x102c;    //Y偏移
};


//怪物列表的构造函数
FreakList::FreakList(){
DWORD nObj = NULL;
memset(freak, 0, sizeof(FREAK)*20);

try{

for (int i = 0; i < MaxFreakNum; i++){
nObj = *(DWORD*)(this->GetBaseFreakAddr() + 4 * i);
//dc[45fb988 + 4 * 7] + 320
if (nObj != NULL){
freak[i].szpName = (char*)(nObj + 0x320);
freak[i].IsDead = *(int*)(nObj + 0x314);
freak[i].level =  *(DWORD*)(nObj + 0x5b8);
freak[i].Hp =	  *(DWORD*)(nObj + 0x5b4);
freak[i].X1 =     *(float*)(nObj + 0x1018);
freak[i].Y1 =     *(float*)(nObj + 0x1020);
freak[i].X2 =     *(float*)(nObj + 0x1024);
freak[i].Y2 =     *(float*)(nObj + 0x102c);
}
}

}
catch (...){

}

}

//怪物列表的析构函数
FreakList::~FreakList(){
memset(freak, 0, sizeof(FREAK)* 20);
}

//获取怪物名字
DWORD FreakList::GetFreakNameOffset(){
return nameOffset;
}

//获取死亡状态
DWORD FreakList::GetFreakIsDeadOffset(){
return IsDeadOffset;
}

//获取怪物HP
DWORD FreakList::GetFreapHpOffset(){
return HpOffset;

}

//获取怪物等级
DWORD FreakList::GetFreakLevelOffset(){

return LevelOffset;
}

//获取怪物的X坐标
DWORD FreakList::GetFreakX1Offset(){

return X1offset;
}

//获取怪物的Y坐标
DWORD FreakList::GetFreakY1Offset(){

return Y1offset;
}

//获取怪物的X坐标
DWORD FreakList::GetFreakX2Offset(){

return X2offset;
}

//获取怪物的Y坐标
DWORD FreakList::GetFreakY2Offset(){
return Y2offset;

}
//调试怪物数组的数据
void FreakList::PrintFreak(){

for (int i = 0; i < MaxFreakNum; i++){
//dc[45fb988 + 4 * 7] + 320
if (freak[i].level >0){
DbgPrint_String("怪物名字:%s ,死亡状态: %d ,怪物等级: %d ,怪物HP: %d ,X1 %f ,Y1 %f ,X2 %f ,Y2 %f",
freak[i].szpName, \
freak[i].IsDead, \
freak[i].level, \
freak[i].Hp, \
freak[i].X1, \
freak[i].Y1, \
freak[i].X2, \
freak[i].Y2
);
}
}
}

以上代码就完成了对怪物列表数据的分析和封装,最后只需要利用SendMessageA来发送消息到主线程就可以了

具体代码参见源码:辅助制作第九课源码下载地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ MFC 辅助
相关文章推荐