首页
社区
课程
招聘
[原创]某韩国游戏驱动保护静态分析
发表于: 2022-2-16 00:39 27749

[原创]某韩国游戏驱动保护静态分析

2022-2-16 00:39
27749

**在DriverMain中驱动主要做了几件事
①初始化系统版本偏移
②注册通信的分发函数
③设置了通讯函数
④注册通知和回调
⑤创建进程通知
图片描述

主要是根据不同的系统版本号初始化一些全局变量,这里不做具体分析了。
图片描述

默认的分发函数,没什么好说的。
图片描述
图片描述

这里就比较关键了,可以注意到这里丢了两个通讯条件,一个是在通讯函数的头部存放了一个长度值,另一个是sysBuffer的值是一个固定值。
由此我们目前可以确定InputBuffer中的前8个字节0x345821AB00000270
前四个字节是长度,后四个字节是固定标识码,用于确认三环程序的身份。

图片描述

由于在上一小节中我们只知道了InputBuffer的前8个字节,我们直接看到我ida分析过后的代码,可以看到while中的条件判断是在判断FuncIndex,函数编号。
图片描述
我们双击FunCallArray进去看看里面是什么,可以看到是标准的8字节排列的对象,由此猜测这很可能是函数数组,那么我怎么确定这个事实,并且也确定FuncIndex就是函数索引的呢?我们继续看下一节“设置函数通讯你列表”
图片描述

我们观察上面的截图,看到第一个140010F88(8字节)和140010F90(4字节)
再看看下方的截图,你发现了什么?
是吧?他就是一个8字节对齐的全局的结构体数组

由此我们可以知道3.2.2小节中FuncCall的命名由来,实际上他在根据索引确定函数的调用。

图片描述

接下来我挑几个我觉得比较有意思的函数发一下分析。

图片描述

可以看到一个附加操作下面,又调用了一个函数,ok,继续跟进去,发现内部调用了“ObSetHandleAttributes”
图片描述
图片描述
如果你在逆向分析的时候不了解这种函数是做什么的,打开wrk搜索一下

我们继续看一下HandleFlags的结构体类型

基本可以确定这是一个用于关闭文件的函数。如果你不是十分肯定的话,再搜索引擎确认一下。

一直跟进可以发现是在做一些函数全局变量的初始化。
图片描述

可以看到这个函数里的关键部分“CraeteDrawDLLDetectMemory”
图片描述

我们继续跟进
图片描述
可以发现里面申请了内存,然后把字符串拷贝进去,显然这是在创建需要检测的dll数据。ok,那我们知道了,这个驱动会在“dwmcore.dll”、“ gdi32.dll”、“ user32.dll” 上做一些监控。

图片描述
继续跟进
图片描述
进入“CreateKernelAndUserDetectThread”,参考图中注释可以看到这个函数在做什么。
图片描述

里面干了两件事,红框圈出来的部分
图片描述
我们深入进去看下RegisterCallBack
图片描述

图片描述
我们深入进去看一下
图片描述
继续跟进CheckInformationProcess
看到两个关键点,ZwQueryInformationProcess, 查询号为27:ProcessImageFileName,然后也出现了ZwClose,兄弟们懂了吧,如果你有在这款驱动加载的情况下打开某些调试器的经验,那么大概就是这个函数搞的鬼。
图片描述

希望自己在学习分析时候遇到的一些经验和思路能够帮助吧友。

 
struct _FunCallArray
{
  ULONG64 FuncAddr;
  ULONG FuncIndex;
};
struct _FunCallArray
{
  ULONG64 FuncAddr;
  ULONG FuncIndex;
};
 
 
NTKERNELAPI
NTSTATUS
ObSetHandleAttributes (
    __in HANDLE Handle,
    __in POBJECT_HANDLE_FLAG_INFORMATION HandleFlags,
    __in KPROCESSOR_MODE PreviousMode
    );
NTKERNELAPI
NTSTATUS
ObSetHandleAttributes (
    __in HANDLE Handle,
    __in POBJECT_HANDLE_FLAG_INFORMATION HandleFlags,
    __in KPROCESSOR_MODE PreviousMode
    );
typedef struct _OBJECT_HANDLE_FLAG_INFORMATION {
    BOOLEAN Inherit;
    BOOLEAN ProtectFromClose;
} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;
typedef struct _OBJECT_HANDLE_FLAG_INFORMATION {
    BOOLEAN Inherit;
    BOOLEAN ProtectFromClose;
} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;
__int64 sub_1400075D4()
{
  unsigned int v0; // ebx
  __int64 (__fastcall *v1)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD); // r15
  __int64 (__fastcall *RtlCreateUserThreadFunc)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD); // r13
  __int64 result; // rax
  int *v4; // rdi
  const void *win32kModule; // r14
  __int64 win32kfullModule; // rax
  __int64 v7; // r8
  __int64 v8; // r9
  __int64 win32kfullModule1; // rsi
  __int64 v10; // r8
  __int64 v11; // r9
  __int64 v12; // r8
  __int64 v13; // r9
  __int64 v14; // r8
  __int64 v15; // r9
  __int64 v16; // r8
  __int64 v17; // r9
  __int64 v18; // r8
  __int64 v19; // r9
  PIMAGE_NT_HEADERS winkNts; // rax
  PIMAGE_NT_HEADERS winkNts1; // rsi
  __int64 win32SizeOfImage; // r12
  int v23; // eax
  const void *v24; // rbx
  const void *W32pServiceTable1; // [rsp+30h] [rbp-48h] BYREF
  __int64 v26; // [rsp+38h] [rbp-40h] BYREF
  const void *v27; // [rsp+40h] [rbp-38h] BYREF
  __int64 v28; // [rsp+48h] [rbp-30h] BYREF
  __int64 (__fastcall *v29)(_QWORD, _QWORD); // [rsp+50h] [rbp-28h] BYREF
  __int64 W32pServiceTable2; // [rsp+58h] [rbp-20h] BYREF
  UNICODE_STRING DestinationString; // [rsp+60h] [rbp-18h] BYREF
  const void *win32kMemoryModule; // [rsp+C0h] [rbp+48h] BYREF
  __int64 v33; // [rsp+C8h] [rbp+50h] BYREF
  __int64 NtUserGetWindowDisplayAffinity; // [rsp+D0h] [rbp+58h] BYREF
  __int64 NtUserSetWindowDisplayAffinity; // [rsp+D8h] [rbp+60h] BYREF
 
  v0 = 0;
  v1 = 0i64;
  v26 = 0i64;
  v27 = 0i64;
  v29 = 0i64;
  v28 = 0i64;
  if ( qword_140011700 )
    return 0i64;
  RtlInitUnicodeString_0(&DestinationString, L"RtlCreateUserThread");
  RtlCreateUserThreadFunc = (__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD))sub_140014948();
  if ( !RtlCreateUserThreadFunc )
  {
    v1 = (__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD))GetNtCreateThreadEx();
    if ( !v1 )
      return 0xE01AF211i64;
  }
  if ( version1 != 1 && version1 != 2 && version1 != 3 )
  {
    if ( version1 != 4 )
    {
      switch ( version1 )
      {
        case 6:
          v4 = (int *)&unk_140010480;
          break;
        case 7:
          v4 = (int *)&unk_1400104D0;
          break;
        case 8:
          v4 = (int *)&unk_140010520;
          break;
        default:
          result = sub_140006D7C();
          if ( (int)result < 0 )
          {
            _mm_lfence();
            return result;
          }
          v4 = (int *)&unk_140010570;
LABEL_20:
          j_DbgPrint_54("check ntusercalloneparam\n");
          if ( v4[9] >= 0 )
          {
            j_DbgPrint_55("load win32k image\n");
            if ( (int)readSysFileToMemory((__int64)&win32kMemoryModule, L"\\systemroot\\system32\\win32k.sys") >= 0 )
            {
              j_DbgPrint_56("get real win32k address\n");
              win32kModule = (const void *)QueryModules("win32k.sys");
              if ( !win32kModule )
                goto LABEL_23;
              j_DbgPrint_57("fetch win32k service table\n");
              win32kfullModule = QueryModules("win32kfull.sys");
              NtUserGetWindowDisplayAffinity = 0i64;
              win32kfullModule1 = win32kfullModule;
              NtUserSetWindowDisplayAffinity = 0i64;
              if ( win32kfullModule )
              {
                writeFileLog("win32kfull => %p\n", win32kfullModule, v7, v8);
                if ( (int)readSysFileToMemory((__int64)&v33, L"\\systemroot\\system32\\win32kfull.sys") < 0 )
                {
                  GetExportTableFunc(
                    &NtUserGetWindowDisplayAffinity,
                    win32kfullModule1,
                    (__int64)"NtUserGetWindowDisplayAffinity");
                  GetExportTableFunc(
                    &NtUserSetWindowDisplayAffinity,
                    win32kfullModule1,
                    (__int64)"NtUserSetWindowDisplayAffinity");
                  writeFileLog("getdisp %p", NtUserGetWindowDisplayAffinity, v16, v17);
                  writeFileLog("setdisp %p", NtUserSetWindowDisplayAffinity, v18, v19);
                }
                else
                {
                  writeFileLog("win32kfull safe => %p\n", v33, v10, v11);
                  if ( (int)GetExportTableFunc(
                              &NtUserGetWindowDisplayAffinity,
                              v33,
                              (__int64)"NtUserGetWindowDisplayAffinity") >= 0 )
                  {
                    writeFileLog(
                      "getdisp %p %08x => %p %p\n",
                      NtUserGetWindowDisplayAffinity,
                      NtUserGetWindowDisplayAffinity - v33,
                      win32kfullModule1);
                    NtUserGetWindowDisplayAffinity += win32kfullModule1 - v33;
                    writeFileLog("getdisp %p", NtUserGetWindowDisplayAffinity, v12, v13);
                  }
                  if ( (int)GetExportTableFunc(
                              &NtUserSetWindowDisplayAffinity,
                              v33,
                              (__int64)"NtUserSetWindowDisplayAffinity") >= 0 )
                  {
                    writeFileLog(
                      "setdisp %p %08x => %p %p\n",
                      NtUserSetWindowDisplayAffinity,
                      NtUserSetWindowDisplayAffinity - v33,
                      win32kfullModule1);
                    NtUserSetWindowDisplayAffinity += win32kfullModule1 - v33;
                    writeFileLog("setdisp %p", NtUserSetWindowDisplayAffinity, v14, v15);
                  }
                  tryPrint(v33);
                }
              }
              W32pServiceTable1 = 0i64;
              if ( (int)GetExportTableFunc(&W32pServiceTable1, (__int64)win32kMemoryModule, (__int64)"W32pServiceTable") >= 0
                && (W32pServiceTable2 = 0i64,
                    (int)GetExportTableFunc(&W32pServiceTable2, (__int64)win32kModule, (__int64)"W32pServiceTable") >= 0) )
              {
                _mm_lfence();
                j_DbgPrint_58("get real win32k nt header\n");
                winkNts = GetImageNts((__int64)win32kModule);
                winkNts1 = winkNts;
                if ( !winkNts )
                {
LABEL_44:
                  tryPrint((__int64)win32kMemoryModule);
                  return v0;
                }
                _mm_lfence();
                win32SizeOfImage = (__int64)win32kModule + winkNts->OptionalHeader.SizeOfImage;
                j_DbgPrint_59("resolve pNtUserGetForegroundWindow\n");
                v23 = sub_1400070A4(
                        &v28,
                        v4[4],
                        (__int64)win32kMemoryModule,
                        (__int64)W32pServiceTable1,
                        (__int64)win32kModule);
                _mm_lfence();
                if ( v23 < 0 )
                {
LABEL_43:
                  v0 = v23;
                  goto LABEL_44;
                }
                j_DbgPrint_60("resolve pNtUserQueryWindow\n");
                v23 = sub_1400070A4(
                        &v29,
                        v4[6],
                        (__int64)win32kMemoryModule,
                        (__int64)W32pServiceTable1,
                        (__int64)win32kModule);
                if ( v23 < 0
                  || (j_DbgPrint_61("resolve NtUserSetWindowDisplayAffinity\n"), v4[15] >= 0)
                  && (_mm_lfence(),
                      v23 = sub_1400070A4(
                              &v27,
                              v4[15],
                              (__int64)win32kMemoryModule,
                              (__int64)W32pServiceTable1,
                              (__int64)win32kModule),
                      v23 < 0)
                  || v4[16] >= 0
                  && (_mm_lfence(),
                      v23 = sub_1400070A4(
                              &v26,
                              v4[16],
                              (__int64)win32kMemoryModule,
                              (__int64)W32pServiceTable1,
                              (__int64)win32kModule),
                      v23 < 0) )
                {
                  _mm_lfence();
                  goto LABEL_43;
                }
                _mm_lfence();
                v24 = v27;
                W32pServiceTable11 = (__int64)W32pServiceTable1;
                qword_1400117C8 = v26;
                qword_140011850 = v28;
                qword_140011858 = v29;
                NtUserGetWindowDisplayAffinity1 = NtUserGetWindowDisplayAffinity;
                NtUserSetWindowDisplayAffinity2 = NtUserSetWindowDisplayAffinity;
                win32kMemoryModule1 = (__int64)win32kMemoryModule;
                win32kModule2 = (__int64)win32kModule;
                win32SizeOfImage1 = win32SizeOfImage;
                NtCreateThreadEx = v1;
                ::RtlCreateUserThreadFunc = RtlCreateUserThreadFunc;
                qword_1400117C0 = (__int64)v27;
                qword_140011708 = (__int64)win32kModule;
                qword_140011700 = (__int64)v4;
                j_DbgPrint_62("z s_safe_win32k == >  %p\n", win32kMemoryModule);
                j_DbgPrint_63("z w32_table == >  %p\n", W32pServiceTable1);
                j_DbgPrint_64("z win32k == >  %p\n", win32kModule);
                j_DbgPrint_65("z nt == >  %p\n", winkNts1);
                j_DbgPrint_66("z s_win32k_begin == >  %p\n", (const void *)win32kModule2);
                j_DbgPrint_67("z s_win32k_end == >  %p\n", (const void *)win32SizeOfImage1);
                j_DbgPrint_68("z s_win32k_table == >  %p\n", (const void *)W32pServiceTable11);
                j_DbgPrint_69("z pNtUserSetWindowDisplayAffinity == >  %p\n", v24);
              }
              else
              {
LABEL_23:
                tryPrint((__int64)win32kMemoryModule);
              }
            }
            return 0i64;
          }
          return 0xC0000001i64;
      }
      sub_140006AC8();
      goto LABEL_20;
    }
    v4 = (int *)&unk_140010430;
    goto LABEL_20;
  }
  return 0xC0000001i64;
__int64 sub_1400075D4()
{
  unsigned int v0; // ebx
  __int64 (__fastcall *v1)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD); // r15
  __int64 (__fastcall *RtlCreateUserThreadFunc)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD); // r13
  __int64 result; // rax
  int *v4; // rdi
  const void *win32kModule; // r14
  __int64 win32kfullModule; // rax
  __int64 v7; // r8
  __int64 v8; // r9
  __int64 win32kfullModule1; // rsi
  __int64 v10; // r8
  __int64 v11; // r9
  __int64 v12; // r8
  __int64 v13; // r9
  __int64 v14; // r8
  __int64 v15; // r9
  __int64 v16; // r8
  __int64 v17; // r9
  __int64 v18; // r8
  __int64 v19; // r9
  PIMAGE_NT_HEADERS winkNts; // rax
  PIMAGE_NT_HEADERS winkNts1; // rsi
  __int64 win32SizeOfImage; // r12
  int v23; // eax
  const void *v24; // rbx
  const void *W32pServiceTable1; // [rsp+30h] [rbp-48h] BYREF
  __int64 v26; // [rsp+38h] [rbp-40h] BYREF
  const void *v27; // [rsp+40h] [rbp-38h] BYREF
  __int64 v28; // [rsp+48h] [rbp-30h] BYREF
  __int64 (__fastcall *v29)(_QWORD, _QWORD); // [rsp+50h] [rbp-28h] BYREF
  __int64 W32pServiceTable2; // [rsp+58h] [rbp-20h] BYREF
  UNICODE_STRING DestinationString; // [rsp+60h] [rbp-18h] BYREF
  const void *win32kMemoryModule; // [rsp+C0h] [rbp+48h] BYREF
  __int64 v33; // [rsp+C8h] [rbp+50h] BYREF
  __int64 NtUserGetWindowDisplayAffinity; // [rsp+D0h] [rbp+58h] BYREF
  __int64 NtUserSetWindowDisplayAffinity; // [rsp+D8h] [rbp+60h] BYREF
 
  v0 = 0;
  v1 = 0i64;
  v26 = 0i64;
  v27 = 0i64;
  v29 = 0i64;
  v28 = 0i64;
  if ( qword_140011700 )
    return 0i64;
  RtlInitUnicodeString_0(&DestinationString, L"RtlCreateUserThread");
  RtlCreateUserThreadFunc = (__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD))sub_140014948();
  if ( !RtlCreateUserThreadFunc )
  {
    v1 = (__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD))GetNtCreateThreadEx();
    if ( !v1 )
      return 0xE01AF211i64;
  }
  if ( version1 != 1 && version1 != 2 && version1 != 3 )
  {
    if ( version1 != 4 )
    {
      switch ( version1 )
      {
        case 6:
          v4 = (int *)&unk_140010480;
          break;
        case 7:
          v4 = (int *)&unk_1400104D0;
          break;
        case 8:
          v4 = (int *)&unk_140010520;
          break;
        default:
          result = sub_140006D7C();
          if ( (int)result < 0 )
          {
            _mm_lfence();
            return result;
          }
          v4 = (int *)&unk_140010570;
LABEL_20:
          j_DbgPrint_54("check ntusercalloneparam\n");
          if ( v4[9] >= 0 )
          {
            j_DbgPrint_55("load win32k image\n");
            if ( (int)readSysFileToMemory((__int64)&win32kMemoryModule, L"\\systemroot\\system32\\win32k.sys") >= 0 )
            {
              j_DbgPrint_56("get real win32k address\n");
              win32kModule = (const void *)QueryModules("win32k.sys");
              if ( !win32kModule )
                goto LABEL_23;
              j_DbgPrint_57("fetch win32k service table\n");
              win32kfullModule = QueryModules("win32kfull.sys");
              NtUserGetWindowDisplayAffinity = 0i64;
              win32kfullModule1 = win32kfullModule;
              NtUserSetWindowDisplayAffinity = 0i64;
              if ( win32kfullModule )
              {
                writeFileLog("win32kfull => %p\n", win32kfullModule, v7, v8);
                if ( (int)readSysFileToMemory((__int64)&v33, L"\\systemroot\\system32\\win32kfull.sys") < 0 )
                {
                  GetExportTableFunc(
                    &NtUserGetWindowDisplayAffinity,
                    win32kfullModule1,
                    (__int64)"NtUserGetWindowDisplayAffinity");

[注意]APP应用上架合规检测服务,协助应用顺利上架!

最后于 2022-2-16 10:44 被铜锣湾扛把子编辑 ,原因: 上传缺失图片
收藏
免费 10
支持
分享
最新回复 (12)
雪    币: 1085
活跃值: (250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bxb
2
能分享一下分析文件吗
2022-2-16 15:56
0
雪    币: 1556
活跃值: (2312)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3

你们做个人吧。。。

2022-2-19 23:34
0
雪    币: 8
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
666 大佬也有群吗 
2022-5-12 19:25
0
雪    币: 12857
活跃值: (9177)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
5
killleer 你们做个人吧。。。
666666 XC3读写.dll准备就绪是吧
2022-5-12 19:51
0
雪    币: 1556
活跃值: (2312)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
hzqst 666666 XC3读写.dll准备就绪是吧

貌似出来N年了不当人了这是,当然第一个里面可能搞了个远控就是了

最后于 2022-5-12 22:01 被killleer编辑 ,原因:
2022-5-12 21:59
0
雪    币: 1556
活跃值: (2312)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
hzqst 666666 XC3读写.dll准备就绪是吧

还有这样的:

2022-5-12 22:09
0
雪    币: 14
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
XIGNCODE3的驱动不是VMP了吗?
2022-5-17 02:23
0
雪    币: 233
活跃值: (1829)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
大佬666
2022-11-9 03:41
0
雪    币: 2199
活跃值: (5293)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
插个眼
2022-11-9 08:27
0
雪    币: 4795
活跃值: (4499)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
代码就只有这么点吗  还是说其他的被加vm了?  没有什么干货的检测淫技
2023-3-7 16:39
0
雪    币: 1832
活跃值: (5379)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12

大陆人: 软件、程序、网络、鼠标

台湾人: 軟體、程式、網路、滑鼠

模仿台湾人的大陆人: 软体、网路

为何模仿?因为早期(十五~二十年前)台湾的计算机大牛多的很, 很多资料都是繁体或繁转简的台湾大牛写的资料. 大陆还比较落后(那时的优秀中文PC游戏, 甚至故意找都叫不出一款大陆的. 而台湾开发的作品比比皆是).所以很多大陆人模仿台湾人对上述术语的称呼, 显得学问更高深, 让外行人更看不懂(更有助于装). 但近十年大陆大牛和简体资料也越来越多, 就很少见继续模仿台湾人的大陆人了.

2023-3-8 03:09
1
雪    币: 1832
活跃值: (5379)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13

最后于 2023-3-8 03:12 被PEDIY编辑 ,原因:
2023-3-8 03:12
0
游客
登录 | 注册 方可回帖
返回
//