Wykonanie zrzutu ekranu i zapisanie do .jpg (GDI+/MASM64)
Napisane 23 grudnia 2018 godz. 14:44 przez Dawid
Windows® GDI+ jest to interfejs programowania aplikacji oraz zbiór komponentów do wykonywania operacji na obiektach graficznych. Jest on elementem Windows® API (WinAPI). W tym krótkim wpisie zaprezentowany zostanie kod źródłowy pozwalający wykonać zrzut ekranu (ang. screenshot) i zapisać go jako obraz JPG. Kod jest w Asemblerze MASM64 (ML64.exe).
;(c) 2018 Dawid - http://haker.info/
;Asembler MASM64 (ML64.EXE)
;Wykonanie zrzutu ekranu i zapisanie jako obraz JPG
;(Take screenshot and save to .jpg image file)
extrn BitBlt : proc
extrn CreateCompatibleBitmap : proc
extrn CreateCompatibleDC : proc
extrn DeleteDC : proc
extrn ExitProcess : proc
extrn GdipCreateBitmapFromHBITMAP : proc
extrn GdipDisposeImage : proc
extrn GdipSaveImageToFile : proc
extrn GdiplusShutdown : proc
extrn GdiplusStartup : proc
extrn GetDC : proc
extrn GetDeviceCaps : proc
extrn MultiByteToWideChar : proc
extrn SelectObject : proc
;definicja struktury GdiplusStartupInput
GdiplusStartupInput struct
GdiplusVersion dd ?
DebugEventCallback dd ?
SuppressBackgroundThread dd ?
SuppressExternalCodecs dd ?
GdiplusStartupInput ends
;definicja struktury
ImageEncoderJPEG_GUID struct
Data1 dd 0
Data2 dw 0
Data3 dw 0
Data4 db 8 dup(0)
ImageEncoderJPEG_GUID ends
.const
HORZRES equ 8
VERTRES equ 10
SRCCOPY equ 00CC0020h
GDIP_IMAGE_JPG equ 1
.data
GDIPlusToken dq 0
gdipsi GdiplusStartupInput <1,0,0,0>
hScreenDC dq 0
hMemoryDC dq 0
screenWidth dq 0
screenHeight dq 0
hScreenBitmap dq 0
hScreenOldBitmap dq 0
pPicture dq 0
szTempJPGUnicode dw 255 dup (0)
imageGUID ImageEncoderJPEG_GUID <0557CF401h,01A04h,011D3h,<09Ah,073h,000h,000h,0F8h,01Eh,0F3h,02Eh>>
;nazwa pliku do którego zapisany zostanie zrzut ekranu
szTempJPG db "temp.jpg", 0
.code
Main proc
;Inicjalizacja Windows GDI+
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, offset gdipsi
mov rcx, offset GDIPlusToken
call GdiplusStartup
add rsp, 28h
;pobranie uchwytu do kontekstu urządzenia
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
xor rcx, rcx
call GetDC
add rsp, 28h
mov hScreenDC, rax
;utworzenie kontekstu urządzenia w pamięci
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
mov rcx, hScreenDC
call CreateCompatibleDC
add rsp, 28h
mov hMemoryDC, rax
;pobranie szerokości ekranu
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, HORZRES
mov rcx, hScreenDC
call GetDeviceCaps
add rsp, 28h
mov screenWidth, rax
;pobranie wysokości ekranu
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, VERTRES
mov rcx, hScreenDC
call GetDeviceCaps
add rsp, 28h
mov screenHeight, rax
;utworzenie bitmapy kompatybilnej z urządzeniem
sub rsp, 28h
xor r9, r9
mov r8, screenHeight
mov rdx, screenWidth
mov rcx, hScreenDC
call CreateCompatibleBitmap
add rsp, 28h
mov hScreenBitmap, rax
;wybiera obiekt do określonego kontekstu urządzenia
;(zastępuje poprzedni obiekt)
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, hScreenBitmap
mov rcx, hMemoryDC
call SelectObject
add rsp, 28h
;zachowanie poprzedniego obiektu w zmiennej
mov hScreenOldBitmap, rax
;kopiowanie kontekstu urządzenia
sub rsp, 48h
mov qword ptr [rsp+40h], SRCCOPY
mov qword ptr [rsp+38h], 0
mov qword ptr [rsp+30h], 0
mov rax, hScreenDC
mov qword ptr [rsp+28h], rax
mov rax, screenHeight
mov qword ptr [rsp+20h], rax
mov r9, screenWidth
xor r8, r8
xor rdx, rdx
mov rcx, hMemoryDC
call BitBlt
add rsp, 48h
sub rsp, 28h
xor r9, r9
xor r8, r8
mov rdx, hScreenOldBitmap
mov rcx, hMemoryDC
call SelectObject
add rsp, 28h
mov hScreenBitmap, rax
;usunięcie kontekstu urządzenia
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
mov rcx, hMemoryDC
call DeleteDC
add rsp, 28h
;usunięcie kontekstu urządzenia
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
mov rcx, hScreenDC
call DeleteDC
add rsp, 28h
;utworzenie bitmapy z uchwytu
sub rsp, 28h
xor r9, r9
mov r8, offset pPicture
xor rdx, rdx
mov rcx, [hScreenBitmap]
call GdipCreateBitmapFromHBITMAP
add rsp, 28h
;zamienia zwykły napis na tzw. wide string
sub rsp, 30h
mov qword ptr [rsp+28h], 255
mov rax, offset szTempJPGUnicode
mov qword ptr [rsp+20h], rax
mov r9, -1
mov r8, offset szTempJPG
mov rdx, 0
mov rcx, 0
call MultiByteToWideChar
add rsp, 30h
;zapisanie obrazu (zrzutu ekranu) do pliku
sub rsp, 28h
xor r9, r9
lea r8d, imageGUID
mov rdx, offset szTempJPGUnicode
mov rcx, pPicture
call GdipSaveImageToFile
add rsp, 28h
;zwolnienie zasobów
sub rsp, 28h
xor r9, r9
xor r8, r8
xor rdx, rdx
mov rcx, pPicture
call GdipDisposeImage
add rsp, 28h
_exit:
sub rsp, 8h
xor rcx, rcx
call ExitProcess
Main endp
end
Skrypt .bat do zbudowania pliku wykonywalnego .exe:
@echo off
ml64.exe prog4.asm /link /entry:Main /subsystem:windows /defaultlib:"kernel32.Lib" /defaultlib:"user32.Lib" /defaultlib:"Gdi32.Lib" /defaultlib:"gdiplus.lib" /LARGEADDRESSAWARE:NO
pause
Tagi: masm64