游戏安全实验室-游戏逆向-游戏辅助开发

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 3814|回复: 2

一种应用层(不用驱动)通杀eac be tp主流游戏检测系统的注入方法

[复制链接]
匿名  发表于 2023-9-18 22:19:44 |阅读模式
先说结论,这是一种劫持系统进程白加黑shellcode注入游戏的方案

没有什么新技术,只是应用了病毒开发的方法,并把应用层技术做到了极致.

想看内核驱动vt ept之类高大上技术可以退散了.

这是一种系统的方法论,我讲述的只是方法,想直接要代码不想看废话的可以直接拉到末尾.

请注意,代码随时可能被特征被检测,当代码公开发表时,已经可以认为是失效了,但是方法论不会失效.

第一次见到这项组合技术时我非常惊讶的,在我印象里,只有驱动才能对抗驱动.

注入不进去怎么办,上驱动,没句柄权限无法读写怎么办,上驱动,驱动还搞不定怎么办,上vt ept

一层层深入技术对抗把问题复杂化.

那么有没有在应用层就能解决问题的方法.

咱们来把视角转回病毒开发.

首先,病毒面对的是什么,病毒面对的是杀毒软件,杀毒软件比游戏检测系统更严密.各种系统漏洞早早就堵死了.

如何开发一款病毒,病毒开发不像外挂,没有驱动,没有系统级执行权限,还有面对各种严密的检测.病毒的二进制文件也会面临杀毒软件一遍遍严密的扫描分析.

因此病毒开发注定了要隐蔽,要隐藏,要最小化特征,要螺蛳壳里做道场,要特别精细.

像注入普通进程里那样打开句柄写入dll写入二进制在win98时代都不行了.

看,杀毒软件和新时代外挂检测系统是不是特别相似,都是把windows系统的所有漏洞统统堵死,都是会检测文件的二进制特征.

一旦文件落地都会反复特征查杀.在我看来,现在的外挂检测系统就是种杀软.
这套技术,使用了句柄劫持,可以读写游戏进程内存.

使用外部读写而设计的,读写性能在我看来已经达到最优水平.(共享内存,极简通信协议,直接调用zw_xxxx函数,开销最小)

至少在我看来,用来制作fps,rpg游戏外挂毫无问题.

它的设计目标是隐蔽性,注入进程和外挂进程分离,当你打开游戏加载反外挂系统时,注入进程已经被删除.以此来增加外挂安全性.

但是,所有已经公开发表的内容,游戏的反外挂开发人员一定会知道该如何反制它.所以,如果你想要继续使用这套方法,请发挥你的创造力和想象力,继续保持这套方法的隐蔽.

请记住,这是一场猫鼠游戏,就像其他任何注入方法一样,失效只是时间问题.,
(本文面向初学者,所以很多概念性需要解释)

要理解本文需要熟悉windows api和句柄劫持.

所谓句柄劫持就是说,
``cpp
OpenProcess()
``
外挂这样打开游戏进程,在游戏反外挂系统保护下,是不允许这样做的.打开游戏进程会失败,或者给你返回一个假句柄.

因此,在早期的外挂制作中,想到了一种办法.

外挂无法打开游戏句柄,但是系统进程是可以打开游戏句柄.

你想想,游戏要和操作系统做无数交互,不允许操作系统进程打开游戏句柄,游戏别想正常运行了.

因此诞生了句柄劫持技术.
一句话解释就是
我没有游戏句柄权限,找一个有打开句柄权限的系统进程,借用它的句柄,来操作游戏.
"借刀杀人"
(本文面向初学者,所以很多概念性需要解释)

要理解本文需要熟悉windows api和句柄劫持.

所谓句柄劫持就是说,
``cpp
OpenProcess()
``
外挂这样打开游戏进程,在游戏反外挂系统保护下,是不允许这样做的.打开游戏进程会失败,或者给你返回一个假句柄.

因此,在早期的外挂制作中,想到了一种办法.

外挂无法打开游戏句柄,但是系统进程是可以打开游戏句柄.

你想想,游戏要和操作系统做无数交互,不允许操作系统进程打开游戏句柄,游戏别想正常运行了.

因此诞生了句柄劫持技术.
一句话解释就是
我没有游戏句柄权限,找一个有打开句柄权限的系统进程,借用它的句柄,来操作游戏.
"借刀杀人"
来列举出反外挂系统的检测条目:

1.句柄.句柄表检测,传统手艺了.不清楚的百度搜索.

并且,在注入的过程中,也不应该有新的句柄,比如,在系统进程lsass.exe中有一个命名管道句柄,这显然是不合理的.
2.模块.不应该使用dll注入,而应该用shellcode.

3.线程.不应该出现的线程但是出现了,注入线程的起始地址真正线程起始地址显然是不同的,通过栈回溯显然可以分析出线程的真实目的.

4额外执行代码页..上面提到的,莫名其妙多出来一块可执行内存页这可就太容易检测了.

因此,要对抗升级后的反外挂系统,我们的注入需要具备以下特点:

无模块 无线程 无新增的可执行代码页 不创建句柄.

这种方法兼容windows 7及更高版本,使用lsass.exe劫持注入.

但是如果要在win10上使用,需要绕过PPL保护(如果不懂什么是PPL保护,请百度)

咱们来逐步解决以上难题.

1.获取一个无句柄的进程间通信系统.

尽可能高性能的进程间通讯,并且要符合隐秘原则.

无论命名管道还是共享内存,都会生成一个新的句柄

比如
CreateFileMapping();
CreateNamePipe();
CreateFile();
有一种方法可以在不保留句柄的情况下,获取共享内存.
以下是MSDN的解释

文件映射对象的映射视图会保持对该对象的内部引用,只有当所有对该对象的引用都被释放后,文件映射对象才会关闭。因此,要完全关闭一个文件映射对象,应用程序必须通过调用UnmapViewOfFile解除所有对文件映射对象的映射视图,并通过调用CloseHandle关闭文件映射对象的句柄。这些函数可以以任何顺序调用。

我们可以利用这点.

在进程A中创建文件映射.获取句柄.

在进程A中使用MapViewOfFile(),创造出一块共享内存,并且获得指向这块共享内存的指针.

在进程B中打开文件映射.OpenFileMapping()获取句柄.

在进程B中使用MapviewOfFile(),在进程B中可以使用这块共享内存,并且获得了指向这块内存的指针.

于此同时,进程A,进程B都使用closeHandle()关闭句柄.

由于这块共享内存对象的所有句柄都关闭,其他任何进程都无法连接它,使用OpenFileMapping也将失败.

但是该共享内存在进程A进程B之间的映射依然是可用的.

现在,我们掌握了一种可以在没有任何句柄下相互发消息的方式.接下来,我们要解决同步的问题.
先解释名词:同步.

在内存高频读写时,1ms可以读写上万次,如果两个线程同时读取写入同一个内存地址,是不是有很高概率会出事.

这里同步,就是告诉其他读取这块内存地址的人,我在读写,你们都先别读写,等我读完,你们再读,防止冲突.

以前,使用信号量进行同步.(信号量:一种进程间同步方式,具体百度)

但是创建信号量会产生句柄.
作为替代,使用了自旋锁进行同步.(自旋锁机制以及如何进行同步防止访问冲突请百度,或者询问gpt-4)

自旋锁将读取共享内存中特定地址处的某个字节值,等待它等于某个值时跳出循环.

以下是自旋锁代码

while (true)
{
        if (*(BYTE*)0x12345678 == 1)
                break;
}
好了,现在我们拥有了一个进程间同步通讯系统,
为了实现以上这些功能,我们需要lsass.exe映射共享内存,释放句柄,这意味着需要lsass.exe执行指令.

由于需要隐蔽性,不使用dll注入,而使用shellcode执行.

要执行shellcode,需要在系统进程中创建一块可执行内存.

但是我们的目标是隐蔽,因此要避免创建新的可执行内存.

下面要科普一些内存分页知识.

内存是按页分配,这就是解释了当你向系统请求申请一段内存时,malloc() 100BYTE
最终你会得到一个4KBYTE内存页.

比如下图中lsass.exe的image 可读可执行页, 在页面末尾还有大量为使用的BYTE
![](upload/attach/202309/1_4JSXXQD4P63WWW4.png)
我之前提及的这项技术有一个专门的名词叫“code coves”(代码洞)。通过使用CE的“code coves”功能,你也可以找到它。

我们可以走得更远,寻找代码中不常用的功能来进行直接修改,比如直接更改系统dll中不常用的内存空间。

直到我编写这篇文章的时间——2023年9月16日,我还没有见到针对这种技术的检测方法。

在Windows系统中,有大量的历史遗留代码,其中一些甚至可以追溯到Win98时代。随意更改这些代码不会产生任何影响。

利用“Process Hacker”软件可以非常方便地找到你想利用的进程空间。

打开“Process Hacker”,双击你想要利用的进程,切换到内存页面,找到可执行内存部分并展开它。这样你就可以看到未使用的可执行内存字节,显示为:

$$
Copy code00 00 00 00 00 00
$$

“Process Hacker”甚至可以帮你很方便地找到被注入的dll或shellcode。

举例来说,如果某个检测程序将shellcode注入到dwm.exe来截图检测用户的游戏行为,你可以通过“Process Hacker”清楚地看到提示表明有一段shellcode存在于该进程中。因此,我们建议你隐藏和混淆你的shellcode以保护它免受检测。
在我给出的代码中,你可以使用FindExecutableMemory()来寻找页面尾部未使用的内存.

ok,现在我们获得了可用的可执行内存,接下来开始设置绕过lsass.exe.

我们目标是在lsass.exe中映射出一个共享内存.

要映射一块内存,必须调用
CreateFileMapping()

MapViewOfFile()

另一个进程
OpenFileMapping()

MapViewOfFile()

请注意,lsass.exe是有高权限的系统进程,(in session 0),如果由lsass创建file mapping

我们的安装程序就无法加入这个file mapping.

因此,安装程序将以较低的权限运行,创建文件映射,然后lsass加入.

完整代码在老外论坛:https://www.unknowncheats.me/forum/anti-cheat-bypass/261176-silentjack-ultimate-handle-hijacking-user-mode-multi-ac-bypass-eac-tested.html
1.png
回复

使用道具

0

主题

23

回帖

52

积分

注册会员

积分
52
发表于 2024-7-24 00:07:56 | 显示全部楼层
感谢分享
回复

使用道具 举报

0

主题

1

回帖

14

积分

新手上路

积分
14
发表于 2024-8-15 14:37:35 | 显示全部楼层
感谢分享
回复

使用道具 举报

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

本版积分规则

QQ|Archiver|手机版|小黑屋|游戏安全实验室

GMT+8, 2024-11-23 16:15 , Processed in 0.054339 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表