郁金香 中级班 0-12 分析怪物数组

郁金香中级班1-12

1.c++的类和对象

数据和函数的集合

2.类的基类和派生类(省)

 

3.读取utf8编码名字

利用别人的转码函数 ->找不到 无笔记

4.分析怪物名字偏移

寻找对应的怪物->寻找对应地址

 0053B8 | 8B4481 5C            | mov eax,dword ptr ds:[ecx+eax*4+0x5C]         | 名字获取
 eax=0
 ecx+0x5c 跟ecx
 0074F8 | 8BC8                 | mov ecx,eax                                   |
 eax+0x5c
 0074F8 | E8 51BEF2FF         | call wow.67B6A0     //大部分对象地址                       |
 0074F8 | 85C0                 | test eax,eax                                 |
 eax=23D30860
  [这个CALL返回值+5C] //怪物名字地址
  分析大部分地址call->
 
 0067B8 | 83C0 18             | add eax,0x18                                 |
 0067B8 | 5B                   | pop ebx                                       |
 0067B8 | 5D                   | pop ebp                                       |
 0067B8 | C2 1400             | ret 0x14                                     |
 eax+0x18+5c->
 0067B7 | 8BF8                 | mov edi,eax                                   |
 0067B7 | 2B7E 04             | sub edi,dword ptr ds:[esi+0x4]               |
 0067B7 | 03CF                 | add ecx,edi                                   |
 0067B7 | 8B7D 10             | mov edi,dword ptr ss:[ebp+0x10]               |
 0067B7 | 8931                 | mov dword ptr ds:[ecx],esi                   |
 0067B7 | 8B08                 | mov ecx,dword ptr ds:[eax]                   |
 0067B7 | 8B70 04             | mov esi,dword ptr ds:[eax+0x4]               |
 0067B7 | 8971 04             | mov dword ptr ds:[ecx+0x4],esi               |
 0067B7 | C700 00000000       | mov dword ptr ds:[eax],0x0                   |
 0067B7 | C740 04 00000000     | mov dword ptr ds:[eax+0x4],0x0               |
 0067B7 | 8B8B 90000000       | mov ecx,dword ptr ds:[ebx+0x90]               |
 0067B8 | 8908                 | mov dword ptr ds:[eax],ecx                   |
 0067B8 | 8B71 04             | mov esi,dword ptr ds:[ecx+0x4]               |
 0067B8 | 8970 04             | mov dword ptr ds:[eax+0x4],esi               |
 0067B8 | 8951 04             | mov dword ptr ds:[ecx+0x4],edx               |
 0067B8 | 8983 90000000       | mov dword ptr ds:[ebx+0x90],eax               |
 0067B8 | 8B45 0C             | mov eax,dword ptr ss:[ebp+0xC]               |
 0067B8 | 897A 08             | mov dword ptr ds:[edx+0x8],edi               |
 0067B8 | 8B08                 | mov ecx,dword ptr ds:[eax]                   |
 0067B8 | 894A 10             | mov dword ptr ds:[edx+0x10],ecx               |
 0067B8 | 8B40 04             | mov eax,dword ptr ds:[eax+0x4]               |
 0067B8 | 8B4D 14             | mov ecx,dword ptr ss:[ebp+0x14]               |
 0067B8 | 8942 14             | mov dword ptr ds:[edx+0x14],eax               |
 0067B8 | 894A 18             | mov dword ptr ds:[edx+0x18],ecx               |
 
 一大堆偏移来获取eax

对象获取

 0072A2 | 8BB6 64090000        | mov esi,dword ptr ds:[esi+0x964]              |
 0072A2 | 85F6                 | test esi,esi                                 |
 0072A2 | 74 CE               | je wow.72A24D                                 |
 0072A2 | 8B46 5C             | mov eax,dword ptr ds:[esi+0x5C]               |
 0072A2 | 5F                   | pop edi                                       |
 偏移
 esi+5c+964
 分析esi是什么
 3011EC70 00A34D90 .M£.
 ->虚函数表00A34D90 00737BA0  {s.
 00A34D94 00734FD0 ÐOs.
 00A34D98 007237F0 ð7r.
 00A34D9C 007402B0 °.t.
 00A34DA0 00632050 P c.
 00A34DA4 007370D0 Ðps.
 //故此esi是对象
 
 3011EC74 00000000 ....
 3011EC78 3011FC78 xü.0
 3011EC7C 3011FEC8 Èþ.0 L"E"
 
5.虚函数指针 虚函数表

自行查看滴水c++逆向分析

6.用ce和xdbg分析对象数组

从以前对象的分析开始

 [[30AEF8E0+964]+5c]
 004D4DE3    | 52                   | push edx                                      |
 0444FB14 00000008 ....
 0444FB18 00000000 ....  一块空间
     
 004D4DE4    | 50                   | push eax                                      |0x8
 004D4DE5    | 8945 F8              | mov dword ptr ss:[ebp-0x8],eax                |
 004D4DE8    | E8 C3FDFFFF          | call wow.4D4BB0                               | 返回对象//存粹的
     
 004D4DED    | 85C0                 | test eax,eax  
     
 004D4BB0    | 55                   | push ebp                                      |
 004D4BB1    | 8BEC                 | mov ebp,esp                                   |
 004D4BB3    | 8B41 24              | mov eax,dword ptr ds:[ecx+0x24]               | 获取ecx+24偏移是这个数组的大小吗
 004D4BB6    | 83F8 FF              | cmp eax,0xFFFFFFFF                            | 越界直接返回
 004D4BB9    | 75 06                | jne wow.4D4BC1                                |
 004D4BBB    | 33C0                 | xor eax,eax                                   |
 004D4BBD    | 5D                   | pop ebp                                       |
 004D4BBE    | C2 0800              | ret 0x8                                       | 未知返回
 004D4BC1    | 8B51 1C              | mov edx,dword ptr ds:[ecx+0x1C]               |
 004D4BC4    | 56                   | push esi                                      |
 004D4BC5    | 8B75 08              | mov esi,dword ptr ss:[ebp+0x8]                |
 004D4BC8    | 23C6                 | and eax,esi                                   |
 004D4BCA    | 8D0440               | lea eax,dword ptr ds:[eax+eax*2]              | 3*eax
 004D4BCD    | 8D4482 04            | lea eax,dword ptr ds:[edx+eax*4+0x4]          | edx+12*eax+0x4//找ecx
 004D4BD1    | 8B40 04              | mov eax,dword ptr ds:[eax+0x4]                | edx+12*eax+0x8=edx+C*eax+0x8
 004D4BD4    | A8 01                | test al,0x1                                   |
     完成了怪物对象的返回
 //ecx来源->
     004D4DB1    | 8BEC                 | mov ebp,esp                                   |
 004D4DB3    | 64:8B0D 2C000000     | mov ecx,dword ptr fs:[0x2C]                   |
 004D4DBF    | 8B1481               | mov edx,dword ptr ds:[ecx+eax*4]              |
 004D4DC2    | 8B8A 08000000        | mov ecx,dword ptr ds:[edx+0x8]                |
     
     ----
     004D4BC1    | 8B51 1C              | mov edx,dword ptr ds:[ecx+0x1C]               |
     
        [[[fs:[2C]+0]+8]+1C]=//基础值
  004D4BC4    | 56                   | push esi                                      |
 004D4BC5    | 8B75 08              | mov esi,dword ptr ss:[ebp+0x8]                |
 004D4BC8    | 23C6                 | and eax,esi                                   |
 004D4BCA    | 8D0440               | lea eax,dword ptr ds:[eax+eax*2]              | 3*eax
 004D4BCD    | 8D4482 04            | lea eax,dword ptr ds:[edx+eax*4+0x4]          | edx+12*eax+0x4
 004D4BD1    | 8B40 04              | mov eax,dword ptr ds:[eax+0x4]                | edx+12*eax+0x8=edx+C*eax+0x8
         // [[[fs:[2C]+0]+8]+1C]=1c->23d4dd88//固定算式
 //23d4dd88+C*eax(eax==2)+0x8
 
        [[[23D4DD88+2*0C+8]+964]+5C]->怪物值
7.链表分析

链表在内存中的形式

 #include<stdio.h>
 #include<malloc.h>
 #include<stdlib.h>
 
 typedef int ElementType;        //   定义数据类型,可根据需要进行其他类型定义
 //class //   链表节点的定义
 typedef struct ListNode {
  ElementType  Element;        //   数据域,存放数据
  int data1;
  int data2;
  ListNode* Next;        // 链表指针   指向下一个链表节点
  float x, y, z;
 }Node, * PNode;
 
 //   链表创建函数定义
 PNode CreateList(void) {
  int len;    //   用于定义链表长度
  int val;    //   用于存放节点数值
  PNode PHead = (PNode)malloc(sizeof(Node));    //   创建分配一个头节点内存空间//头节点相当于链表的哨兵,不存放数据,指向首节点(第一个节点)
  if (PHead == NULL)    //   判断是否分配成功
  {
  printf("空间分配失败 \n");
  exit(-1);
  }
 
  PNode PTail = PHead;    //   链表的末尾节点,初始指向头节点
  PTail->Next = NULL;    //   最后一个节点指针置为空
  printf("请输入节点个数:");
  scanf_s("%d", &len);        //   输入节点个数
  for (int i = 0; i < len; i++) {
 
  PNode pNew = (PNode)malloc(sizeof(Node));    //   分配一个新节点
  if (pNew == NULL) {
  printf("分配新节点失败\n");
  exit(-1);
  }
  printf("请输入第 %d 个节点的数据:", i + 1);
  scanf_s("%d", &val);    //   输入链表节点的数据
 
  pNew->Element = val;    //   把数据赋值给节点数据域
  PTail->Next = pNew;    //   末尾节点指针指向下一个新节点
  pNew->Next = NULL;        //   新节点指针指向为空
  PTail = pNew;    //   将新节点复制给末尾节点        
  }
  printf("创建链表成功\n");
  return PHead;    //   返回头节点
 }
 
 //   主函数
 int main() {
  PNode List = CreateList();    //创建一个指针,使其指向新创建的链表的头指针  
  printf("List链表头=%p\n", List);
 
  getchar();
  MessageBeep(1);
  return 0;
 }
 

List链表头=004D9D18

画图方式

无标题

8.分析链表
 对象
      [[[fs:[2C]+0]+8]+1C]=数组地址=30b12c68 1c数组最大值
 
      [30b12c68+2*0C+8] ->怪物对象地址
 
 [[[30b12c68+2*0C+8]+964]+5C] 染病的狼
 
 [[[30b12c68+0*0C+8]+964]+5C] 染病的狼
 
 [[[30b12c68+1a*0C+8]+964]+5C] 无名
 [[[30b12c68+1e*0C+8]+964]+5C] 杜锡拉
 
 基础对象
 
 [30b12c68+1e*0C+8]->31400F50->迪菲亚暴徒
 [30b12c68+1a*0C+8]->30B12DA5
 3141F6D0
 
 [30b12c68+0*0C+8] 染病的狼 ->3141F6D0->染病的有狼
 [30b12c68+2*0C+8]染病的狼 ->31414000 ->治安官
 
 
 004D4DAF    | CC                   | int3                                          |
 004D4DB0    | 55                   | push ebp                                      | 各种call
 004D4DB1    | 8BEC                 | mov ebp,esp                                   |
 004D4DB3    | 64:8B0D 2C000000     | mov ecx,dword ptr fs:[0x2C]                   |
 004D4DBA    | A1 BC39D400          | mov eax,dword ptr ds:[0xD439BC]               |
 004D4DBF    | 8B1481               | mov edx,dword ptr ds:[ecx+eax*4]              |
 004D4DC2    | 8B8A 08000000        | mov ecx,dword ptr ds:[edx+0x8]                |
 004D4DC8    | 83EC 08              | sub esp,0x8                                   |
 004D4DCB    | 85C9                 | test ecx,ecx                                  |
 
 
 
 
 004D4BB0    | 55                   | push ebp                                      |
 004D4BB1    | 8BEC                 | mov ebp,esp                                   |
 004D4BB3    | 8B41 24              | mov eax,dword ptr ds:[ecx+0x24]               | 获取ecx+24偏移是这个数组的大小吗
 004D4BB6    | 83F8 FF              | cmp eax,0xFFFFFFFF                            | 越界直接返回
 004D4BB9    | 75 06                | jne wow.4D4BC1                                |
 004D4BBB    | 33C0                 | xor eax,eax                                   |
 004D4BBD    | 5D                   | pop ebp                                       |
 004D4BBE    | C2 0800              | ret 0x8                                       | 未知返回
 004D4BC1    | 8B51 1C              | mov edx,dword ptr ds:[ecx+0x1C]               | edx0->数组基地
 004D4BC4    | 56                   | push esi                                      |
 004D4BC5    | 8B75 08              | mov esi,dword ptr ss:[ebp+0x8]                |
 004D4BC8    | 23C6                 | and eax,esi                                   |
 004D4BCA    | 8D0440               | lea eax,dword ptr ds:[eax+eax*2]              | 3*eax
 004D4BCD    | 8D4482 04            | lea eax,dword ptr ds:[edx+eax*4+0x4]          | edx+12*eax+0x4
 004D4BD1    | 8B40 04              | mov eax,dword ptr ds:[eax+0x4]                | 基地址+c*eax=8 ->怪物对象数组
 004D4BD4    | A8 01                | test al,0x1                                   | al 0 与低位与与运算 ZF=1  不相等 ZF=1 JNE 不跳转
 004D4BD6    | 75 04                | jne wow.4D4BDC                                |
 004D4BD8    | 85C0                 | test eax,eax                                  | 一定相等 或者eax-0 大概率跳转
 004D4BDA    | 75 02                | jne wow.4D4BDE                                |
 004D4BDC    | 33C0                 | xor eax,eax                                   | 清空eax 
004D4BDE    | 57                   | push edi                                      
004D4BDF    | 8B7D 0C              | mov edi,dword ptr ss:[ebp+0xC]                
004D4BE2    | 53                   | push ebx                                      
004D4BE3    | A8 01                | test al,0x1                                   | 循环开始  偶数 末尾为0->1 不相等  ZF=1 不跳转 
004D4BE5    | 75 2F                | jne wow.4D4C16                                | 奇数跳转 不存在链表  
004D4BE7    | 85C0                 | test eax,eax                                  | eax=0 跳出循环 
004D4BE9    | 74 2B                | je wow.4D4C16                                
004D4BEB    | 3970 18              | cmp dword ptr ds:[eax+0x18],esi               | 参数1 和对象+0x18 比较 相等ZF=
004D4BEE    | 75 0F                | jne wow.4D4BFF                                | 跳转 ZF=
004D4BF0    | 8B50 30              | mov edx,dword ptr ds:[eax+0x30]              
004D4BF3    | 3B17                 | cmp edx,dword ptr ds:[edi]                    | 对象+30 与edx 比较 相等不跳转 
004D4BF5    | 75 08                | jne wow.4D4BFF                                | 链表偏移 
004D4BF7    | 8B50 34              | mov edx,dword ptr ds:[eax+0x34]              
004D4BFA    | 3B57 04              | cmp edx,dword ptr ds:[edi+0x4]                | 对象_+34 edi+4 比较  相等 ZF=
004D4BFD    | 74 19                | je wow.4D4C18                                 | ZF=1 跳转  直接返回怪物对象 
004D4BFF    | 8B59 1C              | mov ebx,dword ptr ds:[ecx+0x1C]               | 大计算->链表next指针偏移 
004D4C02    | 8BD6                 | mov edx,esi                                   | eax+30 +35 ==edi edi+4 都相等 ->返回怪物对象 
004D4C04    | 2351 24              | and edx,dword ptr ds:[ecx+0x24]               | edx->参数1 1f 与运算 
004D4C07    | 8D1452               | lea edx,dword ptr ds:[edx+edx*2]              | edx=edx*
004D4C0A    | 8D1493               | lea edx,dword ptr ds:[ebx+edx*4]              | ebx+edx*3*
004D4C0D    | 8B12                 | mov edx,dword ptr ds:[edx]                    | ebx+edx*c=1c 
004D4C0F    | 03D0                 | add edx,eax                                   | 1c+对象 
004D4C11    | 8B42 04              | mov eax,dword ptr ds:[edx+0x4]                | 对象+1c+0x4=对象+0x20 
004D4C14    | EB CD                | jmp wow.4D4BE3                                
004D4C16    | 33C0                 | xor eax,eax                                   | 清空eax
9 10 11 .代码遍历怪物
 // my.cpp: 实现文件
 //
 
 #include "pch.h"
 #include "g怪物对象偏移.h"
 #include "my.h"
 #include "afxdialogex.h"
 
 
 // my 对话框
 
 IMPLEMENT_DYNAMIC(my, CDialog)
 
 my::my(CWnd* pParent /*=nullptr*/)
  : CDialog(IDD_DIALOG1, pParent)
 {
 
 }
 
 my::~my()
 {
 }
 
 void my::DoDataExchange(CDataExchange* pDX)
 {
  CDialog::DoDataExchange(pDX);
 }
 
 
 BEGIN_MESSAGE_MAP(my, CDialog)
  ON_BN_CLICKED(IDC_BUTTON1, &my::OnBnClickedButton1)
  ON_BN_CLICKED(IDC_BUTTON2, &my::OnBnClickedButton2)
  ON_BN_CLICKED(IDC_BUTTON3, &my::OnBnClickedButton3)
 END_MESSAGE_MAP()
 
 
 // my 消息处理程序
 
 
 void my::OnBnClickedButton1()
 {
  // TODO: 在此添加控件通知处理程序代码
  AllocConsole();
  FILE* pfile = NULL;
  //重定向到标准输出
  errno_t iret = freopen_s(&pfile, "CONOUT$", "w", stdout); //printf输出重定向到控制台
  // TODO: 在此添加控件通知处理程序代码
 }
 
 
 void my::OnBnClickedButton2()
 {
  FreeConsole();//关闭控制台
  // TODO: 在此添加控件通知处理程序代码
 }
 DWORD R4(UINT_PTR 地址)
 {
  __try
  {
  return *(DWORD*)地址;//ReadProcessMemory
  }
  __except (1)
  {
  return 0;
  }
 }
 
 UINT_PTR 怪物数组地址()
 {
  //[[[fs:[2C] + 0]+ 8] + 1C] = 数组地址 = 30b12c68 1c数组最大值
  //卡主线程
  DWORD fs2c = 0;
  __asm
  {
  mov eax,dword ptr fs:[0x2c]
  mov fs2c,eax
  }
  //读取怪物数组地址
  DWORD 数组地址 = R4(R4(R4(fs2c + 0) + 8) + 0x1c);
  return 数组地址;
 }
 
 UINT_PTR 怪物数组数量()
 {
  //[[[fs:[2C] + 0]+ 8] + 1C] = 数组地址 = 30b12c68 1c数组最大值
  //卡主线程
  DWORD fs2c = 0;
  __asm
  {
  mov eax, dword ptr fs : [0x2c]
  mov fs2c, eax
  }
  //读取怪物数组地址
  DWORD 数量 = R4(R4(R4(fs2c + 0) + 8) + 0x24);
  return 数量;
 }
 
 //怪物对象地址
 ///[30b12c68+2*0C+8] ->怪物对象地址
 UINT_PTR 怪物对象地址(int 下标)
 {
  DWORD 数组地址 = 怪物数组地址();
  return R4(数组地址 + 下标 * 0xc+0x8);
 }
 
 //打印怪物对象
 #include"AsciiUnicodeUtf8.h"
 void day1(UINT_PTR ptr)
 {
  UINT_PTR 虚表 = R4(ptr + 0);
  if (虚表 == 0)
  {
  return;
  }
  UINT_PTR id1 = R4(ptr+0x30);
  UINT_PTR id2 = R4(ptr + 0x34);
  //[[对象 964] + 5C]
  char* name = (char*)R4(R4(ptr + 0x964) + 0x5c);
  if (name == NULL)
  {
 
  return;
  }
  char 多字节怪物名字[256] = { 0 };
  utf8ToAscii(name, 多字节怪物名字);
  printf("有名字对象 虚表:%x id1 ;%x id2 %x name:%s\n", 虚表, id1, id2, 多字节怪物名字);
 
 }
 void day2(UINT_PTR ptr)
 {
  UINT_PTR 虚表 = R4(ptr + 0);
  if (虚表 == 0)
  {
  return;
  }
  UINT_PTR id1 = R4(ptr + 0x30);
  UINT_PTR id2 = R4(ptr + 0x34);
  //[[对象 964] + 5C]
  char* name = (char*)R4(R4(ptr + 0x964) + 0x5c);
  if (name == NULL)
  {
 
  return;
 
char 多字节怪物名字[256] = { 0 }; 
utf8ToAscii(name, 多字节怪物名字); 
printf("链表内 虚表:%x id1 ;%x id2 %x name:%s\n", 虚表, id1, id2, 多字节怪物名字); 
​ 

void 链表(UINT_PTR ptr) 

//对象地址+20->链表->姓名 偶数采用信息 
 
BOOL 偶数判断 = (ptr % 2 == 0); 
   UINT_PTR 链表指向 = R4(ptr + 0x20); 
​ 
while (链表指向 && 偶数判断) 

day2(链表指向); 
链表指向 = R4(链表指向 + 0x20); 
偶数判断 = 链表指向 % 2 == 0; 

return; 

void 遍历对象数组() 

int 数量 = 怪物数组数量(); 
printf("遍历对象数组 数量=%d\n", 数量); 
for (int i = 0; i < 数量; i++) 

UINT_PTR GS = 怪物对象地址(i); 
day1(GS); 
链表(GS); 

​ 

VOID CALLBACK zhuxian(HWND h, UINT arg2, UINT_PTR arg3_id, DWORD time) 

KillTimer(h, 10086); 
printf("进入主线程\n"); 
遍历对象数组(); 
​ 

​ 
​ 
void my::OnBnClickedButton3() 

​ 
​ 
HWND 游戏窗口句柄 = FindWindowA("GxWindowClassD3d", "魔兽世界"); 
::SetTimer(游戏窗口句柄, 10086, 1, zhuxian); 
​ 
​ 
// TODO: 在此添加控件通知处理程序代码 

 
12.分析快捷栏数组

打开技能书

格子有数据 非0

以此查找 四字节对齐

十六进制->对象指针 技能ID->访问断点查看

 005AC05A    | 8D4D F8              | lea ecx,dword ptr ss:[ebp-0x8]                |
 005AC05D    | 51                   | push ecx                                      |///参数1
 005AC05E    | 56                   | push esi                                      |///下标格子
 005AC05F    | E8 5CFBFFFF          | call wow.5ABBC0                               |
 005AC064    | 83C4 18              | add esp,0x18                                  |




posted @ 2023-06-08 15:38  大橘|博客  阅读(53)  评论(0)    收藏  举报