WOWx64怀旧服明文封包及加密解密分析
大家好,我是任鸟飞。
WOWx64怀旧服,与官网正式服差距不大,是一款很热门的游戏。
游戏火爆,自然辅助和刷金脚本猖獗,出于游戏安全,外挂与反外挂的角度,我们来做个课程教程,分析学习下该游戏的明文封包以及功能调用,封包加密等实现流程,看看是否存在安全隐患。
首先,通过下断发现发包是最直接的send发包,没有重新实现发包函数
也没有做线程发包等等处理,等于白送。
从send发包的位置下断,可以直接CTRL+F9 返回到明文发包和功能函数。
调用send的位置如下
第二,分析下心跳包的情况
在我们不切换到游戏窗口的情况下,send下断静静的等待他自然断下
会发现,游戏的心跳包并不多,而且种类也比较少。
在我们切换到游戏窗口,也就是**窗口的时候会断下,这个用来做干扰还是不错的选择,不过心跳包少,只有一个**的动作干扰,很简单的条件断就可以排除掉了。
r8 != 0x13 即可
第三,我们追踪封包内容的来源,分析最内层明文包的所在
1.功能函数 send返回 第一层
没有什么重要代码,继续追踪加密封包来源
$+12E439000007FF7745C4390| 40 53 | push rbx | 函数头部
$+12E439200007FF7745C4392| 55| push rbp |
$+12E439300007FF7745C4393| 57| push rdi |
$+12E439400007FF7745C4394| 48 81 EC A0 00 00 00| sub rsp,A0 |
$+12E439B00007FF7745C439B| 8B 6A 10| mov ebp,dword ptr ds:[rdx+10]|==== [rdx] 包地址 [rdx+10]包长
$+12E439E00007FF7745C439E| 48 8B D9| mov rbx,rcx|
$+12E43A100007FF7745C43A1| 85 ED | test ebp,ebp |
$+12E43A300007FF7745C43A3| 75 21 | jne wowclassic.7FF7745C43C6|
$+12E43A500007FF7745C43A5| 8B 81 BC 00 00 00 | mov eax,dword ptr ds:[rcx+BC]|
$+12E43AB00007FF7745C43AB| BF 02 00 00 00| mov edi,2|
$+12E43B000007FF7745C43B0| 3B C7 | cmp eax,edi|
$+12E43B200007FF7745C43B2| 0F 4D F8| cmovge edi,eax |
$+12E43B500007FF7745C43B5| 89 B9 BC 00 00 00 | mov dword ptr ds:[rcx+BC],edi|
$+12E43BB00007FF7745C43BB| 48 81 C4 A0 00 00 00| add rsp,A0 |
$+12E43C200007FF7745C43C2| 5F| pop rdi|
$+12E43C300007FF7745C43C3| 5D| pop rbp|
$+12E43C400007FF7745C43C4| 5B| pop rbx|
$+12E43C500007FF7745C43C5| C3| ret|
$+12E43C600007FF7745C43C6| 83 B9 D4 00 00 00 05| cmp dword ptr ds:[rcx+D4],5|
$+12E43CD00007FF7745C43CD| 0F 85 E2 03 00 00 | jne wowclassic.7FF7745C47B5|
$+12E43D300007FF7745C43D3| F6 81 A4 00 00 00 02| test byte ptr ds:[rcx+A4],2|
$+12E43DA00007FF7745C43DA| 4C 89 B4 24 98 00 00 00 | mov qword ptr ss:[rsp+98],r14|
$+12E43E200007FF7745C43E2| 4C 8B 32| mov r14,qword ptr ds:[rdx] | [rdx]================ 包地址
$+12E43E500007FF7745C43E5| 4C 89 BC 24 90 00 00 00 | mov qword ptr ss:[rsp+90],r15|
$+12E43ED00007FF7745C43ED| 75 46 | jne wowclassic.7FF7745C4435|
$+12E43EF00007FF7745C43EF| 90| nop|
$+12E43F000007FF7745C43F0| 48 83 7B 18 00| cmp qword ptr ds:[rbx+18],0|
$+12E43F500007FF7745C43F5| 75 3E | jne wowclassic.7FF7745C4435|
$+12E43F700007FF7745C43F7| 48 8B 8B C0 00 00 00| mov rcx,qword ptr ds:[rbx+C0]|
$+12E43FE00007FF7745C43FE| 45 33 C9| xor r9d,r9d| r9d:“HalT”
$+12E440100007FF7745C4401| 44 8B C5| mov r8d,ebp| ===============ebp 包长
$+12E440400007FF7745C4404| 49 8B D6| mov rdx,r14| ==================r14 包地址
$+12E440700007FF7745C4407| FF 15 B3 8D 8D 00 | call qword ptr ds:[7FF774E9D1C0] | ==========返回
2.功能函数 send返回 第二层
真正的头部,call过来的地址
$+12E723000007FF7745C7230| 48 8B 49 08 | mov rcx,qword ptr ds:[rcx+8] | ======call 过来的地址
$+12E723400007FF7745C7234| E9 87 D5 FF FF| jmp wowclassic.7FF7745C47C0|
$+12E723900007FF7745C7239| CC| int3 |
$+12E723A00007FF7745C723A| CC| int3 |
$+12E723B00007FF7745C723B| CC| int3 |
$+12E723C00007FF7745C723C| CC| int3 |
$+12E723D00007FF7745C723D| CC| int3 |
虽然做了call跳转隐藏代码,但是本层依然没有什么重要代码
假头部
$+12E47C000007FF7745C47C0| 45 85 C0| test r8d,r8d |======== 函数头部
$+12E47C300007FF7745C47C3| 0F 8E E5 00 00 00 | jle wowclassic.7FF7745C48AE|
$+12E47C900007FF7745C47C9| 55| push rbp |
$+12E47CA00007FF7745C47CA| 56| push rsi |
$+12E47CB00007FF7745C47CB| 57| push rdi |
$+12E47CC00007FF7745C47CC| 48 83 EC 30 | sub rsp,30 |
$+12E47D000007FF7745C47D0| 4C 89 64 24 58| mov qword ptr ss:[rsp+58],r12|
$+12E47D500007FF7745C47D5| 48 8B FA| mov rdi,rdx| =====[rdx]包地址[rdx+10]包长
$+12E47D800007FF7745C47D8| 48 89 5C 24 50| mov qword ptr ss:[rsp+50],rbx|
$+12E47DD00007FF7745C47DD| 48 8B F1| mov rsi,rcx|
$+12E47E000007FF7745C47E0| 4C 89 74 24 60| mov qword ptr ss:[rsp+60],r14|
$+12E47E500007FF7745C47E5| 45 33 E4| xor r12d,r12d|
$+12E47E800007FF7745C47E8| 4C 89 7C 24 68| mov qword ptr ss:[rsp+68],r15|
$+12E47ED00007FF7745C47ED| 49 63 E8| movsxd rbp,r8d |
$+12E47F000007FF7745C47F0| 44 39 A6 B8 00 00 00| cmp dword ptr ds:[rsi+B8],r12d |
$+12E47F700007FF7745C47F7| 75 10 | jne wowclassic.7FF7745C4809|
$+12E47F900007FF7745C47F9| 48 8B D7| mov rdx,rdi|
$+12E47FC00007FF7745C47FC| 48 8B CE| mov rcx,rsi|
$+12E47FF00007FF7745C47FF| E8 8C FB FF FF| call wowclassic.7FF7745C4390 | ====返回
3.功能函数 send返回 第三层
本层是重要的明文包到加密的过程,再外层是最内层明文封包,再内层是加密封包
本层是明文封包到send发送的封包的转换全过程
$+12FC1F000007FF7745DC1F0| 40 55 | push rbp | //函数头部
$+12FC1F200007FF7745DC1F2| 41 56 | push r14 |
$+12FC1F400007FF7745DC1F4| 41 57 | push r15 |
…
…
…
$+12FC26000007FF7745DC260| 4C 8D 7C 24 20| lea r15,qword ptr ss:[rsp+20]| //[rsp+20] 包地址[rsp+20+10]包长
$+12FC26500007FF7745DC265| 45 85 F6| test r14d,r14d | //来源堆栈,但是此时堆栈里是空的 F7走看什么地方被写入
$+12FC26800007FF7745DC268| 7E 44 | jle wowclassic.7FF7745DC2AE|
$+12FC26A00007FF7745DC26A| 4D 8B C7| mov r8,r15 |
$+12FC26D00007FF7745DC26D| 48 8D 4A 10 | lea rcx,qword ptr ds:[rdx+10]| //[rdx]包地址[rdx+10]包长
$+12FC27100007FF7745DC271| 4D 2B C1| sub r8,r9|
$+12FC27400007FF7745DC274| 4C 8B CE| mov r9,rsi |
$+12FC27700007FF7745DC277| 33 D2 | xor edx,edx|
$+12FC27900007FF7745DC279| 0F 1F 80 00 00 00 00| nop dword ptr ds:[rax] |
$+12FC28000007FF7745DC280| 48 8B 41 F0 | mov rax,qword ptr ds:[rcx-10]|
$+12FC28400007FF7745DC284| 49 89 44 08 F0| mov qword ptr ds:[r8+rcx-10],rax | //写入包地址来源 [rcx-10]
$+12FC28900007FF7745DC289| 49 89 54 08 F8| mov qword ptr ds:[r8+rcx-8],rdx|
$+12FC28E00007FF7745DC28E| 8B 01 | mov eax,dword ptr ds:[rcx] |
$+12FC29000007FF7745DC290| 41 89 04 08 | mov dword ptr ds:[r8+rcx],eax| //写入包长来源 [rcx]
$+12FC29400007FF7745DC294| 8B 41 04| mov eax,dword ptr ds:[rcx+4] |
$+12FC29700007FF7745DC297| 41 89 44 08 04| mov dword ptr ds:[r8+rcx+4],eax|
$+12FC29C00007FF7745DC29C| 8B 41 08| mov eax,dword ptr ds:[rcx+8] |
$+12FC29F00007FF7745DC29F| 41 89 44 08 08| mov dword ptr ds:[r8+rcx+8],eax|
$+12FC2A400007FF7745DC2A4| 48 8D 49 20 | lea rcx,qword ptr ds:[rcx+20]|
$+12FC2A800007FF7745DC2A8| 49 83 E9 01 | sub r9,1 |
$+12FC2AC00007FF7745DC2AC| 75 D2 | jne wowclassic.7FF7745DC280|
$+12FC2AE00007FF7745DC2AE| 41 8B D6| mov edx,r14d |
$+12FC2B100007FF7745DC2B1| 49 8B CF| mov rcx,r15|
$+12FC2B400007FF7745DC2B4| E8 F7 AF FE FF| call wowclassic.7FF7745C72B0 |
$+12FC2B900007FF7745DC2B9| BA 10 00 00 00| mov edx,10 |
$+12FC2BE00007FF7745DC2BE| 49 8B CF| mov rcx,r15|
$+12FC2C100007FF7745DC2C1| 8B D8 | mov ebx,eax|
$+12FC2C300007FF7745DC2C3| E8 98 A0 FE FF| call wowclassic.7FF7745C6360 | //加包头处理[r15]包地址[r15+10]包长 明文
$+12FC2C800007FF7745DC2C8| 4C 8B E0| mov r12,rax|
$+12FC2CB00007FF7745DC2CB| 89 18 | mov dword ptr ds:[rax],ebx | //包头前4字节写入包体长度
$+12FC2CD00007FF7745DC2CD| 0F B6 87 CC 21 00 00| movzx eax,byte ptr ds:[rdi+21CC] |
$+12FC2D400007FF7745DC2D4| A8 10 | test al,10 |
$+12FC2D600007FF7745DC2D6| 0F 84 F9 00 00 00 | je wowclassic.7FF7745DC3D5 |
$+12FC2DC00007FF7745DC2DC| 48 8B 8F E8 21 00 00| mov rcx,qword ptr ds:[rdi+21E8]|
$+12FC2E300007FF7745DC2E3| 4C 8D 45 00 | lea r8,qword ptr ss:[rbp]|
$+12FC2E700007FF7745DC2E7| 48 89 4D 00 | mov qword ptr ss:[rbp],rcx |
$+12FC2EB00007FF7745DC2EB| 48 8D 55 20 | lea rdx,qword ptr ss:[rbp+20]|
$+12FC2EF00007FF7745DC2EF| A8 01 | test al,1|
$+12FC2F100007FF7745DC2F1| B9 43 4C 4E 54| mov ecx,544E4C43 |
$+12FC2F600007FF7745DC2F6| B8 53 52 56 52| mov eax,52565253 |
$+12FC2FB00007FF7745DC2FB| 41 B9 0C 00 00 00 | mov r9d,C| C:’\f’
$+12FC30100007FF7745DC301| 0F 45 C8| cmovne ecx,eax |
$+12FC30400007FF7745DC304| 89 4D 08| mov dword ptr ss:[rbp+8],ecx |
$+12FC30700007FF7745DC307| 48 8B 8F 00 22 00 00| mov rcx,qword ptr ds:[rdi+2200]|
$+12FC30E00007FF7745DC30E| E8 CD B9 41 00| call wowclassic.7FF7749F7CE0 |==== 写入结构体内容call
$+12FC31300007FF7745DC313| 84 C0 | test al,al |
$+12FC31500007FF7745DC315| 74 76 | je wowclassic.7FF7745DC38D |
$+12FC31700007FF7745DC317| 45 8B 4F 10 | mov r9d,dword ptr ds:[r15+10]|==== 包长度
$+12FC31B00007FF7745DC31B| 48 8D 55 20 | lea rdx,qword ptr ss:[rbp+20]|==== rdx 一个结构体
$+12FC31F00007FF7745DC31F| 4D 8B 07| mov r8,qword ptr ds:[r15]| //包地址
$+12FC32200007FF7745DC322| 41 83 E9 10 | sub r9d,10 | //包长度-10 去掉包头
$+12FC32600007FF7745DC326| 48 8B 8F 00 22 00 00| mov rcx,qword ptr ds:[rdi+2200]| //edi 需要追
$+12FC32D00007FF7745DC32D| 49 83 C0 10 | add r8,10| //包地址+10从包体开始加密
$+12FC33100007FF7745DC331| E8 1A 99 41 00| call wowclassic.7FF7749F5C50 | //封包加密call
$+12FC33600007FF7745DC336| 48 83 FE 01 | cmp rsi,1|
$+12FC33A00007FF7745DC33A| 7E 28 | jle wowclassic.7FF7745DC364|
$+12FC33C00007FF7745DC33C| 49 8D 5F 20 | lea rbx,qword ptr ds:[r15+20]|
$+12FC34000007FF7745DC340| 48 FF CE| dec rsi|
$+12FC34300007FF7745DC343| 44 8B 4B 10 | mov r9d,dword ptr ds:[rbx+10]|
$+12FC34700007FF7745DC347| 48 8D 55 20 | lea rdx,qword ptr ss:[rbp+20]|
$+12FC34B00007FF7745DC34B| 4C 8B 03| mov r8,qword ptr ds:[rbx]|
$+12FC34E00007FF7745DC34E| 48 8B 8F 00 22 00 00| mov rcx,qword ptr ds:[rdi+2200]|
$+12FC35500007FF7745DC355| E8 F6 98 41 00| call wowclassic.7FF7749F5C50 |
$+12FC35A00007FF7745DC35A| 48 8D 5B 20 | lea rbx,qword ptr ds:[rbx+20]|
$+12FC35E00007FF7745DC35E| 48 83 EE 01 | sub rsi,1|
$+12FC36200007FF7745DC362| 75 DF | jne wowclassic.7FF7745DC343|
$+12FC36400007FF7745DC364| 48 8B 8F 00 22 00 00| mov rcx,qword ptr ds:[rdi+2200]|==== rcx 需要追
$+12FC36B00007FF7745DC36B| 4C 8D 45 10 | lea r8,qword ptr ss:[rbp+10] |==== r8 存放结果的指针
$+12FC36F00007FF7745DC36F| 48 8D 55 20 | lea rdx,qword ptr ss:[rbp+20]|==== rdx 一个结构体
$+12FC37300007FF7745DC373| E8 08 A6 41 00| call wowclassic.7FF7749F6980 | //来源这个call
$+12FC37800007FF7745DC378| 84 C0 | test al,al |
$+12FC37A00007FF7745DC37A| 74 11 | je wowclassic.7FF7745DC38D |
$+12FC37C00007FF7745DC37C| F2 0F 10 45 10| movsd xmm0,qword ptr ss:[rbp+10] | //来源rbp+10 开始的 C字节
$+12FC38100007FF7745DC381| 8B 45 18| mov eax,dword ptr ss:[rbp+18]|
$+12FC38400007FF7745DC384| F2 41 0F 11 44 24 04| movsd qword ptr ds:[r12+4],xmm0| //修改包头+4后面8字节
$+12FC38B00007FF7745DC38B| EB 4F | jmp wowclassic.7FF7745DC3DC| //这里跳
$+12FC38D00007FF7745DC38D| 48 8B 4F 08 | mov rcx,qword ptr ds:[rdi+8] |
$+12FC39100007FF7745DC391| E8 8A 66 FE FF| call wowclassic.7FF7745C2A20 |
$+12FC39600007FF7745DC396| 45 85 F6| test r14d,r14d |
$+12FC39900007FF7745DC399| 0F 8E 81 01 00 00 | jle wowclassic.7FF7745DC520|
$+12FC39F00007FF7745DC39F| 49 8D 5F 08 | lea rbx,qword ptr ds:[r15+8] |
$+12FC3A300007FF7745DC3A3| 41 8B FE| mov edi,r14d |
$+12FC3A600007FF7745DC3A6| 66 66 0F 1F 84 00 00 00 00 00 | nop word ptr ds:[rax+rax]|
$+12FC3B000007FF7745DC3B0| 48 8B 0B| mov rcx,qword ptr ds:[rbx] |
$+12FC3B300007FF7745DC3B3| 48 8D 15 66 86 96 00| lea rdx,qword ptr ds:[7FF774F44A20]|
$+12FC3BA00007FF7745DC3BA| 45 33 C9| xor r9d,r9d| r9d:“HalT”
$+12FC3BD00007FF7745DC3BD| 45 8D 41 22 | lea r8d,dword ptr ds:[r9+22] |
$+12FC3C100007FF7745DC3C1| E8 9A 6A 93 FF| call wowclassic.7FF773F12E60 |
$+12FC3C600007FF7745DC3C6| 48 8D 5B 20 | lea rbx,qword ptr ds:[rbx+20]|
$+12FC3CA00007FF7745DC3CA| 48 83 EF 01 | sub rdi,1|
$+12FC3CE00007FF7745DC3CE| 75 E0 | jne wowclassic.7FF7745DC3B0|
$+12FC3D000007FF7745DC3D0| E9 4B 01 00 00| jmp wowclassic.7FF7745DC520|
$+12FC3D500007FF7745DC3D5| 33 C0 | xor eax,eax|
$+12FC3D700007FF7745DC3D7| 49 89 44 24 04| mov qword ptr ds:[r12+4],rax |
$+12FC3DC00007FF7745DC3DC| 45 8B C6| mov r8d,r14d |==== 跳过来的
$+12FC3DF00007FF7745DC3DF| 41 89 44 24 0C| mov dword ptr ds:[r12+C],eax | ====修改包头 +C 开始 4字节
$+12FC3E400007FF7745DC3E4| 49 8B D7| mov rdx,r15| ====[r15]包地址[r15+10]包长
$+12FC3E700007FF7745DC3E7| 48 8B CF| mov rcx,rdi|
$+12FC3EA00007FF7745DC3EA| E8 41 AE FE FF| call wowclassic.7FF7745C7230 | ====返回
加密call 没有做太多隐藏
调用接口直接给了我们,当然你可以像我们幻想神域中一样,直接偷加密函数功能出来
$+12FC31300007FF7745DC313| 84 C0 | test al,al |
$+12FC31500007FF7745DC315| 74 76 | je wowclassic.7FF7745DC38D |
$+12FC31700007FF7745DC317| 45 8B 4F 10 | mov r9d,dword ptr ds:[r15+10]| //包长度
$+12FC31B00007FF7745DC31B| 48 8D 55 20 | lea rdx,qword ptr ss:[rbp+20]| //rdx 一个结构体
$+12FC31F00007FF7745DC31F| 4D 8B 07| mov r8,qword ptr ds:[r15]| ====包地址
$+12FC32200007FF7745DC322| 41 83 E9 10 | sub r9d,10 |====包长度-10 去掉包头
$+12FC32600007FF7745DC326| 48 8B 8F 00 22 00 00| mov rcx,qword ptr ds:[rdi+2200]| //edi 需要追
$+12FC32D00007FF7745DC32D| 49 83 C0 10 | add r8,10| //包地址+10从包体开始加密
$+12FC33100007FF7745DC331| E8 1A 99 41 00| call wowclassic.7FF7749F5C50 | //封包加密call
$+12FC33600007FF7745DC336| 48 83 FE 01 | cmp rsi,1|
$+12FC33A00007FF7745DC33A| 7E 28 | jle wowclassic.7FF7745DC364|
如果是完整明文封包我们有了一个HOOK位置
第四,再返回的位置即为明文封包
直接发送明文封包内容实现封包功能
例如喊话call
整个流程分析下来,结论是,这个游戏的调用过程是比较简单的
可以修改加强防护的地方有很多,但是毕竟是多年前的老游戏了,属于正常范围。
不过这里面存在一个问题,我们要Hook明文包的位置,也就是WOW代码段不允许改写,下节课我们来提供改写和Hook 的方法!
深入学习游戏逆向分析,****学院搜索-----吉林飞郁网络培训.
(部分实战篇、安卓篇等因logo以及视频格式问题无法上传,咨询请私我)
****学院免费入门课:https://edu.****.net/course/detail/30509