Windows kernel32.dll 仅装配图像素

Windows kernel32.dll only assembly draw pixel

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

kernel32.dll在windows 64位上有什么命令和函数可以在屏幕上绘制单个像素,最好没有user32.dll windows?

原来我的.错了

win32k.sys does create new syscalls。反过来说,也有道理。

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

DirectComposition API 通过 COM 暴露给 Win32 程序,这使得在没有 Visual Studio 的情况下很难使用,因为我们需要完整的 IDL 定义,并在汇编中进行偏移手动在 vtables 中。
它也很抽象,所以 reverse-engineering 使用的系统调用然后使用它们会很痛苦。

但是,GDI,遗留的 Windows' 图形 API,当然仍然受支持(它是用 DirectComposition 模拟的 by/integrated)。
API 通过一些 DLL 的导出函数公开,而不是根据可组合表面工作,而是根据 Windows 和设备上下文(允许绘制的对象)工作。
这使得 reverse-engineering 它和在汇编中使用它变得容易。

最接近在屏幕上绘制像素的是在桌面设备上下文中绘制像素(因为桌面是全屏 window)。
对于 Win32 API,我们将使用两个函数来实现:

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

如果没有 Win32 API,但只有直接系统调用,它可能会出现问题,因为这些操作不存在于 lower-level 接口上。
例如,此接口可以公开一个共享内存区域,其中使用未记录的格式写入像素。
类似地,设备上下文可以是 Win32 抽象。

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

我 reverse-engineered 这两个 Win32 API 来获取系统调用编号以及它们的使用方式(这两个编号都可以在这个答案的第二个 link 中找到)。
虽然 GetDC 只是系统调用的包装器,但 SetPixel 对颜色进行了一些格式转换。
在下面给出的例子中,这个转换被省略了,如果需要的话由你决定(没有它你可能无法写出你想要的颜色)。

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

一些注意事项:

  • 是64位程序,可以使用syscall指令。这只是为了展示(并且避免解释 WOW32Reserved 指针和 WOW64 是什么以及如何使用它们)。
  • 如果程序无法获取桌面句柄,将触发调试异常。
  • 在顶部,有用于系统调用编号的常量,它们设置为 Windows 7(如果有的话,不确定是哪个确切的次要版本)。
  • 程序是用 NASM 组装的,link 用 golink 编辑的。
  • 这是一个很无聊的节目。避免 Win32 API 不会为编程增加任何洞察力。如果我是你,我会使用 API.

没有外部 PE 依赖项:

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, rcx
  mov eax, 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