吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2675|回复: 1
收起左侧

[会员申请] 申请会员ID:Capricornus

[复制链接]
吾爱游客  发表于 2022-2-16 15:32
1、申请ID:Capricornus
2、个人邮箱:374954038@qq.com
3、原创软件:某韩国游戏驱动保护静态分析

样本介绍:XIGNCODE3 是为大型多人线上游戏所发行的一款游戏反作弊软体,被用于如新枫之谷(南韩版)、战地之王等网路游戏中。XIGNCODE为wellbia所制作。如果哪里写的不好欢迎大佬指正。我大概分析了一下整个驱动的流程部分,下面会依次介绍这个驱动的分析过程和思路,在这个样本里不仅可以学习到很多内核编程的知识,也可以借鉴到一些设计模式上的东西。那么我们直接开始分析,先从入口点开始。1.驱动入口点**在DriverMain中驱动主要做了几件事
①初始化系统版本偏移
②注册通信的分发函数
③设置了通讯函数
④注册通知和回调
⑤创建进程通知2.初始化系统版本偏移主要是根据不同的系统版本号初始化一些全局变量,这里不做具体分析了。3.注册通信的分发函数3.1 DisPatchCreate和DisPatchClose的分发默认的分发函数,没什么好说的。3.2 DispatchWrite函数的分发3.2.1 通讯数据结构的部分分析这里就比较关键了,可以注意到这里丢了两个通讯条件,一个是在通讯函数的头部存放了一个长度值,另一个是sysBuffer的值是一个固定值。
由此我们目前可以确定InputBuffer中的前8个字节0x345821AB00000270
前四个字节是长度,后四个字节是固定标识码,用于确认三环程序的身份。3.2.2 FuncCall分析由于在上一小节中我们只知道了InputBuffer的前8个字节,我们直接看到我IDA分析过后的代码,可以看到while中的条件判断是在判断FuncIndex,函数编号。我们双击FunCallArray进去看看里面是什么,可以看到是标准的8字节排列的对象,由此猜测这很可能是函数数组,那么我怎么确定这个事实,并且也确定FuncIndex就是函数索引的呢?我们继续看下一节“设置函数通讯你列表”4.设置通讯函数列表( SetKeyDisFuncArray的分析)我们观察上面的截图,看到第一个140010F88(8字节)和140010F90(4字节)
再看看下方的截图,你发现了什么?
是吧?他就是一个8字节对齐的全局的结构体数组 由此我们可以知道3.2.2小节中FuncCall的命名由来,实际上他在根据索引确定函数的调用。接下来我挑几个我觉得比较有意思的函数发一下分析。4.1 ReadProcessMemory

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

1

2

3

4

5

6

7

NTKERNELAPI
NTSTATUS
ObSetHandleAttributes (
    __in HANDLE Handle,
    __in POBJECT_HANDLE_FLAG_INFORMATION HandleFlags,
    __in KPROCESSOR_MODE PreviousMode
    );
我们继续看一下HandleFlags的结构体类型

1

2

3

4

typedef struct _OBJECT_HANDLE_FLAG_INFORMATION {
    BOOLEAN Inherit;
    BOOLEAN ProtectFromClose;
} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;
基本可以确定这是一个用于关闭文件的函数。如果你不是十分肯定的话,再搜索引擎确认一下。4.3 DispSetWin32kTable一直跟进可以发现是在做一些函数全局变量的初始化。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

__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;
4.4 DetectUserDrawDllHook可以看到这个函数里的关键部分“CraeteDrawDLLDetectMemory”
我们继续跟进可以发现里面申请了内存,然后把字符串拷贝进去,显然这是在创建需要检测的dll数据。ok,那我们知道了,这个驱动会在“dwmcore.dll”、“ gdi32.dll”、“ user32.dll” 上做一些监控。4.5 DispSetWindowDisplayAffinity

继续跟进

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

5.注册通知和回调里面干了两件事,红框圈出来的部分我们深入进去看下RegisterCallBack6.创建进程通知

我们深入进去看一下

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

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

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2022-2-16 18:11
这复制的乱七八糟啊,你是原作者吗?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-29 16:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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