Windows kernel32.dll仅程序集绘制像素

问题描述

我一直在寻找堆栈溢出,但似乎找不到任何东西

Windows 64位上的kernel32.dll特有的哪些命令和功能可以在屏幕上绘制单个像素,最好没有user32.dll Windows?

解决方法

事实证明我在comments

win32k.sys does create new syscalls。追溯地讲,这是有道理的。

win32k.sys 处理DirectComposition engine,类似于Windows的桌面和Windows管理器:

DirectComposition architecture

DirectComposition API通过COM公开给Win32程序,这使得在没有Visual Studio的情况下使用它非常困难,因为我们需要完整的IDL定义,并且在组装时需要手动在vtable中创建偏移量。
它也很抽象,因此对使用的syscall进行反向工程然后再使用它们会很痛苦。

但是,当然仍然支持旧Windows的图形API GDI(由DirectComposition模拟/集成)。
该API是通过一些DLL的导出功能公开的,而不是在可组合的表面上起作用,而是在Windows和设备上下文(允许绘制的对象)方面起作用。
这样可以很容易地对其进行反向工程并将其用于组装。

在屏幕上绘制像素的最接近的方法是在桌面设备上下文中绘制像素(因为桌面是全屏窗口)。
使用Win32 API,我们可以通过两个功能来做到这一点:

  • GetDC,当使用NULL值调用时,将提供桌面的设备上下文。
  • SetPixel,在设备上下文上绘制一个像素。

如果没有Win32 API,而只能进行直接系统调用,则可能会出现问题,因为这些操作存在于较低级别的接口上是不被允许的。
例如,此接口可以公开共享存储区域,并以未记录格式显示像素。
类似地,设备上下文可以是Win32抽象。

但幸运的是,情况并非如此GetDCSetPixel都有自己的系统调用。
这是非常幸运的,并且可能源于win32k.sys的历史(它与Win32 API结合在一起,实际上是Win32 API,IIRC)。

我对这两个Win32 API进行了反向工程,以获取系统调用号及其用法(这两个数字都在此答案的第二个链接中找到)。
尽管GetDC只是系统调用的包装,但是SetPixel进行了颜色的某种格式转换。
在下面给出的示例中,将省略此转换,如果需要则由您决定(如果没有它,您可能无法编写所需的颜色)。

我制作了一个示例程序,该程序在屏幕的左上角绘制了一个256x256黑色矩形。

Black rectangle

一些注意事项:

  • 这是一个64位程序,因此可以使用syscall指令。这仅是为了进行演示(并且避免解释WOW32Reserved指针和WOW64的含义以及如何使用它们)。
  • 如果程序无法获取桌面句柄,它将触发调试异常。
  • 在顶部,有用于系统调用号的常量,它们是为Windows 7设置的(不确定是否有确切的次要版本)。
  • 该程序由 NASM 组装并与 golink 链接。
  • 这是一个很无聊的程序。避免使用Win32 API不会对编程产生任何影响。如果我是你,我会使用API​​。

没有外部PE依赖项:

No dependencies

DEFAULT REL

GLOBAL main

%define SYS_GetDC                 100ah
%define SYS_SetPixel              10afh


SECTION .text

;.    .     .     .     .     .     .     .     .     .     .     .     .     .
; . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -
;
;Get the HDC of a window
;
;.    .     .     .     .     .     .     .     .     .     .     .     .     .
; . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -

;arg0 (rcx) = HWND
GetDC:
  mov r10,rcx
  mov eax,SYS_GetDC
  syscall
  ret

;.    .     .     .     .     .     .     .     .     .     .     .     .     .
; . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -
;
;Set a pixel in an HDC
;
;.    .     .     .     .     .     .     .     .     .     .     .     .     .
; . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -

SetPixel:
  mov r10,SYS_SetPixel
  syscall
  ret

;.    .     .     .     .     .     .     .     .     .     .     .     .     .
; . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -
;
;Main
;
;.    .     .     .     .     .     .     .     .     .     .     .     .     .
; . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -   . -

main:

  ;Get the desktop HDC

  xor ecx,ecx
  call GetDC
  test eax,eax
  jz .abort

  ;Write a 256x256 black square
  mov ebx,eax          ;HDC into rbx (which is preserved)
  
  xor esi,esi          ;esi = x = 0    
  
.x_loop:  
  xor edi,edi          ;edi = y = 0
  
.y_loop: 
  mov ecx,ebx      ;HDC
  mov edx,edi      ;Y
  mov r8,rsi       ;X
  xor r9,r9        ;Color (black,beware of the correct format!)
  call SetPixel

  inc edi           ;y++
  cmp edi,100h
  jb .y_loop        ;while (y < 256)
 
  inc esi           ;x++
  cmp esi,100h    
  jb .x_loop        ;while (x < 256)


  ;In Windows we can return from main
  ret




  ;Here something went wrong
  ;We must do some eye-catching action,like invoking the debugger

.abort:
  ;This will trigger a debug popup
  int3

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...