Author Topic: Take screenshot and save to JPG (ML64.exe)  (Read 900 times)

davef

  • Regular Member
  • *
  • Posts: 5
Take screenshot and save to JPG (ML64.exe)
« on: November 10, 2018, 09:45:06 PM »
Hello,
I want to share my source code written for ML64.EXE (MASM64) assembler.

Build.bat file content:
Code: [Select]
@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

My source code:
Code: [Select]
;(c) 2018 Dawid_vx7 - http://vx7.pl/
;Assembler MASM64 (ML64.EXE)
;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

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>>
szTempJPG db "temp.jpg", 0

.code
    Main proc
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        mov rdx, offset gdipsi
        mov rcx, offset GDIPlusToken
        call GdiplusStartup
        add rsp, 28h
   
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        xor rdx, rdx
        xor rcx, rcx
        call GetDC
        add rsp, 28h
       
        mov hScreenDC, rax
       
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        xor rdx, rdx
        mov rcx, hScreenDC
        call CreateCompatibleDC
        add rsp, 28h
       
        mov hMemoryDC, rax
       
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        mov rdx, HORZRES
        mov rcx, hScreenDC
        call GetDeviceCaps
        add rsp, 28h
       
        mov screenWidth, rax
       
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        mov rdx, VERTRES
        mov rcx, hScreenDC
        call GetDeviceCaps
        add rsp, 28h
       
        mov screenHeight, rax
       
        sub rsp, 28h
        xor r9, r9
        mov r8, screenHeight
        mov rdx, screenWidth
        mov rcx, hScreenDC
        call CreateCompatibleBitmap
        add rsp, 28h
       
        mov hScreenBitmap, rax
       
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        mov rdx, hScreenBitmap
        mov rcx, hMemoryDC
        call SelectObject
        add rsp, 28h
       
        mov hScreenOldBitmap, rax
       
        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
       
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        xor rdx, rdx
        mov rcx, hMemoryDC
        call DeleteDC
        add rsp, 28h
       
        sub rsp, 28h
        xor r9, r9
        xor r8, r8
        xor rdx, rdx
        mov rcx, hScreenDC
        call DeleteDC
        add rsp, 28h
       
        sub rsp, 28h
        xor r9, r9
        mov r8, offset pPicture
        xor rdx, rdx
        mov rcx, [hScreenBitmap]
        call GdipCreateBitmapFromHBITMAP
        add rsp, 28h
       
        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
       
        sub rsp, 28h
        xor r9, r9
        lea r8d, imageGUID
        mov rdx, offset szTempJPGUnicode
        mov rcx, pPicture
        call GdipSaveImageToFile
        add rsp, 28h
       
        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

Vortex

  • Member
  • *****
  • Posts: 2016
Re: Take screenshot and save to JPG (ML64.exe)
« Reply #1 on: November 11, 2018, 04:18:00 AM »
Hi davef,

Nice work. A small suggestion : you can avoid the multiple sub rsp\add rsp instructions by doing an initial stack allocation taking in account the API MultiByteToWideChar. It has the maximum number of parameters in your code.