NtGdiPolyPolyDraw内核函数逆向分析

0x00前言

分析文件是win11 21h2 的win32kbase.sys 驱动里面的NtGdiPolyPolyDraw 内核函数

0x01NtGdiPolyPolyDraw流程

NtGdiPolyPolyDraw 一共接收5个参数

__int64 __fastcall NtGdiPolyPolyDraw(
__int64 a1, 3环hdc句柄
void *a2, POINT数组
void *a3, POINT数组长度
unsigned int a4  多少组POINT数组
, int a5)type 不同调用不同处理函数

第一步判断a5是不是等于2 如果是就调用NtGdiFastPolyPolyline  返回失败 直接返回函数

 

 接着会调用GrePolyPolyline

 

只有当a4的值大于1 才会去申请内存存放这些数组 循环累加数组有多少个点

 

 a5 决定调用什么函数处理点

 

 

 默认是4 会去调用GrePolylineTo 它又会去调用 EPATHOBJ::bPolyLineTo   生成点

 

 EPATHOBJ::addpoints  实现

 

 关键的是EPATHOBJ::createrec  完成点赋值的

__int64 __fastcall EPATHOBJ::createrec(
        EPATHOBJ *this,
        struct EXFORMOBJ *a2,
        struct _PATHDATAL *a3,
        struct _POINTFIX *a4)
{
  EXFORMOBJ *v6; // r11
  __int64 v8; // r10
  struct PATHALLOC *v9; // r15
  __int64 v10; // rbx
  unsigned __int64 v11; // rcx
  unsigned __int64 v12; // rax
  unsigned int v13; // r12d
  int v14; // r8d
  __int64 v16; // rdi
  __int64 v17; // rax
  struct _POINTFIX *v18; // rcx
  struct _POINTFIX *v19; // rdx
  _DWORD *v20; // rdx
  __int64 v21; // rcx
  __int64 v22; // r8
  _DWORD *v23; // rax
  int v24; // ecx
  int v25; // ecx
  _QWORD *v26; // rax
  __int64 v28; // rax
  struct PATHALLOC *v29; // rax
  __int64 v30; // [rsp+40h] [rbp-38h]

  v6 = a2;
  v8 = *((_QWORD *)this + 1);
  v30 = *(_QWORD *)(v8 + 24);                   // 是否已经有堆
  v9 = (struct PATHALLOC *)v30;
  LODWORD(v10) = 0;
  if ( v30 )
  {
    v11 = *(_QWORD *)(v30 + 8) + 24i64;         // 已经复制到多少地址
    v12 = v30 + *(unsigned int *)(v30 + 16);    // 当前地址
    if ( v12 > v11 )
      v10 = (__int64)(v12 - v11) >> 3;
  }
  v13 = *(_DWORD *)(v8 + 80) & 1;               // 调用是3  0或1
  v14 = *(_DWORD *)a3;
  if ( (v14 & 0x10) != 0 && (_DWORD)v10 )       // v14默认0
    LODWORD(v10) = 3 * (((unsigned int)v10 - v13) / 3) + v13;
  if ( (unsigned int)v10 < v13 + *((_DWORD *)a3 + 1) && (unsigned int)v10 < 8 )// 默认可以走
  {
    v29 = newpathalloc();                       // 默认0xFC0大小
    v9 = v29;
    if ( !v29 )
    {
      EngSetLastError(8u);
      EPATHOBJ::reinit(this);
      return 0i64;
    }
    *(_QWORD *)v29 = *(_QWORD *)(*((_QWORD *)this + 1) + 24i64);// 调试是0
    *(_QWORD *)(*((_QWORD *)this + 1) + 24i64) = v29;// 堆等于
    LODWORD(v10) = (unsigned int)((_DWORD)v29 + *((_DWORD *)v29 + 4) - *((_DWORD *)v29 + 2) - 24) >> 3;// (堆大小-30h)/8
    v14 = *(_DWORD *)a3;
    if ( (*(_DWORD *)a3 & 0x10) != 0 )
      LODWORD(v10) = 3 * (((unsigned int)v10 - v13) / 3) + v13;// 对齐
    v6 = a2;
  }
  if ( (unsigned int)v10 > v13 + *((_DWORD *)a3 + 1) )// 大于就当前要拷贝的长度
    LODWORD(v10) = v13 + *((_DWORD *)a3 + 1);
  v16 = *((_QWORD *)v9 + 1);                    // 堆+8 去地址
  *(_DWORD *)(v16 + 16) = v14 | 2;              // a3[0]
  *(_DWORD *)(v16 + 20) = v10;                  // 真实大小
  *(_QWORD *)v16 = 0i64;
  *(_QWORD *)(v16 + 8) = *(_QWORD *)(*((_QWORD *)this + 1) + 40i64);
  v17 = *((_QWORD *)this + 1);
  if ( v13 )
  {
    *(_QWORD *)(v16 + 24) = *(_QWORD *)(v17 + 64);
    LODWORD(v10) = v10 - 1;                     // v10是要复制的长度
    *(_DWORD *)(v16 + 16) |= *(_DWORD *)(*((_QWORD *)this + 1) + 80i64) & 5;
    *(_DWORD *)(*((_QWORD *)this + 1) + 80i64) &= 0xFFFFFFFA;
  }
  else
  {
    v28 = *(_QWORD *)(v17 + 40);
    if ( v28 )
      *(_DWORD *)(v28 + 16) &= ~2u;
  }
  v18 = (struct _POINTFIX *)(v16 + 8 * (v13 + 3i64));// 控制开始复制地址
  v19 = (struct _POINTFIX *)*((_QWORD *)a3 + 1);// point 地址
  if ( a4 )
  {
    vOffsetPoints(v18, v19, v10, a4->x, a4->y);
  }
  else if ( v6 )                                // a2不为空默认走的
  {
    EXFORMOBJ::bXformRound(v6, (struct _POINTL *)v19, (struct _POINTFIX *)(v16 + 8 * (v13 + 3i64)), (unsigned int)v10);
  }
  else
  {
    memmove(v18, v19, 8i64 * (unsigned int)v10);
  }
  *((_DWORD *)a3 + 1) -= v10;                   // 减去复制大小
  *((_QWORD *)a3 + 1) += 8i64 * (unsigned int)v10;// 增加复制地址
  *(_DWORD *)a3 &= 0xFFFFFFFA;
  v20 = (_DWORD *)(v16 + 24);
  v21 = *((_QWORD *)this + 1);
  if ( !*(_QWORD *)(v21 + 40) )
  {
    *(_DWORD *)(v21 + 56) = *v20;
    *(_DWORD *)(*((_QWORD *)this + 1) + 48i64) = *(_DWORD *)(*((_QWORD *)this + 1) + 56i64);
    *(_DWORD *)(*((_QWORD *)this + 1) + 60i64) = *(_DWORD *)(v16 + 28);
    *(_DWORD *)(*((_QWORD *)this + 1) + 52i64) = *(_DWORD *)(*((_QWORD *)this + 1) + 60i64);
    v21 = *((_QWORD *)this + 1);
  }
  if ( v13 + (_DWORD)v10 )
  {
    v22 = v13 + (unsigned int)v10;              // 复制的点数量
    do
    {
      v23 = (_DWORD *)*((_QWORD *)this + 1);
      v24 = *v20;
      if ( v23[12] > *v20 )                     // 大于20
      {
        v23[12] = v24;                          // this+48
      }
      else if ( v23[14] < v24 )
      {
        v23[14] = v24;
      }
      v25 = v20[1];                             // *(new+24)+4
      if ( v23[15] < v25 )
      {
        v23[15] = v25;
      }
      else if ( v23[13] > v25 )
      {
        v23[13] = v25;
      }
      v20 += 2;
      --v22;
    }
    while ( v22 );
    v21 = *((_QWORD *)this + 1);
  }
  v26 = *(_QWORD **)(v21 + 40);
  if ( v26 )
  {
    *v26 = v16;                                 // 申请的堆
    *(_QWORD *)(*((_QWORD *)this + 1) + 40i64) = v16;
  }
  else
  {
    *(_QWORD *)(v21 + 40) = v16;                // 保存堆
    *(_QWORD *)(*((_QWORD *)this + 1) + 32i64) = v16;
  }
  *((_QWORD *)v9 + 1) = v16 + 8 * (*(unsigned int *)(v16 + 20) + 3i64);// 复制的大小
  return 1i64;
}

 

posted @ 2022-04-23 16:52  紅人  阅读(218)  评论(0编辑  收藏  举报