首页
社区
课程
招聘
[原创]2022腾讯游戏安全竞赛PC赛道初赛writeup
发表于: 2022-4-20 02:23 8903

[原创]2022腾讯游戏安全竞赛PC赛道初赛writeup

2022-4-20 02:23
8903

补丁:

分析过程:
IDA静态分析,互斥体防多开,窗口创建流程,D3D设备初始化,窗口消息循环处初始化shellcode并调用DX绘制流程
运行后一段时间程序停止绘制,在绘制流程中把GetTickCount相关时间检测的流程打补丁,不过多赘述
根据文档说明需要将一面黄色的棋子绘制出来,首先猜测可能跟顶点的绘制模式有关,ida动态调试加载符号信息,将DX相关的虚函数进行标识

IASetPrimitiveTopology 的参数依据msdn尝试修改一下,然而蓝色的方块有变化,黄色方块依旧没有画出来,感觉走远了。
回到shellcode的初始化过程中

shellcode调用的地方首先是对一些绘制的buffer进行初始化,然后调用一个解析器,最后对buffer进行回收,buffer初始化和回收的代码就不贴了,直接贴解析器部分的代码

7种命令
case 0是加法,case 1 是减法,case 2是存储器到存储器的赋值,case 3是立即数到存储器的赋值,case 4是某种加密算法,经过一些简单补丁可以验证case 5是画黄色方块 case 6画蓝色方块,case 7是程序退出

简单的写一个py脚本

case 4好像写的不太对,先凑合着用
然后经过修修改改一段时间发现画case 6的跟画case 5的不太一样啊,明明都是画方块,不太对劲
画case 6即蓝色方块

画case 5即黄色方块

蓝色方块绘制流程中crypt之后只有两条语句
黄色方块绘制流程中crypt之后还有额外的三条语句
所以这个ce搜一下批量打一下补丁

(当然全部改成8也可以,switch case default分支会自动到下一个指令)
然后找了个蓝色方块修改一下立即数赋值的语句,感受一下坐标系,发现黄色方块中的立即数赋值不太合理,手动修改一两个发现黄色方块回来了,于是乎把赋值为500和1000修改一下

02 00 00 00 00 00 00 00 03 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00
=>
02 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00
 
03 00 00 00 E8 03 00 00
=>
03 00 00 00 00 00 00 00
 
03 00 00 00 F4 01 00 00
=>
03 00 00 00 00 00 00 00
02 00 00 00 00 00 00 00 03 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00
=>
02 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00
 
03 00 00 00 E8 03 00 00
=>
03 00 00 00 00 00 00 00
 
03 00 00 00 F4 01 00 00
=>
03 00 00 00 00 00 00 00
__int64 __usercall sub_7FF62C2E5040@<rax>(...)
{
/*省略一些代码*/
  *(_OWORD *)(a1 - 72) = a6;
  *(_OWORD *)(a1 - 88) = a7;
  *(_OWORD *)(a1 - 104) = a8;
  v20 = a5;
  *(_OWORD *)(a1 - 120) = a9;
  v21 = a4;
  v22 = a2;
  v23 = a3;
  v24 = *(__int64 **)&a16;
  a12 = 1;
  v25 = a15 + (a4 ^ (a3 + a2)) % 256 - a5 % 256;
  (*(void (__fastcall **)(_QWORD, signed int *, char *))(**(_QWORD **)&a16 + 0x2F8i64))(*(_QWORD *)&a16, &a12, &v45);// RSGetViewports
  v26 = (v21 ^ v22 * v23) % 256 - (v20 >> 8) % 256;
  v27 = (float)(v47 - (float)(2 * (v26 + v22) - 1)) / v47;
  v28 = (float)(v47 - (float)(2 * v22 + 99)) / v47;
  v29 = (float)((float)(2 * (v26 + v23) - 1) - v46) / v46;
  v30 = (float)((float)(2 * v23 + 99) - v46) / v46;
  (*(void (__fastcall **)(__int64 *, _QWORD, _QWORD, signed __int64, _DWORD, float **))(*v24
                                                                                      + 0x70))(// Map
    v24,
    *(_QWORD *)&a17,
    0i64,
    4i64,
    0,
    &v44);
/*....*/
  (*(void (__fastcall **)(__int64 *, _QWORD, _QWORD))(*v24 + 0x78))(v24, *(_QWORD *)&a17, 0i64);// UnMap
  v42 = *v24;
  a14 = 28;
  a13 = 0;
  (*(void (__fastcall **)(__int64 *, _QWORD, signed __int64, int *, signed int *, int *))(v42
                                                                                        + 0x90))(// IASetVertexBuffers
    v24,
    0i64,
    1i64,
    &a17,
    &a14,
    &a13);
  (*(void (__fastcall **)(__int64 *, signed __int64))(*v24 + 0xC0))(v24, 5i64);// IASetPrimitiveTopology
  (*(void (__fastcall **)(__int64 *, __int64))(*v24 + 0x88))(v24, a18);// IASetInputLayout
  (*(void (__fastcall **)(__int64 *, __int64, _QWORD, _QWORD))(*v24 + 0x58))(v24, a19, 0i64, 0i64);// SetShader
  (*(void (__fastcall **)(__int64 *, __int64, _QWORD, _QWORD))(*v24 + 0x48))(v24, a20, 0i64, 0i64);// SetShader
  (*(void (__fastcall **)(__int64 *, _QWORD, _QWORD, _QWORD))(*v24 + 0xB8))(v24, 0i64, 0i64, 0i64);// SetShader
  return (*(__int64 (__fastcall **)(__int64 *, signed __int64))(*v24 + 0x68))(v24, 4i64);// Draw
}
__int64 __usercall sub_7FF62C2E5040@<rax>(...)
{
/*省略一些代码*/
  *(_OWORD *)(a1 - 72) = a6;
  *(_OWORD *)(a1 - 88) = a7;
  *(_OWORD *)(a1 - 104) = a8;
  v20 = a5;
  *(_OWORD *)(a1 - 120) = a9;
  v21 = a4;
  v22 = a2;
  v23 = a3;
  v24 = *(__int64 **)&a16;
  a12 = 1;
  v25 = a15 + (a4 ^ (a3 + a2)) % 256 - a5 % 256;
  (*(void (__fastcall **)(_QWORD, signed int *, char *))(**(_QWORD **)&a16 + 0x2F8i64))(*(_QWORD *)&a16, &a12, &v45);// RSGetViewports
  v26 = (v21 ^ v22 * v23) % 256 - (v20 >> 8) % 256;
  v27 = (float)(v47 - (float)(2 * (v26 + v22) - 1)) / v47;
  v28 = (float)(v47 - (float)(2 * v22 + 99)) / v47;
  v29 = (float)((float)(2 * (v26 + v23) - 1) - v46) / v46;
  v30 = (float)((float)(2 * v23 + 99) - v46) / v46;
  (*(void (__fastcall **)(__int64 *, _QWORD, _QWORD, signed __int64, _DWORD, float **))(*v24
                                                                                      + 0x70))(// Map
    v24,
    *(_QWORD *)&a17,
    0i64,
    4i64,
    0,
    &v44);
/*....*/
  (*(void (__fastcall **)(__int64 *, _QWORD, _QWORD))(*v24 + 0x78))(v24, *(_QWORD *)&a17, 0i64);// UnMap
  v42 = *v24;
  a14 = 28;
  a13 = 0;
  (*(void (__fastcall **)(__int64 *, _QWORD, signed __int64, int *, signed int *, int *))(v42
                                                                                        + 0x90))(// IASetVertexBuffers
    v24,
    0i64,
    1i64,
    &a17,
    &a14,
    &a13);
  (*(void (__fastcall **)(__int64 *, signed __int64))(*v24 + 0xC0))(v24, 5i64);// IASetPrimitiveTopology
  (*(void (__fastcall **)(__int64 *, __int64))(*v24 + 0x88))(v24, a18);// IASetInputLayout
  (*(void (__fastcall **)(__int64 *, __int64, _QWORD, _QWORD))(*v24 + 0x58))(v24, a19, 0i64, 0i64);// SetShader
  (*(void (__fastcall **)(__int64 *, __int64, _QWORD, _QWORD))(*v24 + 0x48))(v24, a20, 0i64, 0i64);// SetShader
  (*(void (__fastcall **)(__int64 *, _QWORD, _QWORD, _QWORD))(*v24 + 0xB8))(v24, 0i64, 0i64, 0i64);// SetShader
  return (*(__int64 (__fastcall **)(__int64 *, signed __int64))(*v24 + 0x68))(v24, 4i64);// Draw
}
void __fastcall sub_7FF62C2E1090(__int64 a1)
{
/*...*/
  v1 = a1;
  v2 = *(_QWORD *)(a1 + 0x28);
  if ( v2 )
  {
    v3 = *(_QWORD *)(v1 + 0x38);
    v9 = xmmword_7FF62C2E3480;
    (*(void (__fastcall **)(__int64, __int64, __int128 *))(*(_QWORD *)v2 + 0x190i64))(v2, v3, &v9);// ClearRenderTargetView
    if ( !byte_7FF62C2E8314 )
    {
      _mm_storeu_si128((__m128i *)ProcName, _mm_load_si128((const __m128i *)&xmmword_7FF62C2E3490));
      Dst = 0i64;
      v8 = 11257i64;
      strcpy(ModuleName, "ntdll.dll");
      v12 = 1835355500;
      v13 = 7959151;
      v4 = GetModuleHandleA(ModuleName);
      v5 = GetProcAddress(v4, ProcName);
      if ( v5 )
        ((void (__fastcall *)(signed __int64, void **, _QWORD, __int64 *, signed int, signed int))v5)(
          -1i64,
          &Dst,
          0i64,
          &v8,
          4096,
          64);
      v6 = (char *)Dst;
      qword_7FF62C2E8308 = (__int64)Dst;
      if ( Dst )
      {
        memcpy(Dst, sub_7FF62C2E5040, 0x1301ui64);// 填充代码
      }
      else
      {
        *errno() = 22;
        invalid_parameter_noinfo();
      }
      *(_DWORD *)v6 = 0x53C48B48;
      *((_DWORD *)v6 + 1) = 0x41575655;
      *((_WORD *)v6 + 4) = 0x4156;
      if ( v6 == (char *)0xFFFFFFFFFFFFECFFi64 )
      {
        *errno() = 22;
        invalid_parameter_noinfo();
      }
      else
      {
        memcpy(v6 + 0x1301, &unk_7FF62C2E6350, 0x18F0ui64);// 填充数据
      }
      *(_QWORD *)(v6 + 0x2BF1) = D3DCompile;
      qword_7FF62C2E8318 = (__int64 (__fastcall *)(_QWORD))(v6 + 0x650);//***************
      *((_DWORD *)v6 + 411) = 9601;
      *(_DWORD *)(v6 + 1097) = 3764;
      *((_DWORD *)v6 + 384) = 4865;
      byte_7FF62C2E8314 = 1;
      dword_7FF62C2E8310 = GetTickCount();
    }
    if ( qword_7FF62C2E8318 )
    {
      qword_7FF62C2E8318(*(_QWORD *)(v1 + 0x30));//调用shellcode
      GetTickCount();
    }
    (*(void (__fastcall **)(_QWORD, _QWORD, _QWORD))(**(_QWORD **)(v1 + 0x30) + 64i64))(
      *(_QWORD *)(v1 + 0x30),
      0i64,
      0i64);                                    // dxgi!Present
  }
}
void __fastcall sub_7FF62C2E1090(__int64 a1)
{
/*...*/
  v1 = a1;
  v2 = *(_QWORD *)(a1 + 0x28);
  if ( v2 )
  {
    v3 = *(_QWORD *)(v1 + 0x38);
    v9 = xmmword_7FF62C2E3480;
    (*(void (__fastcall **)(__int64, __int64, __int128 *))(*(_QWORD *)v2 + 0x190i64))(v2, v3, &v9);// ClearRenderTargetView
    if ( !byte_7FF62C2E8314 )
    {
      _mm_storeu_si128((__m128i *)ProcName, _mm_load_si128((const __m128i *)&xmmword_7FF62C2E3490));
      Dst = 0i64;
      v8 = 11257i64;
      strcpy(ModuleName, "ntdll.dll");
      v12 = 1835355500;
      v13 = 7959151;
      v4 = GetModuleHandleA(ModuleName);
      v5 = GetProcAddress(v4, ProcName);
      if ( v5 )
        ((void (__fastcall *)(signed __int64, void **, _QWORD, __int64 *, signed int, signed int))v5)(
          -1i64,
          &Dst,
          0i64,
          &v8,
          4096,
          64);
      v6 = (char *)Dst;
      qword_7FF62C2E8308 = (__int64)Dst;
      if ( Dst )
      {
        memcpy(Dst, sub_7FF62C2E5040, 0x1301ui64);// 填充代码
      }
      else
      {
        *errno() = 22;
        invalid_parameter_noinfo();
      }
      *(_DWORD *)v6 = 0x53C48B48;
      *((_DWORD *)v6 + 1) = 0x41575655;
      *((_WORD *)v6 + 4) = 0x4156;
      if ( v6 == (char *)0xFFFFFFFFFFFFECFFi64 )
      {
        *errno() = 22;
        invalid_parameter_noinfo();
      }
      else
      {
        memcpy(v6 + 0x1301, &unk_7FF62C2E6350, 0x18F0ui64);// 填充数据
      }
      *(_QWORD *)(v6 + 0x2BF1) = D3DCompile;
      qword_7FF62C2E8318 = (__int64 (__fastcall *)(_QWORD))(v6 + 0x650);//***************
      *((_DWORD *)v6 + 411) = 9601;
      *(_DWORD *)(v6 + 1097) = 3764;
      *((_DWORD *)v6 + 384) = 4865;
      byte_7FF62C2E8314 = 1;
      dword_7FF62C2E8310 = GetTickCount();
    }
    if ( qword_7FF62C2E8318 )
    {
      qword_7FF62C2E8318(*(_QWORD *)(v1 + 0x30));//调用shellcode
      GetTickCount();
    }
    (*(void (__fastcall **)(_QWORD, _QWORD, _QWORD))(**(_QWORD **)(v1 + 0x30) + 64i64))(
      *(_QWORD *)(v1 + 0x30),
      0i64,
      0i64);                                    // dxgi!Present
  }
}
__int64 __usercall sub_7FF62C2E5460@<rax>(int a1@<r8d>, signed int a2@<r9d>, __int128 *a3@<xmm6>, __int128 *a4@<xmm7>, __int128 *a5@<xmm8>, __int128 *a6@<xmm9>, __int64 a7, signed int a8, signed int a9)
{
  __int64 v9; // rsi
  signed int v10; // er14
  int v11; // er15
  __int64 result; // rax
  __int64 v13; // rcx
  int v14; // edx
  int v15; // er9
  int v16; // eax
  BYTE *v17; // [rsp+50h] [rbp-30h]
  __int64 v18; // [rsp+58h] [rbp-28h]
  __int128 v19; // [rsp+60h] [rbp-20h]
  __int64 v20; // [rsp+70h] [rbp-10h]
  int v21; // [rsp+78h] [rbp-8h]
  int v22; // [rsp+7Ch] [rbp-4h]
 
  v17 = &ContextRecord.FltSave.Reserved4[48];
  v9 = 0i64;
  v10 = a2;
  v11 = a1;
  v18 = 0i64;
  _mm_storeu_si128((__m128i *)&v19, (__m128i)0i64);
  v20 = 0i64;
  v21 = 50;
  v22 = 50;
  while ( 2 )
  {
    result = (__int64)v17;
    switch ( *(_DWORD *)&v17[4 * v9] )
    {
      case 0:
        result = HIDWORD(v18);
        LODWORD(v18) = HIDWORD(v18) + v18;
        goto LABEL_10;
      case 1:
        result = HIDWORD(v18);
        LODWORD(v18) = v18 - HIDWORD(v18);
        goto LABEL_10;
      case 2:
        v13 = *(signed int *)&v17[4 * v9 + 4];
        v9 += 2i64;
        result = *((unsigned int *)&v18 + v13);
        *((_DWORD *)&v18 + *(signed int *)&v17[4 * v9]) = result;
        goto LABEL_10;
      case 3:
        v14 = *(_DWORD *)&v17[4 * v9 + 4];
        v9 += 2i64;
        result = (__int64)v17;
        *((_DWORD *)&v18 + *(signed int *)&v17[4 * v9]) = v14;
        goto LABEL_10;
      case 4:
        ++v9;
        v15 = v18;
        v16 = v18 * (HIDWORD(v18) + 1);
        LODWORD(v18) = *(_DWORD *)&v17[4 * v9] ^ 0x414345;
        result = (unsigned int)((signed int)(v18 ^ (HIDWORD(v18) + v15)) % 256
                              + (((signed int)(v18 ^ v15 * HIDWORD(v18)) % 256
                                + ((signed int)(v18 ^ (HIDWORD(v18) + v16)) % 256 << 8)) << 8));
        HIDWORD(v18) = result;
        goto LABEL_10;
      case 5:
        result = sub_7FF62C2E5040(
                   a7,
                   SHIDWORD(v19),
                   SDWORD2(v19),
                   v20,
                   SHIDWORD(v20),
                   a3,
                   a4,
                   a5,
                   a6,
                   -256,
                   v11,
                   v10,
                   a7,
                   a8,
                   a9,
                   (int)v17,
                   v18,
                   v19,
                   *((__int64 *)&v19 + 1),
                   v20);
        goto LABEL_10;
      case 6:
        result = sub_7FF62C2E5040(
                   a7,
                   SHIDWORD(v19),
                   SDWORD2(v19),
                   v20,
                   SHIDWORD(v20),
                   a3,
                   a4,
                   a5,
                   a6,
                   -13771801,
                   v11,
                   v10,
                   a7,
                   a8,
                   a9,
                   (int)v17,
                   v18,
                   v19,
                   *((__int64 *)&v19 + 1),
                   v20);
        goto LABEL_10;
      case 7:
        return result;
      default:
LABEL_10:
        if ( (unsigned __int64)++v9 < 0x58F )
          continue;
        return result;
    }
  }
}
__int64 __usercall sub_7FF62C2E5460@<rax>(int a1@<r8d>, signed int a2@<r9d>, __int128 *a3@<xmm6>, __int128 *a4@<xmm7>, __int128 *a5@<xmm8>, __int128 *a6@<xmm9>, __int64 a7, signed int a8, signed int a9)
{
  __int64 v9; // rsi
  signed int v10; // er14
  int v11; // er15
  __int64 result; // rax
  __int64 v13; // rcx
  int v14; // edx
  int v15; // er9
  int v16; // eax
  BYTE *v17; // [rsp+50h] [rbp-30h]
  __int64 v18; // [rsp+58h] [rbp-28h]
  __int128 v19; // [rsp+60h] [rbp-20h]
  __int64 v20; // [rsp+70h] [rbp-10h]
  int v21; // [rsp+78h] [rbp-8h]
  int v22; // [rsp+7Ch] [rbp-4h]
 
  v17 = &ContextRecord.FltSave.Reserved4[48];
  v9 = 0i64;
  v10 = a2;
  v11 = a1;
  v18 = 0i64;
  _mm_storeu_si128((__m128i *)&v19, (__m128i)0i64);
  v20 = 0i64;
  v21 = 50;
  v22 = 50;
  while ( 2 )
  {
    result = (__int64)v17;
    switch ( *(_DWORD *)&v17[4 * v9] )
    {
      case 0:
        result = HIDWORD(v18);
        LODWORD(v18) = HIDWORD(v18) + v18;
        goto LABEL_10;
      case 1:
        result = HIDWORD(v18);
        LODWORD(v18) = v18 - HIDWORD(v18);
        goto LABEL_10;
      case 2:
        v13 = *(signed int *)&v17[4 * v9 + 4];
        v9 += 2i64;

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//