2021腾讯游戏安全技术初赛PC客户端解题报告

PC客户端初赛赛题解题报告

概述

本题是一个windows 32位opengl游戏程序,打开发现是一个3d游戏,视角移动受限,未提供坐标移动功能,无法看到屏幕中央箭头指向的区域。

使用ida搜索字符串可以发现使用的glfw版本为3.3,并且使用了opengl es。

由于glfw库采用静态编译,程序中大量调用其api函数而缺少符号信息,为了更方便的分析,从官网现在了glfw 3.3的lib库(https://github.com/glfw/glfw/releases/download/3.3.3/glfw-3.3.3.zip),使用ida的flair功能制作函数sig库,具体命令如下:

pcf glfw3_mt.lib
sigmake glfw3_mt.pat glfw3_mt.sig

将sig放入ida识别,即可成功识别部分库函数。

而对于题目中中大量虚表函数引用,其地址为动态导入,有函数名字符串其实更方便我们识别,例如下面的导入代码:

void sub_404710()
{
  if ( dword_466D24 )
  {
    sub_418CB0("glColorMaski");
    sub_418CB0("glGetBooleani_v");
    sub_418CB0("glGetIntegeri_v");
    sub_418CB0("glEnablei");
    sub_418CB0("glDisablei");
    sub_418CB0("glIsEnabledi");
    sub_418CB0("glBeginTransformFeedback");
    sub_418CB0("glEndTransformFeedback");
    sub_418CB0("glBindBufferRange");
    sub_418CB0("glBindBufferBase");
    sub_418CB0("glTransformFeedbackVaryings");
    sub_418CB0("glGetTransformFeedbackVarying");
    sub_418CB0("glClampColor");
    sub_418CB0("glBeginConditionalRender");
    sub_418CB0("glEndConditionalRender");
    sub_418CB0("glVertexAttribIPointer");
    sub_418CB0("glGetVertexAttribIiv");
    sub_418CB0("glGetVertexAttribIuiv");
    sub_418CB0("glVertexAttribI1i");
    sub_418CB0("glVertexAttribI2i");
    sub_418CB0("glVertexAttribI3i");
    sub_418CB0("glVertexAttribI4i");
    sub_418CB0("glVertexAttribI1ui");
    sub_418CB0("glVertexAttribI2ui");
    sub_418CB0("glVertexAttribI3ui");
    sub_418CB0("glVertexAttribI4ui");
    sub_418CB0("glVertexAttribI1iv");
    sub_418CB0("glVertexAttribI2iv");
    sub_418CB0("glVertexAttribI3iv");
    sub_418CB0("glVertexAttribI4iv");
    sub_418CB0("glVertexAttribI1uiv");
    sub_418CB0("glVertexAttribI2uiv");
    sub_418CB0("glVertexAttribI3uiv");
    sub_418CB0("glVertexAttribI4uiv");
    sub_418CB0("glVertexAttribI4bv");
    sub_418CB0("glVertexAttribI4sv");
    sub_418CB0("glVertexAttribI4ubv");
    sub_418CB0("glVertexAttribI4usv");
    sub_418CB0("glGetUniformuiv");
    sub_418CB0("glBindFragDataLocation");
    sub_418CB0("glGetFragDataLocation");
    sub_418CB0("glUniform1ui");
    sub_418CB0("glUniform2ui");
    sub_418CB0("glUniform3ui");
    sub_418CB0("glUniform4ui");
    sub_418CB0("glUniform1uiv");
    sub_418CB0("glUniform2uiv");
    sub_418CB0("glUniform3uiv");
    sub_418CB0("glUniform4uiv");
    sub_418CB0("glTexParameterIiv");
    sub_418CB0("glTexParameterIuiv");
    sub_418CB0("glGetTexParameterIiv");
    sub_418CB0("glGetTexParameterIuiv");
    sub_418CB0("glClearBufferiv");
    sub_418CB0("glClearBufferuiv");
    sub_418CB0("glClearBufferfv");
    sub_418CB0("glClearBufferfi");
    glGetStringi = sub_418CB0("glGetStringi");
    sub_418CB0("glIsRenderbuffer");
    sub_418CB0("glBindRenderbuffer");
    sub_418CB0("glDeleteRenderbuffers");
    sub_418CB0("glGenRenderbuffers");
    sub_418CB0("glRenderbufferStorage");
    sub_418CB0("glGetRenderbufferParameteriv");
    sub_418CB0("glIsFramebuffer");
    sub_418CB0("glBindFramebuffer");
    sub_418CB0("glDeleteFramebuffers");
    sub_418CB0("glGenFramebuffers");
    sub_418CB0("glCheckFramebufferStatus");
    sub_418CB0("glFramebufferTexture1D");
    sub_418CB0("glFramebufferTexture2D");
    sub_418CB0("glFramebufferTexture3D");
    sub_418CB0("glFramebufferRenderbuffer");
    sub_418CB0("glGetFramebufferAttachmentParameteriv");
    glGenerateMipmap = (int (__stdcall *)(_DWORD))sub_418CB0("glGenerateMipmap");
    sub_418CB0("glBlitFramebuffer");
    sub_418CB0("glRenderbufferStorageMultisample");
    sub_418CB0("glFramebufferTextureLayer");
    sub_418CB0("glMapBufferRange");
    sub_418CB0("glFlushMappedBufferRange");
    glBindVertexArray = (int (__stdcall *)(_DWORD))sub_418CB0("glBindVertexArray");
    glDeleteVertexArrays = (int (__stdcall *)(_DWORD, _DWORD))sub_418CB0("glDeleteVertexArrays");
    glGenVertexArrays = (int (__stdcall *)(_DWORD, _DWORD))sub_418CB0("glGenVertexArrays");
    sub_418CB0("glIsVertexArray");
  }
}

这样大大提高了程序可读性。

程序流程

从winmain函数开始分析,首先程序读取了其文件数据中的两个纹理图案数据:

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  char *v4; // esi
  DWORD v5; // ebx
  HANDLE v6; // eax
  void *v7; // edi
  void *v8; // ebx
  DWORD v9; // edi
  HANDLE v10; // eax
  void *v11; // esi
  LONG lDistanceToMove; // [esp+Ch] [ebp-110h]
  void *lpBuffer; // [esp+10h] [ebp-10Ch]
  LPVOID lpBuffera; // [esp+10h] [ebp-10Ch]
  DWORD NumberOfBytesRead; // [esp+14h] [ebp-108h]
  CHAR Filename; // [esp+18h] [ebp-104h]

  v4 = (char *)hInstance + *(_DWORD *)((char *)hInstance + *((_DWORD *)hInstance + 15) + 0x54);
  memset(&Filename, 0, 0x100u);
  GetModuleFileNameA(hInstance, &Filename, 0x100u);
  lDistanceToMove = *((_DWORD *)v4 - 2);
  sub_407380(&dword_465FE4, *((_DWORD *)v4 - 3));
  lpBuffer = (void *)dword_465FE4;
  v5 = dword_465FE8 - dword_465FE4;
  v6 = CreateFileA(&Filename, 0x80000000, 1u, 0, 3u, 0x80u, 0);
  v7 = v6;
  if ( v6 != (HANDLE)-1 )
  {
    SetFilePointer(v6, lDistanceToMove, 0, 0);
    NumberOfBytesRead = 0;
    ReadFile(v7, lpBuffer, v5, &NumberOfBytesRead, 0);
    CloseHandle(v7);
  }
  lpBuffera = (LPVOID)*((_DWORD *)v4 - 4);
  sub_407380((int *)&::lpBuffer, *((_DWORD *)v4 - 5));
  v8 = ::lpBuffer;
  v9 = dword_465FF8 - (_DWORD)::lpBuffer;
  v10 = CreateFileA(&Filename, 0x80000000, 1u, 0, 3u, 0x80u, 0);
  v11 = v10;
  if ( v10 != (HANDLE)-1 )
  {
    SetFilePointer(v10, (LONG)lpBuffera, 0, 0);
    NumberOfBytesRead = 0;
    ReadFile(v11, v8, v9, &NumberOfBytesRead, 0);
    CloseHandle(v11);
  }
  return sub_4064D0();
}

接着进入关键的sub_4064D0,该函数就是一个较为典型的opengl 3d程序,使用标准的MVP模型构建,使用shader着色器渲染游戏。

signed int sub_4064D0()
{
  glfwInit();
  glfwWindowHint(0x22002, 3);
  glfwWindowHint(0x22003, 3);
  glfwWindowHint(0x22008, 0x32001);
  v0 = glfwCreateWindow(800, 600, (int)"XDDDDDDDDD", 0, 0);
  window = v0;
  if ( !v0 )
  {
    glfwTerminate();
    return -1;
  }
  sub_418D00(v0);
  sub_419330((int)window, (int)sub_407100);
  glfwSetWindowSizeCallback((int)window, (int)sub_407120);
  sub_419A30(window, 208897, 212995);
  if ( !sub_4051B0() )
    return -1;
  glEnable(2929);
  sub_4060D0(&v41, v30, v3);                    // shader init?
  *(_OWORD *)v64 = xmmword_455340;
  v65 = xmmword_456AA0;
  v66 = xmmword_455470;
  v67 = xmmword_4554D0;
  v68 = xmmword_455560;
  v69 = xmmword_455320;
  v70 = xmmword_456AE0;
  v71 = xmmword_456A90;
  v72 = xmmword_455450;
  v73 = xmmword_455300;
  v74 = xmmword_455540;
  v75 = xmmword_4554A0;
  v76 = xmmword_455500;
  v77 = xmmword_456A70;
  v78 = xmmword_4552A0;
  v79 = xmmword_455550;
  v80 = xmmword_456A60;
  v81 = xmmword_456AC0;
  v82 = xmmword_456A80;
  v83 = xmmword_455530;
  v84 = xmmword_4552D0;
  v85 = xmmword_4554B0;
  v86 = xmmword_455470;
  v87 = xmmword_455460;
  v88 = xmmword_455560;
  v89 = xmmword_455330;
  v90 = xmmword_456AB0;
  v91 = xmmword_456A40;
  v92 = xmmword_455450;
  v93 = xmmword_4552F0;
  v94 = xmmword_455340;
  v95 = xmmword_456AB0;
  v96 = xmmword_456A50;
  v97 = xmmword_455460;
  v98 = xmmword_455300;
  v99 = xmmword_4552D0;
  v100 = xmmword_456AD0;
  v101 = xmmword_4554F0;
  v102 = xmmword_4554C0;
  v103 = xmmword_455560;
  v104 = xmmword_455540;
  v105 = xmmword_455480;
  v106 = xmmword_4554E0;
  v107 = xmmword_456A30;
  v108 = xmmword_455520;
  glGenVertexArrays(1, &v63);
  glGenBuffers(1, &v59);
  glBindVertexArray(v63);
  glBindBuffer(34962, v59);
  glBufferData(34962, 720, v64, 35044);
  glVertexAttribPointer(0, 3, 5126, 0, 20, 0);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(1, 2, 5126, 0, 20, 12);
  glEnableVertexAttribArray(1);
  glGenTextures(1, &v61);
  glBindTexture(3553, v61);
  glTexParameteri(3553, 10242, 10497);
  glTexParameteri(3553, 10243, 10497);
  glTexParameteri(3553, 10241, 9729);
  glTexParameteri(3553, 10240, 9729);
  dword_465FC4 = 1;
  v4 = sub_409D00(dword_465FE8 - dword_465FE4, dword_465FE4, &v43, &v42, (int *)&v62);
  v5 = v4;
  if ( v4 )
  {
    glTexImage2D(3553, 0, 6407, v43, v42, 0, 6407, 5121, v4);
    glGenerateMipmap(3553);
  }
  j___free_base(v5);
  glGenTextures(1, &v60);
  glBindTexture(3553, v60);
  glTexParameteri(3553, 10242, 10497);
  glTexParameteri(3553, 10243, 10497);
  glTexParameteri(3553, 10241, 9729);
  glTexParameteri(3553, 10240, 9729);
  v6 = sub_409D00(dword_465FF8 - (_DWORD)lpBuffer, (int)lpBuffer, &v43, &v42, (int *)&v62);
  v7 = v6;
  if ( v6 )
  {
    glTexImage2D(3553, 0, 6407, v43, v42, 0, 6408, 5121, v6);
    glGenerateMipmap(3553);
  }
  j___free_base(v7);
  v8 = v41;
  glUseProgram(v41);
  v46 = 15;
  v45 = 0;
  LOBYTE(lpMem) = 0;
  gl_init_str(&lpMem, "texture1", 8u);
  v109 = 0;
  v9 = &lpMem;
  if ( v46 >= 0x10 )
    v9 = lpMem;
  v10 = glGetUniformLocation(v8, v9, 0);
  glUniform1i(v10);
  v109 = -1;
  sub_407420(&lpMem);
  v46 = 15;
  v45 = 0;
  LOBYTE(lpMem) = 0;
  gl_init_str(&lpMem, "texture2", 8u);
  v109 = 1;
  v11 = &lpMem;
  if ( v46 >= 0x10 )
    v11 = lpMem;
  v12 = glGetUniformLocation(v8, v11, 1);
  glUniform1i(v12);
  v109 = -1;
  sub_407420(&lpMem);
  if ( !sub_419650((int)window) )
  {
    _libm_sse2_tan_precise();
    v41 = 0;
    *(float *)&v43 = 1.0 / (float)0.3926990926265717;
    v62 = 1.0 / (float)((float)0.3926990926265717 * 1.3333334);
    do
    {
      flt_465FBC = glfwGetTime();
      if ( sub_419920((int)window, 256) == 1 )
        sub_419370((int)window, 1);
      glClearColor(1045220557, 1050253722, 1050253722, 1065353216);
      glClear(16640);
      glActiveTexture(33984);
      glBindTexture(3553, v61);
      glActiveTexture(33985);
      glBindTexture(3553, v60);
      glUseProgram(v8);
      sub_409640(&v41);
      v47 = v62;
      v48 = v43;
      v50 = 0xBF800000;
      v49 = 0xBF80419A;
      v51 = 0xBE4D0148;
      v46 = 15;
      v45 = 0;
      LOBYTE(lpMem) = 0;
      gl_init_str(&lpMem, "projection", 0xAu);
      v109 = 2;
      v13 = &lpMem;
      if ( v46 >= 0x10 )
        v13 = lpMem;
      v14 = glGetUniformLocation(v8, v13, 1);
      glUniformMatrix4fv(v14);
      v109 = -1;
      if ( v46 >= 0x10 )
      {
        v15 = (char *)lpMem;
        if ( v46 + 1 >= 0x1000 )
        {
          if ( (unsigned __int8)lpMem & 0x1F
            || (v16 = *((_DWORD *)lpMem - 1), v16 >= (unsigned int)lpMem)
            || (v15 = (char *)lpMem - v16, (char *)lpMem - v16 < (char *)4)
            || (unsigned int)v15 > 0x23 )
          {
LABEL_53:
            _invalid_parameter_noinfo_noreturn(v15);
          }
          v15 = (char *)*((_DWORD *)lpMem - 1);
        }
        j_j___free_base(v15);
      }
      v35 = *(float *)&dword_464CC4 + *(float *)&qword_464CAC;
      v36 = *(float *)&dword_464CC8 + *((float *)&qword_464CAC + 1);
      v37 = *(float *)&dword_464CCC + *(float *)&dword_464CB4;
      sub_4092A0(&v35);
      v46 = 15;
      v45 = 0;
      LOBYTE(lpMem) = 0;
      gl_init_str(&lpMem, "view", 4u);
      v109 = 3;
      v17 = &lpMem;
      if ( v46 >= 0x10 )
        v17 = lpMem;
      v18 = glGetUniformLocation(v8, v17, 1);
      glUniformMatrix4fv(v18);
      v109 = -1;
      if ( v46 >= 0x10 )
      {
        v15 = (char *)lpMem;
        if ( v46 + 1 >= 0x1000 )
        {
          if ( (unsigned __int8)lpMem & 0x1F )
            goto LABEL_53;
          v19 = *((_DWORD *)lpMem - 1);
          if ( v19 >= (unsigned int)lpMem )
            goto LABEL_53;
          v15 = (char *)lpMem - v19;
          if ( (char *)lpMem - v19 < (char *)4 || (unsigned int)v15 > 0x23 )
            goto LABEL_53;
          v15 = (char *)*((_DWORD *)lpMem - 1);
        }
        j_j___free_base(v15);
      }
      v46 = 15;
      v45 = 0;
      LOBYTE(lpMem) = 0;
      glBindVertexArray(v63);
      v20 = 0;
      v21 = dword_46601C;
      if ( (dword_466020 - (signed int)dword_46601C) >> 2 )
      {
        v32 = 0x3F800000;
        v33 = 0x3E99999A;
        v34 = 0x3F000000;
        do
        {
          v22 = v21[v20 + 1];
          v23 = v21[v20 + 2];
          v56 = v21[v20];
          v57 = v22;
          v58 = v23;
          sub_407F30(&v52);
          v25 = (__int128 *)sub_4086F0(v24, (__m128 *)&v31, (float *)&v56);
          v52 = *v25;
          v53 = v25[1];
          v54 = v25[2];
          v55 = v25[3];
          v26 = (__int128 *)sub_408850(&v32);
          v40 = 15;
          v39 = 0;
          LOBYTE(v38) = 0;
          v52 = *v26;
          v53 = v26[1];
          v54 = v26[2];
          v55 = v26[3];
          gl_init_str(&v38, "model", 5u);
          v109 = 4

本文来源于: https://xz.aliyun.com/t/9402

相关推荐

常见横向移动与域控权限维持方法

横向移动 PTH 如果找到了某个用户的ntlm hash,就可以拿这个ntlm hash当作凭证进行远程登陆了 其中若hash加密方式是 rc4 ,那么就是pass the hash 若加密方式是aes key,那么就是pass the k

无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)

题目例子 <?php error_reporting(0); highlight_file(__FILE__); $code=$_GET['code']; if(preg_match('/[a-z0-9]/i',$code)){ die('

一个加密病毒的分析

实验环境:win7 x64 样本信息:(微步获取) 分析工具:火绒,x64dbg,IDA 一:在虚拟机中运行一下,看一下病毒的运行效果 启动前:(笔者创建了一个txt文件进行测试) 启动后:(文件都被加密了) 病毒作者留下的联系信息:

四大主流WebShell管理工具分析 | 防守方攻略

前言 在网络安全实战攻防演练中,只有了解攻击方的攻击思路和运用武器,防守方才能有效应对。以WebShell 为例,由于企业对外提供服务的应用通常以Web形式呈现,因此Web站点经常成为攻击者的攻击目标。攻击者找到Web站点可利用的漏洞后,通

最简单的加载器免杀思路

最简单的加载器免杀思路 将加载器的变量每次生成都要随机也就是变量混淆, 同时在每行之间插入无效指令:比如随机打印,循环打印,随机数计算加减乘除 这个思路的主要作用是加载器伪装。不管shellcode如果变化加密解密,最后都要回到这个模板里面

记一次靠猜的.net代码审计拿下目标

0x00写在前面 在一次授权的实战测试中,需要拿到某OA的权限,经过top500的姓名+top100的密码,爆破出来几个账户,有了账户,进入oa内部,通过上传很轻松的就拿到了shell,但是客户不满足于此,要求找到未授权的RCE.有了she

网络空间搜索引擎的区别

网络空间搜索引擎的区别 ### fofa fofa是白帽汇推出的网络空间测绘引擎。白帽汇是一家专注于网络空间测绘与前沿技术研究的互联网安全公司,主要从事网络安全产品开发与服务支撑等相关工作,为国家监管部门及政企用户提供综合性整体解决方案,有

D-Link路由器漏洞研究分享

0x0 前言 D-Link DIR-816 A2是中国台湾友讯(D-Link)公司的一款无线路由器。攻击者可借助‘datetime’参数中的shell元字符利用该漏洞在系统上执行任意命令。 0x1 准备 固件版本 1.10B05:http:

主流WebShell工具流量层分析

很多人都说冰蝎好用,流量加密的,可是流量加密在哪里,很多人可能还是懵懵懂懂的,于是就分析记录了一下,大佬勿喷。 AntSword流量分析 蚁剑有一个非常好用的扩展功能为编码器和解码器,利用此功能可以自定义加密,这里分析的是默认的加密方式,在

CVE-2019-12422 Apache Shiro RememberMe Padding Oracle

前置知识 CBC模式 首先我们可以看一下CBC模式的流程图 初始化向量IV和第一组明文XOR后得到的结果作为新的IV和下一组明文XOR,按这样循环下去就得到结果。解密是加密的逆过程,也就是密文被Key解密为中间值,然后中间值与IV进行XOR

Nginx_lua 100参数绕过原理详解

一、环境搭建 Nginx_lua 安装 https://github.com/openresty/lua-nginx-module#installation wget 'https://openresty.org/download/ngin