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

来源:互联网 发布:淘宝摄影服务招商 编辑:程序博客网 时间:2024/05/16 17:20

本节课中我们要对怪物列表以及怪物列表属性进行分析
首先我们选中一只怪,然后攻击怪物改变血量来找到怪物血量的地址,然后通过它找到怪物列表的基址
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; //xfloat Y1;//yfloat X2; //xfloat Y2;//y}_FREAK;class FreakList :public BaseData{public:FreakList();~FreakList();DWORD GetFreakNameOffset();   //获取怪物名字DWORD GetFreakIsDeadOffset();  //获取死亡状态DWORD GetFreapHpOffset();     //获取怪物HPDWORD 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] + 320if (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;}//获取怪物HPDWORD 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] + 320if (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来发送消息到主线程就可以了


具体代码参见源码:辅助制作第九课源码下载地址









0 0
原创粉丝点击