403.WOWx64怀旧服明文封包及加密解密分析

2020-09-21 03:25:14 任鸟飞逆向 1152
大家好,我是任鸟飞逆向
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

typedef UINT64(*asmCALLAddr)(QWORD RCX, QWORD RDX, QWORD R8, QWORD R9); asmCALLAddr g_asmCALLAddr = (asmCALLAddr)0x0;


void Call_talk()
{
QWORD Base = (QWORD)GetModuleHandleA("wowclassic.exe") + 0x2673128;
QWORD Temp = *(QWORD*)Base;
Temp = *(QWORD*)(Temp + 0 * 8 + 0x190);
QWORD RCX = *(QWORD*)(Temp + 0x0E0);
Temp = *(QWORD*)RCX;
QWORD Calladdr = *(QWORD*)(Temp + 0x8);
g_asmCALLAddr = (asmCALLAddr)Calladdr;
char d[27] = { 0xE7,0x37,0x07,0,0,0,0x9,0x80,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31 };
DWORD RDX_J[10] = {0,0,0,0,0x1B,0x10};
*(QWORD*)RDX_J = (QWORD)d;
QWORD RDX = (QWORD)RDX_J;
QWORD R8 = 1;
QWORD R9 = 0;
g_asmCALLAddr(RCX, RDX, R8, R9);
}

整个流程分析下来,结论是,这个游戏的调用过程是比较简单的

可以修改加强防护的地方有很多,但是毕竟是多年前的老游戏了,属于正常范围。



不过这里面存在一个问题,我们要Hook明文包的位置,也就是WOW代码段不允许改写,

下节课我们来提供改写和Hook 的方法!




2020.9.20 第11期在线班开课

价格6288

目前已经开启报名通道

课程包含最新热门游戏,热门技术,详情咨询


电话咨询
QQ客服