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; }
从此山高路远,纵马扬鞭。愿往后旅途,三冬暖,春不寒,天黑有灯,下雨有伞。此生尽兴,不负勇往。