当前位置:   article > 正文

47.网络游戏逆向分析与漏洞攻防-角色管理功能通信分析-设计发送数据通用的编码方案_0x33逆向分析

0x33逆向分析

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

如果看不懂、不知道现在做的什么,那就跟着做完看效果

内容参考于:易道云信息技术研究院VIP课

上一个内容:46.设计通用的解码处理过程

码云地址(master 分支):https://gitee.com/dye_your_fingers/titan

码云版本号:e7b59fe6a41bb2cf79502a3b4802af86536d2f89

代码下载地址,在 titan 目录下,文件名为:titan-设计发送数据通用的编码方案.zip

链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg

提取码:q9n5

--来自百度网盘超级会员V4的分享

HOOK引擎,文件名为:黑兔sdk升级版.zip

链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw

提取码:78h8

--来自百度网盘超级会员V4的分享

以 46.设计通用的解码处理过程 它的代码为基础进行修改

在游戏里面发现发送的数据很多都是0A开头的,也比较有规律(详情看44.角色创建服务器反馈数据包分析),里面有数据参数个数和数据参数,现在读取已经是没问题了,然后接下来肯定要有模拟发送的操作,所以现在就是设计数据模拟发送通用的方案,不能每个数据包都去分别实现一遍,这样不专业,代码写起来工程量很大也麻烦,所以要设计一个比较好的综合性的通用的方案。

效果图:

通过点击 Button1按钮,在角色选择界面,非创建角色界面,发送选择阵营数据包

CUIWnd_0.cpp文件的修改:修改了 OnBnClickedButton1函数,OnBnClickedButton1函数是Button1按钮点击事件处理函数

  1. // CUIWnd_0.cpp: 实现文件
  2. //
  3. #include "pch.h"
  4. #include "htdMfcDll.h"
  5. #include "CUIWnd_0.h"
  6. #include "afxdialogex.h"
  7. #include "extern_all.h"
  8. // CUIWnd_0 对话框
  9. IMPLEMENT_DYNAMIC(CUIWnd_0, CDialogEx)
  10. CUIWnd_0::CUIWnd_0(CWnd* pParent /*=nullptr*/)
  11. : CDialogEx(IDD_PAGE_0, pParent)
  12. {
  13. }
  14. CUIWnd_0::~CUIWnd_0()
  15. {
  16. }
  17. void CUIWnd_0::DoDataExchange(CDataExchange* pDX)
  18. {
  19. CDialogEx::DoDataExchange(pDX);
  20. }
  21. BEGIN_MESSAGE_MAP(CUIWnd_0, CDialogEx)
  22. ON_BN_CLICKED(IDC_BUTTON1, &CUIWnd_0::OnBnClickedButton1)
  23. END_MESSAGE_MAP()
  24. // CUIWnd_0 消息处理程序
  25. void CUIWnd_0::OnBnClickedButton1()
  26. {
  27. Client->SelectCamp("xuanrenZQ");
  28. //Client->StartCreateRole();
  29. //Client->DelRole(L"ranzhi11111");
  30. /*
  31. char buff[] = {
  32. 0xA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  33. 0x00, 0x00, 0x00, 0x00, 0x00, 0x4, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 00 ,0x00,
  34. 0x00, 0x07, 0x0E, 0x00, 0x00, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x31, 0x00, 0x32 ,0x00,
  35. 0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  36. };
  37. WinSock->OnSend(buff, sizeof(buff));
  38. */
  39. /*char buff[] = {
  40. 0x27, 0x46, 0x92, 0x02, 0x00, 0x00, 0x89, 0x02, 0x00, 0x00, 0x06, 0x00, 0x06, 0x05,
  41. 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x74, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x07,
  42. 0x0A, 0x00, 0x00, 0x00, 0x34, 0x00, 0x33, 0x00, 0x39, 0x00, 0x39, 0x00, 0x00, 0x00,
  43. 0x07, 0x5A, 0x02, 0x00, 0x00, 0x31, 0x00, 0x32, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  44. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  45. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  46. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  47. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  48. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  49. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  50. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  51. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31,
  52. 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
  53. 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
  54. 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
  55. 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
  56. 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32,
  57. 0x00, 0x32, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
  58. 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
  59. 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
  60. 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
  61. 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
  62. 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33,
  63. 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x35,
  64. 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
  65. 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
  66. 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
  67. 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
  68. 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35,
  69. 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x34,
  70. 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
  71. 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
  72. 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
  73. 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
  74. 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34,
  75. 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36,
  76. 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36,
  77. 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36,
  78. 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, 0x37,
  79. 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00, 0x37, 0x00,
  80. 0x38, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
  81. };
  82. WinSock->OnRecv(buff, sizeof(buff));*/
  83. }

NetClient.cpp文件的修改:修改了 SelectCamp函数、Tips函数

  1. #include "pch.h"
  2. #include "NetClient.h"
  3. #include "extern_all.h"
  4. bool NetClient::login(const char* Id, const char* Pass)
  5. {
  6. const int bufflen = sizeof(DATA_LOGIN) + 1;
  7. char buff[bufflen];
  8. DATA_LOGIN data;
  9. // 有些操作系统这样写会报错,因为内存不对齐,现在Windows下没事
  10. //PDATALOGIN _data = (PDATALOGIN)(buff + 1);
  11. // 这样写就能解决内存对齐问题
  12. PDATALOGIN _data =&data;
  13. int len = strlen(Id);
  14. memcpy(_data->Id, Id, len);
  15. len = strlen(Pass);
  16. memcpy(_data->Pass, Pass, len);
  17. memcpy(buff+1, _data, sizeof(DATA_LOGIN));
  18. buff[0] = I_LOGIN;
  19. return WinSock->OnSend(buff, sizeof(buff));
  20. }
  21. bool NetClient::DelRole(wchar_t* rolename)
  22. {
  23. PROLEDATA _role = GetRoleByName(rolename);
  24. if (_role == nullptr) {
  25. return false;
  26. }
  27. else {
  28. return DelRole(rolename, _role->name.lenth);
  29. }
  30. return false;
  31. }
  32. bool NetClient::StartCreateRole()
  33. {
  34. NET_CREATEROLE_START _data;
  35. return WinSock->OnSend(&_data.op, _data.len);
  36. }
  37. bool NetClient::SelectCamp(const char* _campname)
  38. {
  39. NET_SEND_BUFF _buff;
  40. NET_SEND_CHOOSECAMP _data;
  41. _data.opcode.Set(SC_CHOOSECAMP);
  42. _data.camps.Set(_campname);
  43. /*
  44. sizeof(_data) / sizeof(EnCode)的原因
  45. NET_SEND_CHOOSECAMP结构体里面,没别 东西
  46. 全是 EnCode 这个结构
  47. */
  48. short count = sizeof(_data) / sizeof(EnCode);
  49. _buff.count = count;
  50. /*
  51. CodeMe函数给 _buff.buff里写数据参数的数据
  52. 也就是给0A开头数据包里写,数据参数个数后面的内容
  53. 然后返回值是写了多长的数据
  54. 也就是给0A开头数据包里的数据参数个数后面的数据写了多长
  55. */
  56. int ilen = _data.CodeMe(count, _buff.buff);
  57. ilen = ilen + sizeof(NET_SEND_HEAD) - 1;
  58. return WinSock->OnSend(&_buff.op, ilen);
  59. }
  60. PROLEDATA NetClient::GetRoleByName(wchar_t* rolename)
  61. {
  62. //PROLEDATA result = nullptr;
  63. for (int i = 0; i < rolecount; i++)
  64. {
  65. // StrCmpW判断两个字符串是否相同
  66. // 比较时区分大小写,如果字符串相同返回0
  67. if (StrCmpW(roles[i].name.value(), rolename) == 0) {
  68. return &roles[i];
  69. }
  70. }
  71. return nullptr;
  72. }
  73. bool NetClient::DelRole(wchar_t* rolename, unsigned _len)
  74. {
  75. DATA_DELROLE _data;
  76. _data.op = 0x06;
  77. _data.len = _len;
  78. memcpy(_data.buff, rolename, _len);
  79. return WinSock->OnSend((char*)&_data, sizeof(DATA_DELROLE) - 1);
  80. }
  81. bool NetClient::OnDelRole(wchar_t* rolename, unsigned _len)
  82. {
  83. AfxMessageBox(rolename);
  84. return true;
  85. }
  86. void NetClient::Onlogin(const char* Id, const char* Pass)
  87. {
  88. /*
  89. const int bufflen = sizeof(DATA_LOGIN) + 1;
  90. char buff[bufflen];
  91. DATA_LOGIN data;
  92. // 有些操作系统这样写会报错,因为内存不对齐,现在Windows下没事
  93. //PDATALOGIN _data = (PDATALOGIN)(buff + 1);
  94. // 这样写就能解决内存对齐问题
  95. PDATALOGIN _data =&data;
  96. int len = strlen(Id);
  97. memcpy(_data->Id, Id, len);
  98. len = strlen(Pass);
  99. memcpy(_data->Pass, Pass, len);
  100. memcpy(buff+1, _data, sizeof(DATA_LOGIN));
  101. buff[0] = I_LOGIN;
  102. return WinSock->OnSend(buff, sizeof(buff));
  103. */
  104. }
  105. bool NetClient::OnStartCreateRole(int code)
  106. {
  107. return true;
  108. }
  109. bool NetClient::OnSendCustom(PNET_SEND_CHEAD _coder, char*& buffer, unsigned& len)
  110. {
  111. switch (_coder->opcode.value())
  112. {
  113. case SC_CHOOSECAMP:
  114. return OnChooseCamp((PNS_CHOOSECAMP)_coder);
  115. break;
  116. default:
  117. break;
  118. }
  119. return true;
  120. }
  121. bool NetClient::OnChooseCamp(PNS_CHOOSECAMP _coder)
  122. {
  123. PNS_CHOOSECAMP _p = (PNS_CHOOSECAMP)_coder;
  124. MessageBoxA(0, _p->camps, _p->camps, MB_OK);
  125. return true;
  126. }
  127. bool NetClient::Tips(int code)
  128. {
  129. #ifdef Anly
  130. CString txt;
  131. if (code == 51001) {
  132. txt = L"登陆失败,易道云通行证不存在!";
  133. }else if (code == 51002) {
  134. txt = L"登录失败,密码错误!";
  135. }
  136. else {
  137. txt.Format(L"未知登录错误:%d", code);
  138. }
  139. anly->SendData(TTYPE::I_LOG, 0, txt.GetBuffer(), (txt.GetLength() + 1)*2);
  140. #endif
  141. return true;
  142. }
  143. void NetClient::loginok(ROLE_DATA* _roles, int count)
  144. {
  145. logined = true;
  146. if(roles) delete[] roles;
  147. roles = _roles;
  148. rolecount = count;
  149. }
  150. bool NetClient::OnScrStartCreateRole(short code, wchar_t* _txt)
  151. {
  152. return true;
  153. }

NetClient.h文件的修改:新加 CAMP_NAME_QH宏、CAMP_NAME_ZE宏

  1. #pragma once
  2. #include "NetClass.h"
  3. #define CAMP_NAME_QH "xuanrenQH"
  4. #define CAMP_NAME_ZE "xuanrenZQ"
  5. class NetClient // 监视客户端每一个操作
  6. {
  7. private:
  8. PROLEDATA roles;
  9. unsigned rolecount;
  10. bool logined = false;
  11. bool DelRole(wchar_t* rolename, unsigned _len);
  12. public:
  13. /*
  14. 模拟登陆的方法
  15. Id是账号
  16. Pass是密码
  17. 它要基于发送的方法实现,因为我们没有连接socket的操作
  18. */
  19. bool login(const char* Id, const char* Pass);
  20. bool DelRole(wchar_t* rolename);
  21. bool StartCreateRole();// 用于创建角色
  22. bool SelectCamp(const char* _campname);// 选择阵营
  23. // 根据角色名字获取一个登录成功数据包(选择角色列表里的一个数据)
  24. PROLEDATA GetRoleByName(wchar_t* rolename);
  25. public:
  26. // 用于拦截游戏删除角色功能
  27. bool virtual OnDelRole(wchar_t* rolename, unsigned _len);
  28. // 用于拦截游戏登录功能
  29. void virtual Onlogin(const char* Id, const char*Pass);
  30. // 用于拦截游戏创建角色功能
  31. bool virtual OnStartCreateRole(int code);
  32. // opcode意思是操作码,count意思是数量,buffStart意思是解码的内容开始,buffend意思是解码的内容结束,buffer是原始的数据,len是原始数据的长度
  33. // char& buffer, int& len这俩参数带&的原因是,在 OnSendCustom 里进行修改之后,通过&的方式传递回去
  34. bool virtual OnSendCustom(PNET_SEND_CHEAD _coder, char*& buffer, unsigned& len);
  35. public:
  36. bool virtual OnChooseCamp(PNS_CHOOSECAMP _coder);
  37. public:
  38. // 处理失败,参数是错误码
  39. bool virtual Tips(int code);
  40. void virtual loginok(ROLE_DATA* _roles, int count);
  41. bool virtual OnScrStartCreateRole(short code,wchar_t* _txt);
  42. };

NetClass.cpp文件的修改:修改了 CodeMe函数

  1. #include "pch.h"
  2. #include "NetClass.h"
  3. #include "extern_all.h"
  4. unsigned NET_SEND_CHEAD::CodeMe(int size, char* buffer)
  5. {
  6. EnCode* _coders = (EnCode*)this;
  7. unsigned iResult = 0;
  8. unsigned ilenth;
  9. for (int i = 0; i < size; i++)
  10. {
  11. ilenth = data_desc[_coders[i].index][_coders[i].op].lenth + 1;
  12. memcpy(buffer + iResult, &_coders[i].op, ilenth);
  13. iResult += ilenth;
  14. if ((_coders[i].op == 0x07)||((_coders[i].op == 0x06) && ((_coders[i].index == 1)))) {
  15. ilenth = _coders[i].lenth;
  16. memcpy(buffer + iResult, _coders[i].pointer, ilenth);
  17. iResult += ilenth;
  18. }
  19. }
  20. return iResult;
  21. }

NetClass.h文件的修改:新加 NET_SEND_BUFF结构体,修改了 NET_SEND_CHEAD结构体

  1. #pragma once
  2. #include "EnCode.h"
  3. /*
  4. 最多的数据项, 0A开头的数据包里有数据参数个数,这个宏就是用来设定
  5. 数据参数个数最大数量是多少,0A开头的数据包目前见过最大
  6. 数据参数个数是十几个,这里写20应该完全够用,如果不够用
  7. 到时候再增加
  8. */
  9. #define MAX_SEND_COUNT 20
  10. // 发送数据操作码定义
  11. #define SC_CHOOSECAMP 591 // 阵营选择操作码
  12. // 发送数据标准头
  13. typedef struct NET_SEND_HEAD {
  14. // 为了内存对齐,当前结构不可能超过255,所以这样写是没问题的
  15. char len = sizeof(NET_SEND_HEAD) - 1;
  16. char op = 0x0A;
  17. short unst = 0;
  18. int unnt[4]{};
  19. short unst1 = 0;
  20. short count = 0;
  21. }*PNET_SEND_HEAD;
  22. // 发送数据包含内存空间,也就是数据参数,数据参数的意思看44文章里的内容
  23. typedef struct NET_SEND_BUFF:public NET_SEND_HEAD {
  24. char buff[0x1000]{};
  25. }*PNET_SEND_BUFF;
  26. typedef class NET_SEND_CHEAD {
  27. public:
  28. GINT opcode;
  29. // 实现编码操作,模拟游戏数据包给服务端发送数据,这个模拟的数据包通过调用 CodeMe函数得到
  30. unsigned CodeMe(int size, char* buffer);
  31. }*PNET_SEND_CHEAD;
  32. typedef class NET_SEND_CHOOSECAMP :public NET_SEND_CHEAD {
  33. public:
  34. GCHAR camps;
  35. }*PNS_CHOOSECAMP;
  36. // 申请创建角色结构体
  37. typedef struct NET_CREATEROLE_START {
  38. char un[0x02];// 用来做内存对齐
  39. char len = sizeof(NET_CREATEROLE_START) - 3;// 用来做内存对齐
  40. char op = 0x03;
  41. int code = 0x01;
  42. }*PNET_CREATEROLE_START;
  43. // 删除角色数据结构
  44. typedef struct DATA_DELROLE {
  45. char op;
  46. char buff[0x1F];
  47. int len;
  48. int un[8] = { 0x01 , 0x03};
  49. }*PDATADELROLE;
  50. /*
  51. 数据包还原结构体要注意内存对齐,如果数据不满4字节,它字段会补齐
  52. 比如结构体里有一个char变量,它是1字节,在内存里它可能会为了内存对齐
  53. 让它变成4字节,所以这要注意
  54. */
  55. // 登录数据
  56. typedef struct DATA_LOGIN {
  57. int op = 0x0300;
  58. char buff[0x10]{};
  59. int lenId = 0x10;
  60. /*
  61. 这个是登录的账号,它可能会变成0x20或更长,现在默认让它0x10
  62. 读的时候以长度为准就好了
  63. */
  64. char Id[0x10]{};
  65. int lenPass = 0x10;
  66. /*
  67. 这个是登录的密码,它可能会变成0x20或更长,现在默认让它0x10
  68. 读的时候以长度为准就好了
  69. */
  70. char Pass[0x10]{};
  71. int lenCode = 0x10;
  72. char Code[0x10]{};
  73. int eop = 0x01;
  74. }*PDATALOGIN;
  75. typedef struct DATA_LOGIN_OK {// 登录成功数据包头
  76. int un[8] = { 0, 0, 0x76B, 0x0C, 0x1E,0, 0, 0 };
  77. int index = 0;
  78. int RoleCount = 0;
  79. }*PDATALOGINOK;
  80. typedef class ROLE_DATA {// 登录成功数据包
  81. public:
  82. GBYTE byte;
  83. GINT un;
  84. GINT un1;
  85. GUTF16 name;
  86. GUTF16 infos;
  87. GINT un2;
  88. GINT64 un3;
  89. }*PROLEDATA;

EnCode.cpp文件的修改:新加 AllocPointer函数,新加多个 Set函数,修改了 Init函数

  1. #include "pch.h"
  2. #include "EnCode.h"
  3. #include "extern_all.h"
  4. void EnCode::Init(char*& buff, char EnIndex)
  5. {
  6. index = EnIndex;
  7. op = buff[0];
  8. int len = data_desc[index][op].lenth;
  9. /*
  10. 比如 07 0A 00 00 00 34 00 33 00 39 00 39 00 00 00
  11. buff + 1 的结果是 0A 00 00 00 34 00 33 00 39 00 39 00 00 00
  12. len是 07 所代表的类型的长度,也就是0A 00 00 00 这个东西
  13. memcpy(dataPool, buff + 1, len);也就是把 0A 00 00 00 复制到 dataPool里
  14. 然后从下方的if ((op == 0x7))得到它的字符串
  15. */
  16. memcpy(dataPool, buff + 1, len);
  17. buff = buff + 1 + len;// 下一个结构
  18. if (index == 0) {
  19. if ((op == 0x7)) {
  20. AllocPointer(lenth);
  21. // if (pointer)delete[]pointer;
  22. /*
  23. dataPool 与 lenth是一个联合体,联合体的特性就是
  24. 所有变量共用一个内存,所以 dataPool 的值就是lenth的值
  25. 从上方的注释得知现在dataPool的值是0A 00 00 00
  26. 然后通过 lenth去读 0A 00 00 00结果就是十进制的 10
  27. 然后创建一个10字节的空间给pointer
  28. 然后在通过 memcpy(pointer, buff, lenth); 把字符串赋值给pointer
  29. */
  30. // pointer = new char[lenth];
  31. memcpy(pointer, buff, lenth);
  32. buff = buff + lenth;// 指向下一个字符串
  33. }
  34. }
  35. if (index == 1) {
  36. if ((op == 0x06) || (op == 0x7)) {
  37. AllocPointer(lenth);
  38. memcpy(pointer, buff, lenth);
  39. buff = buff + lenth;
  40. }
  41. }
  42. }
  43. /*
  44. buff是数据包
  45. _len暂时没用
  46. ExIndex是解析方式,因为分析的时候发现6有时是char类型有时是char*类型
  47. 看懂此方法需要分析手动分析一次数据包(数据解析约定的数据包)
  48. 然后带着数据包去看这个函数
  49. */
  50. EnCode::EnCode(char*& buff,char EnIndex)
  51. {
  52. Init(buff,EnIndex);
  53. }
  54. EnCode::~EnCode()
  55. {
  56. if(pointer)
  57. delete[] pointer;
  58. }
  59. void EnCode::AllocPointer(int size)
  60. {
  61. if (size > AllocCount) {
  62. if (pointer) delete[]pointer;
  63. pointer = new char[size];
  64. AllocCount = size;
  65. }
  66. }
  67. EnCode::EnCode()
  68. {
  69. }
  70. EnCode& EnCode::operator=(char*& buff)
  71. {
  72. Init(buff);
  73. return *this;
  74. }
  75. GBYTE::operator char()
  76. {
  77. return this->byte;
  78. }
  79. char GBYTE::value()
  80. {
  81. return this->byte;
  82. }
  83. GSHORT::operator short()
  84. {
  85. return this->stval;
  86. }
  87. short GSHORT::value()
  88. {
  89. return this->stval;
  90. }
  91. GINT::operator int()
  92. {
  93. return this->val;
  94. }
  95. int GINT::value()
  96. {
  97. return this->val;
  98. }
  99. /*
  100. GINT::Set函数得到的数据是
  101. 02 03 00 00 00
  102. 02是数据类型,表示int类型
  103. 03 00 00 00 int类型的值
  104. */
  105. void GINT::Set(int _invalue, char EnIndex)
  106. {
  107. index = EnIndex;// 处理类型
  108. op = 2; // 数据解析约定的数据02表示int
  109. val = _invalue; // 数据
  110. }
  111. GFLOAT::operator float()
  112. {
  113. return this->fval;
  114. }
  115. float GFLOAT::value()
  116. {
  117. return this->fval;
  118. }
  119. void GFLOAT::Set(float invalue, char EnIndex)
  120. {
  121. index = EnIndex;
  122. op = 0x04 ;
  123. fval = invalue;
  124. }
  125. GINT64::operator long long()
  126. {
  127. return this->lval;
  128. }
  129. long long GINT64::value()
  130. {
  131. return this->lval;
  132. }
  133. void GINT64::Set(long long invalue, char EnIndex)
  134. {
  135. index = EnIndex;
  136. op = 0x03;
  137. lval = invalue;
  138. }
  139. GDOUBLE::operator double()
  140. {
  141. return this->dbval;
  142. }
  143. double GDOUBLE::value()
  144. {
  145. return this->dbval;
  146. }
  147. void GDOUBLE::Set(double invalue, char EnIndex)
  148. {
  149. index = EnIndex;
  150. op = 0x05;
  151. dbval = invalue;
  152. }
  153. GCHAR::operator const char*()
  154. {
  155. return this->pointer;
  156. }
  157. const char* GCHAR::value()
  158. {
  159. return this->pointer;
  160. }
  161. /*
  162. GCHAR::Set函数得到的数据是
  163. 06 03 00 00 00 77 65 72 00
  164. 06是数据类型,表示char*类型
  165. 03 00 00 00 表示字符串长度
  166. 77 65 72 00 是字符串
  167. */
  168. void GCHAR::Set(const char* _txt, char EnIndex)
  169. {
  170. index = EnIndex;
  171. op = 6;
  172. lenth = strlen(_txt) + 1;
  173. AllocPointer(lenth);
  174. memcpy(pointer, _txt, lenth);
  175. }
  176. GUTF16::operator const wchar_t*()
  177. {
  178. return (wchar_t*)this->pointer;
  179. }
  180. const wchar_t* GUTF16::value()
  181. {
  182. return (wchar_t*)this->pointer;
  183. }
  184. /*
  185. GUTF16::Set函数得到的数据是
  186. 07 03 00 00 00 77 00 65 00 72 00
  187. 07是数据类型,表示wchar_t*类型
  188. 03 00 00 00 表示字符串长度
  189. 77 00 65 00 72 00 是字符串
  190. */
  191. void GUTF16::Set(const wchar_t* _txt, char EnIndex)
  192. {
  193. index = EnIndex;
  194. op = 7;
  195. lenth = wcslen(_txt) + 1;
  196. AllocPointer(lenth);
  197. memcpy(pointer, _txt, lenth);
  198. }

EnCode.h文件的修改:修改了 EnCode类,其它类新加 Set函数

  1. #pragma once
  2. /*
  3. EnCode结构体
  4. un[6]、index、op是8字节
  5. union里也是8字节
  6. pointer、back它俩虽然是char类型,但它俩是指针类型,所以它们一共是8字节
  7. EnCode结构体一共是24字节
  8. */
  9. class EnCode// 用于表示数据解析约定的数据
  10. {
  11. private:
  12. char un[6]{};//
  13. public:
  14. char index = 0;
  15. // op + un[3]是四字节,op与buffer是6字节,如果自动内存对齐op与buffer可能不会挨在一起
  16. char op = 0;
  17. /*
  18. 这个位置会导致编译器代码生成出现问题
  19. 就是在当前文件一个类里写一个新的函数声明
  20. 这个时候会因为下方的 union 导致编译器无法
  21. 通过函数声明在cpp实现函数,这是因为编译器
  22. 不知道下方的 union 是什么东西导致的
  23. */
  24. union
  25. {
  26. char dataPool[0x8];
  27. int lenth;
  28. char byte;
  29. short stval;
  30. int val;
  31. float fval;
  32. double dbval;
  33. long long lval = 0;
  34. };
  35. char* pointer = 0;
  36. int AllocCount = 0;// 记录内存大小
  37. protected:
  38. void AllocPointer(int size);
  39. public:
  40. EnCode();
  41. EnCode(char*& buff, char ExIndex = 1);
  42. EnCode& operator=(char*& buff);
  43. void Init(char*& buff, char EnIndex = 1);
  44. ~EnCode();
  45. };
  46. class GBYTE :public EnCode {
  47. public:
  48. using EnCode::EnCode;
  49. using EnCode::operator=;
  50. public:
  51. operator char();
  52. char value();
  53. };
  54. class GSHORT :public EnCode {
  55. public:
  56. using EnCode::EnCode;
  57. using EnCode::operator=;
  58. public:
  59. operator short();
  60. short value();
  61. };
  62. class GINT :public EnCode {
  63. public:
  64. using EnCode::EnCode;
  65. using EnCode::operator=;
  66. public:
  67. operator int();
  68. int value();
  69. void Set(int _invalue, char EnIndex = 1);
  70. };
  71. class GFLOAT :public EnCode {
  72. public:
  73. using EnCode::EnCode;
  74. using EnCode::operator=;
  75. operator float();
  76. float value();
  77. void Set(float invalue, char EnIndex = 1);
  78. };
  79. class GINT64 :public EnCode {
  80. public:
  81. using EnCode::EnCode;
  82. using EnCode::operator=;
  83. operator long long();
  84. long long value();
  85. void Set(long long invalue, char EnIndex = 1);
  86. };
  87. class GDOUBLE :public EnCode {
  88. public:
  89. using EnCode::EnCode;
  90. using EnCode::operator=;
  91. operator double();
  92. double value();
  93. void Set(double invalue, char EnIndex = 1);
  94. };
  95. class GCHAR :public EnCode {
  96. public:
  97. using EnCode::EnCode;
  98. using EnCode::operator=;
  99. operator const char*();
  100. const char* value();
  101. void Set(const char* _txt, char EnIndex = 1);
  102. };
  103. class GUTF16 :public EnCode {
  104. public:
  105. using EnCode::EnCode;
  106. using EnCode::operator=;
  107. operator const wchar_t*();
  108. const wchar_t* value();
  109. void Set(const wchar_t* _txt, char EnIndex = 1);
  110. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/731882
推荐阅读
相关标签
  

闽ICP备14008679号