如何解决Windows kernel32.dll仅程序集绘制像素
我一直在寻找堆栈溢出,但似乎找不到任何东西
Windows 64位上的kernel32.dll特有的哪些命令和功能可以在屏幕上绘制单个像素,最好没有user32.dll Windows?
解决方法
事实证明我在comments中错。
win32k.sys does create new syscalls。追溯地讲,这是有道理的。
win32k.sys 处理DirectComposition engine,类似于Windows的桌面和Windows管理器:
DirectComposition API通过COM公开给Win32程序,这使得在没有Visual Studio的情况下使用它非常困难,因为我们需要完整的IDL定义,并且在组装时需要手动在vtable中创建偏移量。
它也很抽象,因此对使用的syscall进行反向工程然后再使用它们会很痛苦。
但是,当然仍然支持旧Windows的图形API GDI(由DirectComposition模拟/集成)。
该API是通过一些DLL的导出功能公开的,而不是在可组合的表面上起作用,而是在Windows和设备上下文(允许绘制的对象)方面起作用。
这样可以很容易地对其进行反向工程并将其用于组装。
在屏幕上绘制像素的最接近的方法是在桌面设备上下文中绘制像素(因为桌面是全屏窗口)。
使用Win32 API,我们可以通过两个功能来做到这一点:
-
GetDC
,当使用NULL值调用时,将提供桌面的设备上下文。 -
SetPixel
,在设备上下文上绘制一个像素。
如果没有Win32 API,而只能进行直接系统调用,则可能会出现问题,因为这些操作存在于较低级别的接口上是不被允许的。
例如,此接口可以公开共享存储区域,并以未记录格式显示像素。
类似地,设备上下文可以是Win32抽象。
但幸运的是,情况并非如此,GetDC
和SetPixel
都有自己的系统调用。
这是非常幸运的,并且可能源于win32k.sys的历史(它与Win32 API结合在一起,实际上是Win32 API,IIRC)。
我对这两个Win32 API进行了反向工程,以获取系统调用号及其用法(这两个数字都在此答案的第二个链接中找到)。
尽管GetDC
只是系统调用的包装,但是SetPixel
进行了颜色的某种格式转换。
在下面给出的示例中,将省略此转换,如果需要则由您决定(如果没有它,您可能无法编写所需的颜色)。
我制作了一个示例程序,该程序在屏幕的左上角绘制了一个256x256黑色矩形。
一些注意事项:
- 这是一个64位程序,因此可以使用
syscall
指令。这仅是为了进行演示(并且避免解释WOW32Reserved
指针和WOW64的含义以及如何使用它们)。 - 如果程序无法获取桌面句柄,它将触发调试异常。
- 在顶部,有用于系统调用号的常量,它们是为Windows 7设置的(不确定是否有确切的次要版本)。
- 该程序由 NASM 组装并与 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,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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。