查看: 2|回复: 1

[国服027]枫叶物语一键端联网版 精修大量社交 技能 链路等BUG

[复制链接]

新人上路

枫币
6
威望
0
贡献
1
在线时间
0 小时
注册时间
2026-9-4
发表于 15 分钟前 | 显示全部楼层 |阅读模式
本帖最后由 Ddov 于 2026-9-4 12:12 编辑

枫叶物语 · 027 联机修复端
高版本降级重构 · 商城/社交/渲染全量实测


很久没来枫叶物语论坛了,这次过来发个端.由于此前的论坛账号密码忘了,索性重新注册一个.此服务端以论坛名命名给论坛引流一下!

▎关于底包
由高版本服务端逆向降级重构而来,已尽可能剥离高版本残留(代码层 / 数据库层均做过清理与回滚),尽量还原 027 原味手感。

▎商城系统
CDKEY 兑换 外全模块实测可用:
  • 商品购买
  • 赠送礼物
  • 换购
  • 背包扩充


▎社交 & 休闲
  • 好友系统 / 组队系统 / 人气值 —— 全收敛修复
  • 小游戏:五子棋、记忆大考验 —— 多人联机实测无异常


▎战斗 & 职业技能
其余全技能已逐条修复实测,仅余以下两处已知问题:

祭司 - 时空门
组队状态下野外回城落位异常,无法用城镇时空门返场;单人使用正常,后续版本跟进修复。

火毒巫师 - 致命毒雾
特定条件下触发客户端空指针跳转导致闪退(逆向定位为客户端原生逻辑缺陷,非服务端侧可完全规避)。

其余技能全量修复完毕,实测可正常释放、无报错。
▎宠物系统
完全对齐官方表现:召唤广播、首次使用弹NPC强制对话(之后召唤不再弹出)、亲密度系统 等全面还原。
▎渲染还原
完全对齐官方表现:召唤物广播、召唤物攻击态、骑士附魔光效 —— 多人同屏下显示一致,无广播丢包
▎其他
关于其他未提及的功能已全面对照官方表现 请自行体验。



版权声明
本端启动时内置出处标识,归属 枫叶物语论坛
仅作社区交流用途,禁止倒卖 / 禁止二次打包售卖。尊重改版时间,且用且珍惜。


下载链接:通过网盘分享的文件:DovMaple.7z
链接:
游客,如果您要查看本帖隐藏内容请回复

有兄弟测到其余异常,欢迎回帖,随报随修
附送网络封包逆向工程报告(附件不支持)详情见楼下:

新人上路

枫币
6
威望
0
贡献
1
在线时间
0 小时
注册时间
2026-9-4
 楼主| 发表于 4 分钟前 | 显示全部楼层
本帖最后由 Ddov 于 2026-9-4 12:09 编辑
  1. # 冒险岛国服 V027 客户端网络封包完整分析报告

  2. > 分析对象:`D:\MXD\MapleStory.exe`(脱壳后,国服 027 版本)
  3. > 工具:Ghidra 12.1.3 headless(工程 `D:\MXD\ghidra_proj\MapleStoryProj7`)
  4. > 所有函数地址均为 VA(虚拟地址),可直接在 Ghidra 跳转复核。

  5. ---

  6. ## 一、结论总览

  7. | 项目 | 结论 |
  8. |---|---|
  9. | 包头 | 4 字节:`[h0][h1][h0^len_lo][h1^len_hi]`,两 LE u16 异或即得长度 |
  10. | opcode | **1 字节**(`CInPacket::Decode1` = FUN_004163ea),复合 opcode(0xB0-0xB5)带 1 字节 2 级子码 |
  11. | payload 加密 | **明文**(无字段级/包级载荷加密,与 My 端 `crypt()` 空操作一致) |
  12. | IV 体系 | 每包滚动 `getNewIv`(种子 `0xC65053F2`,与 My 端字节 `{-14,83,80,-58}` 相同);另有 12 字节 crypto state(`0x4727fe` 导出 / `0x4728b3` 安装) |
  13. | 版本号 | 0x1B(27);握手包内为 u16 `0x001B` |
  14. | 分发架构 | 三层:socket 层 → WvsContext 段(0x16-0x29) → context functor 虚调用 → 主分发器级联 |
  15. | opcode 覆盖 | 0x0E-0xBB 全部枚举(见第八章映射表) |

  16. ---

  17. ## 二、连接与握手协议

  18. ### 2.1 握手读取器:FUN_0043dd01(阻塞 recv 模式)

  19. 客户端 `connect()` 成功后以阻塞模式读取握手包,解析流程(汇编证据 `0x43de42-0x43e053`):

  20. ```
  21. [u16 总长度][u16 版本号][patch字符串][4B IV][4B IV][u8 type]
  22. ```

  23. 逐字段:

  24. | 字段 | 读取位置 | 处理 |
  25. |---|---|---|
  26. | u16 长度 | `0x43de42` `MOV AX,[EDI]` | 接收循环收满 `base+len` 字节 |
  27. | u16 版本 | `0x43debb`,存 `[EBP-0x18]` | `0x43dfa4 CMP word [EBP-0x18],0x1b`:<0x1B 抛异常 `0x22000006`;>0x1B 走版本过旧提示路径(写 `[0x679e38]+0x80`);**必须精确 == 0x1B** |
  28. | patch 串 | `0x43ded0 CALL 0x00430234` | 标准 MapleAsciiString:u16 长度前缀 + 内容,返回消耗 `len+2` 字节 |
  29. | IV#1 | `0x43dee2`(0x4727fe 初始化)→ `0x43df0e`(0x4728b3 安装) | 安装到 crypto 对象 `sock+0x90` |
  30. | IV#2 | `0x43df1b` → `0x43df47` | 安装到 `sock+0x9c` |
  31. | u8 type | `0x43df6b` `MOV AL,[EDI]`,`0x43df7c CMP AL,4` | **必须 == 4**(中国区标识) |

  32. 随后:
  33. - `0x43e00c` `CALL 0x0043fc43`:重置 socket 字段(+0x7c/+0x84/+0x8c 清零)
  34. - `0x43e031` `CALL [0x67b3f8]`(IAT 运行时填充):切换异步模式(WSAAsyncSelect 系)
  35. - 首个收包(`[EBP-0x14] < 1`)做版本一致性校验(见 4.4)

  36. ### 2.2 与 My 服务端的对应(`LoginPacket.getHello`)

  37. ```java
  38. writeShort(0x0E);            // 总长度(此处为固定值)
  39. writeShort(mapleVersion);     // 0x001B ✓
  40. writeMapleAsciiString(MAPLE_PATCH);
  41. write(recvIv);                // 4 字节 → 客户端 sock+0x90
  42. write(sendIv);                // 4 字节 → 客户端 sock+0x9c
  43. write(type);                 // 4 = 中国区 ✓
  44. ```

  45. 注意 My 端 `sessionOpened` 时 session 无 client 属性,`MaplePacketEncoder` 走 raw 分支原样写出(握手明文直发)——与客户端阻塞解析完全兼容。**此前"length 与 version 同址"的歧义已排除**:客户端首 u16 读两次,第一次作长度(收满循环),第二次(`0x43debb`)作版本号,两者是同一字段的两种用途。

  46. ---

  47. ## 三、封包帧格式(4 字节头)

  48. ### 3.1 客户端发送方向编码(FUN_004f38d9,汇编 `0x43ef2a/0x43ef72` 调用)

  49. 调用形式:`FUN_004f38d9(sock+0x19, 0x1b, &IV, 1, IV)`(**0x1B 即版本号参数**)

  50. ```c
  51. u16 h01 = (ushort)(IV >> 16) ^ 0x1B;   // 即 (iv[2]^0x1B) | (iv[3]<<8)
  52. u16 h23 = h01 ^ (u16)payload_len;      // 两 u16 异或
  53. 按 LE 写出 4 字节
  54. ```

  55. 即线上字节序:`[iv[2]^0x1B][iv[3]][h01^len 的两字节]`,分块上限 `0x5B4`(1460,MTU 对齐)。

  56. ### 3.2 客户端接收方向解码(FUN_004f34e9 头状态机,this = sock+0x78)

  57. ```c
  58. *(this+0xE) = Decode2();                 // 第一个 u16(LE)→ 存 sock+0x86
  59. u16 second = Decode2();
  60. len = second ^ *(this+0xE);              // 两 u16 异或 = payload 长度
  61. 状态 1 = 头完成,状态 2 = 包完成
  62. ```

  63. ### 3.3 与 My 服务端互证

  64. - My `MapleAESOFB.getPacketHeader(len)`(sendCypher,版本参数 `0xFFFF-27=0xFFE4`):
  65.   `iiv = (iv[3]|iv[2]<<8) ^ 0xE4FF` → 头 = `[iv[2]^0xE4][iv[3]^0xFF][xored 2B]`
  66. - My `getPacketLength`:`hi16 ^ lo16` 再 bswap —— 客户端无需 bswap 指令即可还原(LE 读两 u16 直接异或)
  67. - My `checkPacket`(收客户端包):`h0^iv[2]==0x1B, h1^iv[3]==0x00` —— 与 3.1 客户端发送公式逐字节吻合
  68. - 客户端首包校验 `hi16(IV) ^ [sock+0x86] == 0xFFE4`:`[sock+0x86]` = 首收包头前两字节(FUN_004f34e9 写入),代入 My 头公式得 `hi16(IV) ^ (iv[2]^0xE4)|(iv[3]^0xFF)<<8 = 0xFFE4` ✓ —— 这就是"服务器必须用 0xFFFF-version 作头编码版本"的强制校验

  69. ---

  70. ## 四、加密与 IV 体系

  71. ### 4.1 IV 滚动:FUN_005fc114(getNewIv)

  72. ```c
  73. uint getNewIv(byte* iv, int len, uint* state) {
  74.     uint s = state ? *state : 0xC65053F2;   // 种子,字节 = F2 53 50 C6 = {-14,83,80,-58}
  75.     for (i=0; i<len; i++) funnyShit(&s, iv<i>);   // FUN_005fc261
  76.     return s;
  77. }
  78. ```

  79. 与 My 端 `MapleAESOFB.getNewIv` 完全一致(含 funnyBytes 表 + ROL32 3)。**每收/发包后调用一次**。

  80. ### 4.2 crypto state 对象(12 字节,堆分配)

  81. ```
  82. +0x00  IV[4]        当前 IV(密文形态存放)
  83. +0x04  key[1]       滚动密钥字节
  84. +0x05..+0x07        pad
  85. +0x08  check[2]     完整性校验值(初始 0x9A65)
  86. ```

  87. 两个操作互为逆:

  88. | 函数 | 方向 | 逻辑 |
  89. |---|---|---|
  90. | FUN_004727fe | **导出**(E) | `out<i> = state<i> ^ key; key += state<i> + 0x2A; check` 滚动;结束时校验 check==state+8,不符抛异常断线;返回导出的 IV dword;**不修改 state** |
  91. | FUN_004728b3 | **安装**(D) | `key = rand()&0xFF; check = 0x9A65; state<i> = in<i> ^ key; key += state<i> + 0x2A` |

  92. 因 key 演化规则相同(都基于 state 字节),`E(D(x)) == x` 恒成立。
  93. 附带反调试:全局计数 `0x67a764` 每 0x37(55)次导出触发一次随机重装;每 0x6F(111)次安装时把 state 结构搬迁到新堆块(0x4024de 分配 / memcpy / 释放旧块)。

  94. **重要结论**:这两个函数只操作 IV state,不接触 payload 数据。所有"字段编码函数大量调用 0x4727fe"的表象(如 FUN_0046f2cd 调用约 25 次)实为对多个 crypto 对象逐个导出 IV(调用点只传 ECX、无数据参数,见 `0x46f3b9` 汇编)——**payload 全明文**。

  95. ### 4.3 每包 IV 滚动(收包方向)

  96. 收包泵(FUN_0043f2d7,`0x43f369-0x43f38c`):

  97. ```c
  98. cur = FUN_004727fe(crypto);          // 导出当前 IV(=握手原文)
  99. FUN_005fc114(&cur, 4, 0);           // getNewIv 滚动
  100. FUN_004728b3(crypto, 新IV);         // 安装回 state
  101. dispatch(packet);
  102. ```

  103. 发包方向(FUN_0043ee73)同理。

  104. ### 4.4 首包版本校验(FUN_0043f2d7,`0x43f323-0x43f34a`)

  105. ```c
  106. if (状态机返回 > 0 && 已收包计数 < 1) {          // 仅第一个包
  107.     dword v = FUN_004727fe(sock+0x9c);          // 导出 IV(=服务端 sendIv 原文)
  108.     if ((v >> 16 ^ *(u16*)(sock+0x86)) != 0xFFE4) disconnect();   // 0xFFE4 = ~0x1B
  109.     if (*(u16*)(sock+0x88) > 0x10000) disconnect();
  110. }
  111. ```

  112. ---

  113. ## 五、客户端收包链路

  114. ```
  115. WSA 异步消息 → FUN_005e0bc3(消息泵)→ FUN_0043f2d7(收包泵)
  116.   └─ FUN_004f34e9(头状态机,this=sock+0x78)
  117.        ├─ 首包:[sock+0x86] = 头前两字节;版本一致性校验(4.4)
  118.        └─ 收满 → 状态 2
  119.   └─ FUN_004f3464(包定稿:拷贝 payload 到 CInPacket,携带头 u16)
  120.   └─ IV 滚动(4.3)
  121.   └─ FUN_0043f3c4(ProcessPacket,分发入口)
  122. ```

  123. 读者函数(CInPacket):
  124. - `FUN_004163ea` = Decode1(1 字节,**opcode**)
  125. - `FUN_00416420` = Decode2(2 字节 LE)
  126. - `FUN_00416459` = Decode4(4 字节 LE)
  127. - `FUN_00430234` = DecodeString(u16 前缀 + 内容)

  128. ---

  129. ## 六、客户端发包链路

  130. ```
  131. 业务函数(FUN_004f3868 = COutPacket 构造器,100+ 调用方)
  132.   └─ FUN_0043ee73(CClientSocket::Send,vtable @0x631f98)
  133.        ├─ FUN_004727fe 导出当前 IV
  134.        ├─ 防弱 IV 循环:lo16(IV)%31==0 时
  135.        │    ├─ FUN_00445b6d 对发送队列所有缓冲滚动校验和
  136.        │    ├─ FUN_004f3868(0x12) 构造保活包 + 附加校验和
  137.        │    └─ 发送并重滚 IV
  138.        ├─ FUN_004f38d9(sock+0x19, 0x1B, &IV, 1, IV)  ← 核心编码发送
  139.        │    ├─ 头:h01 = hi16(IV)^0x1B;h23 = h01^len
  140.        │    └─ 分块 0x5B4,链式缓冲
  141.        └─ getNewIv 滚动 + FUN_004728b3 安装
  142. ```

  143. 服务端应对:客户端主动发的 0x12(超时/保活,FUN_0043f928 处理的是服务端 0x12)与 0x0D(pong)均需 My 端正常兼容(当前已兼容,用户可正常游玩)。

  144. ---

  145. ## 七、封包分发架构(三层)

  146. ```
  147. FUN_0043f3c4(CClientSocket::ProcessPacket)
  148. ├─ opcode 0x0E-0x14      → socket 层内联处理
  149. ├─ opcode 0x16-0x29       → FUN_005e810c(WvsContext 段)
  150. └─ 其余                   → context functor 虚调用 *(*(ctx+8))(opcode, packet)
  151.                               (ctx 由 FUN_004786ad 按登录/游戏状态创建)
  152.        ├─ 登录阶段 functor(FUN_00490a83 构造)→ FUN_005193d7
  153.        │    └─ 0x2B/0x2C → FUN_00519400 / FUN_005197b6(此后切游戏 context)
  154.        └─ 游戏阶段 functor(FUN_00478cf9 构造,0xcf8 大对象)→ FUN_0048a09a
  155.             ├─ 0xB7-0xBB 直处理
  156.             └─ 其余 → FUN_0047d3e8(主分发器)
  157.                  ├─ 0x2F-0x3A / 0x3E 直处理
  158.                  ├─ 0x2A-0x2D → FUN_005193d7
  159.                  └─ 区段级联 → 各业务子分发器(见下表)
  160. ```

  161. 阶段包裹分发器(在主分发器外再套一层,处理 UI 状态相关包):

  162. | 分发器 | opcode | 处理 |
  163. |---|---|---|
  164. | FUN_004837b9 | 0xA1 / 0xA2 | FUN_004838c0 / FUN_0048388e |
  165. | FUN_004865dd | 0x3C / 0x3D | FUN_00486611 / FUN_00486676(船效果/船状态) |
  166. | FUN_0048884b | 0x9F / 0xA0 | FUN_00488881 / FUN_00488955 |

  167. ---

  168. ## 八、完整 opcode → handler 映射表

  169. ### 8.1 Socket 层(FUN_0043f3c4 直处理)

  170. | opcode | handler | My sendops 名称 | 说明 |
  171. |---|---|---|---|
  172. | 0x0E | FUN_0043f50e | CHANGE_CHANNEL | 读 type;≠0 时创建登录 context 并切场景 |
  173. | 0x0F | FUN_0043f49a | PING | **立即回发 0x0D pong** |
  174. | 0x10 | FUN_0043f5ef | — | 标志位(bit1 切换状态;bit4 → 异常断开) |
  175. | 0x11 | FUN_0043f6cb | — | 反外挂 |
  176. | 0x12 | FUN_0043f928 | — | 保活/迁移(子码 1/2 → 异常 0x22000008/9) |
  177. | 0x13 | FUN_0043f9e2 | — | 数据表 |
  178. | 0x14 | FUN_0043fbf6 | CHANNEL_SELECTED | u16 count + 重复 [dword,dword] |

  179. ### 8.2 WvsContext 段(FUN_005e810c,0x16-0x29)

  180. | opcode | handler | My sendops |
  181. |---|---|---|
  182. | 0x17 | FUN_005ef1c7 | MODIFY_INVENTORY_ITEM |
  183. | 0x18 | FUN_005ef3cb | UPDATE_INVENTORY_SLOT |
  184. | 0x19 | FUN_005ef42d | UPDATE_STATS |
  185. | 0x1A | FUN_005ef73e | GIVE_BUFF |
  186. | 0x1B | FUN_005ef7d1 | CANCEL_BUFF |
  187. | 0x1C | FUN_005ef833 | —(My 未用) |
  188. | 0x1D | FUN_005ef08b | UPDATE_SKILLS |
  189. | 0x1E | FUN_005ef8bc | — |
  190. | 0x1F | FUN_005eff2e | FAME_RESPONSE |
  191. | 0x20 | FUN_005ef8d9 | SHOW_STATUS_INFO |
  192. | 0x21 | FUN_005f0fee | SHOW_NOTES |
  193. | 0x22 | FUN_005f1125 | TROCK_LOCATIONS |
  194. | 0x24 | FUN_005f0635 | CHAR_INFO |
  195. | 0x25 | FUN_005f3f9c | PARTY_OPERATION |
  196. | 0x26 | FUN_005f4ae7 | BUDDYLIST |
  197. | 0x27 | FUN_005f01e3 | SPAWN_PORTAL |
  198. | 0x28 | FUN_005f02ae | SERVERMESSAGE |

  199. ### 8.3 主分发器 FUN_0047d3e8 直处理

  200. | opcode | handler | My sendops |
  201. |---|---|---|
  202. | 0x2F | FUN_0047d6c4 | — |
  203. | 0x30 | FUN_0047d7ac | — |
  204. | 0x31 | FUN_0047d81a | — |
  205. | 0x32 | FUN_0047d872 | MULTICHAT |
  206. | 0x33 | FUN_0047da26 | WHISPER |
  207. | 0x34 | FUN_0047e2b2 | — |
  208. | 0x35 | FUN_0047e2eb | MAP_EFFECT |
  209. | 0x36 | FUN_0047ea40 | FULLSCREEN_BLESS |
  210. | 0x37 | FUN_0047ec67 | CASH_SONG |
  211. | 0x38 | FUN_0047ed39 | GM_EFFECT(内含子码 4/5/7/0xE 分发) |
  212. | 0x39 | FUN_0047f092 | OX_QUIZ |
  213. | 0x3A | FUN_0047f768 | — |
  214. | 0x3B | 虚调用 [this-8]+0x1C | CLOCK |
  215. | 0x3E | FUN_0047d9b3 | GUILD_OPERATION |
  216. | 0x2A-0x2D | → FUN_005193d7 | 0x2B WARP_TO_MAP / 0x2C CS_CHAR |

  217. ### 8.4 玩家池区段(0x3F-0x6D → FUN_005a9ff7)

  218. **直处理**:

  219. | opcode | handler | My sendops |
  220. |---|---|---|
  221. | 0x40 | FUN_005aa05c | SPAWN_PLAYER |
  222. | 0x41 | FUN_005aa1fe | REMOVE_PLAYER_FROM_MAP |

  223. **子分发 FUN_005aa293(0x42-0x54)**:

  224. | opcode | handler | My sendops |
  225. |---|---|---|
  226. | 0x43 | FUN_00595ec3 | CHATTEXT |
  227. | 0x44 | FUN_005964e2 | UPDATE_CHAR_BOX |
  228. | 0x45 | FUN_00597ccf | — |
  229. | 0x46-0x4C | FUN_0059661d | 0x47 SPAWN_PET / 0x48 MOVE_PET / 0x49 PET_CHAT / 0x4A PET_NAMECHANGE / 0x4B PET_COMMAND |
  230. | 0x4D-0x53 | FUN_00596674 | 0x4E SPAWN_SUMMON / 0x4F REMOVE_SUMMON / 0x50 MOVE_SUMMON / 0x51 SUMMON_ATTACK / 0x52 DAMAGE_SUMMON |

  231. **子分发 FUN_005aa30c(0x55-0x63)**:

  232. | opcode | handler | My sendops |
  233. |---|---|---|
  234. | 0x56 | FUN_004e2fc0 | MOVE_PLAYER |
  235. | 0x57/0x58/0x59 | FUN_005acd7f | CLOSE_RANGE/RANGED/MAGIC_ATTACK |
  236. | 0x5A | FUN_005ad148 | SKILL_EFFECT |
  237. | 0x5B | FUN_005ad24e | CANCEL_SKILL_EFFECT |
  238. | 0x5C | FUN_005ae883 | DAMAGE_PLAYER |
  239. | 0x5D | FUN_00422f10 | FACIAL_EXPRESSION |
  240. | 0x5E | FUN_005aeb4f | UPDATE_CHAR_LOOK |
  241. | 0x5F | FUN_00596055 | SHOW_FOREIGN_EFFECT |
  242. | 0x60 | FUN_005aecc4 | GIVE_FOREIGN_BUFF |
  243. | 0x61 | FUN_005aecf5 | CANCEL_FOREIGN_BUFF |
  244. | 0x62 | FUN_005aed21 | UPDATE_PARTYMEMBER_HP |

  245. **子分发 FUN_005aa407(0x64-0x6C)→ 统一入口 FUN_0059ece7**:含 0x65 SHOW_CHAIR、0x66 SHOW_SPECIAL_EFFECT、0x6A MESOBAG_SUCCESS、0x6B MESOBAG_FAILURE。

  246. ### 8.5 怪物区段(0x6E-0x7E → FUN_004dc1e1)

  247. | opcode | handler | My sendops |
  248. |---|---|---|
  249. | 0x6F | FUN_004dc2c0 | SPAWN_MONSTER |
  250. | 0x70 | FUN_004dc39e | KILL_MONSTER |
  251. | 0x71 | FUN_004dc47e | SPAWN_MONSTER_CONTROL |
  252. | 0x73 | FUN_004d56e6 | MOVE_MONSTER |
  253. | 0x74 | FUN_004d5aa7 | MOVE_MONSTER_RESPONSE |
  254. | 0x76 | FUN_004d5b59 | APPLY_MONSTER_STATUS |
  255. | 0x77 | FUN_004d5bb1 | CANCEL_MONSTER_STATUS |
  256. | 0x78 | FUN_004d5be6 | — |
  257. | 0x79 | FUN_004d5d4f | — |
  258. | 0x7A | FUN_004d5d99 | DAMAGE_MONSTER |
  259. | 0x7B | FUN_004d5f92 | SKILL_EFFECT_MOB |

  260. ### 8.6 NPC / 掉落 / 爱心 / 防御区区段

  261. | opcode | handler | My sendops |
  262. |---|---|---|
  263. | 0x80 | FUN_004e8265 | SPAWN_NPC |
  264. | 0x81 | FUN_004e82f7 | REMOVE_NPC |
  265. | 0x82 | FUN_004e8355 | SPAWN_NPC_REQUEST_CONTROLLER |
  266. | 0x84 | FUN_004e6a94 | NPC_ACTION |
  267. | 0x88 | FUN_0047001b | DROP_ITEM_FROM_MAPOBJECT |
  268. | 0x89 | FUN_00470abe | REMOVE_ITEM_FROM_MAP |
  269. | 0x8C | FUN_004ca206 | — |
  270. | 0x8D | FUN_004ca22e | SPAWN_LOVE |
  271. | 0x8E | FUN_004ca7df | REMOVE_LOVE |
  272. | 0x91 | FUN_00415fb5 | SPAWN_DEFENDER |
  273. | 0x92 | FUN_00416584 | REMOVE_DEFENDER |

  274. ### 8.7 门 / 反应堆区段

  275. | opcode | handler | My sendops |
  276. |---|---|---|
  277. | 0x95 | FUN_0052bbca | SPAWN_DOOR |
  278. | 0x96 | FUN_0052c558 | REMOVE_DOOR |
  279. | 0x99 | FUN_0050570c | REACTOR_HIT |
  280. | 0x9B | FUN_005057fc | REACTOR_SPAWN |
  281. | 0x9C | FUN_00505bd3 | REACTOR_DESTROY |

  282. ### 8.8 交互区段(复合 opcode)

  283. | opcode | handler | My sendops | 说明 |
  284. |---|---|---|---|
  285. | 0xA5 | FUN_00502d0a | NPC_TALK | |
  286. | 0xA8 | FUN_0050f535 | OPEN_NPC_SHOP | 经 FUN_0050f33f |
  287. | 0xA9 | FUN_0050f33f 内部分发 | CONFIRM_SHOP_TRANSACTION | 子码 0-10(1/5/9→0x205,2/10→0x89,3→0x206,其余→0x207) |
  288. | 0xAC | FUN_00534242 | — | STORAGE 操作(回发 0x0C 确认) |
  289. | 0xAD | FUN_00534498 | STORAGE_OPEN | |
  290. | 0xAE | FUN_00534242 内部分发 | STORAGE_OPERATION | 子码 8/9/10/12/13/15 |
  291. | 0xB0-0xB2 | FUN_0054ef29 | MESSENGER(0xB1) | **2 级子码 0-8**:0→0054ccb2,1→0054cf28,2→0054d03a,3→0054f195,4→0054efc0,5→0054f0a8,6→0054f2c6,7→0054f54f,8→0054f607 |
  292. | 0xB3-0xB5 | FUN_004cc19d | PLAYER_INTERACTION(0xB4) | **2 级子码**:2→004cc5ee,3→004cc795,4→004cc9d0,5→004cc239,6→虚调用 vtable+0x48,9→004ccb11,10→004cca69 |
  293. | 0xB7-0xBB | FUN_0048a09a 直处理 | — | 0048a100 / 0048a25c / 0048a2e7 / 0048a4c4 / 0048a5b6 |

  294. ### 8.9 未在客户端处理表中出现的区间

  295. 0x00-0x0D(登录 UI 包,如 LOGIN_STATUS 0x01 等)不在 socket 层与游戏分发器中——它们由**登录阶段 context functor** 的 vtable 虚调用处理(登录 functor 构造于 FUN_00490a83,0x2B/0x2C 之后切换为游戏 functor)。0xC0-0xFF 区间(My 的 CS_UPDATE/CS_OPERATION/雇佣商店 0xCA-0xCC)在本客户端主分发器中无静态 case,属商城连接独立通道或该版本未启用。

  296. ---

  297. ## 九、与 My 服务端的交叉验证结论

  298. 1. **握手**:`[len][0x1B][patch串][recvIV][sendIV][type=4]` —— My `getHello` 完全吻合,客户端强校验 version==0x1B、type==4。
  299. 2. **帧头**:客户端发送 `[iv[2]^0x1B][iv[3]][...]`、校验服务端头 `hi16(IV)^h01==0xFFE4`(即服务端头必须用 `0xFFFF-27` 编码)—— My `sendCypher(0xFFE4)` / `recvCypher(0x1B)` 的构造**完全正确**。
  300. 3. **长度还原**:两 LE u16 异或 = My `getPacketLength` 的 `hi16^lo16` + bswap —— 等价。
  301. 4. **IV 滚动**:客户端 `FUN_005fc114` ≡ My `getNewIv`(种子、funnyBytes、ROL32 3 全同)。
  302. 5. **payload 明文**:客户端无任何 payload 变换调用(0x4727fe/0x4728b3 仅操作 IV state)—— My `crypt()` 空操作**正确,不是偷工减料**。
  303. 6. **保活**:客户端 0x0F(PING)→自动回 0x0D;客户端主动发 0x12(带发送队列校验和)—— My 需容忍 0x0D/0x12 上行包(当前已兼容)。
  304. 7. **opcode 表**:WvsContext 段 0x17-0x28 与 My sendops.ini 逐项吻合;主分发器各区间与 My 注释一一对应。

  305. ## 十、对照 Other 商业端的移植提示

  306. - 客户端 0xB3-0xB5(FUN_004cc19d)是**统一玩家互动通道**(2 级子码区分交易/小游戏/聊天室等,子码 6 走对象 vtable)——这印证了 Other 商业端 GameRoom/TradeRoom 专门类的设计:**五子棋等小游戏应归入 PLAYER_INTERACTION 通道(0xB4)而非交易**,移植时按子码区分路由。
  307. - 0xB0-0xB2(FUN_0054ef29)是 Messenger(好友聊天室)通道,与 0xB4 是两个不同的复合 opcode 家族,My 端当前 MESSENGER=0xB1 / PLAYER_INTERACTION=0xB4 的区分正确。
  308. - 客户端不处理的 0xC0+ 区间说明:商城独立连接(如 My 的 CS server 通道)有独立分发器,不在主连接 opcode 表内。
  309. - 删档重建后无需处理的换购旧道具兼容问题不受本协议分析影响。

  310. ---

  311. ## 附录:关键函数地址速查

  312. | 地址 | 功能 |
  313. |---|---|
  314. | 0x0043dd01 | 握手读取器(阻塞 recv) |
  315. | 0x0043fc43 | 握手完成 socket 重置 |
  316. | 0x0043f2d7 | 收包泵(CClientSocket::OnReceive) |
  317. | 0x004f34e9 | 收包头状态机(写 sock+0x86) |
  318. | 0x004f3464 | 收包定稿(拷贝 CInPacket) |
  319. | 0x0043f3c4 | 分发入口(ProcessPacket) |
  320. | 0x004727fe / 0x004728b3 | IV 导出 / 安装(互逆对) |
  321. | 0x005fc114 / 0x005fc261 | getNewIv / funnyShit |
  322. | 0x004f3868 | COutPacket 构造器 |
  323. | 0x004f38d9 | 发包编码(4 字节头 + 分块发送) |
  324. | 0x0043ee73 | CClientSocket::Send |
  325. | 0x004163ea / 0x00416420 / 0x00416459 | Decode1 / Decode2 / Decode4 |
  326. | 0x00430234 | DecodeString |
  327. | 0x0045b6d | (0x00445b6d)发送队列校验和(0x12 保活) |
  328. | 0x0047d3e8 | 主游戏分发器 |
  329. | 0x005e810c | WvsContext 分发器(0x17-0x28) |
  330. | 0x005193d7 | 登录→游戏切换分发器(0x2B/0x2C) |
  331. | 0x0048a09a | 游戏阶段分发器(0xB7-0xBB) |
  332. | 0x004727fe 调用计数 0x67a764 | 反调试计数器(%0x37 / %0x6F) |</i></i></i></i></i></i></i>
复制代码

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|枫叶物语冒险岛单机 | 本站已运行:

枫叶物语可能会倒闭,但是绝对不会变质。

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖QQ客服返回顶部