How to take screenshot (MASM64 / ml64.exe source)

novx

New member
Hi all,
I want to share complete source code in MASM x64 (ml64.exe) Assembly Language.
Program takes screenshot and saves it to JPG image file.

Code:
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

GdiplusStartupInput struct
      GdiplusVersion dd ?
      DebugEventCallback dd ?
      SuppressBackgroundThread dd ?
      SuppressExternalCodecs dd ?
GdiplusStartupInput ends

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>>
;file name to save screenshot
szTempJPG db "temp.jpg", 0

.code
    Main proc
        ;initialize Windows GDI+
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        mov rdx, offset gdipsi
        mov rcx, offset GDIPlusToken
        call GdiplusStartup
        add rsp, 28h
  
        ;get context handle
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        xor rdx, rdx
        xor rcx, rcx
        call GetDC
        add rsp, 28h
      
        mov hScreenDC, rax
      
        ;create context
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        xor rdx, rdx
        mov rcx, hScreenDC
        call CreateCompatibleDC
        add rsp, 28h
      
        mov hMemoryDC, rax
      
        ;get screen width
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        mov rdx, HORZRES
        mov rcx, hScreenDC
        call GetDeviceCaps
        add rsp, 28h
      
        mov screenWidth, rax
      
        ;get screen height
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        mov rdx, VERTRES
        mov rcx, hScreenDC
        call GetDeviceCaps
        add rsp, 28h
      
        mov screenHeight, rax
      
        ;create bitmap
        sub rsp, 28h
        xor r9, r9
        mov r8, screenHeight
        mov rdx, screenWidth
        mov rcx, hScreenDC
        call CreateCompatibleBitmap
        add rsp, 28h
      
        mov hScreenBitmap, rax
      
        ;choose object
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        mov rdx, hScreenBitmap
        mov rcx, hMemoryDC
        call SelectObject
        add rsp, 28h
      
        ;save object to variable
        mov hScreenOldBitmap, rax
      
        ;copy context
        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
      
        ;remove context
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        xor rdx, rdx
        mov rcx, hMemoryDC
        call DeleteDC
        add rsp, 28h
      
        ;remove context
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        xor rdx, rdx
        mov rcx, hScreenDC
        call DeleteDC
        add rsp, 28h
      
        ;create bitmap from handle
        sub rsp, 28h
        xor r9, r9
        mov r8, offset pPicture
        xor rdx, rdx
        mov rcx, [hScreenBitmap]
        call GdipCreateBitmapFromHBITMAP
        add rsp, 28h
      
        ;convert to 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
      
        ;save screenshot to file
        sub rsp, 28h
        xor r9, r9
        lea r8d, imageGUID
        mov rdx, offset szTempJPGUnicode
        mov rcx, pPicture
        call GdipSaveImageToFile
        add rsp, 28h
      
        ;release resources
        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
Author of this code: haker.info <redacted-because-we-aren't-a-backlink-farm>

Building the code:
Code:
ml64.exe program1.asm /link /entry:Main /subsystem:windows /defaultlib:"kernel32.Lib" /defaultlib:"user32.Lib" /defaultlib:"Gdi32.Lib" /defaultlib:"gdiplus.lib" /LARGEADDRESSAWARE:NO
MASM x64 Assembler is included in Microsoft Visual Studio.
 
Zuletzt bearbeitet von einem Moderator:
Oben