首页
论坛
课程
招聘
雪    币: 5282
活跃值: 活跃值 (61)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝

[调试逆向] [原创]那些年我曾今玩过的魔兽外挂(一)

2019-3-6 12:30 8652

[调试逆向] [原创]那些年我曾今玩过的魔兽外挂(一)

2019-3-6 12:30
8652

0x0 序言  

本系列文章的发布顺序并非按照外挂功能复杂程度排序,这点请各位看官注意。

  另外,亲爱的大手子们,你以为不封你们真的是因为没检测到你们吗?

  那么,接下来要说的这个,应该是我目前玩过的在思路上最巧妙的,涉及到的点也是个检测的盲点,在长达10年(毫不夸张)的对抗过程中被双方都忽略点。

  文件名:jasstools.zip

  包含文件:jasstools.m3d,globals.txt,function.txt,main.txt,Game.dll

  MD5:

  jasstools.m3d: f55f15eb7a6c5b962df6a32c40d09372

  game.dll:267861a0dfd416dbad13e7ee3ec7794a

0x1 分析

  OK,依照惯例从DllMain()开始:


  DllMain()非常清晰没什么好看的,当 ul_reason_for_call == DLL_PROCESS_ATTACH,即dll挂靠的时候执行 InitHack()函数

  显然这个“InitHack()”函数才是我们要关注的重点。


  就一份外挂来说,这个流程是写得非常符合“war3的规范的”,甚至比一些商业代码都要规范,当然还有更规范的外挂代码。其中有一句代码是我要吐槽的:

if ( strstr(&v_file_name, "War3.exe") || (v_ret_val = strstr(&v_file_name, "war3.exe")) != 0 )

  这种代码在这份显得“非常正规”的代码中简直是神一样的存在,因为正常做法大概是:

std::transform(name.begin(), name.end(), name.begin(), ::tolower);

  虽然这样要多写一点代码,但是看起来更符合这份代码的风格不是吗?

  当然这句话我在很多易语言源码中见过比如:“game.dll”、““Game.dll” 、“GAME.DLL”比较三次的,实际上根本不用比较。


  其流程图大致如下:


  吐槽完毕,显然通过观察流程我们发现样本做了一个非常关键的操作,即hook g_game_module_handle + 0x1FAB34 也就是compline_jass_script()这个函数。
  不得了啦!偷梁换柱嘞!不被发现的那种~~~
  好,那么我们看下这个回调函数DetourGameComplineJassScript()

  就截图了上半部分,下半部分不是关键,所以省略了。
  那么这一大串东西,到底做了些什么?其实很简单,看以下伪代码:
while(编译的脚本 != nullptr)
{
    if(v_当前编译的脚本名称 == "war3map.j")
    {
        ......
        v_修改后的脚本大小 == 向原地图脚本中插入作弊脚本();
        将脚本使用暴雪字符串处理规范进行处理();
        覆盖原脚本Buffer();
        ...... 
    }
}
调用原ComplineJassScript();
  看以下流程图:

  所以,这个外挂的核心功能流程已经被我们分析清晰了,当然这个关键函数里还有一个关键点:InsertCheatScriptToMapOrginJassScript()
这个函数负责向内存中的原地图脚本插入作弊脚本,那么我们跟进去看看它是怎么实现这个操作的:

  哇!这密密麻麻的一坨是啥?看着好恐怖啊!实际上一点都不恐怖,你只需要关注我画红框的地方。这些就是这个函数的关键,你只要关心它们就好了。
再给出流程图之前,我们要引入一个前置知识,Jass2语言:

  当然,百科上说的太抽象了,实际上你可以这么理解,jass2是一种脚本语言,运行在一个名为“jass虚拟机”的解释器上,因此jass2 ≈  java,jass2 ≈ C#,jass2  ≈ lua等等,这样是不是就好理解了?
为了理解这个外挂为什么要这么做,以及这么做能达到什么效果,我们来实际操作一下帮助大家理解一下。
首先新建一个地图, 编写一个示例喊话call,其效果如下所示:

  然后。解压出它的脚本文件“war3map.j”,为其添加,外挂作者的喊话call函数:

 
  这里再讲到一个概念:就是触发器模式。
  这个模式已经被广泛应用到unity、虚幻等引擎中,教科书般得阐述了“事件驱动”编程这个思想。 那么jass2中的一个触发器的结构是什么样子的?
  它由三个部分组成,触发器变量 trigger xxx,一个自定义条件或者动作函数,当然条件或者动作函数只要有一种就好,两者都有就是一个标准的触发器,当然如果都没有那么这个触发器就没有任何意义了。
  那么它是如何工作的?如上图所示,首先要对触发器变量进行初始化,即"CreateTrigger()",当然在其定义的时候也可以一次性初始化,可以少写一行代码。然后为其绑定条件和动作( 这里不再展开其中的区别 ),最后在main函数对这个触发器进行“ 注册 ”,即在main函数中调用初始化函数。
  到这里,相信你也应该明白了它的工作原理,可以做如下猜测 globals区域以endglobals为结尾(对应globals.txt),从下一行开始为自定义函数区域(对应functions.txt),直到main函数为止,main函数类似于c语言中的main函数(对应main.txt)。
我们将修改过的“war3map.j”文件替换回原地图,其效果如下:

所以,InsertCheatScriptToMapOrginJassScript核心流程如下所示:

  怎么样,是不是能看懂了?
  至此,这个外挂样本的功能已经基本逆向完毕。
  现在回过头来说说它的“ Anti检测功能 ”。我们知道Themida会处理几个函数,分别是:
“ DbgBreakPoint ”,“DbgUiRemoteBreakin”,“DbgUserBreakPoint”,这个外挂处理的方法也很暴力,通过GetProcAddress获得其地址以后,直接恢复原来的字节试图达到恢复hook的目的。

  注意,我说的是“试图”,你以为恢复了hook就能调试了?太年轻了,小伙子。
  他还处理了硬断检测使用了ClearDrRegisters,不过,单hook不会触发这个检测,就不多讲了,流程就是暂停线程->获取线程上下文->清空调试寄存器->恢复线程。
  至此,整个样本分析完毕。

0x2 检测

  好了,知道它干了哪些坏事,我们就可以针对他进行一波检测。
  1.还记得这句代码吗?
g_int_game_compline_jass_script = (int)(g_game_module_handle + 0x1FAB34);
 我们可以检测这个hook点,当然,由于反作弊系统的加载要远早于外挂的加载,所以,在初始化的时候检测是不可行的,因此可以把这个检测的时机延后到jass_vm_entry()。这个时候外挂已经加载,且因为他没有清理和卸载工作,所以hook不会恢复,必定能检测到。
  2.拦截模块加载,这里采用白名单模式,IAThook mss32.LoadLibrary来过滤魔兽的自加载插件,不在白名单内的全部砍了。
  3.文件CRC,时机同样在 jass_vm_entry()。这里的CRC有个技巧:先从服务器上得到地图j文件的md5保证其未被篡改,然后从地图中提取它并映射到内存,然后运算其CRC32值,然后与内存中已经加载的j文件的CRC32做比较,如不同,就判定为作弊。
  4.函数列表检测,从jass虚拟机中取出所有的函数名称以及数量,与原始文件进行比较,如有差异则判定为作弊(当然这里要对dota特殊处理,将自己添加的函数也加入原文件的函数列表中,其数量亦增加相应数值。)
  5.CallStack检测,栈帧回溯,没啥用,放弃这个方案。

0x2 总结

  这个外挂样本为我们展现了静态替换的升级版本,动态替换,直接攻击了游戏的脚本编译函数,切中了反作弊系统的忙点,有一定的研究价值,也提醒我们在与外挂对抗的过程中,不要忽略任何一个可能被利用的点,道高一尺,魔高一丈,不能用老眼光、老思路看待作弊手段。

0x3 补充

  那位说,“该编译函数一共只调用了4次,所以我们可以检测它的调用次数,如果超过4次就判定为作弊。”的同学,你的思路没错,就是没考虑完全。外挂加载的时机要远远晚于反作弊模块,且它是inlinehook不会额外增加引用计数、其次它的hook的会覆盖你的inlinehook,所以你就永远检测不到它,这也是这个样本为什么能在线上活跃两年之久的原因。希望你看完这篇文章以后能更新一下代码,让这款外挂从线上消失。
  那么,大家一起加油吧!





最后于 2019-3-6 12:35 被黑洛编辑 ,原因:
上传的附件:
最新回复 (23)
雪    币: 0
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
uestclv 活跃值 2019-3-6 13:25
2
0
支持~~~
雪    币: 436
活跃值: 活跃值 (98)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
BkHumor 活跃值 2019-3-6 13:45
3
0
打魔兽吗?我人族贼菜
雪    币: 4783
活跃值: 活跃值 (1042)
能力值: (RANK:40 )
在线值:
发帖
回帖
粉丝
Editor 活跃值 2019-3-6 14:11
4
0
感谢分享~
雪    币: 1611
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
aabiaobiao 活跃值 2019-3-6 14:13
5
0
占个楼 你算是比较有牌面的  至少比那个大黄狗 好多了 我就看他很不舒服
雪    币: 6334
活跃值: 活跃值 (49)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
HadesW 活跃值 1 2019-3-6 14:30
6
0
等老哥下一篇!
雪    币: 402
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
DWwinter 活跃值 2019-3-6 14:59
7
0
aabiaobiao 占个楼 你算是比较有牌面的 至少比那个大黄狗 好多了 我就看他很不舒服
吐槽千万条,文明第一条。用语不规范,四楼两行泪。
雪    币: 2251
活跃值: 活跃值 (15)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
刘铠文 活跃值 2019-3-6 15:06
8
0
aabiaobiao 占个楼 你算是比较有牌面的 至少比那个大黄狗 好多了 我就看他很不舒服
你看外挂相关帖子应该都会觉得很舒服,很有排面
雪    币: 515
活跃值: 活跃值 (12)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
ggsuper 活跃值 2019-3-31 14:56
9
0
感谢分享~
雪    币: 1582
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
木志本柯 活跃值 2019-4-8 02:28
10
0
呦西检测手段收藏了
雪    币: 1
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whitelen 活跃值 2019-4-8 17:49
11
0
妈呀
雪    币: 0
活跃值: 活跃值 (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
pengrui 活跃值 2019-4-8 22:45
12
0
只看到了喊话功能,没有变态功能
雪    币: 5282
活跃值: 活跃值 (61)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
黑洛 活跃值 1 2019-4-9 00:14
13
0
pengrui 只看到了喊话功能,没有变态功能
那说明你没看懂,再看一遍,没看懂就再看10遍,看到看懂为止。
雪    币: 321
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
岭南散人 活跃值 1 2019-4-9 08:51
14
0
对于电脑游戏几乎从不感兴趣。但开阔了眼界。谢谢
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
上古七夜 活跃值 2019-11-22 15:48
15
0
网易平台 对抗图 无效。 自定义脚本 能开起来, 不过跟平台玩家不同步,看不到任何一个人。 可以聊天。
雪    币: 347
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
mb_qkotfqiz 活跃值 2019-11-23 13:36
16
0
注入类型的都是垃圾外挂,外挂功能全驱动内核操作才是正确姿势。
最后于 2019-11-23 13:37 被mb_qkotfqiz编辑 ,原因:
雪    币: 5282
活跃值: 活跃值 (61)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
黑洛 活跃值 1 2019-11-24 20:17
17
0
mb_qkotfqiz 注入类型的都是垃圾外挂,外挂功能全驱动内核操作才是正确姿势。
山总说的对,山总开发个 全内核的挂开源啊。
雪    币: 347
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
mb_qkotfqiz 活跃值 2019-11-24 21:17
18
0
黑洛 山总说的对,山总开发个 全内核的挂开源啊。
开源是不可能的,这辈子是不可能开源的。
雪    币: 0
活跃值: 活跃值 (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
pengrui 活跃值 2020-1-7 16:01
19
0
你说这句话我就觉得你很无知,愚昧
雪    币: 224
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_qjljtrkk 活跃值 2020-3-7 16:02
21
0
老哥麻烦您能加我一下联系方式吗我的qq1255165501  想请教您几个问题 高价回报
雪    币: 33
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
wx_洛溪 活跃值 6天前
22
0
请问下大佬子啊官方对战调试过没 用od断下来魔兽就崩溃了
雪    币: 5282
活跃值: 活跃值 (61)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
黑洛 活跃值 1 6天前
23
0
wx_洛溪 请问下大佬子啊官方对战调试过没 用od断下来魔兽就崩溃了
写个驱动把那个反调试过了吧,r3也能搞,但是r3要处理的东西太多了。具体看我git吧,有例子
雪    币: 33
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
wx_洛溪 活跃值 6天前
24
0
大佬git ID是啥或者给个链接
游客
登录 | 注册 方可回帖
返回