【转】【原创】某超级模块中游戏双开功能实现

【转】某超级模块中游戏双开功能实现

超级模块中有个双开功能,能够双开腾讯的大部分游戏,例如DNF。于是就下载模块下来分析了一下。

随便在网上找一个用超级模块写的双开工具。然后OD载入,下bp DeleteFileA断点。

为什么要下deleteFile断点,而不是CreateFile,是因为该模块注册驱动文件后就会将驱动文件删除。

下了断点之后点击启动双开的时候,OD断下。查看堆栈,可以看到写出的驱动路径。


点击图片以查看大图  图片名称: del.jpg 查看次数: 4 文件大小: 33.2 KB 文件 ID : 78833

将驱动文件拷贝出来,文件大小只有3kb,用IDA打开。

代码:
INIT:00010985 ; NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
INIT:00010985                 public DriverEntry
INIT:00010985 DriverEntry     proc near
INIT:00010985
INIT:00010985 DriverObject    = dword ptr  8
INIT:00010985 RegistryPath    = dword ptr  0Ch
INIT:00010985
INIT:00010985                 mov     edi, edi
INIT:00010987                 push    ebp
INIT:00010988                 mov     ebp, esp
INIT:0001098A                 mov     eax, dword_10904
INIT:0001098F                 test    eax, eax
INIT:00010991                 mov     ecx, 0BB40h
INIT:00010996                 jz      short loc_1099C
INIT:00010998                 cmp     eax, ecx
INIT:0001099A                 jnz     short loc_109BF
INIT:0001099C
INIT:0001099C loc_1099C:                              ; CODE XREF: DriverEntry+11j
INIT:0001099C                 mov     edx, ds:KeTickCount
INIT:000109A2                 mov     eax, offset dword_10904
INIT:000109A7                 shr     eax, 8
INIT:000109AA                 xor     eax, [edx]
INIT:000109AC                 and     eax, 0FFFFh
INIT:000109B1                 mov     dword_10904, eax
INIT:000109B6                 jnz     short loc_109BF
INIT:000109B8                 mov     eax, ecx
INIT:000109BA                 mov     dword_10904, eax
INIT:000109BF
INIT:000109BF loc_109BF:                              ; CODE XREF: DriverEntry+15j
INIT:000109BF                                         ; DriverEntry+31j
INIT:000109BF                 not     eax
INIT:000109C1                 mov     dword_10900, eax
INIT:000109C6                 pop     ebp
INIT:000109C7                 jmp     sub_106F8
INIT:000109C7 DriverEntry     endp

入口函数处没什么特殊的,跳到了sub_106F8,下面来看看这个函数里面具体实现。

代码:
.text:000106F8 ; int __stdcall sub_106F8(PDRIVER_OBJECT DeviceObject, int)
.text:000106F8 sub_106F8       proc near               ; CODE XREF: DriverEntry+42j
.text:000106F8
.text:000106F8 SymbolicLinkName= UNICODE_STRING ptr -10h
.text:000106F8 DestinationString= UNICODE_STRING ptr -8
.text:000106F8 DeviceObject    = dword ptr  8
.text:000106F8
.text:000106F8                 mov     edi, edi
.text:000106FA                 push    ebp
.text:000106FB                 mov     ebp, esp
.text:000106FD                 sub     esp, 10h
.text:00010700                 push    esi
.text:00010701                 mov     esi, [ebp+DeviceObject]
.text:00010704                 push    edi
.text:00010705                 mov     edi, ds:RtlInitUnicodeString
.text:0001070B                 push    offset word_106A6 ; SourceString
.text:00010710                 lea     eax, [ebp+DestinationString]
.text:00010713                 push    eax             ; DestinationString
.text:00010714                 mov     dword ptr [esi+38h], offset sub_10486      //设置IRP处理函数
.text:0001071B                 mov     dword ptr [esi+40h], offset sub_10486
.text:00010722                 mov     dword ptr [esi+70h], offset sub_104AA
.text:00010729                 mov     dword ptr [esi+34h], offset sub_10670
.text:00010730                 call    edi ; RtlInitUnicodeString        //初始化设备名称
.text:00010732                 lea     eax, [ebp+DeviceObject]
.text:00010735                 push    eax             ; DeviceObject
.text:00010736                 push    0               ; Exclusive
.text:00010738                 push    0               ; DeviceCharacteristics
.text:0001073A                 push    22h             ; DeviceType
.text:0001073C                 lea     eax, [ebp+DestinationString]
.text:0001073F                 push    eax             ; DeviceName
.text:00010740                 push    0               ; DeviceExtensionSize
.text:00010742                 push    esi             ; DriverObject
.text:00010743                 call    ds:IoCreateDevice          //创建设备
.text:00010749                 test    eax, eax
.text:0001074B                 jl      short loc_10780
.text:0001074D                 push    offset word_106CA ; SourceString
.text:00010752                 lea     eax, [ebp+SymbolicLinkName]
.text:00010755                 push    eax             ; DestinationString
.text:00010756                 call    edi ; RtlInitUnicodeString        //初始化符号链接名称
.text:00010758                 lea     eax, [ebp+DestinationString]
.text:0001075B                 push    eax             ; DeviceName
.text:0001075C                 lea     eax, [ebp+SymbolicLinkName]
.text:0001075F                 push    eax             ; SymbolicLinkName
.text:00010760                 call    ds:IoCreateSymbolicLink          //创建符号链接        
.text:00010766                 mov     esi, eax
.text:00010768                 test    esi, esi
.text:0001076A                 jge     short loc_10779            //创建成功就跳过去
.text:0001076C                 push    [ebp+DeviceObject] ; DeviceObject
.text:0001076F                 call    ds:IoDeleteDevice          //创建失败则删除设备
.text:00010775                 mov     eax, esi
.text:00010777                 jmp     short loc_10780
.text:00010779 ; ---------------------------------------------------------------------------
.text:00010779
.text:00010779 loc_10779:                              ; CODE XREF: sub_106F8+72j
.text:00010779                 call    sub_105C8
.text:0001077E                 xor     eax, eax
.text:00010780
.text:00010780 loc_10780:                              ; CODE XREF: sub_106F8+53j
.text:00010780                                         ; sub_106F8+7Fj
.text:00010780                 pop     edi
.text:00010781                 pop     esi
.text:00010782                 leave
.text:00010783                 retn    8
.text:00010783 sub_106F8       endp

创建设备,创建符号链接,用于与R3层通讯。那么主要的功能实现就在  call    sub_105C8 这个函数里面了。


代码:
.text:000105C8 sub_105C8       proc near               ; CODE XREF: sub_106F8:loc_10779p
.text:000105C8                 mov     eax, ds:KeServiceDescriptorTable    //得到系统服务描述表的地址
.text:000105CD                 push    esi          
.text:000105CE                 mov     esi, [eax]        //得到表中第一个函数的位置
.text:000105D0                 add     esi, 0ACh        // 加上0xAC,表中每个函数地址占4个字节,0ac / 4 = 43
.text:000105D6                 mov     eax, [esi]        
.text:000105D8                 mov     dword_1090C, eax        //保存ssdt表中的43号函数地址到全局变量
.text:000105DD                 call    sub_104EA        //通过cr0寄存器去掉写保护
.text:000105E2                 call    ds:KeRaiseIrqlToDpcLevel      //提升中断请求等级
.text:000105E8                 mov     cl, al          ; NewIrql  
.text:000105EA                 mov     dword ptr [esi], offset MyNtCreateMutant  //SSDT HOOK 43号函数
.text:000105F0                 call    ds:KfLowerIrql
.text:000105F6                 sti            //恢复cr0
.text:000105F7                 push    eax
.text:000105F8                 mov     eax, dword_10908
.text:000105FD                 mov     cr0, eax
.text:00010600                 pop     eax
.text:00010601                 xor     eax, eax
.text:00010603                 inc     eax
.text:00010604                 pop     esi
.text:00010605                 retn
.text:00010605 sub_105C8       endp

通过上面可以看出驱动仅仅是对 SSDT表中的43号函数进行了hook。
点击图片以查看大图  图片名称: 43.jpg 查看次数: 8 文件大小: 188.5 KB 文件 ID : 78834

用XT看了一下43号 即:NtCreateMutant函数。

而用户层的CreateMetux函数最终调用的就是内核层的NtCreateMutant。

也就是说 DNF判断游戏双开的方法之一就是互斥体。

最后再来看看HOOK函数中是怎样处理的。


代码:
.text:00010574                 mov     edi, edi
.text:00010576                 push    ebp
.text:00010577                 mov     ebp, esp
.text:00010579                 push    ecx
.text:0001057A                 push    ecx
.text:0001057B                 push    esi
.text:0001057C                 push    offset SourceString     ; sourceString = "\\basenamedobjects\\dbefeuate_ccen_khxfor"...
.text:00010581                 lea     eax, [ebp-4]       ; 局部变量1
.text:00010584                 push    eax                   ; DestinationString
.text:00010585                 call    ds:RtlInitUnicodeString     ; 初始化一个内容为\\basenamedobjects\\dbefeuate_ccen_khxfor的PUNICODE_STRING到局部变量1
.text:0001058B                 mov     esi, [ebp-8]       ; 局部变量2
.text:0001058E                 test    esi, esi
.text:00010590                 jz      short loc_105A5       ; 如果局部变量2为0,跳
.text:00010592                 push    0                     ; 不区分大小写
.text:00010594                 push    dword ptr [esi+8] ; String2  ; 
.text:00010597                 lea     eax, [ebp-8]       ; 局部变量2
.text:0001059A                 push    eax                   ; String1
.text:0001059B                 call    ds:RtlEqualUnicodeString    ;变量2 与参数3中的Unicode_String比较
.text:000105A1                 test    al, al  
.text:000105A3                 jnz     short loc_105BB       ; 如果两个字符串相等  函数直接返回

.text:000105A5
.text:000105A5 loc_105A5:                                    ; 如果字符串不相等
.text:000105A5                 push    [ebp+arg_C]
.text:000105A8                 mov     eax, dword_1090C      ;dword_1090C 保存真实的NtCreateMutant函数地址
.text:000105AD                 push    esi
.text:000105AE                 push    [ebp+arg_4]
.text:000105B1                 mov     dword_10910, eax
.text:000105B6                 push    [ebp+arg_0]
.text:000105B9                 call    eax ; dword_1090C    ;调用真实的NtCreateMutant
.text:000105BB
.text:000105BB loc_105BB:                              ; CODE XREF: sub_10574+2Fj
.text:000105BB                 xor     eax, eax
.text:000105BD                 pop     esi
.text:000105BE                 leave
.text:000105BF                 retn    10h
.text:000105BF sub_10574       endp

到这里之后可以看出在 hook NtCreateMutant的 处理函数当中 进行了判断。

NtCreateMutant的原型为:

NTSTATUS
NtCreateMutant (
    __out PHANDLE MutantHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in BOOLEAN InitialOwner
    )


typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR
    PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;

参数3中的UNICODE_STRING进行对比,如果值为\\basenamedobjects\\dbefeuate_ccen_khxfor,那么NtCreateMetux返回失败。


另外,根据双开工具上面的 隐藏游戏窗口功能 可以看出DNF双开限制是 通过互斥体 跟 FindWindow()来进行判断。

转载于:https://www.cnblogs.com/yujiancanfeng/archive/2013/05/07/3065898.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用AngularJs编写的简单 益智游戏(附源代码)  这是一个简单的 javascript 项目。这是一个拼图游戏,也包含一个填字游戏。这个游戏玩起来很棒。有两个不同的版本可以玩这个游戏。你也可以玩填字游戏。 关于游戏 这款游戏的玩法很简单。如上所述,它包含拼图和填字游戏。您可以通过移动图像来玩滑动拼图。您还可以选择要在滑动面板拥有的列数和网格数。 另一个是填字游戏。在这里你只需要找到浏览器左侧提到的那些单词。 要运行此游戏,您需要在系统上安装浏览器。下载并在代码编辑器打开此项目。然后有一个 index.html 文件可供您修改。在命令提示符运行该文件,或者您可以直接运行索引文件。使用 Google Chrome 或 FireFox 可获得更好的用户体验。此外,这是一款多人游戏,双方玩家都是人类。 这个游戏包含很多 JavaScript 验证。这个游戏很有趣,如果你能用一点 CSS 修改它,那就更好了。 总的来说,这个项目使用了很多 javascript 和 javascript 库。如果你可以添加一些具有不同颜色选项的级别,那么你一定可以利用其库来提高你的 javascript 技能。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值